Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
6461120
docs: add rewrite architecture records
xz-dev Jun 22, 2026
9527287
chore: add rewrite agent guardrails
xz-dev Jun 22, 2026
ae0d72c
feat(app): add Flutter shell scaffold
xz-dev Jun 22, 2026
4756f7c
feat(getter): wire package-centric getter submodule
xz-dev Jun 22, 2026
a5730a9
ci: add rewrite validation workflow
xz-dev Jun 22, 2026
59c1a0d
fix(getter): keep Android proxy off Lua deps
xz-dev Jun 22, 2026
3201d92
fix(app): use Flutter-compatible Gradle wrapper
xz-dev Jun 22, 2026
35e6c3d
ci: restrict Telegram notifications to master pushes
xz-dev Jun 22, 2026
80e1eb6
fix(app): use Flutter-compatible AGP
xz-dev Jun 22, 2026
384aee6
docs: add rewrite next-step audit plan
xz-dev Jun 22, 2026
a1c43f4
fix(app): use Flutter-compatible Kotlin plugin
xz-dev Jun 22, 2026
c6838b5
docs: update rewrite next-step completion status
xz-dev Jun 22, 2026
76f771a
feat(app): add getter bridge contract
xz-dev Jun 22, 2026
47f5811
feat(getter): add offline repo validation
xz-dev Jun 22, 2026
0976844
feat(getter): import legacy Room databases
xz-dev Jun 22, 2026
81a5dec
feat(getter): add installed app autogen
xz-dev Jun 22, 2026
8f3ca13
feat(getter): add offline update check
xz-dev Jun 22, 2026
9bb18f2
feat(getter): add offline task lifecycle
xz-dev Jun 23, 2026
1ba7614
feat(app): render getter task DTOs
xz-dev Jun 23, 2026
aed83cb
ci(app): publish Flutter APK artifacts
xz-dev Jun 23, 2026
2e22767
feat(app): add legacy Room migration adapter
xz-dev Jun 23, 2026
39af4c7
feat(app): add Android platform adapter spine
xz-dev Jun 23, 2026
3a5a602
feat(app): add Android installed inventory provider
xz-dev Jun 23, 2026
dd94154
feat(app): bridge installed autogen to Flutter
xz-dev Jun 23, 2026
8a6ac21
feat(app): bridge legacy room import
xz-dev Jun 24, 2026
044ca72
ci: set Android ar for cargo checks
xz-dev Jun 24, 2026
65df6ab
test(app): cover legacy room preparation
xz-dev Jun 24, 2026
c0f6752
test(app): validate native bridge on device
xz-dev Jun 24, 2026
d392b5c
docs(architecture): accept runtime task ADRs
xz-dev Jun 25, 2026
dba34ec
feat(app): bridge runtime task operations
xz-dev Jun 25, 2026
108625a
feat(app): stream runtime notifications
xz-dev Jun 25, 2026
2b98939
docs(todo): update runtime bridge progress
xz-dev Jun 25, 2026
ced8576
feat(app): issue runtime actions from update checks
xz-dev Jun 25, 2026
5061d20
docs(todo): note offline action issuance
xz-dev Jun 25, 2026
71c71c9
docs(lua): document static update candidates
xz-dev Jun 25, 2026
75b9f65
feat(app): issue actions from registered packages
xz-dev Jun 25, 2026
2aad93f
docs(todo): note registered package action issuance
xz-dev Jun 25, 2026
7ebf9be
feat(app): adopt pin version DTOs
xz-dev Jun 25, 2026
c1f7126
feat(app): add typed runtime task APIs
xz-dev Jun 25, 2026
b2c03b7
chore(app): point CLI debug tasks at runtime script
xz-dev Jun 25, 2026
3897038
refactor(app): drop fake task DTOs from product adapter
xz-dev Jun 25, 2026
dd9115c
docs(lua): describe static mock provider boundary
xz-dev Jun 25, 2026
1530a42
refactor(app): drop CLI fake task adapter APIs
xz-dev Jun 25, 2026
7bcaa0b
ci: install multilib for Android LuaJIT builds
xz-dev Jun 25, 2026
4e6274a
chore(app): update Flutter toolchain baseline
xz-dev Jun 25, 2026
25af79c
feat(app): load snapshots from native getter read model
xz-dev Jun 25, 2026
1a5d822
feat(app): submit update checks to runtime
xz-dev Jun 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
201 changes: 130 additions & 71 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,9 @@ name: Android CI

on:
push:
branches:
branches:
- master
paths-ignore:
- 'source/**'
- '**.md'
- '.**'
- 'fastlane/**'
pull_request:
paths-ignore:
- 'source/**'
- '**.md'
- '.**'
- 'fastlane/**'
workflow_dispatch:

jobs:
Expand All @@ -37,97 +27,166 @@ jobs:
distribution: 'temurin'
java-version: 21

- name: Install Linux host build dependencies
run: |
sudo apt-get update
sudo apt-get install -y gcc-multilib g++-multilib

- name: Setup Android SDK
uses: android-actions/setup-android@v3

- name: Install NDK
run: echo "y" | sdkmanager --install "ndk;${{ env.NDK_VERSION }}"
- name: Install Android SDK packages
run: yes | sdkmanager --install "platforms;android-36" "build-tools;36.0.0" "platform-tools" "ndk;${{ env.NDK_VERSION }}"

- name: Install Cargo with aarch64-linux-android
- name: Add Android tools to environment
shell: bash
run: |
BUILD_TOOL_VERSION=$(ls "$ANDROID_HOME/build-tools" | sort -V | tail -n 1)
echo "BUILD_TOOL_VERSION=$BUILD_TOOL_VERSION" >> "$GITHUB_ENV"
echo "$ANDROID_HOME/build-tools/$BUILD_TOOL_VERSION" >> "$GITHUB_PATH"
NDK_HOME="$ANDROID_HOME/ndk/$NDK_VERSION"
echo "ANDROID_NDK_HOME=$NDK_HOME" >> "$GITHUB_ENV"
echo "ANDROID_NDK_ROOT=$NDK_HOME" >> "$GITHUB_ENV"
echo "CC_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android23-clang" >> "$GITHUB_ENV"
echo "AR_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" >> "$GITHUB_ENV"
echo "Android build tools: $BUILD_TOOL_VERSION"
echo "Android NDK: $NDK_HOME"

- name: Install Flutter
uses: subosito/flutter-action@v2
with:
channel: stable
cache: true

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-linux-android
components: clippy, rustfmt

- name: Install Android Rust targets
run: rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android

- name: Add Rust targe tarchitectures
- name: Install just
run: |
rustup target add x86_64-linux-android
rustup target add armv7-linux-androideabi
if ! command -v just >/dev/null 2>&1; then
cargo install just --locked
fi

- name: Retrieve version
shell: bash
run: |
echo VERSION=$(git rev-parse --short HEAD) >> $GITHUB_ENV

# Split due https://github.com/mozilla/rust-android-gradle/issues/38
- name: Build with Gradle (debug)
run: ./gradlew -PappVerName=${{ env.VERSION }} assembleDebug
env:
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}

- name: Build with Gradle (release)
if: ${{ !github.event.pull_request }}
run: ./gradlew -PappVerName=${{ env.VERSION }} assembleRelease
VERSION=$(git rev-parse --short HEAD)
APP_VERSION=$(awk '/^version:/ {print $2}' app_flutter/pubspec.yaml)
FLUTTER_BASE_VERSION="${APP_VERSION%%+*}"
FLUTTER_BUILD_NUMBER="${APP_VERSION##*+}"
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
echo "FLUTTER_BUILD_NAME=${FLUTTER_BASE_VERSION}_${VERSION}" >> "$GITHUB_ENV"
echo "FLUTTER_BUILD_NUMBER=$FLUTTER_BUILD_NUMBER" >> "$GITHUB_ENV"

- name: Run rewrite validation
run: just verify

- name: Build Android Rust bridge libraries
run: ./gradlew --no-daemon ':core-getter:buildDebugApi_proxyRust[arm64-v8a]' ':core-getter:buildDebugApi_proxyRust[armeabi-v7a]' ':core-getter:buildDebugApi_proxyRust[x86_64]'

- name: Configure Flutter release signing
if: ${{ github.event_name != 'pull_request' }}
shell: bash
env:
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
KEY_ALIAS: ${{ secrets.ALIAS }}
run: |
set -euo pipefail
: "${SIGNING_KEY:?SIGNING_KEY secret is required}"
: "${KEY_STORE_PASSWORD:?KEY_STORE_PASSWORD secret is required}"
: "${KEY_PASSWORD:?KEY_PASSWORD secret is required}"
: "${KEY_ALIAS:?ALIAS secret is required}"
printf '%s' "$SIGNING_KEY" | base64 --decode > app_flutter/android/upload-keystore.jks
{
printf 'storePassword=%s\n' "$KEY_STORE_PASSWORD"
printf 'keyPassword=%s\n' "$KEY_PASSWORD"
printf 'keyAlias=%s\n' "$KEY_ALIAS"
printf 'storeFile=../upload-keystore.jks\n'
} > app_flutter/android/key.properties

- name: Build Flutter APK artifacts
shell: bash
run: |
cd app_flutter
flutter build apk --debug --build-name "$FLUTTER_BUILD_NAME" --build-number "$FLUTTER_BUILD_NUMBER"
flutter build apk --release --build-name "$FLUTTER_BUILD_NAME" --build-number "$FLUTTER_BUILD_NUMBER"

- name: Setup build tool version variable
- name: Locate Flutter APK artifacts
shell: bash
run: |
BUILD_TOOL_VERSION=$(ls /usr/local/lib/android/sdk/build-tools/ | tail -n 1)
echo "BUILD_TOOL_VERSION=$BUILD_TOOL_VERSION" >> $GITHUB_ENV
echo Last build tool version is: $BUILD_TOOL_VERSION

- name: Sign Android release
if: ${{ !github.event.pull_request }}
id: sign
uses: r0adkll/sign-android-release@v1.0.4
DEBUG_APK="app_flutter/build/app/outputs/flutter-apk/app-debug.apk"
RELEASE_APK="app_flutter/build/app/outputs/flutter-apk/app-release.apk"
test -f "$DEBUG_APK"
test -f "$RELEASE_APK"
echo "DEBUG_APK=$DEBUG_APK" >> "$GITHUB_ENV"
echo "RELEASE_APK=$RELEASE_APK" >> "$GITHUB_ENV"

- name: Verify Flutter APK identity and signature
shell: bash
env:
BUILD_TOOLS_VERSION: ${{ env.BUILD_TOOL_VERSION }}
with:
releaseDirectory: app/build/outputs/apk/release
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
alias: ${{ secrets.ALIAS }}
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}
EXPECTED_SIGNING_CERT_SHA256: ${{ secrets.EXPECTED_SIGNING_CERT_SHA256 }}
run: |
set -euo pipefail
aapt dump badging "$DEBUG_APK" | tee /tmp/upgradeall-debug-badging.txt
aapt dump badging "$RELEASE_APK" | tee /tmp/upgradeall-release-badging.txt
grep -F "package: name='net.xzos.upgradeall.debug'" /tmp/upgradeall-debug-badging.txt
grep -F "versionCode='$FLUTTER_BUILD_NUMBER'" /tmp/upgradeall-debug-badging.txt
grep -F "versionName='$FLUTTER_BUILD_NAME'" /tmp/upgradeall-debug-badging.txt
grep -F "package: name='net.xzos.upgradeall'" /tmp/upgradeall-release-badging.txt
grep -F "versionCode='$FLUTTER_BUILD_NUMBER'" /tmp/upgradeall-release-badging.txt
grep -F "versionName='$FLUTTER_BUILD_NAME'" /tmp/upgradeall-release-badging.txt
apksigner verify --print-certs "$RELEASE_APK" | tee /tmp/upgradeall-release-certs.txt
if [[ "${{ github.event_name }}" != "pull_request" ]] && grep -q "CN=Android Debug" /tmp/upgradeall-release-certs.txt; then
echo "::error::Flutter release APK is debug-signed; CI release signing did not take effect"
exit 1
fi
actual_sha256=$(awk -F': ' '/Signer #1 certificate SHA-256 digest/ { gsub(":", "", $2); print toupper($2); exit }' /tmp/upgradeall-release-certs.txt)
expected_sha256=$(printf '%s' "$EXPECTED_SIGNING_CERT_SHA256" | tr -d ':[:space:]' | tr '[:lower:]' '[:upper:]')
if [[ -n "$expected_sha256" && "$actual_sha256" != "$expected_sha256" ]]; then
echo "::error::Flutter release APK signer SHA-256 does not match EXPECTED_SIGNING_CERT_SHA256"
exit 1
fi
if [[ "${{ github.event_name }}" != "pull_request" && -z "$expected_sha256" ]]; then
echo "::warning::EXPECTED_SIGNING_CERT_SHA256 is not set; release signer identity was not pinned"
fi

- name: Upload debug apk
- name: Upload Flutter debug apk
uses: actions/upload-artifact@v6
if: ${{ !github.event.pull_request }}
if: ${{ github.event_name != 'pull_request' }}
with:
path: './app/build/outputs/apk/debug/*.apk'
name: build_debug_${{ env.VERSION }}
path: ${{ env.DEBUG_APK }}
name: build_flutter_debug_${{ env.VERSION }}

- name: Upload release apk
- name: Upload Flutter release apk
uses: actions/upload-artifact@v6
if: ${{ !github.event.pull_request }}
if: ${{ github.event_name != 'pull_request' }}
with:
path: ${{ steps.sign.outputs.signedReleaseFile }}
name: build_release_${{ env.VERSION }}
path: ${{ env.RELEASE_APK }}
name: build_flutter_release_${{ env.VERSION }}

- name: Get apk info
if: ${{ !github.event.pull_request }}
if: ${{ github.event_name != 'pull_request' }}
id: apk-info
uses: hkusu/apk-info-action@v1
with:
apk-path: ${{ steps.sign.outputs.signedReleaseFile }}
apk-path: ${{ env.RELEASE_APK }}

# - name: Upload mappings with App Center CLI
# if: ${{ !github.event.pull_request }}
# if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
# uses: zhaobozhen/AppCenter-Github-Action@1.0.1
# with:
# command: appcenter crashes upload-mappings --mapping app/build/outputs/mapping/release/mapping.txt --version-name ${{ steps.apk-info.outputs.version-name }} --version-code ${{ steps.apk-info.outputs.version-code }} --app DUpdateSystem/UpgradeAll
# command: appcenter crashes upload-mappings --mapping app_flutter/build/app/outputs/mapping/release/mapping.txt --version-name ${{ steps.apk-info.outputs.version-name }} --version-code ${{ steps.apk-info.outputs.version-code }} --app DUpdateSystem/UpgradeAll
# token: ${{secrets.APP_CENTER_TOKEN}}

- name: Find debug APK
if: ${{ !github.event.pull_request }}
run: |
if [ ! -z "${{ secrets.BOT_TOKEN }}" ]; then
OUTPUT="app/build/outputs/apk/debug/"
DEBUG_APK=$(find $OUTPUT -name "*.apk")
echo "DEBUG_APK=$DEBUG_APK" >> $GITHUB_ENV
fi

- name: Generate Commit Message
if: ${{ !github.event.pull_request }}
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
run: |
COMMIT_MESSAGE=$(git log -1 --pretty=format:%s)
AUTHOR_NAME=$(git log -1 --pretty=format:%an)
Expand All @@ -139,14 +198,14 @@ jobs:
\`\`\`$COMMIT_MESSAGE\`\`\`
by \`$AUTHOR_NAME\`
See commit detail [Here]($COMMIT_URL)
Snapshot apk is attached"
Flutter snapshot apk is attached"

echo "TELEGRAM_MESSAGE<<EOF" >> $GITHUB_ENV
echo "$TELEGRAM_MESSAGE" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV

- name: Send commit to Telegram
if: ${{ !github.event.pull_request }}
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
uses: xz-dev/TelegramFileUploader@v1
env:
BOT_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}
Expand All @@ -156,7 +215,7 @@ jobs:
to-who: ${{ secrets.TELEGRAM_TO }}
message: ${{ env.TELEGRAM_MESSAGE }}
files: |
/github/workspace/${{ steps.sign.outputs.signedReleaseFile }}
/github/workspace/${{ env.RELEASE_APK }}
/github/workspace/${{ env.DEBUG_APK }}

- name: Delete workflow runs
Expand Down
69 changes: 69 additions & 0 deletions .github/workflows/upgradeall-rewrite-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
name: UpgradeAll Rewrite Validation

on:
pull_request:
push:
branches:
- master
workflow_dispatch:

jobs:
rewrite-validation:
name: Rewrite validation
runs-on: ubuntu-latest
env:
NDK_VERSION: 29.0.14206865
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
submodules: true
fetch-depth: 0

- name: Set up Java
uses: actions/setup-java@v5
with:
distribution: temurin
java-version: 21

- name: Install Linux host build dependencies
run: |
sudo apt-get update
sudo apt-get install -y gcc-multilib g++-multilib

- name: Set up Android SDK
uses: android-actions/setup-android@v3

- name: Install Android SDK packages
run: sdkmanager --install "platforms;android-36" "build-tools;36.0.0" "platform-tools" "ndk;${{ env.NDK_VERSION }}"

- name: Add Android NDK to environment
run: |
NDK_HOME="$ANDROID_HOME/ndk/$NDK_VERSION"
echo "ANDROID_NDK_HOME=$NDK_HOME" >> "$GITHUB_ENV"
echo "ANDROID_NDK_ROOT=$NDK_HOME" >> "$GITHUB_ENV"
echo "CC_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android23-clang" >> "$GITHUB_ENV"
echo "AR_aarch64_linux_android=$NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar" >> "$GITHUB_ENV"

- name: Install Flutter
uses: subosito/flutter-action@v2
with:
channel: stable
cache: true

- name: Set up Rust
uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt

- name: Install Android Rust targets
run: rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android

- name: Install just
run: |
if ! command -v just >/dev/null 2>&1; then
cargo install just --locked
fi

- name: Run rewrite validation
run: just verify
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
/android-studio/sdk
out/
/tmp
/.pi/
/intellij
workspace.xml
*.versionsBackup
Expand Down
Loading
Loading