Skip to content

fix: consolidate matrix build passthrough artifacts before upload - #187

Merged
joshua-temple merged 1 commit into
mainfrom
fix/matrix-artifact-consolidation
Jun 16, 2026
Merged

joshua-temple merged 1 commit into
mainfrom
fix/matrix-artifact-consolidation

Conversation

@joshua-temple

Copy link
Copy Markdown
Collaborator

Problem

A matrix build that declares artifact.upload got a cascade-owned <build>-upload post-job that ran actions/upload-artifact on a fresh ubuntu-latest runner without first fetching anything. For a matrix build the callback fans out across legs that each run on their own runner, so the upload-path files only ever exist on those leg runners. The post-job runner's upload path was empty, so it reported No files were found with the provided path, produced no build-<name> artifact, and a downstream consumer's download step failed with Artifact not found for name: build-<name>. A live run of a matrix os/arch image build feeding a bundle build exposed this.

Fix

writePassthroughUploadJob now emits a Collect matrix leg artifacts step before the upload step when the build declares a matrix. cascade cannot inject upload steps into a reusable callback's legs, so the fix defines a per-leg artifact-name convention the callback is expected to follow.

Convention: matrix legs upload artifacts named <build-name>-<leg-suffix> (for a build named image the legs upload image-linux-amd64, image-linux-arm64, and so on). The post-job downloads pattern: <build-name>-* with merge-multiple: true into the upload directory, then uploads the single consolidated build-<name> artifact consumers download. The download path is the upload path with a trailing glob stripped to a directory (dist/** and dist/ both become dist; a bare ** becomes .).

Non-matrix builds are unchanged: their callback runs on one runner whose files already live at the upload path, so they upload directly with no collect step.

Verification

  • go build ./... passes.
  • go test ./... passes (1359 tests across 23 packages).
  • golangci-lint run ./... reports no issues.
  • gofmt/goimports clean; go test -race ./internal/generate/ passes.
  • New test TestGenerator_PassthroughArtifact_MatrixUploadCollectsLegs (failing-first, then passing) asserts the matrix upload job collects per-leg artifacts via pattern: image-*, merge-multiple: true, into dist, before uploading build-image, and that the consumer download references the same build-image name. TestGenerator_PassthroughArtifact_NonMatrixUploadNoCollect guards that non-matrix uploads add no spurious collect step.

No e2e scenario: the e2e harness runs under act, which has no artifact server, so upload/download-artifact cannot execute there. Coverage is provided through the generator test on the emitted workflow, matching the precedent set by PR #183 for the same reason.

A matrix build's cascade-owned <build>-upload post-job ran upload-artifact
on a fresh runner that never held the matrix legs' files, so the upload
found an empty path, produced no build-<name> artifact, and a downstream
consumer's download failed with "Artifact not found".

The post-job now collects the per-leg artifacts first when the build
declares a matrix. cascade cannot inject upload steps into a reusable
callback's legs, so each leg is expected to upload an artifact named
<build-name>-<leg-suffix>; the post-job downloads pattern <build-name>-*
with merge-multiple into the upload directory, then uploads the single
consolidated build-<name>. Non-matrix builds keep uploading directly.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
@joshua-temple
joshua-temple merged commit 8b1b84d into main Jun 16, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant