Skip to content

feat: change-aware PR builds for product images#621

Open
ianpittwood wants to merge 13 commits into
mainfrom
feat/dynamic-pr-builds
Open

feat: change-aware PR builds for product images#621
ianpittwood wants to merge 13 commits into
mainfrom
feat/dynamic-pr-builds

Conversation

@ianpittwood

@ianpittwood ianpittwood commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Closes #589

Summary

PR builds in product image repos currently rebuild the entire image × version × platform matrix on every PR, regardless of what changed. This adds change-aware filtering so PR builds only build/test the images and versions a PR plausibly affects.

bakery ci matrix gains --base-ref <ref> (and --changed-files-from <file|->). When given the PR base SHA, a pure classifier maps the PR's changed files to a filtered matrix:

  • Markdown (**/*.md) → ignored (build nothing).
  • <image>/<version-subpath>/** → build + test that release version.
  • <image>/template/** → build that image's dev versions (if declared); release version dirs are already-rendered snapshots, so a template edit only affects dev builds.
  • Matrix images (e.g. connect-content) → latest matrix slice + dev versions if declared.
  • bakery.yaml, .github/workflows/**, or anything unattributablefull matrix (fail-safe).

Filtering is PR-only: push-to-main, scheduled, and release builds call bakery ci matrix without --base-ref and are byte-for-byte unchanged.

Implementation

  • New pure classifier classify_changes + git helper git_changed_files in posit_bakery/config/changeset.py (no filesystem/network reads — fully unit-testable).
  • bakery ci matrix wires in --base-ref/--changed-files-from, resolving dev/matrix versions per-image only when the selection requires them. The no-flag path is preserved exactly.
  • bakery-build-pr.yml: fetch-depth: 0, passes the PR base SHA, derives --dev-versions per matrix entry, and adds an always-green Build/Test result gate job so docs-only PRs still satisfy branch protection.
  • Docs in CONTRIBUTING.md.

Branch protection: the required check should be Build/Test result (the per-image build jobs don't run on docs-only PRs).

Test Plan

  • Unit tests for the classifier (one per classification bucket + combinations + empty + matrix), _version_selected, and the git merge-base helper.
  • BDD scenarios for the end-to-end CLI (version-only, markdown-empty, bakery.yaml-full), isolated via temp contexts.
  • Regression: no-flag bakery ci matrix output unchanged on basic/multiplatform suites.
  • Regression test for dev-version de-duplication under --dev-versions only/include.
  • Follow-up: hermetic coverage of the matrix-image-with-dev-versions emit path (currently network-bound via dependency-constraint resolution).
  • Validate on a real PR in a product repo (images-connect) before relying on it.

🤖 Generated with Claude Code

ianpittwood and others added 11 commits June 16, 2026 11:04
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Implements the pure classify_changes(config, changed_files) -> MatrixSelection
function that maps a PR's changed file paths to image/version build selections,
with fail-safe fallback to full builds for unrecognized paths.
Wire the classify_changes classifier into `bakery ci matrix`. When neither
flag is set, behavior is byte-identical to before (full matrix). When
--changed-files-from or --base-ref is provided, the matrix is filtered to
only the images and versions touched by the PR's changed files; a repo-wide
change (bakery.yaml, workflows) falls back to the full matrix automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ected

When matrix versions are not globally excluded, the candidate list already
contains the full matrix (including latest rows). Guard the change-aware
include_matrix_latest injection so it only appends the latest slice when
matrix_versions == EXCLUDE, preventing duplicate entries. Also annotates
the `ver` parameter of _version_selected with the correct ImageVersion type.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add three pytest-bdd scenarios covering the hermetic paths of the
--changed-files-from feature: version-dir change (filtered), Markdown-only
change (empty matrix), and bakery.yaml change (full fallback). Adds a
"with changed files in {filename}:" step that writes the list to the
context dir and injects --changed-files-from into the command args.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bug 1: when --dev-versions include/only, BakeryConfig already called
load_dev_versions() at config time; the change-aware branch was calling
it again, duplicating dev entries. Guard the load with
`dev_versions == EXCLUDE` to only load when the baseline didn't.

Bug 2: for matrix images, the change-aware branch could overwrite the
full matrix candidate list with only img.versions (losing all matrix
rows). The new path always combines list(img.versions) +
to_image_versions() exactly once, and _version_selected() gates which
rows are actually emitted.

Also adds unit tests for _version_selected and a hermetic regression
test (load_dev_versions monkeypatched) for the dev-dedup bug.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ianpittwood ianpittwood force-pushed the feat/dynamic-pr-builds branch from 3a2ae89 to 124cd24 Compare June 16, 2026 19:10
@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown

Test Results

1 918 tests  +24   1 918 ✅ +24   7m 46s ⏱️ +14s
    1 suites ± 0       0 💤 ± 0 
    1 files   ± 0       0 ❌ ± 0 

Results for commit 6362d48. ± Comparison against base commit 781830e.

♻️ This comment has been updated with latest results.

@ianpittwood ianpittwood marked this pull request as ready for review June 16, 2026 21:20
@ianpittwood ianpittwood requested a review from bschwedler as a code owner June 16, 2026 21:20
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.

feat: selective PR builds

1 participant