Skip to content

Add arm64 release packages and multi-arch Docker images#94

Merged
renecannao merged 3 commits intomasterfrom
arm64-packages
Apr 16, 2026
Merged

Add arm64 release packages and multi-arch Docker images#94
renecannao merged 3 commits intomasterfrom
arm64-packages

Conversation

@renecannao
Copy link
Copy Markdown

@renecannao renecannao commented Apr 16, 2026

Summary

  • Extend the release workflow to build linux/arm64 packages (tar.gz/.deb/.rpm) alongside linux/amd64, using a native ubuntu-24.04-arm runner for each arch.
  • Publish a multi-arch Docker manifest to ghcr.io/proxysql/orchestrator covering both linux/amd64 and linux/arm64.
  • Add docs/release.md documenting the tag-driven release flow, verification commands, and local reproduction; link it from docs/toc.md.

Verification

End-to-end test via tag v4.30.1-rc2:

  • 5/5 workflow jobs green (amd64 + arm64 package matrix, amd64 + arm64 Docker matrix, manifest merge).
  • GitHub prerelease contains 14 assets: tar.gz, .deb, .rpm × (full, -cli, -client) × (amd64, arm64).
  • docker buildx imagetools inspect in the workflow confirms both linux/arm64 and linux/amd64 platforms in the merged manifest.
  • rc tags are correctly marked prerelease and do not move the Docker latest tag.

Test plan

  • Tag-triggered release workflow completes for both archs
  • All 14 release assets uploaded
  • Multi-arch Docker manifest published
  • Prerelease detection works for -rcN tags

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for arm64 architecture in releases alongside existing amd64 support.
    • Multi-architecture Docker images now published for both amd64 and arm64 platforms.
    • Release packages now available in multiple formats (tar.gz, .deb, .rpm).
  • Documentation

    • Added comprehensive guide documenting the release and publishing process.

Matrix the release workflow over amd64 and arm64 native GitHub runners
(ubuntu-latest, ubuntu-24.04-arm). Each arch runs build.sh to produce
tar.gz/.deb/.rpm (full, -cli, -client) and uploads to the same Release.

Docker build is split into per-arch push-by-digest jobs plus a merge
job that creates a multi-arch manifest on ghcr.io/proxysql/orchestrator.

docs/release.md documents the tag-triggered release flow.
build.sh's precheck requires GOPATH to be set; setup-go@v5 does not
export it. Set it from 'go env GOPATH'.
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 16, 2026

Warning

Rate limit exceeded

@renecannao has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 48 minutes and 0 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 48 minutes and 0 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b0d9025e-b13b-44d0-96b9-ee38a1c98e35

📥 Commits

Reviewing files that changed from the base of the PR and between 7011113 and 2b203a3.

📒 Files selected for processing (1)
  • docs/README.md
📝 Walkthrough

Walkthrough

This PR introduces multi-architecture (amd64, arm64) release automation by updating the GitHub Actions release workflow to build OS packages for both architectures via build.sh, collect artifacts from /tmp/orchestrator-release/, and publish Docker images as a multi-arch manifest list using docker buildx imagetools create. Build script and release documentation are updated accordingly.

Changes

Cohort / File(s) Summary
GitHub Actions Release Workflow
.github/workflows/release.yml
Replaces single-arch amd64 builds with matrix-based amd64/arm64 packaging via ./build.sh -a "$GOARCH", updates artifact collection to /tmp/orchestrator-release/*.{tar.gz,deb,rpm}, and refactors Docker publication into separate docker-build (per-arch native builds pushed by digest) and docker-merge (assembles multi-arch manifest via docker buildx imagetools create) jobs.
Build Script & Documentation
build.sh, docs/release.md, docs/toc.md
Updates build.sh usage text to include arm64 alongside existing architectures; adds comprehensive release documentation covering multi-arch builds, prerelease handling, workflow jobs, verification steps, and troubleshooting; links new documentation in table of contents.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A rabbit hops through build matrices bright,
Two architectures dancing left and right,
Manifests merge like carrots in a feast,
arm64 and amd64, each a release beast!
Multi-arch harmony—no more single-path plight! 🏗️

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add arm64 release packages and multi-arch Docker images' accurately and specifically summarizes the main changes: extending release workflows to support arm64 architecture alongside amd64, producing multi-arch packages and Docker images.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch arm64-packages

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds arm64 support to the build script and introduces a new documentation file detailing the release and publishing workflow. The review feedback highlights an inconsistency in the darwin build target, suggests aligning runner versions for consistency, and identifies a missing rsync dependency in the local reproduction steps.

Comment thread build.sh
echo "-t (linux|darwin) Target OS Default:(linux)"
echo "-i (systemd|sysv) Target init system Default:(systemd)"
echo "-a (amd64|386) Arch Default:(amd64)"
echo "-a (amd64|386|arm64) Arch Default:(amd64)"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The help message now includes arm64 as a supported architecture. However, the build_binary function (line 125) still hardcodes GOARCH=amd64 for the darwin target. This results in an inconsistency where running ./build.sh -t darwin -a arm64 will produce a tarball labeled as arm64 but containing an amd64 binary. Consider updating build_binary to use the $arch variable for the darwin case as well.

Comment thread docs/release.md

### 1. `build-and-release` (matrix: amd64, arm64)

Runs on `ubuntu-latest` (amd64) and `ubuntu-24.04-arm` (arm64) — GitHub's native ARM runners, free for public repos. No QEMU, no cross-compilation: each job builds on its own native architecture, so CGO (`go-sqlite3`) works without any special toolchain.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There is a discrepancy between the PR description (which mentions using ubuntu-24.04 for each architecture) and this documentation (which mentions ubuntu-latest for amd64). To ensure consistent build environments and GLIBC requirements across architectures, it is recommended to use an explicit version like ubuntu-24.04 for both.

Suggested change
Runs on `ubuntu-latest` (amd64) and `ubuntu-24.04-arm` (arm64) — GitHub's native ARM runners, free for public repos. No QEMU, no cross-compilation: each job builds on its own native architecture, so CGO (`go-sqlite3`) works without any special toolchain.
Runs on ubuntu-24.04 (amd64) and ubuntu-24.04-arm (arm64) — GitHub's native ARM runners, free for public repos. No QEMU, no cross-compilation: each job builds on its own native architecture, so CGO (go-sqlite3) works without any special toolchain.

Comment thread docs/release.md
-v $PWD:/src -w /src \
ubuntu:24.04 bash -c '
apt-get update &&
apt-get install -y golang git ruby ruby-dev build-essential rpm &&
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The build.sh script relies on rsync to copy resource artifacts (lines 163-164). The ubuntu:24.04 base image does not include rsync by default, so the local reproduction command provided here will fail. Please add rsync to the apt-get install command.

Suggested change
apt-get install -y golang git ruby ruby-dev build-essential rpm &&
apt-get install -y golang git ruby ruby-dev build-essential rpm rsync &&

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/release.yml:
- Around line 92-100: The workflow hardcodes the image name in the "Build and
push by digest" step (outputs: ... name=ghcr.io/proxysql/orchestrator ...) which
prevents forks from pushing; update the step to derive the image name from the
current repo (e.g. use ghcr.io/${{ github.repository }} or an IMAGE_NAME
input/variable) instead of the hardcoded ghcr.io/proxysql/orchestrator string,
and propagate that variable wherever the hardcoded name is used (the other
occurrences called out in the review) so forks can push to their own GHCR
namespace or document that the name must be overridden.

In `@docs/release.md`:
- Around line 100-110: The Docker example for producing ARM64 packages is
missing GOPATH, causing build.sh to abort in precheck(); update the container
command to export GOPATH (e.g. export GOPATH="$(go env GOPATH)") before invoking
./build.sh -a arm64 so the precheck() sees a valid GOPATH; ensure the export
happens in the same shell session inside the container (or pass GOPATH via
environment in the docker run) so build.sh and its precheck() succeed.
- Around line 42-48: The docs currently claim all three package variants from
package_linux (referencing build.sh and package_linux) produce .tar.gz, .deb and
.rpm; correct this to state that only the full "orchestrator" variant emits a
.tar.gz (in addition to .deb/.rpm if applicable), while "orchestrator-cli" and
"orchestrator-client" are packaged only as .deb/.rpm; update the paragraph that
lists formats for orchestrator, orchestrator-cli, and orchestrator-client to
reflect these exact outputs and keep the note about arch-specific
names/matrix-job upload collisions unchanged.
- Around line 119-121: The doc's "Docker manifest is missing one arch" note is
incorrect about job execution: update the text to state that because the
`docker-merge` job has `needs: docker-build` and no `if: always()`, any failed
`docker-build` matrix leg will cause `docker-merge` to be skipped (even with
`fail-fast: false`), so you must re-run the failed `docker-build` job (or the
whole workflow) before `docker-merge` can produce a multi-arch manifest; mention
`imagetools create` will only produce a single-arch manifest if `docker-merge`
runs with only one successful arch and clarify that re-running the failed
`docker-build` leg (not just `docker-merge`) is required to recover.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c84563cb-1b14-46a5-b764-3ee35766b13b

📥 Commits

Reviewing files that changed from the base of the PR and between 3e00b7f and 7011113.

📒 Files selected for processing (4)
  • .github/workflows/release.yml
  • build.sh
  • docs/release.md
  • docs/toc.md

Comment on lines +92 to +100
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: .
file: docker/Dockerfile
platforms: ${{ matrix.platform }}
outputs: type=image,name=ghcr.io/proxysql/orchestrator,push-by-digest=true,name-canonical=true,push=true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

Can a GitHub Actions workflow running in a forked repository publish to a hardcoded GHCR image in the upstream owner's namespace (for example ghcr.io/proxysql/orchestrator) using the fork's GITHUB_TOKEN, or must the image name use the fork repository/owner namespace?

💡 Result:

No, a GitHub Actions workflow running in a forked repository cannot publish to a hardcoded GHCR image in the upstream owner's namespace (e.g., ghcr.io/proxysql/orchestrator) using the fork's GITHUB_TOKEN. The GITHUB_TOKEN is scoped to the repository where the workflow runs (the fork) and only grants write access to packages in that repository's namespace (e.g., ghcr.io/forkowner/forkrepo). Publishing to the upstream namespace requires write permission on the upstream package, which the fork's GITHUB_TOKEN lacks. To publish to the upstream image: - Use a Personal Access Token (PAT) with write:packages scope for the upstream owner/org, stored as a secret in the fork. - Grant the fork repository explicit write access to the upstream package via the package settings ("Manage Actions access"). All examples and docs use ${{ github.repository }} or similar for the current repo's namespace, confirming GITHUB_TOKEN does not cross namespaces without explicit package-level grants (which forks typically don't have by default).

Citations:


🏁 Script executed:

# Check if docs/release.md exists and examine line 26 area
fd -t f "release.md" docs/ 2>/dev/null && \
  echo "=== Checking docs/release.md around line 26 ===" && \
  sed -n '20,35p' docs/release.md || echo "docs/release.md not found"

Repository: ProxySQL/orchestrator

Length of output: 782


🏁 Script executed:

# Verify the actual .github/workflows/release.yml file
fd -t f "release.yml" .github/workflows/ 2>/dev/null && \
  echo "=== Checking lines 92-100 ===" && \
  sed -n '92,100p' .github/workflows/release.yml && \
  echo -e "\n=== Checking lines 137-158 ===" && \
  sed -n '137,158p' .github/workflows/release.yml

Repository: ProxySQL/orchestrator

Length of output: 1276


🏁 Script executed:

# Search for all occurrences of the hardcoded namespace
echo "=== All occurrences of 'ghcr.io/proxysql/orchestrator' ===" && \
  rg "ghcr\.io/proxysql/orchestrator" .github/workflows/release.yml -n

Repository: ProxySQL/orchestrator

Length of output: 446


The hardcoded GHCR namespace blocks the documented fork dry-run flow.

The documentation states that RC tags can be used to test the release pipeline end-to-end on a fork, but the hardcoded ghcr.io/proxysql/orchestrator image name at lines 99, 141, 152, and 158 prevents this from working. A fork's GITHUB_TOKEN cannot push to the upstream owner's namespace—it only has write access to its own ghcr.io/${{ github.repository }} namespace. Either derive the image name from the current repository or update the documentation to remove the fork dry-run promise.

Suggested refactor
 jobs:
   build-and-release:
@@
   docker-build:
+    env:
+      IMAGE_NAME: ghcr.io/${{ github.repository }}
     strategy:
@@
     - name: Build and push by digest
       id: build
       uses: docker/build-push-action@v6
       with:
         context: .
         file: docker/Dockerfile
         platforms: ${{ matrix.platform }}
-        outputs: type=image,name=ghcr.io/proxysql/orchestrator,push-by-digest=true,name-canonical=true,push=true
+        outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
@@
   docker-merge:
+    env:
+      IMAGE_NAME: ghcr.io/${{ github.repository }}
     needs: docker-build
@@
     - name: Extract metadata
       id: meta
       uses: docker/metadata-action@v5
       with:
-        images: ghcr.io/proxysql/orchestrator
+        images: ${{ env.IMAGE_NAME }}
         tags: |
           type=semver,pattern={{version}}
           type=semver,pattern={{major}}.{{minor}}
           type=raw,value=latest,enable=${{ !contains(github.ref_name, 'rc') }}
@@
     - name: Create manifest list and push
       working-directory: /tmp/digests
       run: |
         docker buildx imagetools create \
           $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
-          $(printf 'ghcr.io/proxysql/orchestrator@sha256:%s ' *)
+          $(printf '${IMAGE_NAME}@sha256:%s ' *)
@@
     - name: Inspect image
       env:
         VERSION: ${{ steps.meta.outputs.version }}
       run: |
-        docker buildx imagetools inspect "ghcr.io/proxysql/orchestrator:${VERSION}"
+        docker buildx imagetools inspect "${IMAGE_NAME}:${VERSION}"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yml around lines 92 - 100, The workflow hardcodes
the image name in the "Build and push by digest" step (outputs: ...
name=ghcr.io/proxysql/orchestrator ...) which prevents forks from pushing;
update the step to derive the image name from the current repo (e.g. use
ghcr.io/${{ github.repository }} or an IMAGE_NAME input/variable) instead of the
hardcoded ghcr.io/proxysql/orchestrator string, and propagate that variable
wherever the hardcoded name is used (the other occurrences called out in the
review) so forks can push to their own GHCR namespace or document that the name
must be overridden.

Comment thread docs/release.md
Comment on lines +42 to +48
Per arch, `build.sh` produces three variants (see `package_linux` in [`build.sh`](../build.sh)):

- `orchestrator` — full package (binary + web resources + sample configs + systemd unit)
- `orchestrator-cli` — binary only
- `orchestrator-client` — the `orchestrator-client` shell script only

Each variant is emitted as `.tar.gz`, `.deb`, and `.rpm`. Package names differ by arch (`_amd64.deb` / `_arm64.deb`, `.x86_64.rpm` / `.aarch64.rpm`), so the two matrix jobs don't collide when uploading to the same Release.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Package formats are overstated in this section.

package_linux only emits a .tar.gz for the full orchestrator package. The -cli and -client variants are packaged as .deb/.rpm only, so this text will send readers looking for tarballs that are never produced.

Suggested doc fix
-Each variant is emitted as `.tar.gz`, `.deb`, and `.rpm`. Package names differ by arch (`_amd64.deb` / `_arm64.deb`, `.x86_64.rpm` / `.aarch64.rpm`), so the two matrix jobs don't collide when uploading to the same Release.
+The full `orchestrator` package is emitted as `.tar.gz`, `.deb`, and `.rpm`. The `-cli` and `-client` variants are emitted as `.deb` and `.rpm` only. Package names differ by arch (`_amd64.deb` / `_arm64.deb`, `.x86_64.rpm` / `.aarch64.rpm`), so the two matrix jobs don't collide when uploading to the same Release.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/release.md` around lines 42 - 48, The docs currently claim all three
package variants from package_linux (referencing build.sh and package_linux)
produce .tar.gz, .deb and .rpm; correct this to state that only the full
"orchestrator" variant emits a .tar.gz (in addition to .deb/.rpm if applicable),
while "orchestrator-cli" and "orchestrator-client" are packaged only as
.deb/.rpm; update the paragraph that lists formats for orchestrator,
orchestrator-cli, and orchestrator-client to reflect these exact outputs and
keep the note about arch-specific names/matrix-job upload collisions unchanged.

Comment thread docs/release.md
Comment on lines +100 to +110
The release workflow does the same thing you can do locally with `build.sh` — see [Building and testing](build.md) and [`build.sh`](../build.sh). To produce ARM64 packages on a non-ARM host (outside of CI), run inside an arm64 container:

```
docker run --rm -it --platform linux/arm64 \
-v $PWD:/src -w /src \
ubuntu:24.04 bash -c '
apt-get update &&
apt-get install -y golang git ruby ruby-dev build-essential rpm &&
gem install --no-document fpm &&
./build.sh -a arm64
'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

The local arm64 recipe is missing GOPATH.

build.sh aborts in precheck() when GOPATH is unset, and the workflow already works around that by exporting go env GOPATH first. The container example should do the same or it won't reproduce CI.

Suggested doc fix
     docker run --rm -it --platform linux/arm64 \
       -v $PWD:/src -w /src \
       ubuntu:24.04 bash -c '
         apt-get update &&
         apt-get install -y golang git ruby ruby-dev build-essential rpm &&
         gem install --no-document fpm &&
+        export GOPATH="$(go env GOPATH)" &&
         ./build.sh -a arm64
       '
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
The release workflow does the same thing you can do locally with `build.sh` — see [Building and testing](build.md) and [`build.sh`](../build.sh). To produce ARM64 packages on a non-ARM host (outside of CI), run inside an arm64 container:
```
docker run --rm -it --platform linux/arm64 \
-v $PWD:/src -w /src \
ubuntu:24.04 bash -c '
apt-get update &&
apt-get install -y golang git ruby ruby-dev build-essential rpm &&
gem install --no-document fpm &&
./build.sh -a arm64
'
The release workflow does the same thing you can do locally with `build.sh` — see [Building and testing](build.md) and [`build.sh`](../build.sh). To produce ARM64 packages on a non-ARM host (outside of CI), run inside an arm64 container:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/release.md` around lines 100 - 110, The Docker example for producing
ARM64 packages is missing GOPATH, causing build.sh to abort in precheck();
update the container command to export GOPATH (e.g. export GOPATH="$(go env
GOPATH)") before invoking ./build.sh -a arm64 so the precheck() sees a valid
GOPATH; ensure the export happens in the same shell session inside the container
(or pass GOPATH via environment in the docker run) so build.sh and its
precheck() succeed.

Comment thread docs/release.md
Comment on lines +119 to +121
- **Workflow didn't run after tagging.** The tag must start with `v` (see the `on.push.tags` filter). Tags pushed without `git push --tags` or without pushing the specific ref won't trigger it.
- **A matrix job failed mid-way and part of the release is missing.** The workflow uses `fail-fast: false`, so the other arch still completes. Re-running only the failed job from the Actions UI is safe — the GitHub Release and GHCR both accept re-uploads (fpm uses `-f` to overwrite, `action-gh-release` replaces files of the same name).
- **Docker manifest is missing one arch.** If `docker-build` succeeded for only one arch, `docker-merge` will still run but `imagetools create` will produce a single-arch manifest. Re-run the failed `docker-build` job, then re-run `docker-merge`.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🌐 Web query:

In GitHub Actions, when a job depends on a matrix job via needs, does the dependent job get skipped if any matrix leg fails and the job has no if: always() condition?

💡 Result:

Yes, in GitHub Actions, when a job depends on a matrix job via needs, the dependent job gets skipped if any matrix leg (individual job instance from the matrix) fails, unless the dependent job has an if: always (or equivalent condition like if: ${{ !failure && !cancelled }}) condition. The official documentation states: "Use jobs..<job_id>.needs to identify any jobs that must complete successfully before this job will run. [...] If a job fails or is skipped, all jobs that need it are skipped unless the jobs use a conditional expression that causes the job to continue." A matrix job is treated as a single logical job composed of multiple legs. If any leg fails (and fail-fast: true default or explicit, or even with fail-fast: false if not all succeed), the matrix job does not complete "successfully." Thus, dependents via needs are skipped without an overriding if condition. This behavior is confirmed across Stack Overflow examples (e.g., test_finish skipped when matrix test has failures) and GitHub issues discussing propagation of failure/skip states through needs dependencies.

Citations:


🏁 Script executed:

# First, find the workflow file(s) referenced in release.md
find . -name "*.md" -path "*/docs/*" | xargs grep -l "docker-merge\|docker-build" | head -5

Repository: ProxySQL/orchestrator

Length of output: 82


🏁 Script executed:

# List GitHub Actions workflow files
git ls-files ".github/workflows/" 2>/dev/null || fd -e ".yml" -e ".yaml" ".github/workflows"

Repository: ProxySQL/orchestrator

Length of output: 213


🏁 Script executed:

# Read the release.yml workflow file to examine docker-merge and docker-build jobs
cat .github/workflows/release.yml

Repository: ProxySQL/orchestrator

Length of output: 4254


Update the Docker manifest recovery note to reflect actual job dependency behavior.

The documentation incorrectly states that docker-merge will run if only one arch succeeds. With docker-merge declared as needs: docker-build and no if: always() condition, a failed docker-build matrix leg causes the entire job to fail, which skips docker-merge. The fail-fast: false setting only allows the other arch to complete; it doesn't prevent the job from failing.

Suggested doc fix
-- **Docker manifest is missing one arch.** If `docker-build` succeeded for only one arch, `docker-merge` will still run but `imagetools create` will produce a single-arch manifest. Re-run the failed `docker-build` job, then re-run `docker-merge`.
+- **Docker manifest is missing one arch.** If either `docker-build` matrix leg fails, `docker-merge` is skipped because it depends on `docker-build`. Re-run the failed `docker-build` job, then re-run `docker-merge`.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- **Workflow didn't run after tagging.** The tag must start with `v` (see the `on.push.tags` filter). Tags pushed without `git push --tags` or without pushing the specific ref won't trigger it.
- **A matrix job failed mid-way and part of the release is missing.** The workflow uses `fail-fast: false`, so the other arch still completes. Re-running only the failed job from the Actions UI is safe — the GitHub Release and GHCR both accept re-uploads (fpm uses `-f` to overwrite, `action-gh-release` replaces files of the same name).
- **Docker manifest is missing one arch.** If `docker-build` succeeded for only one arch, `docker-merge` will still run but `imagetools create` will produce a single-arch manifest. Re-run the failed `docker-build` job, then re-run `docker-merge`.
- **Workflow didn't run after tagging.** The tag must start with `v` (see the `on.push.tags` filter). Tags pushed without `git push --tags` or without pushing the specific ref won't trigger it.
- **A matrix job failed mid-way and part of the release is missing.** The workflow uses `fail-fast: false`, so the other arch still completes. Re-running only the failed job from the Actions UI is safe — the GitHub Release and GHCR both accept re-uploads (fpm uses `-f` to overwrite, `action-gh-release` replaces files of the same name).
- **Docker manifest is missing one arch.** If either `docker-build` matrix leg fails, `docker-merge` is skipped because it depends on `docker-build`. Re-run the failed `docker-build` job, then re-run `docker-merge`.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/release.md` around lines 119 - 121, The doc's "Docker manifest is
missing one arch" note is incorrect about job execution: update the text to
state that because the `docker-merge` job has `needs: docker-build` and no `if:
always()`, any failed `docker-build` matrix leg will cause `docker-merge` to be
skipped (even with `fail-fast: false`), so you must re-run the failed
`docker-build` job (or the whole workflow) before `docker-merge` can produce a
multi-arch manifest; mention `imagetools create` will only produce a single-arch
manifest if `docker-merge` runs with only one successful arch and clarify that
re-running the failed `docker-build` leg (not just `docker-merge`) is required
to recover.

@renecannao renecannao merged commit 521fda1 into master Apr 16, 2026
7 of 17 checks passed
@renecannao renecannao deleted the arm64-packages branch April 16, 2026 07:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant