From e4978d779e47f099bc84caa825a8d503335d55c2 Mon Sep 17 00:00:00 2001 From: Will Wang Date: Wed, 27 Aug 2025 11:33:14 -0700 Subject: [PATCH 1/4] add disk cleanup --- .github/workflows/build-image.yml | 47 ++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index b190cb26..3c256ec0 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -25,24 +25,39 @@ jobs: attestations: write id-token: write steps: - - uses: actions/checkout@v4 + # Disk cleanup + - run: df -h + - name: "disk-cleanup" + run: | + sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL + sudo docker image prune --all --force + sudo docker builder prune -a + - run: df -h + + - name: Checkout + uses: actions/checkout@v4 + - name: Log in to ghcr.io - uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Set up QEMU uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - + + # Build & push per-arch under SHA-suffixed tags to avoid a single-arch :latest window - name: Build and push (amd64) + id: build_amd64 uses: docker/build-push-action@v6 with: platforms: linux/amd64 push: ${{ github.event_name == 'push' }} - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:amd64-${{ github.sha }} cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max,compression=zstd,oci-mediatypes=true provenance: false @@ -51,22 +66,40 @@ jobs: GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} - name: Build and push (arm64) + id: build_arm64 uses: docker/build-push-action@v6 with: platforms: linux/arm64 push: ${{ github.event_name == 'push' }} - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:arm64-${{ github.sha }} cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max,compression=zstd,oci-mediatypes=true provenance: false sbom: false secrets: | GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} - + + # Create a multi-arch manifest for :latest and :{sha} + - name: Create multi-arch manifest + if: ${{ github.event_name == 'push' }} + run: | + docker buildx imagetools create \ + -t "$REGISTRY/$IMAGE_NAME:latest" \ + -t "$REGISTRY/$IMAGE_NAME:${GITHUB_SHA}" \ + "$REGISTRY/$IMAGE_NAME@${{ steps.build_amd64.outputs.digest }}" \ + "$REGISTRY/$IMAGE_NAME@${{ steps.build_arm64.outputs.digest }}" + + - name: Get manifest digest + id: manifest_digest + if: ${{ github.event_name == 'push' }} + run: | + DIGEST=$(docker buildx imagetools inspect "$REGISTRY/$IMAGE_NAME:latest" | awk '/^Digest:/{print $2; exit}') + echo "digest=$DIGEST" >> "$GITHUB_OUTPUT" + - name: Generate artifact attestation uses: actions/attest-build-provenance@v2 if: ${{ github.event_name == 'push' }} with: push-to-registry: true subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - subject-digest: ${{ steps.docker_build.outputs.digest }} + subject-digest: ${{ steps.manifest_digest.outputs.digest }} From 2a147621c2a777f1e18760617a9493df0216d70c Mon Sep 17 00:00:00 2001 From: Will Wang Date: Wed, 27 Aug 2025 12:34:38 -0700 Subject: [PATCH 2/4] fix java version for jdk 11 --- Dockerfile | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index fa5bb0c1..c744f8e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -165,13 +165,20 @@ RUN mise use --global "bun@${BUN_VERSION}" ### JAVA ### -ARG JAVA_VERSIONS="21 17 11" ARG GRADLE_VERSION=8.14 ARG MAVEN_VERSION=3.9.10 -RUN for v in $JAVA_VERSIONS; do mise install "java@${v}"; done \ - && mise use --global "java@${JAVA_VERSIONS%% *}" \ - && mise use --global "gradle@${GRADLE_VERSION}" \ - && mise use --global "maven@${MAVEN_VERSION}" + +# OpenJDK 11 is not available for arm64. Codex Web only uses amd64 which +# does support 11. +RUN if [ "$TARGETARCH" = "arm64" ]; then \ + JAVA_VERSIONS="21 17"; \ + else \ + JAVA_VERSIONS="21 17 11"; \ + fi; \ + for v in $JAVA_VERSIONS; do mise install "java@${v}"; done && \ + mise use --global "java@${JAVA_VERSIONS%% *}" && \ + mise use --global "gradle@${GRADLE_VERSION}" && \ + mise use --global "maven@${MAVEN_VERSION}" ### SWIFT ### From d8be823076159d8d6da9026f461cf81a11fc7a99 Mon Sep 17 00:00:00 2001 From: Will Wang Date: Wed, 27 Aug 2025 12:54:03 -0700 Subject: [PATCH 3/4] only use gha cache --- .github/workflows/build-image.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 3c256ec0..dbe86557 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -31,7 +31,7 @@ jobs: run: | sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL sudo docker image prune --all --force - sudo docker builder prune -a + sudo docker builder prune -af - run: df -h - name: Checkout @@ -58,8 +58,8 @@ jobs: platforms: linux/amd64 push: ${{ github.event_name == 'push' }} tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:amd64-${{ github.sha }} - cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max,compression=zstd,oci-mediatypes=true + cache-from: type=gha,scope=${{ github.workflow }}-${{ runner.os }}-amd64 + cache-to: type=gha,mode=min,scope=${{ github.workflow }}-${{ runner.os }}-amd64 provenance: false sbom: false secrets: | @@ -72,8 +72,8 @@ jobs: platforms: linux/arm64 push: ${{ github.event_name == 'push' }} tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:arm64-${{ github.sha }} - cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache - cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max,compression=zstd,oci-mediatypes=true + cache-from: type=gha,scope=${{ github.workflow }}-${{ runner.os }}-arm64 + cache-to: type=gha,mode=min,scope=${{ github.workflow }}-${{ runner.os }}-arm64 provenance: false sbom: false secrets: | From 663f7c2033a99001a01f4580ac6c6185d9aea197 Mon Sep 17 00:00:00 2001 From: Will Wang Date: Wed, 27 Aug 2025 12:57:20 -0700 Subject: [PATCH 4/4] split gha jobs --- .github/workflows/build-image.yml | 166 ++++++++++++++++-------------- 1 file changed, 87 insertions(+), 79 deletions(-) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index dbe86557..cfeb1f49 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -17,89 +17,97 @@ env: IMAGE_NAME: ${{ github.repository }} jobs: - build-and-push: + build-amd64: runs-on: ubuntu-latest - permissions: - contents: read - packages: write - attestations: write - id-token: write + outputs: + digest: ${{ steps.build.outputs.digest }} steps: - # Disk cleanup - - run: df -h - - name: "disk-cleanup" - run: | - sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL - sudo docker image prune --all --force - sudo docker builder prune -af - - run: df -h + - name: Free disk + run: | + sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL || true + docker system prune -af || true + - uses: actions/checkout@v4 + - uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-buildx-action@v3 + - name: Build & push (amd64) + id: build + uses: docker/build-push-action@v6 + with: + platforms: linux/amd64 + push: ${{ github.event_name == 'push' }} + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:amd64-${{ github.sha }} + # Use GHA cache only (works on PRs). Swap to registry cache on pushes if you prefer. + cache-from: type=gha,scope=${{ github.workflow }}-${{ runner.os }}-amd64 + cache-to: type=gha,mode=min,scope=${{ github.workflow }}-${{ runner.os }}-amd64 + provenance: false + sbom: false + secrets: | + GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} - - name: Checkout - uses: actions/checkout@v4 - - - name: Log in to ghcr.io - uses: docker/login-action@v3 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - # Build & push per-arch under SHA-suffixed tags to avoid a single-arch :latest window - - name: Build and push (amd64) - id: build_amd64 - uses: docker/build-push-action@v6 - with: - platforms: linux/amd64 - push: ${{ github.event_name == 'push' }} - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:amd64-${{ github.sha }} - cache-from: type=gha,scope=${{ github.workflow }}-${{ runner.os }}-amd64 - cache-to: type=gha,mode=min,scope=${{ github.workflow }}-${{ runner.os }}-amd64 - provenance: false - sbom: false - secrets: | - GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} + build-arm64: + runs-on: ubuntu-latest + outputs: + digest: ${{ steps.build.outputs.digest }} + steps: + - name: Free disk + run: | + sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL || true + docker system prune -af || true + - uses: actions/checkout@v4 + - uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - uses: docker/setup-qemu-action@v3 + - uses: docker/setup-buildx-action@v3 + - name: Build & push (arm64) + id: build + uses: docker/build-push-action@v6 + with: + platforms: linux/arm64 + push: ${{ github.event_name == 'push' }} + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:arm64-${{ github.sha }} + cache-from: type=gha,scope=${{ github.workflow }}-${{ runner.os }}-arm64 + cache-to: type=gha,mode=min,scope=${{ github.workflow }}-${{ runner.os }}-arm64 + provenance: false + sbom: false + secrets: | + GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} - - name: Build and push (arm64) - id: build_arm64 - uses: docker/build-push-action@v6 - with: - platforms: linux/arm64 - push: ${{ github.event_name == 'push' }} - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:arm64-${{ github.sha }} - cache-from: type=gha,scope=${{ github.workflow }}-${{ runner.os }}-arm64 - cache-to: type=gha,mode=min,scope=${{ github.workflow }}-${{ runner.os }}-arm64 - provenance: false - sbom: false - secrets: | - GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} + manifest-and-attest: + if: ${{ github.event_name == 'push' }} + runs-on: ubuntu-latest + needs: [build-amd64, build-arm64] + steps: + - uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - # Create a multi-arch manifest for :latest and :{sha} - - name: Create multi-arch manifest - if: ${{ github.event_name == 'push' }} - run: | - docker buildx imagetools create \ - -t "$REGISTRY/$IMAGE_NAME:latest" \ - -t "$REGISTRY/$IMAGE_NAME:${GITHUB_SHA}" \ - "$REGISTRY/$IMAGE_NAME@${{ steps.build_amd64.outputs.digest }}" \ - "$REGISTRY/$IMAGE_NAME@${{ steps.build_arm64.outputs.digest }}" + - name: Stitch multi-arch manifest (:latest and :sha) + run: | + docker buildx imagetools create \ + -t "$REGISTRY/$IMAGE_NAME:latest" \ + -t "$REGISTRY/$IMAGE_NAME:${GITHUB_SHA}" \ + "$REGISTRY/$IMAGE_NAME@${{ needs.build-amd64.outputs.digest }}" \ + "$REGISTRY/$IMAGE_NAME@${{ needs.build-arm64.outputs.digest }}" - - name: Get manifest digest - id: manifest_digest - if: ${{ github.event_name == 'push' }} - run: | - DIGEST=$(docker buildx imagetools inspect "$REGISTRY/$IMAGE_NAME:latest" | awk '/^Digest:/{print $2; exit}') - echo "digest=$DIGEST" >> "$GITHUB_OUTPUT" + - name: Get manifest digest + id: manifest + run: | + DIGEST=$(docker buildx imagetools inspect "$REGISTRY/$IMAGE_NAME:latest" | awk '/^Digest:/{print $2; exit}') + echo "digest=$DIGEST" >> "$GITHUB_OUTPUT" - - name: Generate artifact attestation - uses: actions/attest-build-provenance@v2 - if: ${{ github.event_name == 'push' }} - with: - push-to-registry: true - subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - subject-digest: ${{ steps.manifest_digest.outputs.digest }} + - name: Generate artifact attestation + uses: actions/attest-build-provenance@v2 + with: + push-to-registry: true + subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + subject-digest: ${{ steps.manifest.outputs.digest }}