fix(ci): complete ext-workflow cutover (PR 2.5/6)#57
Merged
Conversation
remote.Push was ErrUnsupported in PR 1+2; this completes the remote backend so `phpup build ext --registry ghcr.io/<owner>` can publish ext bundles directly (PR 2's deferred follow-up). Design: Ref gains a Tag field used by remote push only. OCI remotes are tag-addressed for writes (the registry computes the digest from the manifest; callers cannot supply one), so remoteStore.Push needs a tag and errors out with a clear message if Ref.Tag is empty. layoutStore ignores Ref.Tag because its Push writes by index annotation, not by tag. Byte-identity with the existing `oras push` command in build-php-core.yml / build-extension.yml is a hard requirement: - layer 0: application/vnd.oci.image.layer.v1.tar+zstd (bundle) - layer 1: application/vnd.buildrush.meta.v1+json (meta sidecar) - manifest annotation org.opencontainers.artifact.type set to application/vnd.buildrush.php-core.v1 for php-core and application/vnd.buildrush.php-ext.v1 for php-ext-* Keeping these strings byte-identical with the CI path means cosign and downstream OCI clients see remoteStore-pushed bundles as indistinguishable from oras-pushed ones. Tests round-trip Push+ResolveDigest+Fetch through the in-process pkg/registry and assert both the artifact-type annotation and the layer media types match the CI contract. Known follow-up: internal/build/sidecar.go's SeedCore still builds its OCI image by hand via buildTwoLayerImage; it could now delegate to remoteStore.Push. Left as-is to keep this task's scope tight.
Follow-up from PR 2 Task 5 code review. Drop the ad-hoc map[string]any parser in favour of the existing typed catalog API so the extension-schema shape lives in one place. Behavior is byte-identical — .build_deps.linux is joined with spaces exactly as before.
Flagged in PR 2 Task 5 code review as Important #1. If a sidecar lifecycle aborts before its deferred stop (panic, outer timeout, SIGKILL), the distribution:3 container and its docker network linger and can block future runs. Label all sidecar-created containers + networks with buildrush.phpup.sidecar=1, and at the top of Start, sweep anything matching that label. Opportunistic: errors from the sweep are ignored — either the zombies didn't collide with the new run (fine), or docker is broken enough that the subsequent Start will report its own clear error. Gated TestSidecar_SweepsZombiesOnStart_Real seeds a fake zombie container + network, calls Start, and asserts the zombie is gone.
MatrixCell gains a CoreDigest string field populated only for Kind=="ext". ExpandExtMatrix reads the already-resolved core digests (by php_abi+os+arch key) and sets CoreDigest on each ext cell. Emitted in the matrix JSON as `core_digest` (omitempty so php/tool cells stay unchanged). plan-and-build.yml passes `matrix.core_digest` as `php_core_digest` input to build-extension.yml; the workflow declares the input but doesn't yet consume it (Task 5 does the phpup build ext rewire). No behavior change for the current CI pipeline — build-extension.yml still uses oras push unchanged. This commit is purely preparatory wiring for Task 5.
Mirrors PR 2 Task 6's pattern for build-php-core.yml. Builder script stays unchanged; phpup build ext docker-wraps it and writes into ./build/ext/<slug>/. A "Stage bundle for publish" step cp's the emitted bundle.tar.zst + .sha256 + meta.json to /tmp/ so the existing Push to GHCR, Sign bundle, and Upload artifact steps read from the same paths -- preserving the digest job-output contract byte-for-byte. inputs.php_core_digest now required (previously declared as optional stub by PR 2.5 Task 4). plan-and-build.yml already passes matrix.core_digest from the planner, so the CI wiring closes. Completes the deferred ext-workflow work from PR 2.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes the four follow-up items explicitly deferred from PR 2 (#56). Ships the remaining plumbing so
phpup build extworks against remote GHCR and.github/workflows/build-extension.ymluses the same rewire pattern Task 6 of PR 2 established forbuild-php-core.yml.Changes
registry.remoteStore.Pushimplemented (previouslyErrUnsupported). Wrapsgo-containerregistry/pkg/v1/remote.Writewith byte-identical media types and artifact-type annotations to whatoras pushemits today.Refgains aTagfield used by remote push only (layout ignores it).loadExtBuildDepsrefactor — drops the ad-hocmap[string]anyparser in favor of the existing typedcatalog.LoadExtensionSpecAPI.defaultSidecarLifecycle.Startnow sweeps stale containers + networks labeledbuildrush.phpup.sidecar=1before creating fresh ones. Gated integration test seeds a fake zombie and verifies it's swept.planner.MatrixCell.CoreDigestthreading — populated during ext-matrix expansion from already-resolved php-core digests; emitted in matrix JSON ascore_digest; plumbed throughplan-and-build.ymlasphp_core_digest: ${{ matrix.core_digest }}.build-extension.ymlrewired to callphpup build extvia the sameoci-layout+cpstaging shim pattern used bybuild-php-core.yml. Digest job-output contract preserved byte-for-byte; downstream Push to GHCR, Sign bundle, and Upload artifact steps unchanged.Test plan
make checkgreen end-to-end locally (full gate including docker-backed local-ci smoke).go test ./internal/registry/... ./internal/build/... ./internal/planner/...— all pass with coverage unchanged or improved.cmd/planneragainst real./catalog+./bundles.lock→ 172 ext cells withcore_digestpopulated; 10 PHP cells without (as expected viaomitempty).Artifact parity
The remote Push's media types and artifact-type annotation were extracted verbatim from the existing
oras pushcommands inbuild-php-core.yml:104-106andbuild-extension.yml:85-87. Clients and signing tools should see byte-identical artifacts regardless of whether phpup or oras was the push origin.Notes
//nolintsite in PR 2.5 is reusing the existing G204 suppression onexecDockerfor the newsweepStaleSidecarshelper — already justified as a genuine false positive (execve without shell, argv from typed struct fields).SeedCoreininternal/build/sidecar.gostill builds its image by hand viabuildTwoLayerImage— now thatremoteStore.Pushworks, it could delegate. Left as-is per Task 1's scope; clean follow-up for a future DRY pass.