Skip to content

fix(docker-build,go): lowercase image refs, optional Go cache, PG pre-pull - #78

Merged
nkg merged 1 commit into
mainfrom
fix/image-ref-case-go-cache-pg-readiness
Sep 10, 2026
Merged

nkg merged 1 commit into
mainfrom
fix/image-ref-case-go-cache-pg-readiness

Conversation

@nkg

@nkg nkg commented Sep 10, 2026

Copy link
Copy Markdown
Owner

Three failures seen on a consumer repo (HordiaLabs/store-postgres), all in shared workflow code rather than in the consumer.

1. docker-build.yml — mixed-case image refs break Trivy and SBOM

The Trivy scan and SBOM steps assemble their reference by hand:

image-ref: ${{ inputs.registry }}/${{ inputs.image-name }}@${{ steps.build.outputs.digest }}

image-name is normally github.repository, which preserves the org's casing. OCI references must be lowercase, so Trivy fails:

could not parse reference: ghcr.io/HordiaLabs/store-postgres@sha256:71f6eab…

docker/metadata-action lowercases internally, so the push succeeds and only the scan afterwards fails. PR builds are unaffected (push: false short-circuits the scan), so this only ever breaks the default branch — store-postgres has had a red CI on every push to main since 2026-06-11 because of it.

A new Resolve image ref step lowercases registry + name once; all three digest refs use it. It uses tr rather than bash 4's ${VAR,,} because this reusable also runs on self-hosted macOS, where bash is still 3.2 (verified both ways locally).

Affects any org with capitals in its name.

2. go.yml — new go-cache input

Default true, so no behaviour change. Setting it false skips actions/setup-go's cache on runners where the post-job save is unreliable.

Observed on a containerized self-hosted runner: every real step passed, then tar packing a cold cgo-heavy build cache was still running 28 minutes later and consumed the job's whole 30-minute timeout in Post Set up Go. The runner log ends with Terminate orphan process: pid (703) (tar).

3. go.yml — Postgres pre-pull + postgres-ready-timeout

Default 60, unchanged. The image is now pulled before the readiness clock starts, so the budget covers container init rather than a cold download.

A cold pull was eating most of the 60s, so the wait expired on init that had barely begun. It surfaced as postgres did not become ready in 60s while the container log showed the server starting right at the boundary — a slow download that read like a hung database.

Test plan

  • actionlint and yamllint clean on both files
  • Lowercase resolution verified under bash 5.3 and bash 3.2: ghcr.io/HordiaLabs/store-postgresghcr.io/hordialabs/store-postgres
  • Readiness loop boundary verified: with the timeout reached it emits ::error::postgres did not become ready in 3s and exits non-zero
  • Defaults chosen so existing consumers are byte-for-byte unchanged

Needs a tag release before consumers pick it up.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Pa92NWDRAbDNXGrSuqcQDa

Three failures observed on a consumer repo (HordiaLabs/store-postgres),
all in shared workflow code rather than in the consumer.

docker-build: the Trivy scan and SBOM steps build their image reference by
hand from the raw `image-name` input, normally `github.repository`, which
keeps the org's casing. OCI references must be lowercase, so Trivy failed
with `could not parse reference: ghcr.io/HordiaLabs/store-postgres@sha256:…`
on every push to the default branch — after the image had already built and
pushed, since metadata-action lowercases for the tags it generates. PR
builds were unaffected (push: false short-circuits the scan), so this only
ever broke the default branch. Resolve the lowercase ref once in a new step
and use it for all three digest refs. `tr` rather than bash 4's ${VAR,,},
because this reusable also runs on self-hosted macOS, still on bash 3.2.

go: add `go-cache` (default true, no behaviour change) so consumers can
disable setup-go's cache on runners where the post-job save is unreliable.
Observed on a containerized self-hosted runner: `tar` packing a cold
cgo-heavy build cache was still running 28 minutes after the last test
passed and took the job's whole 30-minute timeout with it.

go: pull the Postgres image before the readiness clock starts, and make the
wait configurable via `postgres-ready-timeout` (default 60, unchanged). A
cold pull was eating most of the budget, so the wait expired on init that
had barely begun — surfacing as "postgres did not become ready in 60s"
while the container log showed the server starting right at the boundary.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pa92NWDRAbDNXGrSuqcQDa
@nkg
nkg merged commit 25e3675 into main Sep 10, 2026
12 checks passed
@nkg
nkg deleted the fix/image-ref-case-go-cache-pg-readiness branch September 10, 2026 17:30
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