@@ -33,7 +33,6 @@ function makeKey({ dir, repoRoot }) {
3333
3434 let key = dir ;
3535
36- // Auto-invalidate node_modules with yarn.lock changes
3736 if ( dir === "node_modules" ) {
3837 const yarnLockPath = path . join ( repoRoot , "yarn.lock" ) ;
3938 const hash = fileSha256 ( yarnLockPath ) ;
@@ -42,98 +41,104 @@ function makeKey({ dir, repoRoot }) {
4241 }
4342 }
4443
45- // On-demand busting
4644 if ( cacheVersion ) {
4745 key = `${ key } @cv-${ cacheVersion } ` ;
4846 }
4947
50- // Per-branch isolation
5148 if ( perBranch ) {
5249 key = `${ key } @${ branch } ` ;
5350 }
5451 return key ;
5552}
5653
57- async function restoreDir ( utils , absPath , key ) {
54+ async function restoreDir ( utils , absPath , key , results ) {
5855 try {
59- // File-based caching: check if cache exists, then restore
60- const cacheExists = await utils . cache . has ( key ) ;
61- if ( ! cacheExists ) {
62- utils . status . show ( {
63- title : `No cache: ${ key } ` ,
64- summary : `No prior cache for ${ absPath } ` ,
65- } ) ;
66- return false ;
67- }
56+ const restored = await utils . cache . restore ( absPath , { key } ) ;
6857
69- const restored = await utils . cache . restore ( key ) ;
7058 if ( restored ) {
71- // File-based caching often requires manual copy from cache location
72- // The exact implementation may vary based on Netlify's file-based API
73- utils . status . show ( {
74- title : `Cache restored: ${ key } ` ,
75- summary : `Restored into ${ absPath } ` ,
76- } ) ;
59+ const msg = `✓ Restored cache: ${ key } ` ;
60+ console . log ( `[CACHE] ${ msg } ` ) ;
61+ results . push ( msg ) ;
7762 } else {
78- utils . status . show ( {
79- title : `Cache restore failed: ${ key } ` ,
80- summary : `Failed to restore cache for ${ absPath } ` ,
81- } ) ;
63+ const msg = `No cache found for ${ key } ` ;
64+ console . log ( `[CACHE] ${ msg } ` ) ;
65+ results . push ( msg ) ;
8266 }
8367 return restored ;
8468 } catch ( err ) {
85- utils . status . show ( {
86- title : `Cache restore failed: ${ key } ` ,
87- summary : err . message ,
88- } ) ;
69+ const msg = `✗ Error restoring ${ key } : ${ err . message } ` ;
70+ console . log ( `[CACHE] ${ msg } ` ) ;
71+ results . push ( msg ) ;
8972 return false ;
9073 }
9174}
9275
93- async function saveDir ( utils , absPath , key ) {
76+ async function saveDir ( utils , absPath , key , results , dir ) {
9477 try {
95- // File-based caching: save directory to cache
96- const saved = await utils . cache . save ( key , absPath ) ;
97- utils . status . show ( {
98- title : saved ? `Cache saved: ${ key } ` : `Cache skipped: ${ key } ` ,
99- summary : `${ saved ? "Saved" : "Skipped" } from ${ absPath } ` ,
100- } ) ;
78+ const saved = await utils . cache . save ( absPath , { key } ) ;
79+ const msg = saved ? `✓ Saved cache: ${ key } ` : `⊖ Skipped cache: ${ key } ` ;
80+ console . log ( `[CACHE] ${ msg } ` ) ;
81+ results . push ( msg ) ;
10182 return saved ;
10283 } catch ( err ) {
103- utils . status . show ( {
104- title : `Cache save failed: ${ key } ` ,
105- summary : err . message ,
106- } ) ;
84+ // Known issue: node_modules/.bin symlinks can cause EISDIR errors
85+ // This is non-critical as the rest of node_modules still gets cached
86+ if ( dir === "node_modules" && err . message . includes ( "EISDIR" ) ) {
87+ const msg = `⚠ Partial cache saved for ${ key } (symlink issue in .bin - non-critical)` ;
88+ console . log ( `[CACHE] ${ msg } ` ) ;
89+ results . push ( msg ) ;
90+ return true ; // Consider it a success since most of node_modules is cached
91+ }
92+ const msg = `✗ Error saving ${ key } : ${ err . message } ` ;
93+ console . log ( `[CACHE] ${ msg } ` ) ;
94+ results . push ( msg ) ;
10795 return false ;
10896 }
10997}
11098
11199module . exports = {
112100 async onPreBuild ( { inputs, utils } ) {
101+ const results = [ ] ;
102+ console . log ( '[CACHE] ========== Cache Restore Starting ==========' ) ;
103+ console . log ( '[CACHE] Environment:' , {
104+ CACHE_VERSION : process . env . CACHE_VERSION ,
105+ CACHE_PER_BRANCH : process . env . CACHE_PER_BRANCH ,
106+ NETLIFY_BRANCH : process . env . NETLIFY_BRANCH
107+ } ) ;
108+
113109 const repoRoot = process . cwd ( ) ;
114110 const dirs = inputs . dirs ;
115111
116112 for ( const dir of dirs ) {
117113 const key = makeKey ( { dir, repoRoot } ) ;
114+ console . log ( `[CACHE] Processing ${ dir } with key: ${ key } ` ) ;
118115 const abs = path . resolve ( repoRoot , dir ) ;
119116
120- await restoreDir ( utils , abs , key ) ;
117+ await restoreDir ( utils , abs , key , results ) ;
121118
122- // Guidance for node_modules: ensure yarn.lock exists to keep cache fresh
123119 if ( dir === "node_modules" ) {
124120 const yarnLockPath = path . join ( repoRoot , "yarn.lock" ) ;
125121 if ( ! fs . existsSync ( yarnLockPath ) ) {
126- utils . status . show ( {
127- title : "node_modules cache warning" ,
128- summary :
129- "yarn.lock not found. Caching node_modules without yarn.lock can lead to stale dependencies. Ensure yarn.lock is committed." ,
130- } ) ;
122+ const msg = "⚠ Warning: yarn.lock not found - node_modules cache may be stale" ;
123+ console . log ( `[CACHE] ${ msg } ` ) ;
124+ results . push ( msg ) ;
131125 }
132126 }
133127 }
128+
129+ console . log ( '[CACHE] ========== Cache Restore Complete ==========' ) ;
130+
131+ // Show combined status in deploy summary
132+ utils . status . show ( {
133+ title : "Cache Restore Summary" ,
134+ summary : results . length > 0 ? results . join ( '\n' ) : 'No cache operations performed' ,
135+ } ) ;
134136 } ,
135137
136138 async onPostBuild ( { inputs, utils } ) {
139+ const results = [ ] ;
140+ console . log ( '[CACHE] ========== Cache Save Starting ==========' ) ;
141+
137142 const repoRoot = process . cwd ( ) ;
138143 const dirs = inputs . dirs ;
139144
@@ -142,23 +147,29 @@ module.exports = {
142147 const abs = path . resolve ( repoRoot , dir ) ;
143148
144149 if ( ! dirExists ( abs ) ) {
145- utils . status . show ( {
146- title : `Cache not saved (missing directory)` ,
147- summary : `${ abs } does not exist.` ,
148- } ) ;
150+ const msg = `⊖ Skipped ${ dir } : directory does not exist` ;
151+ console . log ( `[CACHE] ${ msg } ` ) ;
152+ results . push ( msg ) ;
149153 continue ;
150154 }
151155
152156 const hasFiles = fs . readdirSync ( abs ) . length > 0 ;
153157 if ( ! hasFiles ) {
154- utils . status . show ( {
155- title : `Cache not saved (empty directory)` ,
156- summary : `${ abs } is empty.` ,
157- } ) ;
158+ const msg = `⊖ Skipped ${ dir } : directory is empty` ;
159+ console . log ( `[CACHE] ${ msg } ` ) ;
160+ results . push ( msg ) ;
158161 continue ;
159162 }
160163
161- await saveDir ( utils , abs , key ) ;
164+ await saveDir ( utils , abs , key , results , dir ) ;
162165 }
166+
167+ console . log ( '[CACHE] ========== Cache Save Complete ==========' ) ;
168+
169+ // Show combined status in deploy summary (this overrides the onPreBuild status)
170+ utils . status . show ( {
171+ title : "Cache Operations Complete" ,
172+ summary : results . length > 0 ? results . join ( '\n' ) : 'No cache operations performed' ,
173+ } ) ;
163174 } ,
164175} ;
0 commit comments