Skip to content

Dispatched image-version mismatches bakery's stream-derived version #527

@bschwedler

Description

@bschwedler

Problem

bakery ci matrix --image-version <X> can return an empty matrix when the product dispatcher and bakery disagree about the current version of a stream-style dev version.

Chain:

  1. Product CI builds <X> (e.g. 2026.05.0-dev+130-gSHA).
  2. Product CI uploads artifacts to the CDN (asynchronous).
  3. Product CI dispatches development.yml in the images repo with version=<X>.
  4. images-* workflow runs bakery ci matrix --image-version <X>.
  5. Bakery's stream dev version resolution calls get_product_artifact_by_stream(...) (posit-bakery/posit_bakery/config/image/dev_version/stream.py:54), which hits the CDN. While step 2 propagates, that call returns the previous version.
  6. Matrix ImageVersion.name<X>--image-version filter doesn't match → empty matrix → workflow fails.

Two observed failure modes:

  • Dispatched version has a build number + commit SHA, bakery's rendered version has a different one.
  • Dispatched version is just YYYY.MM — matches too broadly or nothing at all.

Proposed fixes

1. Override semantics on the existing --image-version flag

When --dev-versions=only and --image-version <X> are both set, treat <X> as the authoritative version for stream-style dev versions: skip the CDN version fetch and use <X> as the ImageVersion.name. The matrix is then guaranteed to contain <X> because it was provided, not discovered.

--dev-versions --image-version Behavior
exclude (default) any / unset unchanged — filter release versions only
include any / unset unchanged — fetch dev versions, filter normally
only unset unchanged — fetch dev versions from CDN
only set to a full version override: skip CDN fetch, use --image-version as the dev version's name
only set to a prefix (e.g. 2026.05) error — override mode requires a full version

Why ride on the existing flag rather than add --dev-version: the two flags already co-occur in every dev-build workflow (bakery-build-native.yml, bakery-build.yml). The combination uniquely signals "this run is for a specific dev version," so the CDN fetch is redundant when both are present. No new CLI surface, no workflow changes.

Ambiguity guard

If override is set and the materialization finds more than one stream dev version in scope (e.g. an image declares both daily and preview dev versions and --dev-stream wasn't specified), error:

"--image-version with --dev-versions=only is ambiguous: image <name> has dev versions for streams [daily, preview]. Add --dev-stream to disambiguate."

URL resolution unchanged

Per-OS URL lookup still happens via _resolve_os_urls()get_product_artifact_by_stream(...). If the CDN doesn't yet have an artifact for <X> on a given OS, the existing log-and-skip behavior applies: that OS is excluded from the build with a clear warning. This is failure-loud rather than failure-silent — much better than "the version doesn't exist anywhere in bakery."

Files touched

File Change
posit-bakery/posit_bakery/config/image/dev_version/stream.py add version_override field, branch in get_version()
posit-bakery/posit_bakery/config/config.py add dev_version_override on BakerySettings; thread into config materialization with the ambiguity guard
posit-bakery/posit_bakery/cli/ci.py, cli/build.py, cli/get.py derive override from (dev_versions == ONLY) and image_version and validate it's a full version
posit-bakery/test/... unit tests for stream override + CLI plumbing

2. Dispatchers stop hitting upstream for the version

  • rstudio/package-manager/.github/workflows/ci.yml: drop --from-api from scripts/release/version.py in the dispatch path. On a tag push, ${{ github.ref_name }} (minus the leading v) is the version. For pushes to main, read full_version from the same local artifact publish produced.
  • posit-dev/connect/.github/workflows/ci.yml: already correct — reads primary-version from packaging/build/latest-packages.json.

3. Optional --image-version-strict

Less urgent once the override semantics in (1) ship — the matrix is then guaranteed to contain the dispatched version, so silent-empty-matrix can't happen for dev builds. Still useful as a defense for release/prod paths where prefix matching can over-match.

References

  • posit-bakery/posit_bakery/config/image/dev_version/stream.py:43-94
  • posit-bakery/posit_bakery/config/config.py:252 (version_matches)
  • posit-bakery/posit_bakery/cli/ci.py:128
  • Dispatchers: rstudio/package-manager/.github/workflows/ci.yml:1225-1265, posit-dev/connect/.github/workflows/ci.yml:2720-2755, posit-dev/connect/tools/release/publish_release.py:274-301

Metadata

Metadata

Assignees

Labels

cvp:0Necessary projects we are undertaking that don’t directly deliver value to the customerdockerRelated to container images we producetdp:1The individual working on it notices.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions