-
Notifications
You must be signed in to change notification settings - Fork 595
Improve cache plugin API calls and improve logging #1858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -33,7 +33,6 @@ function makeKey({ dir, repoRoot }) { | |||||||||||||||
|
|
||||||||||||||||
| let key = dir; | ||||||||||||||||
|
|
||||||||||||||||
| // Auto-invalidate node_modules with yarn.lock changes | ||||||||||||||||
| if (dir === "node_modules") { | ||||||||||||||||
| const yarnLockPath = path.join(repoRoot, "yarn.lock"); | ||||||||||||||||
| const hash = fileSha256(yarnLockPath); | ||||||||||||||||
|
|
@@ -42,98 +41,104 @@ function makeKey({ dir, repoRoot }) { | |||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // On-demand busting | ||||||||||||||||
| if (cacheVersion) { | ||||||||||||||||
| key = `${key}@cv-${cacheVersion}`; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| // Per-branch isolation | ||||||||||||||||
| if (perBranch) { | ||||||||||||||||
| key = `${key}@${branch}`; | ||||||||||||||||
| } | ||||||||||||||||
| return key; | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| async function restoreDir(utils, absPath, key) { | ||||||||||||||||
| async function restoreDir(utils, absPath, key, results) { | ||||||||||||||||
| try { | ||||||||||||||||
| // File-based caching: check if cache exists, then restore | ||||||||||||||||
| const cacheExists = await utils.cache.has(key); | ||||||||||||||||
| if (!cacheExists) { | ||||||||||||||||
| utils.status.show({ | ||||||||||||||||
| title: `No cache: ${key}`, | ||||||||||||||||
| summary: `No prior cache for ${absPath}`, | ||||||||||||||||
| }); | ||||||||||||||||
| return false; | ||||||||||||||||
| } | ||||||||||||||||
| const restored = await utils.cache.restore(absPath, { key }); | ||||||||||||||||
|
|
||||||||||||||||
| const restored = await utils.cache.restore(key); | ||||||||||||||||
| if (restored) { | ||||||||||||||||
| // File-based caching often requires manual copy from cache location | ||||||||||||||||
| // The exact implementation may vary based on Netlify's file-based API | ||||||||||||||||
| utils.status.show({ | ||||||||||||||||
| title: `Cache restored: ${key}`, | ||||||||||||||||
| summary: `Restored into ${absPath}`, | ||||||||||||||||
| }); | ||||||||||||||||
| const msg = `✓ Restored cache: ${key}`; | ||||||||||||||||
| console.log(`[CACHE] ${msg}`); | ||||||||||||||||
| results.push(msg); | ||||||||||||||||
| } else { | ||||||||||||||||
| utils.status.show({ | ||||||||||||||||
| title: `Cache restore failed: ${key}`, | ||||||||||||||||
| summary: `Failed to restore cache for ${absPath}`, | ||||||||||||||||
| }); | ||||||||||||||||
| const msg = `No cache found for ${key}`; | ||||||||||||||||
| console.log(`[CACHE] ${msg}`); | ||||||||||||||||
| results.push(msg); | ||||||||||||||||
| } | ||||||||||||||||
| return restored; | ||||||||||||||||
| } catch (err) { | ||||||||||||||||
| utils.status.show({ | ||||||||||||||||
| title: `Cache restore failed: ${key}`, | ||||||||||||||||
| summary: err.message, | ||||||||||||||||
| }); | ||||||||||||||||
| const msg = `✗ Error restoring ${key}: ${err.message}`; | ||||||||||||||||
| console.log(`[CACHE] ${msg}`); | ||||||||||||||||
| results.push(msg); | ||||||||||||||||
| return false; | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| async function saveDir(utils, absPath, key) { | ||||||||||||||||
| async function saveDir(utils, absPath, key, results, dir) { | ||||||||||||||||
| try { | ||||||||||||||||
| // File-based caching: save directory to cache | ||||||||||||||||
| const saved = await utils.cache.save(key, absPath); | ||||||||||||||||
| utils.status.show({ | ||||||||||||||||
| title: saved ? `Cache saved: ${key}` : `Cache skipped: ${key}`, | ||||||||||||||||
| summary: `${saved ? "Saved" : "Skipped"} from ${absPath}`, | ||||||||||||||||
| }); | ||||||||||||||||
| const saved = await utils.cache.save(absPath, { key }); | ||||||||||||||||
| const msg = saved ? `✓ Saved cache: ${key}` : `⊖ Skipped cache: ${key}`; | ||||||||||||||||
| console.log(`[CACHE] ${msg}`); | ||||||||||||||||
| results.push(msg); | ||||||||||||||||
| return saved; | ||||||||||||||||
| } catch (err) { | ||||||||||||||||
| utils.status.show({ | ||||||||||||||||
| title: `Cache save failed: ${key}`, | ||||||||||||||||
| summary: err.message, | ||||||||||||||||
| }); | ||||||||||||||||
| // Known issue: node_modules/.bin symlinks can cause EISDIR errors | ||||||||||||||||
| // This is non-critical as the rest of node_modules still gets cached | ||||||||||||||||
| if (dir === "node_modules" && err.message.includes("EISDIR")) { | ||||||||||||||||
| const msg = `⚠ Partial cache saved for ${key} (symlink issue in .bin - non-critical)`; | ||||||||||||||||
| console.log(`[CACHE] ${msg}`); | ||||||||||||||||
| results.push(msg); | ||||||||||||||||
| return true; // Consider it a success since most of node_modules is cached | ||||||||||||||||
| } | ||||||||||||||||
| const msg = `✗ Error saving ${key}: ${err.message}`; | ||||||||||||||||
| console.log(`[CACHE] ${msg}`); | ||||||||||||||||
| results.push(msg); | ||||||||||||||||
| return false; | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| module.exports = { | ||||||||||||||||
| async onPreBuild({ inputs, utils }) { | ||||||||||||||||
| const results = []; | ||||||||||||||||
| console.log('[CACHE] ========== Cache Restore Starting =========='); | ||||||||||||||||
| console.log('[CACHE] Environment:', { | ||||||||||||||||
| CACHE_VERSION: process.env.CACHE_VERSION, | ||||||||||||||||
| CACHE_PER_BRANCH: process.env.CACHE_PER_BRANCH, | ||||||||||||||||
| NETLIFY_BRANCH: process.env.NETLIFY_BRANCH | ||||||||||||||||
| }); | ||||||||||||||||
|
|
||||||||||||||||
| const repoRoot = process.cwd(); | ||||||||||||||||
| const dirs = inputs.dirs; | ||||||||||||||||
|
|
||||||||||||||||
| for (const dir of dirs) { | ||||||||||||||||
| const key = makeKey({ dir, repoRoot }); | ||||||||||||||||
| console.log(`[CACHE] Processing ${dir} with key: ${key}`); | ||||||||||||||||
| const abs = path.resolve(repoRoot, dir); | ||||||||||||||||
|
|
||||||||||||||||
| await restoreDir(utils, abs, key); | ||||||||||||||||
| await restoreDir(utils, abs, key, results); | ||||||||||||||||
|
|
||||||||||||||||
| // Guidance for node_modules: ensure yarn.lock exists to keep cache fresh | ||||||||||||||||
| if (dir === "node_modules") { | ||||||||||||||||
| const yarnLockPath = path.join(repoRoot, "yarn.lock"); | ||||||||||||||||
| if (!fs.existsSync(yarnLockPath)) { | ||||||||||||||||
| utils.status.show({ | ||||||||||||||||
| title: "node_modules cache warning", | ||||||||||||||||
| summary: | ||||||||||||||||
| "yarn.lock not found. Caching node_modules without yarn.lock can lead to stale dependencies. Ensure yarn.lock is committed.", | ||||||||||||||||
| }); | ||||||||||||||||
| const msg = "⚠ Warning: yarn.lock not found - node_modules cache may be stale"; | ||||||||||||||||
| console.log(`[CACHE] ${msg}`); | ||||||||||||||||
| results.push(msg); | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
| } | ||||||||||||||||
|
|
||||||||||||||||
| console.log('[CACHE] ========== Cache Restore Complete =========='); | ||||||||||||||||
|
|
||||||||||||||||
| // Show combined status in deploy summary | ||||||||||||||||
| utils.status.show({ | ||||||||||||||||
| title: "Cache Restore Summary", | ||||||||||||||||
| summary: results.length > 0 ? results.join('\n') : 'No cache operations performed', | ||||||||||||||||
| }); | ||||||||||||||||
| }, | ||||||||||||||||
|
|
||||||||||||||||
| async onPostBuild({ inputs, utils }) { | ||||||||||||||||
| const results = []; | ||||||||||||||||
| console.log('[CACHE] ========== Cache Save Starting =========='); | ||||||||||||||||
|
||||||||||||||||
| console.log('[CACHE] ========== Cache Save Starting =========='); | |
| console.log('[CACHE] ========== Cache Save Starting =========='); | |
| console.log('[CACHE] Environment:', { | |
| CACHE_VERSION: process.env.CACHE_VERSION, | |
| CACHE_PER_BRANCH: process.env.CACHE_PER_BRANCH, | |
| NETLIFY_BRANCH: process.env.NETLIFY_BRANCH | |
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The environment object is being logged directly to console.log, which will output "[object Object]" instead of the actual values. To properly display the environment variables, either use JSON.stringify() or log each variable separately.