Chapter 13Lesson 04~180 minutes

Artifacts, Retention, Cross-Job Data, and Workflow Result Management: Diagnostics, Failure Modes, and Production Practices

Artifact failures become dangerous when teams troubleshoot by re-uploading, renaming, or deleting evidence before proving what the first run produced. This lesson diagnoses cache misuse, sensitive-file leakage, expiry assumptions, matrix collisions, run/SHA confusion and deprecated action majors while preserving first-failure evidence.

Evidence-firstSensitive filesExpiryMatrix collisionsRun/SHA binding

Learning objectives

  • Diagnose missing/wrong artifacts by preserving run/attempt/SHA and artifact metadata before repair.
  • Recognize sensitive-file leakage, cache misuse, expiry assumptions and matrix name collisions as different failure layers.
  • Treat downloaded artifacts as untrusted until their producing run/SHA and expected content are verified.
  • Identify deprecated/unsupported artifact action majors as platform compatibility failures rather than application failures.
  • Apply the least destructive repair and rerun only the smallest equivalent scope.

1. Evidence-first diagnostic sequence

  1. Preserve the run ID, attempt, event, ref/SHA and workflow revision.
  2. Record the generated job graph and conclusions before rerun/cancellation changes them.
  3. Record artifact list/IDs/names/digests/sizes/expiry for that run.
  4. Confirm runner/image and exact pinned action SHAs.
  5. Compare configured upload paths with pre-upload filesystem evidence.
  6. Inspect download selection: name, ID, source run/repository and destination path.
  7. Inspect sensitivity/hidden-file policy and whether any artifact should be quarantined/deleted.
  8. Apply the narrowest fix, create a new run/attempt, and keep the original evidence.

2. Symptom → likely layer → evidence

Symptom Likely cause Preserve first Least-destructive correction
Release job restored stale files cache used as authoritative build evidence cache key/hit + source SHA + release input use artifact tied to producing run/SHA; keep cache only for dependencies
Secret-like file visible in artifact path selection/data classification failure artifact ID/digest + exact selected paths + access history revoke credential, restrict access, delete/quarantine artifact after evidence, fix path selection
Artifact disappeared retention expiry or run deletion REST metadata if available + repo retention policy + run status increase future retention or promote records externally; cannot “repair” expired bytes from metadata alone
Matrix upload says artifact already exists same-name collision under immutable semantics matrix cell values + upload logs unique artifact name per cell; aggregate later
Consumer has valid artifact but wrong build wrong run/name selection source run ID, head SHA, artifact ID/digest select by expected run/ID and verify SHA before use
Action unsupported/failing before upload deprecated/incompatible artifact action/backend action major/SHA + GitHub.com/GHES version use supported major for target platform; do not downgrade blindly

3. Intentionally broken example: name-only selection finds no artifact

The producer uploads build-${{ github.run_id }}, while the consumer assumes the name is simply build. The download failure is not a runner or network problem; the selection contract is wrong.

# Producer
- id: upload
  uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a
  with:
    name: build-${{ github.run_id }}
    path: dist/build.txt

# Broken consumer: wrong human name
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
  with:
    name: build
    path: ${{ runner.temp }}/incoming

Preserve the failed run and upload output. Repair the dataflow by promoting artifact-id to a job output and selecting artifact-ids in the consumer. This removes hidden coupling to naming convention.

# Repaired consumer selection
with:
  artifact-ids: ${{ needs.build.outputs.artifact_id }}
  path: ${{ runner.temp }}/incoming
  digest-mismatch: error

4. Sensitive artifact response is an incident, not a cosmetic bug

If a real credential or private key is uploaded, deleting the artifact is not sufficient. Assume authorized readers or automation may already have downloaded it. Preserve incident metadata, revoke/rotate the credential, inspect access/audit evidence where available, then remove the artifact and fix the workflow selection. Never publish the secret in a ticket or log “to prove” the leak.

Masking does not protect artifacts

GitHub log redaction does not encrypt artifact contents. Base64 is reversible encoding, not protection. Secrets, token-bearing headers and private keys must not be artifact inputs.

5. Matrix collisions are evidence loss

Under current immutable artifact semantics, multiple matrix cells cannot all upload to the same artifact name as if appending. Give every cell a unique name, for example test-${{ matrix.os }}-${{ matrix.runtime }}-${{ github.run_id }}. If you want one combined object, use a downstream aggregation step after all cells complete.

6. Expiry is not transient failure

An expired artifact download can return Gone/404-like outcomes depending on interface. Retrying will not resurrect it. Check expired/expires_at and the repository retention policy. Rebuilding a release artifact merely to make the error disappear breaks provenance because the new bytes are produced by a new run; treat it as a new build with a new identity.

7. Read metadata before delete

GH_REPO='OWNER/gha-artifact-lab'
ARTIFACT_ID='123456789'
# Preserve metadata first
gh api -H 'X-GitHub-Api-Version: 2026-03-10'   "repos/$GH_REPO/actions/artifacts/$ARTIFACT_ID"   --jq '{id,name,size_in_bytes,digest,expired,created_at,expires_at,workflow_run}'

# Destructive cleanup only after evidence/authorization
# gh api --method DELETE .../actions/artifacts/$ARTIFACT_ID

Knowledge check

A consumer downloaded a valid-digest artifact from the wrong run. Is integrity sufficient?

What is the first response to a real secret found in an artifact?

Why is retrying an expired artifact download not useful?

Why should matrix jobs use unique artifact names?

Why not rebuild a missing release artifact as a troubleshooting shortcut?

Next lesson

Prove one artifact lifecycle end to end

The checkpoint preserves an intentional first failure, repairs the consumer to use artifact identity, and produces a compact evidence packet before optional cleanup.

Official references and version notes

Version and compatibility note

Version-sensitive behavior was rechecked on 2026-09-09. Mandatory examples target GitHub.com and ubuntu-24.04. actions/upload-artifact v7.0.1 and actions/download-artifact v8.0.1 are pinned by full commit SHA. Upload v7 excludes dot-prefixed hidden files by default, supports compression levels 0–9, returns artifact ID/URL/SHA-256 digest, and treats overwrite as delete-and-create rather than in-place mutation. Download v8 can select by artifact ID and defaults digest mismatch handling to error. Artifact/log retention is policy bounded: GitHub documents 1–90 days for public repositories and up to 400 days for private repositories when repository/organization/enterprise policy permits. Upload-artifact v4+ is not supported on GitHub Enterprise Server; GHES users must use an appliance-compatible artifact action/backend and must not copy GitHub.com majors blindly.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.