I’m working on a Gatsby project and want to cache build folders between runs in GitHub Actions using the cache action. My goal is to speed up builds by preserving the cache and public directories.
The first build works fine and creates both directories from scratch. The second build finds the cached folders but doesn’t seem to update them afterward. I think my cache key strategy might be wrong but I’m not sure how to properly invalidate the cache when needed.
Cache keys must change when your source code changes - otherwise you’ll get stale builds. Gatsby’s .cache folder is tricky since it depends on both dependencies AND content. I’d include runner.os in the key too because Gatsby caches can be platform-specific. Try something like ${{ runner.os }}-gatsby-${{ hashFiles('package*.json', 'src/**') }}. Don’t forget restore-keys so you won’t lose everything on small changes.
Your cache keys are static and never change, so the cache never updates. I had the same issue last year with a similar Gatsby setup. You need dynamic cache keys that bust when dependencies or source files change. For the .cache directory, include your package-lock.json hash in the key since Gatsby’s cache depends on your dependencies. I suggest skipping caching the public directory entirely - it gets completely rebuilt, and caching it can cause stale content issues. Try using a key like gatsby-cache-${{ hashFiles('**/package-lock.json') }} with restore-keys as fallback. You’ll get cache benefits when dependencies haven’t changed, but proper invalidation when they have. My build times improved significantly after fixing this.
Your cache config is missing proper invalidation triggers. Those static keys like gatsby-cache-files stick around forever once they’re created - that’s why your updates aren’t showing up in new builds. I hit this exact same issue last month with a client’s Gatsby site. Don’t use separate cache actions. Instead, combine both paths in one cache step with a composite key that includes your source code hash. Try something like gatsby-build-${{ hashFiles('gatsby-config.js', 'src/**', 'package-lock.json') }}-${{ github.sha }} as your main key, then add restore-keys with less specific patterns for fallbacks. This way your cache gets invalidated when content or config changes, but you still get the performance boost when nothing’s changed. The github.sha part makes sure each commit gets its own cache entry when it needs one.