From a3aeda56d7de2d493f25ccbc3a3264bd0146bd9a Mon Sep 17 00:00:00 2001 From: Arthur Kepler <610274+excalq@users.noreply.github.com> Date: Mon, 10 Aug 2026 15:56:48 -0700 Subject: [PATCH 1/6] chore: add arm platform release support --- .github/workflows/sf_release.yml | 23 ++++++++++++++++++++--- Makefile | 6 ++++-- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/.github/workflows/sf_release.yml b/.github/workflows/sf_release.yml index 5608b9b36a3..a0667b796ae 100644 --- a/.github/workflows/sf_release.yml +++ b/.github/workflows/sf_release.yml @@ -8,6 +8,14 @@ on: description: "Firehose Ethereum Docker image" required: false default: "ghcr.io/streamingfast/firehose-ethereum:latest" + platform: + description: "Target platform for image builds" + required: false + default: "linux/arm64" + type: choice + options: + - linux/arm64 + - linux/arm push: tags: - "*" @@ -18,6 +26,7 @@ env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} FIREHOSE_ETHEREUM_IMAGE: ${{ inputs.firehose_ethereum_image || 'ghcr.io/streamingfast/firehose-ethereum:latest' }} + TARGET_PLATFORM: ${{ inputs.platform || 'linux/arm64' }} jobs: push: @@ -95,6 +104,7 @@ jobs: target: nitro-node file: ./Dockerfile push: false + platforms: ${{ env.TARGET_PLATFORM }} tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-base:${{ steps.extract-versions.outputs.VERSION }} labels: ${{ steps.meta-bare.outputs.labels }} @@ -104,6 +114,7 @@ jobs: context: . file: ./Dockerfile.sf push: true + platforms: ${{ env.TARGET_PLATFORM }} build-args: | NITRO_BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-base:${{ steps.extract-versions.outputs.VERSION }} FIREHOSE_ETHEREUM_IMAGE=${{ env.FIREHOSE_ETHEREUM_IMAGE }} @@ -125,9 +136,15 @@ jobs: echo "ID=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT" - name: Extract assets + id: assets run: | - # The --platform are not really needed here, but it removes the warning - docker cp $(docker create --platform=linux/amd64 ${{ steps.image.outputs.ID }}):/usr/local/bin/nitro ./nitro_linux_amd64 + suffix=arm64 + if [ "${TARGET_PLATFORM}" = "linux/arm" ]; then + suffix=arm + fi + asset="./nitro_linux_${suffix}" + docker cp $(docker create --platform=${TARGET_PLATFORM} ${{ steps.image.outputs.ID }}):/usr/local/bin/nitro "$asset" + echo "asset=$asset" >> "$GITHUB_OUTPUT" - name: Extract Changelog id: changelog @@ -145,4 +162,4 @@ jobs: body: ${{ steps.changelog.outputs.changelog }} prerelease: ${{ contains(github.ref, 'beta') || contains(github.ref, 'rc') }} files: | - ./nitro_linux_amd64 + ${{ steps.assets.outputs.asset }} diff --git a/Makefile b/Makefile index 405082497db..01bd5786ef7 100644 --- a/Makefile +++ b/Makefile @@ -364,8 +364,8 @@ endef docker: @$(resolve_gh_token_and_secret); \ for t in nitro-node-slim nitro-node nitro-node-dev; do \ - echo "+ docker build $$SECRET -t $$t --target $$t ."; \ - docker build $$SECRET -t "$$t" --target "$$t" . || exit 1; \ + echo "+ docker build $$SECRET --platform $(ARCH) -t $$t --target $$t ."; \ + docker build $$SECRET --platform "$(ARCH)" -t "$$t" --target "$$t" . || exit 1; \ done .PHONY: docker-machine-versions ## Build Docker image for machine versions. @@ -762,3 +762,5 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(prover_bin) always: # use this to force other rules to always build .DELETE_ON_ERROR: # causes a failure to delete its target + +ARCH ?= linux/arm64 From 88fd2de4fe3d6b99eaf16b07f3379443219a2aee Mon Sep 17 00:00:00 2001 From: Arthur Kepler <610274+excalq@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:02:23 -0700 Subject: [PATCH 2/6] chore: simplify release asset name derivation --- .github/workflows/sf_release.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/sf_release.yml b/.github/workflows/sf_release.yml index a0667b796ae..383bd845176 100644 --- a/.github/workflows/sf_release.yml +++ b/.github/workflows/sf_release.yml @@ -138,13 +138,12 @@ jobs: - name: Extract assets id: assets run: | - suffix=arm64 - if [ "${TARGET_PLATFORM}" = "linux/arm" ]; then - suffix=arm - fi - asset="./nitro_linux_${suffix}" - docker cp $(docker create --platform=${TARGET_PLATFORM} ${{ steps.image.outputs.ID }}):/usr/local/bin/nitro "$asset" - echo "asset=$asset" >> "$GITHUB_OUTPUT" + # linux/arm64 -> nitro_linux_arm64, linux/arm -> nitro_linux_arm + asset="nitro_${TARGET_PLATFORM/\//_}" + container=$(docker create --platform="$TARGET_PLATFORM" "${{ steps.image.outputs.ID }}") + docker cp "$container:/usr/local/bin/nitro" "./$asset" + docker rm "$container" + echo "asset=./$asset" >> "$GITHUB_OUTPUT" - name: Extract Changelog id: changelog From e449a47b101241ce1337d0dfc361d98cea0bbf59 Mon Sep 17 00:00:00 2001 From: Arthur Kepler <610274+excalq@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:03:51 -0700 Subject: [PATCH 3/6] chore: drop container cleanup to keep upstream diff minimal --- .github/workflows/sf_release.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/sf_release.yml b/.github/workflows/sf_release.yml index 383bd845176..9b87f931434 100644 --- a/.github/workflows/sf_release.yml +++ b/.github/workflows/sf_release.yml @@ -140,9 +140,7 @@ jobs: run: | # linux/arm64 -> nitro_linux_arm64, linux/arm -> nitro_linux_arm asset="nitro_${TARGET_PLATFORM/\//_}" - container=$(docker create --platform="$TARGET_PLATFORM" "${{ steps.image.outputs.ID }}") - docker cp "$container:/usr/local/bin/nitro" "./$asset" - docker rm "$container" + docker cp "$(docker create --platform="$TARGET_PLATFORM" "${{ steps.image.outputs.ID }}"):/usr/local/bin/nitro" "./$asset" echo "asset=./$asset" >> "$GITHUB_OUTPUT" - name: Extract Changelog From 1656950e3630e07b447429b2e04fdbb05681ae1a Mon Sep 17 00:00:00 2001 From: Arthur Kepler <610274+excalq@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:09:54 -0700 Subject: [PATCH 4/6] ci: build multi-arch (amd64+arm64) manifest via native matrix runners --- .github/workflows/sf_release.yml | 149 ++++++++++++++++++++----------- 1 file changed, 96 insertions(+), 53 deletions(-) diff --git a/.github/workflows/sf_release.yml b/.github/workflows/sf_release.yml index 9b87f931434..ca2073e7c84 100644 --- a/.github/workflows/sf_release.yml +++ b/.github/workflows/sf_release.yml @@ -8,14 +8,6 @@ on: description: "Firehose Ethereum Docker image" required: false default: "ghcr.io/streamingfast/firehose-ethereum:latest" - platform: - description: "Target platform for image builds" - required: false - default: "linux/arm64" - type: choice - options: - - linux/arm64 - - linux/arm push: tags: - "*" @@ -26,12 +18,42 @@ env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }} FIREHOSE_ETHEREUM_IMAGE: ${{ inputs.firehose_ethereum_image || 'ghcr.io/streamingfast/firehose-ethereum:latest' }} - TARGET_PLATFORM: ${{ inputs.platform || 'linux/arm64' }} jobs: - push: - name: Docker build & push + prepare: + name: Resolve versions runs-on: ubuntu-24.04 + outputs: + version: ${{ steps.extract-versions.outputs.VERSION }} + fireeth_docker_suffix: ${{ steps.extract-versions.outputs.FIREETH_DOCKER_SUFFIX }} + steps: + - name: Extract versions + id: extract-versions + run: | + version="edge-${GITHUB_SHA::7}" + if [[ "${GITHUB_REF}" == refs/tags/* ]]; then + version=${GITHUB_REF#refs/tags/} + fi + + docker pull "${{ env.FIREHOSE_ETHEREUM_IMAGE }}" + fireeth_version=$(docker inspect "${{ env.FIREHOSE_ETHEREUM_IMAGE }}" --format='{{index .Config.Labels "org.opencontainers.image.version"}}') + + echo "VERSION=${version}" >> "$GITHUB_OUTPUT" + echo "FIREETH_VERSION=${fireeth_version}" >> "$GITHUB_OUTPUT" + echo "FIREETH_DOCKER_SUFFIX=${version}-fireeth-${fireeth_version}" >> "$GITHUB_OUTPUT" + + build: + name: Build & push (${{ matrix.arch }}) + needs: prepare + strategy: + fail-fast: false + matrix: + include: + - arch: amd64 + runner: ubuntu-24.04 + - arch: arm64 + runner: ubuntu-24.04-arm + runs-on: ${{ matrix.runner }} permissions: contents: read packages: write @@ -70,78 +92,98 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract versions - id: extract-versions - run: | - version="edge-${GITHUB_SHA::7}" - if [[ "${GITHUB_REF}" == refs/tags/* ]]; then - version=${GITHUB_REF#refs/tags/} - fi - - docker pull "${{ env.FIREHOSE_ETHEREUM_IMAGE }}" - fireeth_version=$(docker inspect "${{ env.FIREHOSE_ETHEREUM_IMAGE }}" --format='{{index .Config.Labels "org.opencontainers.image.version"}}') - - echo "VERSION=${version}" >> "$GITHUB_OUTPUT" - echo "FIREETH_VERSION=${fireeth_version}" >> "$GITHUB_OUTPUT" - echo "FIREETH_DOCKER_SUFFIX=${version}-fireeth-${fireeth_version}" >> "$GITHUB_OUTPUT" - - - name: Generate docker tags/labels from github build context + - name: Generate docker labels from github build context id: meta-bare uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=ref,event=tag - type=sha,prefix= - type=raw,value=${{ steps.extract-versions.outputs.VERSION }} - type=raw,value=${{ steps.extract-versions.outputs.VERSION }},suffix=${{ steps.extract-versions.outputs.FIREETH_DOCKER_SUFFIX }} - type=raw,enable=${{ github.ref == 'refs/heads/develop' }},value=develop - - name: Build and push nitro Docker image + - name: Build nitro Docker image uses: docker/build-push-action@v6 with: context: . target: nitro-node file: ./Dockerfile push: false - platforms: ${{ env.TARGET_PLATFORM }} - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-base:${{ steps.extract-versions.outputs.VERSION }} + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-base:${{ needs.prepare.outputs.version }} labels: ${{ steps.meta-bare.outputs.labels }} - - name: Build and push final (fireeth + nitro) Docker image + - name: Build and push final (fireeth + nitro) per-arch image uses: docker/build-push-action@v6 with: context: . file: ./Dockerfile.sf push: true - platforms: ${{ env.TARGET_PLATFORM }} build-args: | - NITRO_BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-base:${{ steps.extract-versions.outputs.VERSION }} + NITRO_BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-base:${{ needs.prepare.outputs.version }} FIREHOSE_ETHEREUM_IMAGE=${{ env.FIREHOSE_ETHEREUM_IMAGE }} - tags: ${{ steps.meta-bare.outputs.tags }} + tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare.outputs.version }}-${{ matrix.arch }} labels: ${{ steps.meta-bare.outputs.labels }} + manifest: + name: Create multi-arch manifests + needs: [prepare, build] + runs-on: ubuntu-24.04 + permissions: + contents: read + packages: write + + steps: + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Generate docker tags from github build context + id: meta-bare + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=tag + type=sha,prefix= + type=raw,value=${{ needs.prepare.outputs.version }} + type=raw,value=${{ needs.prepare.outputs.version }},suffix=${{ needs.prepare.outputs.fireeth_docker_suffix }} + type=raw,enable=${{ github.ref == 'refs/heads/develop' }},value=develop + + - name: Create and push manifests + env: + VERSION: ${{ needs.prepare.outputs.version }} + TAGS: ${{ steps.meta-bare.outputs.tags }} + run: | + src_prefix="${REGISTRY}/${IMAGE_NAME}:${VERSION}" + while IFS= read -r tag; do + [ -n "$tag" ] || continue + docker buildx imagetools create -t "$tag" \ + "${src_prefix}-amd64" "${src_prefix}-arm64" + done <<< "$TAGS" + release: if: startsWith(github.ref, 'refs/tags/') - needs: push + needs: [prepare, manifest] runs-on: ubuntu-24.04 permissions: contents: write + packages: read steps: - - name: Extract image - id: image - run: | - # The run is done only on tags, so we can ref/tags/ replace directly here - echo "ID=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT" + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Extract assets - id: assets + - name: Extract binaries + env: + VERSION: ${{ needs.prepare.outputs.version }} run: | - # linux/arm64 -> nitro_linux_arm64, linux/arm -> nitro_linux_arm - asset="nitro_${TARGET_PLATFORM/\//_}" - docker cp "$(docker create --platform="$TARGET_PLATFORM" "${{ steps.image.outputs.ID }}"):/usr/local/bin/nitro" "./$asset" - echo "asset=./$asset" >> "$GITHUB_OUTPUT" + for arch in amd64 arm64; do + src="${REGISTRY}/${IMAGE_NAME}:${VERSION}-${arch}" + docker cp "$(docker create "$src"):/usr/local/bin/nitro" "./nitro_linux_${arch}" + done - name: Extract Changelog id: changelog @@ -159,4 +201,5 @@ jobs: body: ${{ steps.changelog.outputs.changelog }} prerelease: ${{ contains(github.ref, 'beta') || contains(github.ref, 'rc') }} files: | - ${{ steps.assets.outputs.asset }} + ./nitro_linux_amd64 + ./nitro_linux_arm64 From 8b19e15e356c551ebf940d2923b380bf4e74c7b5 Mon Sep 17 00:00:00 2001 From: Arthur Kepler <610274+excalq@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:32:13 -0700 Subject: [PATCH 5/6] ci: lowercase image name for container tags --- .github/workflows/sf_release.yml | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/sf_release.yml b/.github/workflows/sf_release.yml index ca2073e7c84..8fe0ea4f518 100644 --- a/.github/workflows/sf_release.yml +++ b/.github/workflows/sf_release.yml @@ -16,7 +16,6 @@ on: env: REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} FIREHOSE_ETHEREUM_IMAGE: ${{ inputs.firehose_ethereum_image || 'ghcr.io/streamingfast/firehose-ethereum:latest' }} jobs: @@ -26,7 +25,14 @@ jobs: outputs: version: ${{ steps.extract-versions.outputs.VERSION }} fireeth_docker_suffix: ${{ steps.extract-versions.outputs.FIREETH_DOCKER_SUFFIX }} + image_name: ${{ steps.image.outputs.name }} steps: + - name: Lowercase image name + id: image + # Container registries require lowercase repository names; github.repository + # preserves the org's original casing, so normalize it here. + run: echo "name=${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT" + - name: Extract versions id: extract-versions run: | @@ -96,7 +102,7 @@ jobs: id: meta-bare uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: ${{ env.REGISTRY }}/${{ needs.prepare.outputs.image_name }} - name: Build nitro Docker image uses: docker/build-push-action@v6 @@ -105,7 +111,7 @@ jobs: target: nitro-node file: ./Dockerfile push: false - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-base:${{ needs.prepare.outputs.version }} + tags: ${{ env.REGISTRY }}/${{ needs.prepare.outputs.image_name }}-base:${{ needs.prepare.outputs.version }} labels: ${{ steps.meta-bare.outputs.labels }} - name: Build and push final (fireeth + nitro) per-arch image @@ -115,9 +121,9 @@ jobs: file: ./Dockerfile.sf push: true build-args: | - NITRO_BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}-base:${{ needs.prepare.outputs.version }} + NITRO_BASE_IMAGE=${{ env.REGISTRY }}/${{ needs.prepare.outputs.image_name }}-base:${{ needs.prepare.outputs.version }} FIREHOSE_ETHEREUM_IMAGE=${{ env.FIREHOSE_ETHEREUM_IMAGE }} - tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare.outputs.version }}-${{ matrix.arch }} + tags: ${{ env.REGISTRY }}/${{ needs.prepare.outputs.image_name }}:${{ needs.prepare.outputs.version }}-${{ matrix.arch }} labels: ${{ steps.meta-bare.outputs.labels }} manifest: @@ -140,7 +146,7 @@ jobs: id: meta-bare uses: docker/metadata-action@v5 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + images: ${{ env.REGISTRY }}/${{ needs.prepare.outputs.image_name }} tags: | type=ref,event=tag type=sha,prefix= @@ -150,6 +156,7 @@ jobs: - name: Create and push manifests env: + IMAGE_NAME: ${{ needs.prepare.outputs.image_name }} VERSION: ${{ needs.prepare.outputs.version }} TAGS: ${{ steps.meta-bare.outputs.tags }} run: | @@ -178,6 +185,7 @@ jobs: - name: Extract binaries env: + IMAGE_NAME: ${{ needs.prepare.outputs.image_name }} VERSION: ${{ needs.prepare.outputs.version }} run: | for arch in amd64 arm64; do From 9b2446056103c033908dbed785a2579d784b9174 Mon Sep 17 00:00:00 2001 From: Arthur Kepler <610274+excalq@users.noreply.github.com> Date: Mon, 10 Aug 2026 18:58:21 -0700 Subject: [PATCH 6/6] chore: default docker platform to amd64 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 01bd5786ef7..15b960c69c2 100644 --- a/Makefile +++ b/Makefile @@ -763,4 +763,4 @@ contracts/test/prover/proofs/%.json: $(arbitrator_cases)/%.wasm $(prover_bin) always: # use this to force other rules to always build .DELETE_ON_ERROR: # causes a failure to delete its target -ARCH ?= linux/arm64 +ARCH ?= linux/amd64