Cache Dependencies in GitLab CI with cache:key:files
Cache dependencies in GitLab CI with cache:key:files so the key follows the lock file, and share one definition between jobs with a YAML anchor and a changed policy.
Several jobs need the same dependency cache, and only one of them should upload it.
.node-cache: &node-cache
key:
files:
- package-lock.json
paths:
- node_modules/
policy: pull
install:
script: npm ci
cache:
<<: *node-cache
policy: pull-push
test:
script: npm test
cache: *node-cacheimport yaml
doc = yaml.safe_load("""
.node-cache: &node-cache
key:
files:
- package-lock.json
paths:
- node_modules/
policy: pull
install:
script: npm ci
cache:
<<: *node-cache
policy: pull-push
test:
script: npm test
cache: *node-cache
""")
for job in ("install", "test"):
print(job, doc[job]["cache"])install {'key': {'files': ['package-lock.json']}, 'paths': ['node_modules/'], 'policy': 'pull-push'}
test {'key': {'files': ['package-lock.json']}, 'paths': ['node_modules/'], 'policy': 'pull'}key:files derives the cache key from the lock file, so it changes when the dependencies do. The anchor &node-cache names the block once, *node-cache reuses it, and <<: *node-cache merges it into a mapping so the job can override a field. The parsed result shows install with policy: pull-push and test with policy: pull, which means install saves the cache and test only reads it. See Caching in GitLab CI/CD.
Cache paths must be inside the project directory, and a cache is best effort: a job has to work without it. A job that can run in parallel with a failing one may still restore an older entry. GitLab also offers extends and !reference for reuse. The parser here is PyYAML, not GitLab's.