chore(release): v0.2.10 — svg v1, screencast damage fix, zero-blitz s… #29
Workflow file for this run
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: docker | |
| on: | |
| workflow_dispatch: | |
| push: | |
| tags: ["v*"] | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| # One native runner per architecture (amd64 + arm64) — cross-compiling the | |
| # Rust + BoringSSL + V8 stack under QEMU takes an hour; native arm64 runners | |
| # are free for public repos. Each job pushes arch-suffixed tags; `merge` | |
| # stitches them into multi-arch manifest lists. | |
| build: | |
| runs-on: ${{ matrix.os }} | |
| permissions: | |
| contents: read | |
| packages: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| platform: linux/amd64 | |
| arch: amd64 | |
| - os: ubuntu-24.04-arm | |
| platform: linux/arm64 | |
| arch: arm64 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| # Same tag set as the final manifest, each suffixed with -<arch>. | |
| - id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| flavor: | | |
| suffix=-${{ matrix.arch }},onlatest=true | |
| - uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| platforms: ${{ matrix.platform }} | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha,scope=build-${{ matrix.arch }} | |
| cache-to: type=gha,scope=build-${{ matrix.arch }},mode=max | |
| # Merge the arch tags into multi-arch manifest lists under the final tags | |
| # (0.2.x, 0.x, latest). `imagetools create` assembles the list server-side | |
| # from the per-arch tags pushed above. | |
| merge: | |
| runs-on: ubuntu-latest | |
| needs: build | |
| permissions: | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - name: Merge arch tags into multi-arch manifests | |
| env: | |
| FINAL_TAGS: ${{ steps.meta.outputs.tags }} | |
| run: | | |
| for tag in $FINAL_TAGS; do | |
| echo "→ ${tag} (amd64 + arm64)" | |
| docker buildx imagetools create \ | |
| --tag "$tag" \ | |
| "${tag}-amd64" \ | |
| "${tag}-arm64" | |
| done | |
| # The arm64 build compiles natively but nothing has ever *executed* it — | |
| # V8 snapshots and BoringSSL asm can build fine and still not run. Pull the | |
| # merged multi-arch tag on a real arm64 runner and smoke it: health, | |
| # status page, cookie-store write under a non-root user. | |
| verify: | |
| runs-on: ubuntu-24.04-arm | |
| needs: merge | |
| steps: | |
| - name: Smoke merged image on native arm64 | |
| run: | | |
| # Image tags strip the leading "v" (metadata-action semver format): | |
| # tag pushes verify the bare version, dispatches verify latest. | |
| if [[ "$GITHUB_REF" == refs/tags/v* ]]; then | |
| TAG="${GITHUB_REF_NAME#v}" | |
| else | |
| TAG=latest | |
| fi | |
| echo "TAG=$TAG" | tee -a "$GITHUB_ENV" | |
| mkdir -p /tmp/smoke-data/cookies /tmp/smoke-data/downloads && sudo chown -R 1000:1000 /tmp/smoke-data | |
| # Any unresolved dynamic library shows up here first (exit 127 gives | |
| # no such hint from docker run alone). | |
| docker run --rm --entrypoint sh "ghcr.io/yinnho/aginxbrowser:${TAG}" \ | |
| -c 'ldd /usr/local/bin/aginxbrowser | grep "not found" || echo "ldd: all libs resolved"' | |
| docker run -d --name smoke -p 18089:8089 \ | |
| -e AGINXBROWSER_COOKIE_STORE_DIR=/data/cookies \ | |
| -e AGINXBROWSER_DOWNLOAD_DIR=/data/downloads \ | |
| -u 1000:1000 \ | |
| -v /tmp/smoke-data/cookies:/data/cookies \ | |
| -v /tmp/smoke-data/downloads:/data/downloads \ | |
| "ghcr.io/yinnho/aginxbrowser:${TAG}" | |
| # Diagnose first — a dead container must print its dying words before | |
| # the curl loop can eat the exit code. | |
| sleep 5 | |
| docker ps -a --filter name=smoke --format '{{.Status}}' | |
| docker logs smoke 2>&1 | tail -15 || true | |
| ok="" | |
| for i in $(seq 1 30); do | |
| if curl -fsS http://127.0.0.1:18089/health > /tmp/health.json 2>/dev/null; then ok=1; break; fi | |
| sleep 2 | |
| done | |
| echo "--- health body:" | |
| cat /tmp/health.json 2>/dev/null || docker logs smoke 2>&1 | tail -25 | |
| test -n "$ok" | |
| echo "--- status page head:" | |
| curl -fsS http://127.0.0.1:18089/ | head -3 | |
| echo "--- cookie store written by uid 1000:" | |
| ls -ln /tmp/smoke-data/cookies/ | tail -3 | |
| # Mirror to Docker Hub when DOCKERHUB_USERNAME/TOKEN secrets are set | |
| # (steps skip — not fail — otherwise). Copies the merged multi-arch GHCR | |
| # manifests, so no second build. The secrets context can't be referenced in | |
| # `if:`, so each gated step mirrors the secrets into env and tests that. | |
| dockerhub: | |
| runs-on: ubuntu-latest | |
| needs: merge | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| - id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: docker.io/yinnho/aginxbrowser | |
| tags: | | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - name: Login Docker Hub | |
| env: | |
| DH_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
| DH_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
| if: ${{ env.DH_USERNAME != '' && env.DH_TOKEN != '' }} | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Copy GHCR tags to Docker Hub | |
| env: | |
| DH_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} | |
| DH_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} | |
| # Multi-line output: interpolating it directly into the script | |
| # text splits mid-line into raw shell syntax (the v0.2.2 release | |
| # run died on `syntax error near unexpected token`). Route through | |
| # env so the split happens at word-splitting, not in the source. | |
| DH_TAGS: ${{ steps.meta.outputs.tags }} | |
| if: ${{ env.DH_USERNAME != '' && env.DH_TOKEN != '' }} | |
| run: | | |
| for tag in $DH_TAGS; do | |
| name="${tag##*:}" | |
| echo "→ docker.io/yinnho/aginxbrowser:$name (from ghcr.io/yinnho/aginxbrowser:$name)" | |
| docker buildx imagetools create \ | |
| --tag "docker.io/yinnho/aginxbrowser:$name" \ | |
| "ghcr.io/yinnho/aginxbrowser:$name" | |
| done |