build: multi-stage scratch Docker image + Go 1.26 + ci-templates migration#189
build: multi-stage scratch Docker image + Go 1.26 + ci-templates migration#189michaelbeutler wants to merge 2 commits into
Conversation
…ers_v2 - Replace the prebuilt-binary build/buildx*.Dockerfile pair with a single root Dockerfile: an Alpine stage sources CA certs/tzdata/passwd, the final image is FROM scratch with the binary as ENTRYPOINT (non-root, EXPOSE 8080). - Migrate .goreleaser.yaml from dockers: to dockers_v2: (single multi-arch amd64+arm64 manifest), gate moving tags (latest/major/minor) to stable releases, add docker_digest, keyless docker_signs (cosign) and binary SBOMs. - Modernize deprecated archives.format -> formats and add -trimpath. - Bump the go directive to 1.26.0 (CGO_ENABLED=0, fully static, runs on scratch). - Update README docker examples for the ENTRYPOINT image.
- ci.yml -> quality-gates.yml + go-ci.yml (Go 1.26, runs check-json-tags/ check-metrics in lint; goreleaser-snapshot off since syft/cosign live in the release workflow, matching truvami/gateway#96). - release.yml -> go-release.yml (single workflow auto-detecting RC vs stable, installs cosign + syft, sets up QEMU for the multi-arch image). - Delete release-candidate.yml (folded into release.yml) and codecov.yml (Codecov upload dropped; go-ci uploads coverage as an artifact). - Regenerate .secrets.baseline: record the benign 'secrets: inherit' keyword matches in the new workflows plus the build-artifact exclude pattern, so the quality-gates detect-secrets rescan matches the committed baseline.
|
Warning Review limit reached
More reviews will be available in 4 minutes and 8 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the 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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (11)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
This PR modernizes the project’s build/release pipeline by switching to a minimal multi-stage scratch Docker image, bumping the Go toolchain to 1.26, and migrating CI/release automation to truvami/ci-templates@v1 reusable workflows. It also updates GoReleaser to publish a single multi-arch image (with signing/SBOM/digests support).
Changes:
- Replace prior buildx Dockerfiles with a root multi-stage
scratchDockerfile using anENTRYPOINTand non-root user. - Update GoReleaser config to
dockers_v2multi-arch publishing plus signing/SBOM/digests outputs. - Migrate GitHub Actions workflows to
truvami/ci-templates@v1and bump Go to 1.26.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
README.md |
Updates Docker usage examples to reflect ENTRYPOINT behavior. |
go.mod |
Bumps the module Go version directive to 1.26.0. |
Dockerfile |
Introduces a multi-stage scratch runtime image with CA certs/tzdata and non-root user. |
.goreleaser.yaml |
Migrates to dockers_v2 and adds image signing/SBOM/digest generation configuration. |
.github/workflows/ci.yml |
Replaces bespoke CI with quality-gates.yml + go-ci.yml reusable workflows. |
.github/workflows/release.yml |
Replaces bespoke release logic with go-release.yml reusable workflow. |
.github/workflows/release-candidate.yml |
Deletes RC-specific workflow (folded into unified release workflow). |
build/buildx.Dockerfile |
Deletes legacy Docker build file. |
build/buildx-alpine.Dockerfile |
Deletes legacy Alpine Docker build file. |
codecov.yml |
Removes Codecov configuration (coverage upload dropped). |
.secrets.baseline |
Regenerates detect-secrets baseline and adds exclude regex for reproducibility. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Files a networked, time-aware, non-root CLI needs (scratch ships none): | ||
| # - CA certificates: outbound TLS (AWS IoT Wireless, LoRa Cloud, self-update, ...) | ||
| # - tzdata: timezone-aware time handling | ||
| # - passwd/group: so USER nonroot resolves to a real uid/gid | ||
| COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ |
| ARG TARGETPLATFORM | ||
| COPY ${TARGETPLATFORM}/decoder /usr/bin/decoder | ||
|
|
||
| USER nonroot:nonroot |
|
|
||
| # Run the Docker container | ||
| docker run -it ghcr.io/truvami/decoder decoder --help | ||
| # Run the Docker container (the image ENTRYPOINT is `decoder`) |
|
|
||
| # Write a digests file with the digests of all published images/manifests. | ||
| # https://goreleaser.com/customization/package/docker_digests/ | ||
| docker_digest: |
| # cosign + syft (for dockers_v2 signing/SBOM) and publishes to GHCR. | ||
| uses: truvami/ci-templates/.github/workflows/go-release.yml@v1 | ||
| with: | ||
| go-version: '1.26' |
| go-ci: | ||
| name: Go CI | ||
| uses: truvami/ci-templates/.github/workflows/go-ci.yml@v1 | ||
| with: | ||
| # No `make generate` target / no go:generate directives in this repo. | ||
| code-generation: false | ||
| # Off (matches truvami/gateway#96): the snapshot job isn't provisioned with | ||
| # the syft/cosign that the dockers_v2 SBOM + keyless signing config needs — | ||
| # the Release workflow (go-release.yml) is. PR correctness is covered by | ||
| # lint + test, and `make check-json-tags` / `make check-metrics` run in lint. | ||
| goreleaser-snapshot: false | ||
| secrets: inherit |
Summary
Reworks the Docker image, bumps Go to 1.26, introduces the
ENTRYPOINTpattern, and migrates CI to the sharedtruvami/ci-templates@v1reusable workflows — the same shape as truvami/gateway#96, adapted for this pure-Go CLI.Docker image rework
The old
build/buildx.Dockerfile+build/buildx-alpine.Dockerfilepair only copied a prebuilt binary into a fullgolang:1.23(~800 MB) base. Replaced with a single rootDockerfile:scratch: analpinestage sources only CA certs, tzdata and a non-rootpasswd/groupentry (uid/gid65532); the final image isFROM scratch.ENTRYPOINT ["/usr/bin/decoder"](wasCMD), non-root,EXPOSE 8080(HTTP API +/metrics). Absolute path becausescratchhas noPATH.linux/amd64+linux/arm64): unlike gateway (cgo/musl → amd64-only), decoder is pureCGO_ENABLED=0, so the static binary runs onscratchand a single multi-arch manifest is trivial.COPY $TARGETPLATFORM/decoder.Verified locally: the built scratch image runs (
docker run … --version→ exit 0) at 19.9 MB.GoReleaser
dockers:→dockers_v2:(ghcr.io/truvami/decoder, single multi-arch manifest).latest/{major}/{major.minor}) gated to stable releases — an RC can never move them;{{ .Tag }}/{{ .Version }}always apply.docker_digest:— digests file for published images.docker_signs:— keyless cosign (OIDC) signing.sboms:— SBOM for the binary;dockers_v2.sbom: "true"for the image.archives.format→formats, added-trimpath.CI migration (truvami/ci-templates@v1)
ci.ymlquality-gates.yml+go-ci.yml(Go 1.26, runscheck-json-tags/check-metricsin lint)release.ymlgo-release.yml(auto-detects RC vs stable; installs cosign + syft; QEMU for the multi-arch image)release-candidate.ymlrelease.ymlcodecov.ymlNotes:
go-ci.ymlalready runscheck-json-tags+check-metricsautomatically, so noextra-make-targetsneeded.goreleaser-snapshot: false(matches gateway): the snapshot job isn't provisioned with the syft/cosign the dockers_v2 SBOM + keyless signing need — the Release workflow is. PR correctness is covered by lint + test.private-modules: false(public repo); no AWS secrets needed (the AWS solver testt.Skips and the example test recovers/skips).Go 1.26
go.modbumped to1.26.0;go mod tidyonly changed the directive.govulncheck's only called vulnerabilities are Go stdlib, fixed by the 1.26.x toolchain — so no dependency bumps were required (unlike gateway#96).Quality gates / …,Go CI / Lint,Go CI / Test (Go 1.26.x).:alpine,:latest-alpine,*-arm64suffix tags, thegolang-base variants.latest/{tag}/{version}/{major}/{major.minor}remain (arm64 now via the multi-arch manifest, not a-arm64tag).Validation done locally
goreleaser check✅ andgoreleaser release --snapshotbuilds both arches ✅go build ./...✅,go test ./...✅ on Go 1.26gofmt,go vet,make check-json-tags,make check-metrics,yamllint✅go mod tidy→ only thego 1.26.0directive changesTest plan
vX.Y.Z-rcN→ pre-release image to GHCR, signed, with digests/SBOMvX.Y.Z→ stable release (moving tags applied)cosign verifythe pushed image