The silent failures are the most dangerous. Consider these scenarios:
Standard logs just show Received 0 of 0 artifacts. That is useless. To see the truth, you need step-level debug logging, specifically for the cache action.
GitHub doesn’t let you browse caches directly, but you can list them via API:
gh api \
-H "Accept: application/vnd.github+json" \
/repos/:owner/:repo/actions/caches
Look at:
This explains why a key isn’t matching.
Problem: Cache restored only 20% of the time.
Logs show: Cache not found for key: linux-npm-xyz123 debug-action-cache
Check key generation:
- name: Debug cache key
run: |
echo "key: $ runner.os -npm-$ hashFiles('**/package-lock.json') "
ls -la **/package-lock.json
Output shows:
package-lock.json changes every build (e.g., due to npm install --package-lock-only differences).
Fix:
key: $ runner.os -npm-$ hashFiles('package-lock.json')
restore-keys: |
$ runner.os -npm-
Now even if exact key misses, it restores the most recent linux-npm-* cache.
True mastery of debug-action-cache is not reactive—it is proactive. Implement these strategies:
- name: Report cache metrics
run: |
if [ -d "node_modules" ]; then
echo "cache_status=hit" >> $GITHUB_OUTPUT
else
echo "cache_status=miss" >> $GITHUB_OUTPUT
fi