mirror of
				https://github.com/actions/setup-node.git
				synced 2025-10-31 16:23:34 +00:00 
			
		
		
		
	add devEngines.packageManager detection logic for npm auto-caching
This commit is contained in:
		
							parent
							
								
									7024c214c6
								
							
						
					
					
						commit
						8f225c52ce
					
				| @ -285,13 +285,12 @@ describe('main tests', () => { | ||||
|   }); | ||||
| 
 | ||||
|   describe('cache feature tests', () => { | ||||
|     it('Should enable caching with the resolved package manager from packageManager field in package.json when the cache input is not provided', async () => { | ||||
|     it('Should enable caching when packageManager is npm and cache input is not provided', async () => { | ||||
|       inputs['package-manager-cache'] = 'true'; | ||||
|       inputs['cache'] = ''; // No cache input is provided
 | ||||
|       inputs['cache'] = ''; | ||||
|       isCacheActionAvailable.mockImplementation(() => true); | ||||
| 
 | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
| 
 | ||||
|       const readFileSpy = jest.spyOn(fs, 'readFileSync'); | ||||
|       readFileSpy.mockImplementation(() => | ||||
|         JSON.stringify({ | ||||
| @ -304,16 +303,106 @@ describe('main tests', () => { | ||||
|       expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm'); | ||||
|     }); | ||||
| 
 | ||||
|     it('Should not enable caching if the packageManager field is missing in package.json and the cache input is not provided', async () => { | ||||
|     it('Should enable caching when devEngines.packageManager.name is "npm" and cache input is not provided', async () => { | ||||
|       inputs['package-manager-cache'] = 'true'; | ||||
|       inputs['cache'] = ''; // No cache input is provided
 | ||||
|       inputs['cache'] = ''; | ||||
|       isCacheActionAvailable.mockImplementation(() => true); | ||||
| 
 | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
| 
 | ||||
|       const readFileSpy = jest.spyOn(fs, 'readFileSync'); | ||||
|       readFileSpy.mockImplementation(() => | ||||
|         JSON.stringify({ | ||||
|           //packageManager field is not present
 | ||||
|           devEngines: { | ||||
|             packageManager: {name: 'npm'} | ||||
|           } | ||||
|         }) | ||||
|       ); | ||||
| 
 | ||||
|       await main.run(); | ||||
| 
 | ||||
|       expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm'); | ||||
|     }); | ||||
| 
 | ||||
|     it('Should enable caching when devEngines.packageManager is array and one entry has name "npm"', async () => { | ||||
|       inputs['package-manager-cache'] = 'true'; | ||||
|       inputs['cache'] = ''; | ||||
|       isCacheActionAvailable.mockImplementation(() => true); | ||||
| 
 | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
|       const readFileSpy = jest.spyOn(fs, 'readFileSync'); | ||||
|       readFileSpy.mockImplementation(() => | ||||
|         JSON.stringify({ | ||||
|           devEngines: { | ||||
|             packageManager: [{name: 'pnpm'}, {name: 'npm'}] | ||||
|           } | ||||
|         }) | ||||
|       ); | ||||
| 
 | ||||
|       await main.run(); | ||||
| 
 | ||||
|       expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm'); | ||||
|     }); | ||||
| 
 | ||||
|     it('Should not enable caching if packageManager is "pnpm@8.0.0" and cache input is not provided', async () => { | ||||
|       inputs['package-manager-cache'] = 'true'; | ||||
|       inputs['cache'] = ''; | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
|       const readFileSpy = jest.spyOn(fs, 'readFileSync'); | ||||
|       readFileSpy.mockImplementation(() => | ||||
|         JSON.stringify({ | ||||
|           packageManager: 'pnpm@8.0.0' | ||||
|         }) | ||||
|       ); | ||||
| 
 | ||||
|       await main.run(); | ||||
| 
 | ||||
|       expect(saveStateSpy).not.toHaveBeenCalled(); | ||||
|     }); | ||||
| 
 | ||||
|     it('Should not enable caching if devEngines.packageManager.name is "pnpm"', async () => { | ||||
|       inputs['package-manager-cache'] = 'true'; | ||||
|       inputs['cache'] = ''; | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
|       const readFileSpy = jest.spyOn(fs, 'readFileSync'); | ||||
|       readFileSpy.mockImplementation(() => | ||||
|         JSON.stringify({ | ||||
|           devEngines: { | ||||
|             packageManager: {name: 'pnpm'} | ||||
|           } | ||||
|         }) | ||||
|       ); | ||||
| 
 | ||||
|       await main.run(); | ||||
| 
 | ||||
|       expect(saveStateSpy).not.toHaveBeenCalled(); | ||||
|     }); | ||||
| 
 | ||||
|     it('Should not enable caching if devEngines.packageManager is array without "npm"', async () => { | ||||
|       inputs['package-manager-cache'] = 'true'; | ||||
|       inputs['cache'] = ''; | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
|       const readFileSpy = jest.spyOn(fs, 'readFileSync'); | ||||
|       readFileSpy.mockImplementation(() => | ||||
|         JSON.stringify({ | ||||
|           devEngines: { | ||||
|             packageManager: [{name: 'pnpm'}, {name: 'yarn'}] | ||||
|           } | ||||
|         }) | ||||
|       ); | ||||
| 
 | ||||
|       await main.run(); | ||||
| 
 | ||||
|       expect(saveStateSpy).not.toHaveBeenCalled(); | ||||
|     }); | ||||
| 
 | ||||
|     it('Should not enable caching if packageManager field is missing in package.json and cache input is not provided', async () => { | ||||
|       inputs['package-manager-cache'] = 'true'; | ||||
|       inputs['cache'] = ''; | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
|       const readFileSpy = jest.spyOn(fs, 'readFileSync'); | ||||
|       readFileSpy.mockImplementation(() => | ||||
|         JSON.stringify({ | ||||
|           // packageManager field is not present
 | ||||
|         }) | ||||
|       ); | ||||
| 
 | ||||
| @ -324,24 +413,18 @@ describe('main tests', () => { | ||||
| 
 | ||||
|     it('Should skip caching when package-manager-cache is false', async () => { | ||||
|       inputs['package-manager-cache'] = 'false'; | ||||
|       inputs['cache'] = ''; // No cache input is provided
 | ||||
| 
 | ||||
|       inputs['cache'] = ''; | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
| 
 | ||||
|       await main.run(); | ||||
| 
 | ||||
|       expect(saveStateSpy).not.toHaveBeenCalled(); | ||||
|     }); | ||||
| 
 | ||||
|     it('Should enable caching with cache input explicitly provided', async () => { | ||||
|       inputs['package-manager-cache'] = 'true'; | ||||
|       inputs['cache'] = 'npm'; // Explicit cache input provided
 | ||||
| 
 | ||||
|       inputs['cache'] = 'npm'; | ||||
|       inSpy.mockImplementation(name => inputs[name]); | ||||
|       isCacheActionAvailable.mockImplementation(() => true); | ||||
| 
 | ||||
|       await main.run(); | ||||
| 
 | ||||
|       expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm'); | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
							
								
								
									
										27
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							| @ -99838,17 +99838,32 @@ function resolveVersionInput() { | ||||
|     return version; | ||||
| } | ||||
| function getNameFromPackageManagerField() { | ||||
|     // Enable auto-cache for npm
 | ||||
|     var _a; | ||||
|     const npmRegex = /^(\^)?npm(@.*)?$/; // matches "npm", "npm@...", "^npm@..."
 | ||||
|     try { | ||||
|         const packageJson = JSON.parse(fs_1.default.readFileSync(path.join(process.env.GITHUB_WORKSPACE, 'package.json'), 'utf-8')); | ||||
|         const pm = packageJson.packageManager; | ||||
|         if (typeof pm === 'string') { | ||||
|             const match = pm.match(/^(?:\^)?(npm)@/); | ||||
|             return match ? match[1] : undefined; | ||||
|         // Check devEngines.packageManager first (object or array)
 | ||||
|         const devPM = (_a = packageJson === null || packageJson === void 0 ? void 0 : packageJson.devEngines) === null || _a === void 0 ? void 0 : _a.packageManager; | ||||
|         if (devPM) { | ||||
|             if (Array.isArray(devPM)) { | ||||
|                 for (const obj of devPM) { | ||||
|                     if (typeof (obj === null || obj === void 0 ? void 0 : obj.name) === 'string' && npmRegex.test(obj.name)) { | ||||
|                         return 'npm'; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             else if (typeof (devPM === null || devPM === void 0 ? void 0 : devPM.name) === 'string' && npmRegex.test(devPM.name)) { | ||||
|                 return 'npm'; | ||||
|             } | ||||
|         } | ||||
|         // Check top-level packageManager
 | ||||
|         const topLevelPM = packageJson === null || packageJson === void 0 ? void 0 : packageJson.packageManager; | ||||
|         if (typeof topLevelPM === 'string' && npmRegex.test(topLevelPM)) { | ||||
|             return 'npm'; | ||||
|         } | ||||
|         return undefined; | ||||
|     } | ||||
|     catch (err) { | ||||
|     catch (_b) { | ||||
|         return undefined; | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										28
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								src/main.ts
									
									
									
									
									
								
							| @ -138,7 +138,7 @@ function resolveVersionInput(): string { | ||||
| } | ||||
| 
 | ||||
| export function getNameFromPackageManagerField(): string | undefined { | ||||
|   // Enable auto-cache for npm
 | ||||
|   const npmRegex = /^(\^)?npm(@.*)?$/; // matches "npm", "npm@...", "^npm@..."
 | ||||
|   try { | ||||
|     const packageJson = JSON.parse( | ||||
|       fs.readFileSync( | ||||
| @ -146,13 +146,29 @@ export function getNameFromPackageManagerField(): string | undefined { | ||||
|         'utf-8' | ||||
|       ) | ||||
|     ); | ||||
|     const pm = packageJson.packageManager; | ||||
|     if (typeof pm === 'string') { | ||||
|       const match = pm.match(/^(?:\^)?(npm)@/); | ||||
|       return match ? match[1] : undefined; | ||||
| 
 | ||||
|     // Check devEngines.packageManager first (object or array)
 | ||||
|     const devPM = packageJson?.devEngines?.packageManager; | ||||
|     if (devPM) { | ||||
|       if (Array.isArray(devPM)) { | ||||
|         for (const obj of devPM) { | ||||
|           if (typeof obj?.name === 'string' && npmRegex.test(obj.name)) { | ||||
|             return 'npm'; | ||||
|           } | ||||
|         } | ||||
|       } else if (typeof devPM?.name === 'string' && npmRegex.test(devPM.name)) { | ||||
|         return 'npm'; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     // Check top-level packageManager
 | ||||
|     const topLevelPM = packageJson?.packageManager; | ||||
|     if (typeof topLevelPM === 'string' && npmRegex.test(topLevelPM)) { | ||||
|       return 'npm'; | ||||
|     } | ||||
| 
 | ||||
|     return undefined; | ||||
|   } catch (err) { | ||||
|   } catch { | ||||
|     return undefined; | ||||
|   } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user