Docs

How images stay current

Rebuilding an image and upgrading its application are different operations, so they run on separate loops. Neither waits on the other, and neither needs a human.

1 · Six-hour rebuilds

build.yml rebuilds the complete catalog every six hours. It keeps the currently pinned application version but consumes current Wolfi packages and toolchains — so an upstream glibc or OpenSSL fix reaches every image without anyone changing a line of code.

For a source-built image the pipeline is:

verified source archive
  → native x86_64 and ARM64 Melange packages
  → production and dev Apko images
  → smoke test and production-image Grype scan
  → multi-architecture publish
  → Cosign signature, SPDX SBOM, and SLSA provenance
  → verification and catalog artifacts

Pull requests build and test but never publish. Only trusted non-PR runs push to GHCR.

2 · Application-version updates

update-versions.yml checks source-built applications daily against a declarative registry (versions.yaml). It updates the version, verifies the upstream artifact checksum, resets the epoch, opens a pull request, and enables auto-merge once required checks pass.

Major-version pins stop unattended breaking upgrades. When a new major appears the workflow can open an issue for explicit review rather than bumping across it.

For package-based images:

  • Rolling Wolfi packages (nginx-mainline, apache2, sqlite, bun) advance through the six-hour rebuild.
  • Versioned families (Python, Go, Node.js, .NET, Java, PostgreSQL) get patch releases through rebuilds, while update-wolfi-packages.yml opens PRs when the package family itself must change.

3 · Transitive dependency patches

patch-go-deps.yml scans published Go binaries every six hours and proposes targeted module updates for fixable vulnerabilities. It preserves existing security pins, harmonizes related module families, and for dependency-sensitive applications probes each candidate fix against a real compile, keeping only those that still build.

patch-deps.yml does the same for Rails gems, Qdrant Rust crates, Keycloak Maven dependencies, and bundled Java archives in OpenSearch and Keycloak.

Generated changes land as automated pull requests — the normal image build is the integration gate before auto-merge. Cassandra, Solr, and Pulsar bundled-JAR findings are report-only until their tightly coupled dependency families get an explicit compatibility review.

4 · Guardrails

Automation that fails silently is worse than none, so each of these turns an invisible problem into a failed build.

CheckRunsEnforces
Auto-update coverageEvery buildAll 96 images have exactly one live update mechanism — an image cannot be silently frozen.
Catalog validationEvery buildThe published catalog and the build matrix can never drift apart.
Workflow lintWorkflow changesActionlint and ShellCheck, so a shell error cannot reach a scheduled run on main.
Branch auto-updatePush to main, every 30 minKeeps auto-merge pull requests from stalling under strict branch protection.
RetentionWeeklyPrunes untagged and expired dated versions. Deletion is dry-run unless explicitly enabled.