rewrite QwenPreamble: self-aware, tighter, plan-act-verify for 3.8 #30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Termux (Android arm64) | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ['[0-9]+.[0-9]+.[0-9]+'] | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: jiro4989/setup-nim-action@v2 | |
| with: | |
| nim-version: stable | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| parent-nim-install-directory: $HOME | |
| nim-install-directory: nim-toolchain | |
| - name: Install dependencies | |
| run: | | |
| nimble install -y https://github.com/capocasa/sandwall | |
| nimble install -y --depsOnly | |
| - name: Download Android NDK | |
| # The main binary builds for Termux via NDK cross-compile. No | |
| # -d:termux: that links -landroid-glob (a Termux package for | |
| # pre-API-28 devices); targeting API 28+ gets glob natively. | |
| # OpenSSL is dlopen'ed at runtime (Termux's openssl package | |
| # provides libssl.so.3), so no TLS libs are linked here. | |
| run: | | |
| curl -fsSL -o ndk.zip https://dl.google.com/android/repository/android-ndk-r26c-linux.zip | |
| unzip -q ndk.zip | |
| echo "NDK_CLANG=$PWD/android-ndk-r26c/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android28-clang" >> "$GITHUB_ENV" | |
| - name: Build (cross, --os:android --cpu:arm64) | |
| run: | | |
| nim c -d:release --os:android --cpu:arm64 -d:ssl -d:testPlainHttp \ | |
| --clang.exe:"$NDK_CLANG" --clang.linkerexe:"$NDK_CLANG" \ | |
| -o:3code-android src/threecode.nim | |
| file 3code-android | |
| - name: Verify Termux RUNPATH | |
| # Nim's openssl wrapper dlopens libssl.so.3/libcrypto.so.3 at | |
| # module init; Android's linker only finds them via the binary's | |
| # DT_RUNPATH (config.nims bakes in the Termux prefix). The android | |
| # binary can't run on this x86 host, so guard the runpath here; | |
| # without it the binary dies on startup with "could not import: | |
| # SSL_CTX_ctrl". | |
| run: | | |
| readelf -d 3code-android | grep -q 'RUNPATH.*\[/data/data/com.termux/files/usr/lib\]' | |
| - name: Package | |
| run: | | |
| mkdir -p 3code-termux-arm64 | |
| cp 3code-android 3code-termux-arm64/3code | |
| # Can't run the android binary on the x86 host; version comes | |
| # from the nimble file (tag releases) or the short SHA. | |
| grep -m1 '^version' threecode.nimble | cut -d'"' -f2 > 3code-termux-arm64/VERSION | |
| git rev-parse --short=8 HEAD >> 3code-termux-arm64/VERSION | |
| cp README.md LICENSE 3code-termux-arm64/ | |
| tar czf 3code-termux-arm64.tar.gz 3code-termux-arm64 | |
| - name: Upload artifact (GitHub Actions) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: 3code-termux-arm64 | |
| path: 3code-termux-arm64.tar.gz | |
| smoke: | |
| # Run the cross-built binary inside an emulated Termux (qemu-aarch64 | |
| # + bionic, provided by termux/termux-docker). The x86 runner can't | |
| # execute the binary natively, so this container is the only way to | |
| # catch startup failures (dlopen paths, tmpdir, TLS) without a phone. | |
| needs: build | |
| runs-on: ubuntu-22.04 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: 3code-termux-arm64 | |
| - name: Smoke test in emulated Termux | |
| run: | | |
| set -e | |
| tar xzf 3code-termux-arm64.tar.gz | |
| # Register qemu binfmt handlers; runner docker can't exec arm64 | |
| # images without this (locally docker-desktop does it for you). | |
| docker run --rm --privileged multiarch/qemu-user-static --reset -p yes > /dev/null | |
| # The image's Termux tree is owned by uid/gid 1000 (system); run | |
| # the container as that user so pkg and $HOME behave. | |
| CID=$(docker create -t --platform linux/arm64 --user 1000:1000 \ | |
| termux/termux-docker:latest sleep 900) | |
| docker start $CID >/dev/null | |
| trap 'docker rm -f $CID >/dev/null 2>&1 || true' EXIT | |
| docker exec $CID mkdir -p /data/data/com.termux/files/usr/tmp | |
| docker cp 3code-termux-arm64/3code $CID:/data/data/com.termux/files/usr/tmp/3code | |
| docker exec -t -e THREECODE_ALLOW_ROOT=1 $CID \ | |
| /data/data/com.termux/files/usr/tmp/3code --version | |
| # --help exits 2 (ExitUsage) by design; assert it runs at all. | |
| docker exec -t -e THREECODE_ALLOW_ROOT=1 $CID sh -c \ | |
| '/data/data/com.termux/files/usr/tmp/3code --help > /dev/null; \ | |
| test $? -eq 2' | |
| # TLS init is the fragile part on Termux: the openssl wrapper | |
| # dlopens libssl.so.3/libcrypto.so.3 at module init, and it only | |
| # works when DT_RUNPATH (asserted in the build job) points at the | |
| # Termux lib dir. A bare --version doesn't touch TLS; this tiny | |
| # program does a verified handshake the same way api.nim does. | |
| docker cp tests/android_tlscheck.nim $CID:/data/data/com.termux/files/usr/tmp/ | |
| docker exec -t $CID sh -lc \ | |
| 'command -v nim >/dev/null || pkg install -y nim >/dev/null 2>&1; \ | |
| nim c -r -d:ssl /data/data/com.termux/files/usr/tmp/android_tlscheck.nim' \ | |
| | grep -q 'tls handshake ok' | |
| - name: Upload artifact to 3code.capocasa.dev | |
| if: github.ref == 'refs/heads/main' | |
| run: | | |
| curl -f -H "Authorization: Bearer ${{ secrets.RELEASE_SECRET }}" -F "file=@3code-termux-arm64.tar.gz" \ | |
| https://3code.capocasa.dev/main/builds/upload.nim |