| … | … | @@ -0,0 +1,96 @@ |
| 1 | # pear-git CI for the cthuloid repo: builds the Android app (android/) on |
| 2 | # android-v<x.y.z> TAGS ONLY, and publishes a signed APK as a forge download: |
| 3 | # https://7rnx.net/git/releases/cthuloid/android-v<x.y.z>/dist/cthuloid-lights.apk |
| 4 | # See docs/DESIGN-android.md §5. |
| 5 | # |
| 6 | # ⛔ The forge runs this for EVERY pushed branch and tag and cannot filter, so each |
| 7 | # step checks the ref itself (GIT_REF / GIT_REF_KIND are injected) and does nothing |
| 8 | # unless the gate step decided to build. Every push publishes `dist/` -- on a |
| 9 | # non-release ref it holds only skipped.txt. (A listed-but-missing file would make |
| 10 | # collectArtifacts throw and leave a misleading error in the forge log.) |
| 11 | # |
| 12 | # ⛔ CI runs in a `git archive | tar -x` extraction: no .git, no node_modules, no |
| 13 | # PATH guarantees, `sh -c` (not bash). Host paths are absolute, as in |
| 14 | # favela-surface-android's ci.yaml. |
| 15 | # |
| 16 | # ⛔ THE SIGNING KEY is ~/android-toolchain/cthuloid.keystore with its password in |
| 17 | # cthuloid.keystore.pass -- outside the repo, never in git. Android refuses an |
| 18 | # update signed with any other key (uninstall, i.e. data loss, is the only way |
| 19 | # out), so the build FAILS if the key is missing rather than signing with another. |
| 20 | |
| 21 | steps: |
| 22 | - name: gate |
| 23 | run: | |
| 24 | set -e |
| 25 | mkdir -p dist |
| 26 | if [ "$GIT_REF_KIND" = "tag" ] && echo "$GIT_REF" | grep -Eq '^android-v[0-9]+\.[0-9]+\.[0-9]+$'; then |
| 27 | echo "release build: $GIT_REF" |
| 28 | else |
| 29 | echo "not an android-v<x.y.z> tag ($GIT_REF_KIND $GIT_REF): nothing to build" |
| 30 | echo "APKs are built on android-v<x.y.z> tags only; this ref ($GIT_REF_KIND $GIT_REF) built nothing." > dist/skipped.txt |
| 31 | touch .skip |
| 32 | fi |
| 33 | timeout: 30 |
| 34 | |
| 35 | - name: deps |
| 36 | run: | |
| 37 | set -e |
| 38 | [ -f .skip ] && exit 0 |
| 39 | export PATH=/home/fleeky/.nvm/versions/node/v24.13.0/bin:$PATH |
| 40 | (cd webui && npm ci --no-audit --no-fund) |
| 41 | (cd android && npm ci --no-audit --no-fund) |
| 42 | test -e android/node_modules/cthuloid-web/lib/app.js |
| 43 | timeout: 900 |
| 44 | |
| 45 | - name: version |
| 46 | # The version comes from the tag, never from hand-editing a field. |
| 47 | run: | |
| 48 | set -e |
| 49 | [ -f .skip ] && exit 0 |
| 50 | export PATH=/home/fleeky/.nvm/versions/node/v24.13.0/bin:$PATH |
| 51 | V=${GIT_REF#android-v} |
| 52 | (cd android && node -e "const fs=require('fs');const p=JSON.parse(fs.readFileSync('package.json'));p.version=process.argv[1];fs.writeFileSync('package.json',JSON.stringify(p,null,2)+'\n')" "$V") |
| 53 | grep '"version"' android/package.json |
| 54 | timeout: 30 |
| 55 | |
| 56 | - name: prebuild |
| 57 | run: | |
| 58 | set -e |
| 59 | [ -f .skip ] && exit 0 |
| 60 | export PATH=/home/fleeky/.nvm/versions/node/v24.13.0/bin:$PATH |
| 61 | (cd android && npm run prebuild:android) |
| 62 | test -s android/android/app/src/main/assets/worklet.bundle |
| 63 | timeout: 900 |
| 64 | |
| 65 | - name: assemble |
| 66 | run: | |
| 67 | set -e |
| 68 | [ -f .skip ] && exit 0 |
| 69 | T=/home/fleeky/android-toolchain |
| 70 | test -s $T/cthuloid.keystore |
| 71 | test -s $T/cthuloid.keystore.pass |
| 72 | export JAVA_HOME=$T/jdk-17.0.13+11 |
| 73 | export ANDROID_HOME=$T/sdk |
| 74 | export PATH=/home/fleeky/.nvm/versions/node/v24.13.0/bin:$PATH |
| 75 | export CTHULOID_KEYSTORE=$T/cthuloid.keystore |
| 76 | CTHULOID_KEYSTORE_PASS=$(cat $T/cthuloid.keystore.pass) |
| 77 | export CTHULOID_KEYSTORE_PASS |
| 78 | # Every new-architecture library's codegen must exist before CMake configure |
| 79 | # (favela-surface-android's ci.yaml); unqualified so it covers all of them. |
| 80 | $T/gradle-8.13/bin/gradle -p android/android generateCodegenArtifactsFromSchema |
| 81 | $T/gradle-8.13/bin/gradle -p android/android assembleRelease |
| 82 | cp android/android/app/build/outputs/apk/release/app-release.apk dist/cthuloid-lights.apk |
| 83 | # The artifact, not the intent: every native lib's NEEDED entries are in the APK... |
| 84 | (cd android && node scripts/verify-apk-addons.mjs ../dist/cthuloid-lights.apk) |
| 85 | # ...and it is signed with THIS key, not a debug or stray one. |
| 86 | WANT=$($JAVA_HOME/bin/keytool -list -v -keystore $T/cthuloid.keystore -storepass:file $T/cthuloid.keystore.pass | sed -n 's/.*SHA256: //p' | head -1 | tr -d ': ' | tr 'A-F' 'a-f') |
| 87 | GOT=$($ANDROID_HOME/build-tools/34.0.0/apksigner verify --print-certs dist/cthuloid-lights.apk | sed -n 's/.*certificate SHA-256 digest: //p' | head -1) |
| 88 | echo "signer want=$WANT got=$GOT" |
| 89 | [ -n "$WANT" ] && [ "$WANT" = "$GOT" ] |
| 90 | (cd dist && sha256sum cthuloid-lights.apk > cthuloid-lights.apk.sha256) |
| 91 | ls -l dist |
| 92 | timeout: 2700 |
| 93 | |
| 94 | artifacts: |
| 95 | # A directory: files only on a release tag, skipped.txt otherwise. |
| 96 | - dist |