You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The current `ci.yml` violates the stated PR self-containment design from `docs/superpowers/specs/2026-04-23-local-ci-unification-design.md` and `docs/superpowers/specs/2026-04-20-bundle-schema-and-rollout-design.md`. PRs that bump a bundle version cannot pass the `smoke-action` checks because `smoke-action` resolves bundles through the committed `bundles.lock` + GHCR, and PR runs do not publish bundles to GHCR or update `bundles.lock`.
A pipeline cell builds PHP-core → builds extensions → runs fixtures against the just-built artifacts in its own OCI layout. GHCR is touched only by the `publish` job after the full matrix passes on `main`.
PR CI produces a self-consistent artifact set: every runtime assertion the PR introduces is validated against a bundle that the PR itself published.
Current implementation:
`pipeline` job builds bundles in-cell and tests fixtures against them in a local oci-layout (matches design).
`pipeline` Step `Upload oci-layout artifact` is gated on `if: github.ref == 'refs/heads/main'` (.github/workflows/ci.yml:117) — PR runs build the artifacts then discard them.
`smoke-action` builds phpup from PR HEAD, invokes `uses: ./` which runs `phpup install`. `phpup install` reads the committed `bundles.lock` + fetches from GHCR. No way to point it at a PR-local layout.
Open any PR that bumps a PECL extension version in `catalog/extensions/*.yaml`. `smoke-action` cells will fail with:
```
resolve: extension for PHP 8.4 linux/x86_64/nts not found in lockfile
```
(see PR #76 — runs $(gh pr view 76 --json url -q .url) — for a concrete instance.)
Proposed fix
Infrastructure for the fix already exists. `phpup` honors `PHPUP_REGISTRY=oci-layout:` and `PHPUP_LOCKFILE=` env overrides. `internal/testsuite/runner.go:writeLayoutLockfileOverride` already synthesizes a lockfile JSON from an oci-layout — but it is unexported and inaccessible from a CI shell step.
Three small changes:
ci.ymlpipeline job: drop the `if: github.ref == 'refs/heads/main'` on the `Upload oci-layout artifact` step. PR runs upload per-cell layouts (cost: artifact storage per PR run, retention 7d already set).
New phpup subcommand: `phpup internal lockfile-from-layout --layout oci-layout: --out ` — a thin wrapper that calls the existing logic in `internal/testsuite/runner.go:writeLayoutLockfileOverride` (the function may need to be moved or have a sibling exported).
ci.ymlsmoke-action job: before `uses: ./`, download the matching `oci-layout---` artifact, run the new subcommand to synthesize a lockfile override, and set `PHPUP_REGISTRY=oci-layout:...` and `PHPUP_LOCKFILE=...` env vars on the action invocation.
After this, `smoke-action` validates the public action surface against the PR's own bundles, end-to-end, with no GHCR roundtrip. Matches the design.
Out of scope (deliberate)
Promoting PR-local bundles to GHCR (the `publish` job remains main-only — that's intended).
Changing the smoke-action matrix shape.
Touching `pipeline`'s test execution (already self-contained).
Why a separate slice
Discovered while working on #38 / PR #76 (redis PECL bump). The fix is a CI workflow change cross-cutting all bump PRs, not specific to redis — better landed as its own slice with its own review and isolated risk surface.
Summary
The current `ci.yml` violates the stated PR self-containment design from `docs/superpowers/specs/2026-04-23-local-ci-unification-design.md` and `docs/superpowers/specs/2026-04-20-bundle-schema-and-rollout-design.md`. PRs that bump a bundle version cannot pass the `smoke-action` checks because `smoke-action` resolves bundles through the committed `bundles.lock` + GHCR, and PR runs do not publish bundles to GHCR or update `bundles.lock`.
Design intent vs. current behavior
Design (
2026-04-23-local-ci-unification-design.md§"No cross-job GHCR roundtrip"):Design (
2026-04-20-bundle-schema-and-rollout-design.md§goals):Current implementation:
.github/workflows/ci.yml:117) — PR runs build the artifacts then discard them.Repro
Open any PR that bumps a PECL extension version in `catalog/extensions/*.yaml`. `smoke-action` cells will fail with:
```
resolve: extension for PHP 8.4 linux/x86_64/nts not found in lockfile
```
(see PR #76 — runs $(gh pr view 76 --json url -q .url) — for a concrete instance.)
Proposed fix
Infrastructure for the fix already exists. `phpup` honors `PHPUP_REGISTRY=oci-layout:` and `PHPUP_LOCKFILE=` env overrides. `internal/testsuite/runner.go:writeLayoutLockfileOverride` already synthesizes a lockfile JSON from an oci-layout — but it is unexported and inaccessible from a CI shell step.
Three small changes:
ci.ymlpipelinejob: drop the `if: github.ref == 'refs/heads/main'` on the `Upload oci-layout artifact` step. PR runs upload per-cell layouts (cost: artifact storage per PR run, retention 7d already set).phpupsubcommand: `phpup internal lockfile-from-layout --layout oci-layout: --out ` — a thin wrapper that calls the existing logic in `internal/testsuite/runner.go:writeLayoutLockfileOverride` (the function may need to be moved or have a sibling exported).ci.ymlsmoke-actionjob: before `uses: ./`, download the matching `oci-layout---` artifact, run the new subcommand to synthesize a lockfile override, and set `PHPUP_REGISTRY=oci-layout:...` and `PHPUP_LOCKFILE=...` env vars on the action invocation.After this, `smoke-action` validates the public action surface against the PR's own bundles, end-to-end, with no GHCR roundtrip. Matches the design.
Out of scope (deliberate)
Why a separate slice
Discovered while working on #38 / PR #76 (redis PECL bump). The fix is a CI workflow change cross-cutting all bump PRs, not specific to redis — better landed as its own slice with its own review and isolated risk surface.