Caching and artifacts¶
Cache and artifacts solve different problems. Cache is for regenerable dependencies and intermediate state across runs. Artifacts are for build outputs, reports, and passing data between jobs. Do not use one where the other fits.
Dependency caching¶
- Prefer the built-in caching of setup actions (
setup-node,setup-python,setup-java,setup-go, and similar) over hand-writtenactions/cachesteps. Enabling it for a committed lockfile on trusted triggers is a low-risk default; manualactions/cacheentries for other paths need justification. actions/cachelookup order: exactkeyon the current branch, thenkeyprefix, then eachrestore-keysprefix, then the same on the default branch. The most recently created match wins.cache-hitistrueonly for an exact key match. Arestore-keyshit is still a miss for gating.- Key on lockfile hashes, not on
github.run_idor timestamps. Add a run-id suffix only when a cache must never be reused. - Scope: a branch can restore its own caches and default-branch caches; PR runs can also restore the base branch. Caches are not shared between unrelated branches or tags.
- Limits: 10 GB per repository by default, evicted after 7 days without access (LRU).
actions/cache/restoreandactions/cache/saveallow split restore and save, which is useful when a job may only read caches.
Cache trust¶
Caches are unsigned and can be written by less-privileged runs. Do not restore caches into a privileged workflow when untrusted code can influence the cache key, and never cache secrets or credentials.
Low-trust triggers (pull_request_target, workflow_run, issue_comment) get read-only
cache access by default. Overriding that reintroduces cache poisoning. The cache-mode key
(read, write, write-only, none) controls this on supported GitHub plans; do not set
write on an untrusted trigger without a concrete reason.
Artifacts¶
- Upload with
actions/upload-artifact, download withactions/download-artifact. Artifacts are immutable per name in v4 and later: uploading the same name again fails unlessoverwrite: true. - Give each matrix leg a unique artifact name, or uploads collide.
- Hidden files and directories are excluded by default (
include-hidden-files: false). - Zip archives do not preserve the executable bit. Use
tarplusarchive: falsewhen permissions matter. download-artifactextracts a single artifact directly topath; multiple artifacts create per-name subdirectories unlessmerge-multiple: true.- Default retention is 90 days. Set
retention-daysdeliberately for large or sensitive data. - To pass data between jobs, upload in the producer and declare
needs:on the consumer. Job outputs are for small values only.
Artifact trust¶
Artifacts produced by fork PRs or other workflows are untrusted. A privileged workflow_run
may download them as data but must not execute their contents, and should validate paths when
extracting because archives can contain traversal entries. The same applies to reports
rendered as HTML or interpreted as scripts.