Repository navigation
Description
Summary
The reusable build pipeline cannot complete the first pull-request build of a new image when that image has no published :edge baseline.
The image builds and is merged/tagged successfully, but .github/actions/container-size-diff unconditionally inspects the missing baseline and throws.
An expected bootstrap condition therefore becomes a fatal build failure.
Please support a genuinely missing baseline image without weakening validation of the newly built image or hiding registry/authentication failures.
The report should clearly say that comparison is unavailable because no baseline exists, while still reporting the current image's platform sizes.
Affected versions and entry points
- Observed with
philips-software/amp-devcontainer/.github/workflows/wc-build-push-test.yml@af840070c907d71ce06334ea65eded00dc3946a4(actions/v2.3.2). - The same unconditional baseline inspection is present on default branch
mainatb918131cee77028a37ac9a18fb05d0c0b46a0c4f. - Affects direct callers of the
container-size-diffcomposite action and derived repositories using the reusable build pipeline. - The failing phase is the Merge Image job, not Dockerfile compilation.
Relevant upstream source:
- Current implementation
- Composite action
- Existing Node tests
- Reusable build workflow, including the comparison and subsequent supply-chain steps
- Documented reusable build system
Reproduction
- Add a new image/flavor to a repository consuming
wc-build-push-test.yml. - Give it a new image name that has never had an
edgetag published. - Build it in a pull request with
enable-edge-tag: false, as the normal PR/merge-queue tagging policy expects. - Allow the architecture builds, manifest merge, version tagging, and digest extraction to succeed.
- The workflow then invokes size analysis with the absent
<new-image>:edgeasfrom-containerand the newly published PR image asto-container. docker manifest inspect -v <new-image>:edgefails with a missing-manifest error, and the size action terminates the merge job.
An anonymized example of the action inputs:
from-container: registry.example.invalid/my-org/fake-new-flavor:edge
to-container: registry.example.invalid/my-org/fake-new-flavor:pr-123The image names above are illustrative, not registry endpoints to contact.
A real first-build PR exhibited the following error; private registry/image names have been replaced:
ExecaSyncError: Command failed with exit code 1:
docker manifest inspect -v 'registry.example.invalid/my-org/fake-new-flavor:edge'
no such manifest: registry.example.invalid/my-org/fake-new-flavor:edge
at inspectManifest (.../container-size-diff.js)
at getSizes (.../container-size-diff.js)
at containerSizeDiff (.../container-size-diff.js)
Unhandled error: ExecaSyncError
The preceding semantic diffoci comparison also reports that the edge image is not found, but its command is already best-effort (|| true).
The subsequent size comparison is not: actions/github-script propagates the exception.
Actual behavior and impact
- A successful first image build fails solely because a previous version of that image does not exist.
- The failure occurs before subsequent SBOM, curated inventory, attestation, and verification steps in the merge job can complete.
- Integration tests depending on the successful build/publish workflow cannot proceed.
- New flavors, renamed images, newly adopted registries, and legitimately deleted/expired baselines can all hit this condition.
- Derived repositories need manual baseline provisioning or a workaround even though the reusable build system is intended to support a family of newly introduced images.
This is not a request to suppress an actual compiler, image, signature, platform, or registry failure.
Absence of the old comparison target is the specific expected condition.
Root cause
inspectManifest() executes docker manifest inspect -v through execaSync, which throws on a nonzero result.
containerSizeDiff() immediately calls getSizes(fromContainer, inspect) with no baseline-absence handling.
Consequently the current image is never inspected when the old image is absent.
The existing test suite verifies normal reports, invalid images, and platform mismatch, but does not cover a known missing baseline with a valid current image.
platformRow() already has behavior for a zero-sized platform, but a zero-sized existing image is not the same as a nonexistent image.
There is also a strict platform-set comparison, so simply changing the baseline to an empty map is not sufficient: bootstrap must be handled explicitly and separately from normal two-image comparison.
Expected behavior / acceptance criteria
- A confirmed missing
from-containermanifest does not fail the action or the reusable pipeline when the current image is valid. - The current image is still inspected and validated, including when the baseline is missing.
- A useful Markdown output is always produced for the bootstrap case, with the current image's platform sizes and an explicit explanation that the baseline does not exist.
- Previous size and percentage/delta are clearly marked unavailable, or the comparison portion is explicitly omitted; do not silently invent
0 B, a growth percentage, or a misleading successful comparison. - The normal existing-baseline report and strict platform-set validation remain unchanged.
- A missing or inaccessible current image, malformed manifest, or current image without valid platform sizes remains a hard failure.
- Baseline authentication/authorization failures, networking/timeouts, unexpected registry errors, and malformed/no-platform baseline data are not indiscriminately treated as missing images.
- Recognition of genuine manifest absence works with the relevant Docker/registry diagnostic formats; do not rely on catching every exception or treating every nonzero exit as absence.
- The PR comment remains usable in bootstrap builds and the workflow can continue to its normal supply-chain and integration-test gates.
- Existing PR versus merge-queue/release tag semantics are preserved; do not create or overwrite
edgein a PR just to manufacture a comparison target.
Implementation guidance
- Keep the fix upstream and reusable rather than requiring every derived repository to preseed an image or special-case this action.
- Preserve strict behavior in the general manifest/size reader where possible; make the permissible absence behavior specific to the baseline comparison path.
- Prefer a small, explicit representation of a missing manifest or narrowly classified inspection failure over broad
catch/continue-on-errorhandling. - Avoid globally setting
continue-on-error: true, which would hide unrelated failures and could allow misleading reports. - Keep the public action/function/output API stable unless an additive status field is genuinely necessary.
- Check the semantic-diff/artifact path for bootstrap consistency, but do not expand this into unrelated workflow refactoring.
- Update the action README, which currently states that inability to inspect either image is always fatal, and document the first-image exception.
- If the reusable-build-system documentation needs clarification, add a short bootstrap explanation rather than duplicating implementation details.
Focused regression coverage
Use the existing node:test suite and injected fake inspectors; no live registry, credentials, or container engine should be required.
Use clearly fake image references and generated manifests.
| Scenario | Required result |
|---|---|
| Confirmed missing baseline; valid AMD64 + ARM64 current image | Nonfatal explicit bootstrap report with current sizes |
| Existing baseline and current image | Existing report preserved |
| Zero-sized existing baseline | Existing zero-size behavior preserved; not mislabeled as absent |
| Existing baseline/current platform mismatch | Hard failure preserved |
| Missing current image | Hard failure |
| Both baseline and current missing | Hard failure identifying the current-image problem |
| Baseline unauthorized/forbidden | Hard failure, not bootstrap |
| Baseline timeout/network/unexpected inspection error | Hard failure |
| Baseline invalid JSON or no known platforms | Hard failure |
| Baseline missing but current invalid JSON/no platforms | Hard failure |
| Recognized missing-manifest diagnostic variants | Correct narrow classification without swallowing unrelated errors |
At minimum, run:
npm ci --ignore-scripts --prefix .github/actions/container-size-diff
npm test --prefix .github/actions/container-size-diffFollow the repository instructions and existing lint/format checks.
GitHub workflow execution itself should be verified through an actual new-image bootstrap run where available, rather than claimed from mocked tests alone.
Completion and downstream adoption
Submit a focused upstream PR with regression tests and documentation.
The changes to the reusable action/workflow should be released through the repository's actions/vX.Y.Z release path.
Consumers pinned to af840070... will then need to adopt the verified fixed action-release commit; merely changing main does not repair an already-pinned downstream workflow.
Activity