This guide covers common maintenance tasks shared across the Posit container image
repositories (images-connect, images-workbench, images-package-manager). For
product-specific context, examples, and CI workflow details, see CONTRIBUTING.md in
the product repository.
The product-release.yml workflow creates versions automatically when a product releases. For hotfixes or when the dispatch fails, use the bakery CLI directly.
See Step 3: Create an image version in the bakery getting-started guide for the full command reference.
The product-release.yml shared workflow handles automatic releases:
- If the version's edition (e.g.,
2026.05) already exists inbakery.yaml, it patches it withbakery update version. - If the edition is new, it creates it with
bakery create version, marking it--mark-latestif it is newer than the current latest edition.
After any version create or update, re-render templates:
bakery update files --image-name <name> --image-version <edition>Adding an image means a new entry in bakery.yaml and a new template/ directory.
Follow the existing images in the repo as your model.
See Step 2: Create an image for the full bakery CLI walkthrough.
When a new image name is added:
- Update the relevant CI caller workflows to include it in the build scope.
- Add goss tests in
template/test/goss.yaml.jinja2. - If the image pushes to a separate registry namespace, add a registry entry in
bakery.yaml.
# Scaffold the image entry and template directory
bakery create image <image-name>Bakery resolves dependency versions (Python, R, Quarto) at build time using
dependencyConstraints in bakery.yaml. A constraint of latest: true causes bakery
to query upstream registries for the current latest compatible version.
See DependencyConstraint in the configuration reference for the full schema.
To pin a specific version instead of tracking latest, replace the constraint with an
explicit dependencyVersions list for the relevant image version. See
DependencyVersions.
UV availability: see Footguns before adding a new Python minor version.
Update older versions when a base image or system package receives a Common Vulnerabilities and Exposures (CVE) fix, or when a shared template change needs to apply retroactively.
-
Edit the template in
template/. Never edit the rendered file in the version directory. -
Re-render:
bakery update files --image-name <name> --image-version <edition>. -
Build and test locally:
bakery build --image-name <name> --image-version <edition> bakery dgoss run --image-name <name> --image-version <edition>
-
Open a pull request (PR) that includes both the template change and the re-rendered version directory.
Do not backport cosmetic changes, new feature additions, or non-security dependency upgrades. Backports increase maintenance surface. Reserve them for security fixes and regressions.
-
Never edit rendered files. Files in version directories (e.g.,
<image>/<edition>/Containerfile.<os>.<variant>) are generated from templates.bakery update filessilently overwrites any edits there. Always edit thetemplate/files. -
Never work directly on
main. Multiple CI sessions may be running concurrently. Use a branch. For changes spanning multiple repos, use a git worktree per repo so each change is isolated frommain. -
Python version not yet in UV. When a new CPython minor version is released, there is a lag before UV's managed Python manifest includes it.
bakery buildfails with auv python installerror. Check UV's download-metadata.json to confirm availability before adding the version. -
Stale UV base image cache. Even after UV upstream adds a new Python version, a cached builder layer from a previous run might not know about it. If a build fails on
uv python installdespite the version being in the manifest, clear the cache:bakery clean cache-registry ghcr.io/posit-dev
The
clean.ymlworkflow removes caches older than 14 days on a schedule. -
Version format mismatch. Product repos dispatch with raw git-describe versions (e.g.,
v2026.03.0-473-g072bb6fd1f). Bakery normalizes these to semver-with-metadata (e.g.,2026.03.0-dev+473-g072bb6fd1f). Ifbakery ci matrixproduces an empty matrix after a dispatch, the formats did not align. The shared workflows strip a leadingvautomatically. Check the rest of the version string against bakery's normalization.
bakery ci matrix supports --base-ref <ref> and --changed-files-from <file|-> to emit
only the matrix entries affected by a PR's changed files. This keeps PR CI fast: a template
change builds only the images whose templates changed; a version-directory change builds only
that version.
This filtering applies to PR builds only. Push-to-main, scheduled, and release builds
call bakery ci matrix without --base-ref, so they always build the full matrix.
After ignoring Markdown (*.md) paths, changed files are classified as follows:
| Changed path | What builds |
|---|---|
bakery.yaml / bakery.yml or .github/workflows/** |
Full matrix (fail-safe) |
<image>/template/** |
That image's dev versions (if any are declared) |
<image>/<version-subpath>/** |
That release version only |
| An image-root file or unrecognized subdir under an image | That image's release versions (fail-safe) |
Matrix image (e.g. connect-content) |
Latest matrix slice + dev versions if declared |
| Anything else not attributable and not ignored | Full matrix (fail-safe) |
Because per-image build jobs may not run on docs-only PRs, branch protection rules should
require the always-green Build/Test result gate job rather than individual build jobs.
The gate job is defined in bakery-build-pr.yml and always runs, even when no images need
to be built.
1. Find the failing run:
gh run list -R posit-dev/<product-repo>2. View the run to see which job failed (matrix, build-amd64, build-arm64,
merge, readme):
gh run view <run-id> -R posit-dev/<product-repo>3. Read the failed logs:
gh run view <run-id> -R posit-dev/<product-repo> --log-failed4. Common failure modes:
| Failure | Symptom | Fix |
|---|---|---|
| Python version not in UV | uv python install fails — "no managed Python" |
Check UV's download-metadata.json; wait or pin |
| Stale UV cache | Same error but version is in manifest | bakery clean cache-registry ghcr.io/posit-dev |
| Goss test timeout | Container exits before goss probes | Increase wait: in the image's options block in bakery.yaml |
| Registry auth | Login step fails | Check DOCKER_HUB_ACCESS_TOKEN (Docker Hub) or AWS_ROLE + id-token: write (Amazon ECR) |
| ARM64 runner unavailable | build-arm64 job queued but never starts |
Re-run the job; capacity usually clears |
| Empty matrix after dispatch | bakery ci matrix returns [] |
Dispatched version format didn't match bakery normalization; inspect image-version input |
Dev build pushed without -preview |
Release version matches current daily dev-channel version | Known issue (#553); check bakery ci merge inputs |
For the shared workflow reference (inputs, secrets, flow diagrams), see CI.md. For the cross-repo dispatch chain, see CI_CROSS_REPO_WORKFLOWS.md.