Skip to content

Add Docker multistep build#475

Merged
Flaminel merged 8 commits intomainfrom
add_docker_multistep_build
Feb 27, 2026
Merged

Add Docker multistep build#475
Flaminel merged 8 commits intomainfrom
add_docker_multistep_build

Conversation

@Flaminel
Copy link
Contributor

@Flaminel Flaminel commented Feb 27, 2026

Summary by Sourcery

Introduce a multi-stage GitHub Actions workflow to build, push, and publish multi-architecture Docker images using Buildx digests and manifests.

Build:

  • Add a prepare job to compute image tags, version metadata, target branch, and push conditions for downstream Docker build jobs.
  • Refactor the Docker build workflow into separate prepare, per-platform build, and merge jobs to build linux/amd64 and linux/arm64 images in parallel and assemble a multi-arch manifest.
  • Switch Docker publishing to push per-platform images by digest, then create and push a manifest list with the final tags to GHCR.
  • Tighten GitHub Actions permissions, centralize the registry image name in an env var, and adjust caching and login logic to use scoped caches and GitHub token-based auth.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request refactors the Docker build workflow to use a multi-step, digest-based approach for building multi-platform images. The workflow is split into three jobs: prepare (computes tags and build metadata), build (builds each platform in parallel), and merge (creates multi-platform manifest and pushes with tags).

Changes:

  • Restructured workflow into three sequential jobs for better parallelization of platform builds
  • Implemented digest-based builds with separate build jobs for linux/amd64 and linux/arm64 platforms
  • Migrated from GITHUB_ENV to GITHUB_OUTPUT for passing data between steps (following GitHub Actions best practices)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@Flaminel
Copy link
Contributor Author

@sourcery-ai review

@sourcery-ai
Copy link

sourcery-ai bot commented Feb 27, 2026

Reviewer's Guide

Refactors the Docker GitHub Actions workflow into a multi-job, multi-arch, digest-based build and manifest-merge pipeline, exposes build metadata via job outputs instead of env vars, and makes a minor formatting fix in Program.cs.

File-Level Changes

Change Details Files
Refactor Docker workflow into prepare, per-platform build, and merge jobs with multi-arch manifest creation.
  • Add workflow-level permissions and a REGISTRY_IMAGE env for GHCR
  • Introduce a prepare job that computes tags, version, branch, and push decision and exposes them as job outputs
  • Replace single multi-platform build with a matrix build job for linux/amd64 and linux/arm64, including QEMU and Buildx setup
  • Switch Docker builds to push-by-digest outputs, uploading per-platform digests as artifacts
  • Add a merge job that downloads digests and uses docker buildx imagetools to create and push a multi-arch manifest with all computed tags
.github/workflows/build-docker.yml
Adjust secrets and GitHub context usage in the workflow and tighten push conditions.
  • Remove Vault retrieval of Docker username/password and rely on GITHUB_TOKEN for GHCR login
  • Use github.* context directly instead of exporting to env, and pass branch via job outputs to checkout
  • Gate registry login, digest export, and merge jobs on the computed push flag
.github/workflows/build-docker.yml
Minor formatting fix in API Program.cs by adding a trailing newline.
  • Ensure Program partial class line is terminated with a newline at end of file
code/backend/Cleanuparr.Api/Program.cs

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The image name ghcr.io/cleanuparr/cleanuparr is now defined both in the REGISTRY_IMAGE env var and hard-coded when constructing githubTags; consider switching the tag construction to use REGISTRY_IMAGE to avoid duplication and future drift.
  • The push decision is currently computed inside the shell script using a GitHub expression (push="${{ github.event_name == 'pull_request' || inputs.push_docker == true }}"); it would be clearer and less error-prone to derive this as a pure workflow expression (e.g. a job-level output or env) rather than mixing template evaluation with bash.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The image name `ghcr.io/cleanuparr/cleanuparr` is now defined both in the `REGISTRY_IMAGE` env var and hard-coded when constructing `githubTags`; consider switching the tag construction to use `REGISTRY_IMAGE` to avoid duplication and future drift.
- The `push` decision is currently computed inside the shell script using a GitHub expression (`push="${{ github.event_name == 'pull_request' || inputs.push_docker == true }}"`); it would be clearer and less error-prone to derive this as a pure workflow expression (e.g. a job-level output or env) rather than mixing template evaluation with bash.

## Individual Comments

### Comment 1
<location path=".github/workflows/build-docker.yml" line_range="159" />
<code_context>
-        uses: docker/setup-qemu-action@v3
-
       - name: Login to GitHub Container Registry
+        if: needs.prepare.outputs.push == 'true'
         uses: docker/login-action@v3
         with:
</code_context>
<issue_to_address>
**🚨 issue (security):** Pushing images on pull_request events can fail or behave unexpectedly for forked PRs due to restricted GITHUB_TOKEN permissions.

Since `push` resolves to `true` for `pull_request` events, the `build`/`merge` jobs will try to push with the default GITHUB_TOKEN. For forked PRs this token is read‑only, so pushes will fail and can block the workflow. If forked PRs should run this workflow, consider narrowing the `push` condition (e.g. only on `push`/`workflow_dispatch`/internal PRs) or adding a check like `github.event.pull_request.head.repo.full_name == github.repository` before attempting to push.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@codecov
Copy link

codecov bot commented Feb 27, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Flaminel
Copy link
Contributor Author

@sourcery-ai review

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The push flag is now computed inside the shell script via push="${{ github.event_name == 'pull_request' || inputs.push_docker == true }}", which mixes GitHub expressions and bash; consider moving this logic back into the workflow YAML (e.g., as an outputs expression) so it remains purely declarative and easier to reason about.
  • In the merge job, the manifest creation step assumes that prepare.outputs.tags is non-empty; it may be worth guarding against an empty or malformed tags string (e.g., all whitespace or leading/trailing commas) to avoid creating a manifest with no valid tags.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `push` flag is now computed inside the shell script via `push="${{ github.event_name == 'pull_request' || inputs.push_docker == true }}"`, which mixes GitHub expressions and bash; consider moving this logic back into the workflow YAML (e.g., as an `outputs` expression) so it remains purely declarative and easier to reason about.
- In the `merge` job, the manifest creation step assumes that `prepare.outputs.tags` is non-empty; it may be worth guarding against an empty or malformed tags string (e.g., all whitespace or leading/trailing commas) to avoid creating a manifest with no valid tags.

## Individual Comments

### Comment 1
<location path=".github/workflows/build-docker.yml" line_range="95-97" />
<code_context>
           githubTags=""
-
           if [ -n "$latestDockerTag" ]; then
             githubTags="$githubTags,ghcr.io/cleanuparr/cleanuparr:$latestDockerTag"
           fi
</code_context>
<issue_to_address>
**suggestion:** Consider using REGISTRY_IMAGE env var instead of hardcoding the image name in multiple places.

`REGISTRY_IMAGE` is defined as `ghcr.io/cleanuparr/cleanuparr`, but this tag construction still hardcodes that value. Referencing `REGISTRY_IMAGE` here (e.g. `"$githubTags,${REGISTRY_IMAGE}:$latestDockerTag"`) avoids duplication and prevents drift if the image name or registry changes.

```suggestion
           if [ -n "$latestDockerTag" ]; then
             githubTags="$githubTags,${REGISTRY_IMAGE}:$latestDockerTag"
           fi
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@Flaminel Flaminel merged commit 5fea8a0 into main Feb 27, 2026
10 of 11 checks passed
@Flaminel Flaminel deleted the add_docker_multistep_build branch February 27, 2026 18: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.

2 participants