Skip to content

feat: add SOCI indexing plugin and bakery ci publish orchestrator#555

Draft
ianpittwood wants to merge 28 commits into
mainfrom
feature/soci-images
Draft

feat: add SOCI indexing plugin and bakery ci publish orchestrator#555
ianpittwood wants to merge 28 commits into
mainfrom
feature/soci-images

Conversation

@ianpittwood
Copy link
Copy Markdown
Contributor

Summary

  • Adds a new soci builtin plugin that wraps soci convert / soci push and an in-module ctr image pull helper to materialize images in containerd. The plugin probes containerd namespaces (defaultmoby) and supports both non-standalone (default) and --standalone modes via SociOptions in bakery.yaml.
  • Splits OrasMergeWorkflow into three composable primitives (OrasIndexCreateWorkflow, OrasIndexCopyWorkflow, OrasIndexCleanupWorkflow) and rebuilds the existing merge workflow on top of them to preserve back-compat with bakery oras merge.
  • Adds bakery ci publish, which composes oras index-create → optional SOCI convert (gated by --enable-soci) → oras index-copy → cleanup. bakery ci merge is preserved as a thin alias that delegates with --no-enable-soci.
  • Adds a setup-soci composite action and wires an enable-soci workflow input + Publish step into bakery-build-native.yml. bakery-build.yml (QEMU) is explicitly deferred with an in-file note since it has no merge phase to interleave SOCI into.

The implementation follows the spec at docs/superpowers/specs/2026-05-18-soci-indexing-design.md (local-only) and the task-by-task plan at docs/superpowers/plans/2026-05-18-soci-indexing.md (local-only).

Test plan

  • Full bakery test suite passes (1587 tests, no regressions in oras / dgoss / ci suites)
  • `bakery soci --help` and `bakery soci convert --help` show the expected flags
  • `bakery ci --help` lists both `merge` (back-compat alias) and `publish` (new orchestrator)
  • Pre-commit hooks clean across all changed files
  • Manual: build a small image, run `bakery ci publish --enable-soci --dry-run` and confirm the soci convert / push commands are produced as expected
  • Manual: full run against a single image (e.g. `connect-content-init`) with `enable-soci: true` in a sibling repo's workflow — verify the published manifest via `oras manifest fetch` and confirm SOCI metadata is present
  • Manual: confirm layer-digest stability across `soci convert` (spec verification item Implement a configuration standard for Posit image builds #3)
  • Per-product opt-in (e.g. flipping `tool: soci, enabled: true` on a Connect image and `enable-soci: true` in `images-connect`'s production workflow) lands as a follow-up PR in that repo, not here.

🤖 Generated with Claude Code

ianpittwood and others added 26 commits May 28, 2026 16:52
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Walk candidate_namespaces in order, retrying ctr pull on the canonical
"image not found" error and short-circuiting on any other failure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When `standalone=True`, `SociConvertWorkflow.run()` skips the `ctr image
pull` and `soci push` steps and only invokes `soci convert --standalone`;
the caller is responsible for pushing the resulting OCI layout via ORAS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces the stub execute() with the full orchestration loop: resolves
SociOptions per target, skips disabled targets with a skipped=True
artifact, and runs SociConvertWorkflow for enabled ones. Introduces the
module-level get_soci_options_for_target helper (merges variant-level
over image-version-parent-level options).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the stub register_cli() in SociPlugin with a full Typer
command: bakery soci convert <metadata-file...>. Ingests build-metadata
JSON files, resolves them into ImageTargets, builds a source_refs map
from each target's latest build metadata, and invokes plugin.execute()
+ plugin.results().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add OrasIndexCreateResult and OrasIndexCreateWorkflow alongside the
existing OrasMergeWorkflow as the first composable primitive for the
upcoming refactor (Tasks 13-16). OrasMergeWorkflow is unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add OrasIndexCopyWorkflow and OrasIndexCopyResult alongside
OrasIndexCreateWorkflow. The copy workflow fans out a temp-registry
source ref to all configured destinations, grouping tags by destination
repo (same logic as OrasMergeWorkflow.run step 2). OrasMergeWorkflow is
unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the inline create/copy/delete logic in OrasMergeWorkflow.run()
with calls to OrasIndexCreateWorkflow, OrasIndexCopyWorkflow, and
OrasIndexCleanupWorkflow, while preserving the existing public API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds `bakery ci publish` which composes oras index-create → optional
soci-convert → oras index-copy → cleanup phases. The existing `merge`
command is untouched; Task 18 will make it a thin alias for publish.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Task 18: Convert the existing bakery ci merge command to a thin delegating
alias for bakery ci publish with --no-enable-soci. This consolidates the
merge/publish orchestration logic while preserving backward compatibility.

Changes:
- Replace merge function body with delegation to publish(enable_soci=False)
- Keep merge signature unchanged for back-compat (same params as before)
- Update publish to emit logging that merge tests expect
- Update merge feature test to pass --temp-registry (required by publish)
- Update merge test fixture to mock OrasIndexCreateWorkflow, etc.
- Add new unit test verifying merge calls publish with enable_soci=False

All 158 existing tests pass; new test validates the delegation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds two regression tests asserting that when a user explicitly sets a
field to its default value (scalar default False, list default empty),
self still wins over `other` in `update()`. These guard the
`model_fields_set`-based check introduced when the default_factory bug
was fixed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@ianpittwood ianpittwood force-pushed the feature/soci-images branch from db0ba57 to e779f7d Compare May 28, 2026 22:52
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 28, 2026

Test Results

1 623 tests   1 623 ✅  7m 56s ⏱️
    1 suites      0 💤
    1 files        0 ❌

Results for commit 87e9953.

♻️ This comment has been updated with latest results.

…MERGE)

Temporary commit to make end-to-end CI testing of SOCI work. The
new setup-soci composite action only exists on this branch, so any
sibling-repo workflow that calls bakery-build-native.yml@feature/soci-images
needs the internal setup-soci@main reference to resolve against this
branch instead. Updates the other setup-* references for consistency
so the test run exercises exactly the bakery + setup actions from
this branch.

Drop this commit (and the parallel commits in product repos) once
testing is complete and before merging the PR.
The CI runner reports a fixed terminal width of 80 columns and emits
rich-styled help output, which causes typer/rich to wrap long option
names like \`--enable-soci/--no-enable-soci\` across rows with
embedded ANSI escapes. That defeats substring assertions like
\`"--enable-soci" in result.stdout\` even though the option is present.

Pass \`COLUMNS=200\`, \`TERM=dumb\`, and \`NO_COLOR=1\` via the
CliRunner's \`env\` argument so the rendered help is wide enough to
keep flag names on a single line and unstyled enough that no escape
codes get interleaved with the option text. Applied to all four help-
output assertions in \`test_ci_publish.py\` and \`test_cli.py\`.

Fixes the \`test_publish_command_flags_present\` failure on PR #555 CI.
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.

1 participant