Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,26 @@ jobs:
type=sha,format=short
type=raw,value=latest,enable={{is_default_branch}}

# OCI references must be lowercase, but `image-name` is normally
# `github.repository`, which preserves the org's casing (e.g.
# HordiaLabs/store-postgres). docker/metadata-action lowercases
# internally, so the push tags are fine — but the digest-based refs
# handed to Trivy and the SBOM generator below are built by hand from
# the raw input, and those tools reject a mixed-case reference with
# "could not parse reference". Resolve the lowercase form once here.
- name: Resolve image ref
id: imageref
shell: bash
env:
REGISTRY: ${{ inputs.registry }}
IMAGE_NAME: ${{ inputs.image-name }}
run: |
set -euo pipefail
# `tr` rather than bash 4's ${VAR,,}: this reusable also runs on
# self-hosted runners, and macOS still ships bash 3.2.
lower="$(printf '%s/%s' "$REGISTRY" "$IMAGE_NAME" | tr '[:upper:]' '[:lower:]')"
echo "repo=${lower}" >> "$GITHUB_OUTPUT"

- name: Build & push
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
Expand Down Expand Up @@ -200,7 +220,7 @@ jobs:
if: inputs.run-trivy-scan && inputs.push
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: ${{ inputs.registry }}/${{ inputs.image-name }}@${{ steps.build.outputs.digest }}
image-ref: ${{ steps.imageref.outputs.repo }}@${{ steps.build.outputs.digest }}
format: table
exit-code: '1'
severity: ${{ inputs.trivy-severity }}
Expand All @@ -210,7 +230,7 @@ jobs:
if: inputs.run-trivy-scan && inputs.push && github.event_name != 'pull_request'
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
with:
image-ref: ${{ inputs.registry }}/${{ inputs.image-name }}@${{ steps.build.outputs.digest }}
image-ref: ${{ steps.imageref.outputs.repo }}@${{ steps.build.outputs.digest }}
format: sarif
output: trivy.sarif
severity: ${{ inputs.trivy-severity }}
Expand All @@ -226,7 +246,7 @@ jobs:
if: inputs.generate-sbom && inputs.push
uses: anchore/sbom-action@3ad7283483fc7af8ff2b4ea19663c2d5ca935e26 # v0.24.2
with:
image: ${{ inputs.registry }}/${{ inputs.image-name }}@${{ steps.build.outputs.digest }}
image: ${{ steps.imageref.outputs.repo }}@${{ steps.build.outputs.digest }}
format: spdx-json
output-file: sbom.spdx.json
upload-artifact: ${{ inputs.upload-artifacts }}
Expand Down
33 changes: 29 additions & 4 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ on:
description: "Package pattern to fuzz"
type: string
default: "./..."
go-cache:
description: |
Cache the Go module and build directories via actions/setup-go.
Set false on runners where the post-job cache save is unreliable:
on containerized self-hosted runners the `tar` that packs a cold
cgo-heavy build cache has been observed to wedge, burning the job's
whole timeout in the "Post Set up Go" step. Only applies to the
setup-go path (use-mise: false).
type: boolean
default: true
postgres-enabled:
description: |
Start a throwaway Postgres container before the test step and export
Expand All @@ -149,6 +159,13 @@ on:
postgres-db:
type: string
default: "postgres"
postgres-ready-timeout:
description: |
Seconds to wait for Postgres to accept TCP connections before
failing. The image is pulled before the clock starts, so this
budgets container init only.
type: number
default: 60
secrets:
DEPS_READER_PRIVATE_KEY:
description: "Private key for the deps-reader GitHub App (required when deps-reader-client-id is set)"
Expand Down Expand Up @@ -198,6 +215,7 @@ jobs:
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version: ${{ inputs.go-version }}
cache: ${{ inputs.go-cache }}
cache-dependency-path: ${{ inputs.working-directory }}/go.sum

# setup-go caches the module/build dirs itself; the mise path has no
Expand Down Expand Up @@ -279,21 +297,28 @@ jobs:
PG_USER: ${{ inputs.postgres-user }}
PG_PASSWORD: ${{ inputs.postgres-password }}
PG_DB: ${{ inputs.postgres-db }}
PG_READY_TIMEOUT: ${{ inputs.postgres-ready-timeout }}
run: |
set -euo pipefail
# On self-hosted runners the workspace isn't ephemeral, so a
# container left over from a prior run (e.g. a cancelled job that
# skipped teardown) collides on the `ci-postgres` name. Remove any
# stale one first so the step is idempotent and self-healing.
docker rm -f ci-postgres >/dev/null 2>&1 || true
# Pull before starting the readiness clock. A cold pull of the
# postgres image on a slow runner used to eat most of the budget,
# so the wait below timed out on container init that had barely
# begun — the failure looked like a hung database rather than a
# slow download.
docker pull -q "$PG_IMAGE"
docker run -d --name ci-postgres \
-e POSTGRES_USER="$PG_USER" \
-e POSTGRES_PASSWORD="$PG_PASSWORD" \
-e POSTGRES_DB="$PG_DB" \
-p 5432:5432 \
"$PG_IMAGE"
# Poll pg_isready inside the container until it accepts connections
# (image pull + init can take a few seconds), capped at ~60s.
# (init can take a few seconds), capped at postgres-ready-timeout.
#
# -h 127.0.0.1 IS THE POINT, not decoration. On first init the
# postgres image's entrypoint runs a TEMPORARY server so it can
Expand All @@ -307,14 +332,14 @@ jobs:
# and gets `FATAL 57P03 (cannot_connect_now) the database system is
# starting up`. Probing TCP cannot pass early: pg_isready exits 1
# ("rejecting connections") for the whole of that window.
for i in $(seq 1 60); do
for i in $(seq 1 "$PG_READY_TIMEOUT"); do
if docker exec ci-postgres \
pg_isready -h 127.0.0.1 -p 5432 -U "$PG_USER" -d "$PG_DB" >/dev/null 2>&1; then
echo "postgres accepting TCP connections after ${i}s"
break
fi
if [ "$i" = "60" ]; then
echo "::error::postgres did not become ready in 60s"
if [ "$i" = "$PG_READY_TIMEOUT" ]; then
echo "::error::postgres did not become ready in ${PG_READY_TIMEOUT}s"
docker logs ci-postgres || true
exit 1
fi
Expand Down
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,32 @@ project uses [SemVer](https://semver.org/) for the `vMAJOR.MINOR.PATCH` tags.

### Fixed

- `docker-build.yml` no longer fails the Trivy image scan and SBOM step for
orgs whose name contains uppercase letters. The digest-based refs were
assembled by hand from the raw `image-name` input — normally
`github.repository`, which preserves casing — while `docker/metadata-action`
lowercases internally for the push tags. Trivy rejected the result with
`could not parse reference: ghcr.io/HordiaLabs/store-postgres@sha256:...`,
so every push to the default branch failed at the scan step even though the
image had built and pushed cleanly. A new `Resolve image ref` step
lowercases registry + name once, and the three digest refs use it.
Lowercasing uses `tr` rather than bash 4's `${VAR,,}`, since this reusable
also runs on self-hosted macOS runners, where bash is still 3.2.

- `go.yml` gained `go-cache` (default `true`, unchanged behaviour). Setting it
`false` skips `actions/setup-go`'s module/build cache on runners where the
post-job save is unreliable: on a containerized self-hosted runner the `tar`
that packs a cold cgo-heavy build cache has been seen to wedge, still
running 28 minutes later and consuming the job's entire 30-minute timeout in
the `Post Set up Go` step, after every real step had passed.

- `go.yml` now pulls the Postgres image before starting the readiness clock,
and the wait is configurable via `postgres-ready-timeout` (default `60`,
unchanged). A cold pull on a slow runner used to consume most of the 60s
budget, so the wait expired on container init that had barely started —
reported as `postgres did not become ready in 60s` while the container log
showed the server coming up right at the boundary.

- Renovate's `customManager` now matches every `# renovate:` annotation in
the repo (8 of 8, previously 5). The regex anchored `default:` to the line
*immediately* after the comment, so three inputs that carried a `type:`
Expand Down
Loading