Skip to content

Add release_branch field to channel dev version#590

Open
bschwedler wants to merge 12 commits into
mainfrom
workbench-release-branch
Open

Add release_branch field to channel dev version#590
bschwedler wants to merge 12 commits into
mainfrom
workbench-release-branch

Conversation

@bschwedler

Copy link
Copy Markdown
Contributor

Adds a release_branch field to ImageDevelopmentVersionFromProductChannel so
the Workbench dailies branch can be configured directly in bakery.yaml instead
of relying on the BAKERY_WORKBENCH_RELEASE_BRANCH environment variable.

The field threads through all get_product_artifact_by_channel() call sites.
When a version is supplied via --dev-spec, the YYYY.MM segment is extracted
automatically and used as the release branch. When only release_branch is set
in the dev spec, it is assigned directly.

Also adds a release-branch input to bakery-build-native.yml so product repo
workflows can override the branch at dispatch time.

@zachhannum zachhannum left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown

Test Results

1 709 tests   1 707 ✅  7m 6s ⏱️
    1 suites      0 💤
    1 files        2 ❌

For more details on these failures, see this check.

Results for commit 943929e.

♻️ This comment has been updated with latest results.

@ianpittwood ianpittwood left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated to this change specifically, but the dev spec appears to not work against any daily build that isn't exactly what is current. This makes it effectively the same as the previous daily build implementation, doesn't it?

❌ Dispatched version '2026.06.0-daily+173.pro12' does not match manifest version '2026.06.0-daily+183.pro2' at 'https://dailies.rstudio.com/rstudio/2026.06/index.json'. The upstream manifest has not propagated the dispatched build yet.

I did ensure using something like "release_branch": "golden-wattle" works as expected.

@@ -295,5 +298,6 @@ def get_product_artifact_by_channel(
raise ValueError(f"Channel {channel} is not supported for product {product}.")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a warning about release_branch being ineffectual if product != ProductEnum.WORKBENCH. Not sure the best place to put the check. I guess and release_branch != "latest" could be another part of the if statement to make it work here?

@bschwedler

Copy link
Copy Markdown
Contributor Author

Unrelated to this change specifically, but the dev spec appears to not work against any daily build that isn't exactly what is current. This makes it effectively the same as the previous daily build implementation, doesn't it?

❌ Dispatched version '2026.06.0-daily+173.pro12' does not match manifest version '2026.06.0-daily+183.pro2' at 'https://dailies.rstudio.com/rstudio/2026.06/index.json'. The upstream manifest has not propagated the dispatched build yet.

I intentionally put this safety net #565. When implementing, I felt that failing louder early would be good.

The alternatives were:

  • Replacing the version string in the URL
  • Having it 404 later in the build process

Do you have a preference for how this would look?

@ianpittwood

Copy link
Copy Markdown
Contributor

Unrelated to this change specifically, but the dev spec appears to not work against any daily build that isn't exactly what is current. This makes it effectively the same as the previous daily build implementation, doesn't it?

❌ Dispatched version '2026.06.0-daily+173.pro12' does not match manifest version '2026.06.0-daily+183.pro2' at 'https://dailies.rstudio.com/rstudio/2026.06/index.json'. The upstream manifest has not propagated the dispatched build yet.

I intentionally put this safety net #565. When implementing, I felt that failing louder early would be good.

The alternatives were:

* Replacing the version string in the URL

* Having it 404 later in the build process

Do you have a preference for how this would look?

It makes sense to me to check if what's posted on daily is behind what the user is attempting to build, but if the user is attempting to build something older, I don't think it should fail. Does that make sense?

To me if you can't build an arbitrary version, then we only added a complex entry to the original dev version retrieval logic. If there needs to be a pre-check, I would suggest making a request against the resolved URL. If it returns 4XX/5XX, then we error.

Remove BAKERY_WORKBENCH_RELEASE_BRANCH import-time env var.
WORKBENCH_DAILY_URL is now a {release_branch} template string
formatted at runtime by ReleaseChannelPath.get().
Make version optional; require at least one of version or
release_branch via model_validator. Adds release_branch for
Workbench daily builds targeting a non-latest branch.
Pass release_branch through all get_product_artifact_by_channel()
call sites. Defaults to 'latest' when not set.
When version is set, derive release_branch from its YYYY.MM segment
so the Workbench daily URL targets the correct branch. When only
release_branch is set, assign it directly. version always takes
precedence.
Includes release_branch in the jq-assembled dev-spec JSON when set.
Supports branch-only specs (no pinned version) for scheduled
Workbench preview builds.
When a `version_override` is supplied to `ReleaseChannelPath.get()`,
substitute the override version into the channel's manifest URL (for
Connect/Workbench) or template URL (for PPM) and verify the artifact
exists via HTTP HEAD before returning it. Compute `channel_latest` by
comparing the override against the channel-head version with exact
string equality (semver build-metadata-ignoring equality is wrong here).

Propagate `channel_latest` through `ReleaseChannelResult` →
`ImageDevelopmentVersionFromProductChannel.resolved_channel_latest` →
`ImageVersion.metadata["channel_latest"]` → `ImageTarget.is_channel_latest`.

Suppress floating channel tags (`daily`, `daily-ubuntu-24.04`, etc.) for
non-head builds by adding a `CHANNEL_LATEST` filter to `TagPatternFilter`
and checking it unconditionally before the `ALL` short-circuit in the
tag-pattern loop.

New errors: `ArtifactNotAvailableError` (HEAD probe failed) and
`VersionSubstitutionError` (version string not found in manifest URL).
Both are plain `Exception` subclasses to avoid being swallowed by
existing per-OS `ValueError`/`RequestException` catches.
ArtifactNotAvailableError and VersionSubstitutionError were added in the
previous commit but not caught by the build CLI's exception handler,
causing raw tracebacks instead of clean error messages.

Add both to the existing except clause alongside DispatchVersionMismatchError,
and add two CLI tests mirroring the existing mismatch test.

@ssinnott ssinnott left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

Validate CalVer format in DevBuildSpec.version so a non-CalVer input
fails at the Pydantic boundary with a clear message instead of raising
an uncaught ValueError from _extract_calver_minor. Add a corresponding
test.

Remove dead bakery_yaml.write_text() block from _make_image test
helper — the file was written but never read; BakeryConfigDocument was
constructed from the dict directly.

Remove magic tag-pattern count assertions from the channel_latest
image-target tests — the meaningful behavioral assertions above them
(which tags emit vs. don't) are sufficient coverage.
Remove DispatchVersionMismatchError from the CLI error handler and its
test — no production path raises it after the URL-substitution rewrite.
The exception class is preserved in errors.py for external callers.

Pass version_override in get_url_by_os so overridden dev builds return
the correct artifact URL rather than silently fetching the channel head.

Fix misleading CHANNEL_LATEST comment in image_target.py to accurately
describe that ALL-only patterns skip the check and always emit.

Document the plain-text assumption for PPM channel_latest detection.
@bschwedler bschwedler force-pushed the workbench-release-branch branch from 084cd49 to 943929e Compare June 11, 2026 15:12
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.

4 participants