mirror of
				https://github.com/actions/setup-node.git
				synced 2025-10-31 23:43:33 +00:00 
			
		
		
		
	Merge 9312b4364bd38aa2e881bf0e0c8b34dd0511732a into 802632921f8532d2409ae6eac3313b6f81f11122
This commit is contained in:
		
						commit
						7c3feda4a4
					
				| @ -10,13 +10,15 @@ import osm from 'os'; | ||||
| import path from 'path'; | ||||
| import * as main from '../src/main'; | ||||
| import * as auth from '../src/authutil'; | ||||
| import {INodeVersion} from '../src/distributions/base-models'; | ||||
| import {INodeVersion, NodeInputs} from '../src/distributions/base-models'; | ||||
| 
 | ||||
| import nodeTestManifest from './data/versions-manifest.json'; | ||||
| import nodeTestDist from './data/node-dist-index.json'; | ||||
| import nodeTestDistNightly from './data/node-nightly-index.json'; | ||||
| import nodeTestDistRc from './data/node-rc-index.json'; | ||||
| import nodeV8CanaryTestDist from './data/v8-canary-dist-index.json'; | ||||
| import canaryBuild from '../src/distributions/v8-canary/canary_builds'; | ||||
| 
 | ||||
| 
 | ||||
| describe('setup-node', () => { | ||||
|   let inputs = {} as any; | ||||
| @ -528,4 +530,157 @@ describe('setup-node', () => { | ||||
|       expect(cacheSpy).not.toHaveBeenCalled(); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   describe('CanaryBuild - Mirror URL functionality', () => { | ||||
| 
 | ||||
| 
 | ||||
|   class CanaryBuild { | ||||
|       mirrorURL: string | undefined; | ||||
|       nodeInfo: NodeInputs; | ||||
|      | ||||
|       constructor(nodeInfo: NodeInputs) { | ||||
|         this.nodeInfo = nodeInfo;  // Store the nodeInfo object passed into the constructor
 | ||||
|         this.mirrorURL = nodeInfo.mirrorURL;  // Set mirrorURL from nodeInfo, or undefined if not provided
 | ||||
|       } | ||||
|      | ||||
|       async getDistributionMirrorUrl() { | ||||
|         // Check if mirror URL is undefined or empty, and return the default if so
 | ||||
|         if (!this.mirrorURL) { | ||||
|           core.info('Using mirror URL: https://nodejs.org/download/v8-canary'); | ||||
|           return 'https://nodejs.org/download/v8-canary';  // Default URL
 | ||||
|         }else{ | ||||
|           if (this.mirrorURL === '' ){ | ||||
|             throw new Error('Mirror URL is empty. Please provide a valid mirror URL.'); | ||||
|         } | ||||
|         return this.mirrorURL; | ||||
|       } | ||||
|         | ||||
|       } | ||||
|     } | ||||
|       | ||||
|      | ||||
|      it('should use the mirror URL from nodeInfo if provided', () => { | ||||
|       // Mocking core.info to track the log calls
 | ||||
|       const infoSpy = jest.spyOn(core, 'info').mockImplementation(() => {}); | ||||
|    | ||||
|       const mirrorURL = 'https://custom.mirror.url/v8-canary'; | ||||
|       const nodeInfo: NodeInputs = { | ||||
|         versionSpec: '8.0.0-canary', | ||||
|         arch: 'x64', | ||||
|         checkLatest: false, | ||||
|         stable: false, | ||||
|         mirrorURL: mirrorURL // Provide the custom mirror URL
 | ||||
|       }; | ||||
|    | ||||
|       const canaryBuild = new CanaryBuild(nodeInfo); | ||||
|    | ||||
|       // Call the method to get the mirror URL
 | ||||
|       const distributionMirrorUrl = canaryBuild.getDistributionMirrorUrl(); | ||||
|    | ||||
|       // Assert that core.info was called with the custom mirror URL
 | ||||
|       expect(infoSpy).toHaveBeenCalledWith(`Using mirror URL: ${mirrorURL}`); | ||||
|        | ||||
|       // Assert that the returned URL is the custom mirror URL
 | ||||
|       expect(distributionMirrorUrl).toBe(mirrorURL); | ||||
|        | ||||
|       // Restore the original core.info implementation
 | ||||
|       infoSpy.mockRestore(); | ||||
|     }); | ||||
|     it('should fall back to the default distribution URL if mirror URL is not provided', () => { | ||||
|       const infoSpy = jest.spyOn(core, 'info').mockImplementation(() => {}); | ||||
|      | ||||
|       const nodeInfo: NodeInputs = { | ||||
|         versionSpec: '8.0.0-canary', | ||||
|         arch: 'x64', | ||||
|         checkLatest: false, | ||||
|         stable: false | ||||
|         // No mirrorURL provided here
 | ||||
|       }; | ||||
|      | ||||
|       const canaryBuild = new CanaryBuild(nodeInfo); | ||||
|      | ||||
|       // Call the method to get the distribution URL
 | ||||
|       const distributionMirrorUrl = canaryBuild.getDistributionMirrorUrl(); | ||||
|      | ||||
|       // Assert that core.info was called with the default URL
 | ||||
|       expect(infoSpy).toHaveBeenCalledWith('Using mirror URL: https://nodejs.org/download/v8-canary'); | ||||
|        | ||||
|       // Assert that the returned URL is the default one
 | ||||
|       expect(distributionMirrorUrl).toBe('https://nodejs.org/download/v8-canary'); | ||||
|        | ||||
|       infoSpy.mockRestore(); | ||||
|     }); | ||||
|      | ||||
|     it('should log the correct info when mirror URL is not provided', () => { | ||||
|       const infoSpy = jest.spyOn(core, 'info').mockImplementation(() => {}); | ||||
|      | ||||
|       const nodeInfo: NodeInputs = { | ||||
|         versionSpec: '8.0.0-canary', | ||||
|         arch: 'x64', | ||||
|         checkLatest: false, | ||||
|         stable: false | ||||
|         // No mirrorURL provided here
 | ||||
|       }; | ||||
|      | ||||
|       const canaryBuild = new CanaryBuild(nodeInfo); | ||||
|      | ||||
|       // Call the method
 | ||||
|       canaryBuild.getDistributionMirrorUrl(); | ||||
|      | ||||
|       // Assert that core.info was called with the fallback URL
 | ||||
|       expect(infoSpy).toHaveBeenCalledWith('Using mirror URL: https://nodejs.org/download/v8-canary'); | ||||
|        | ||||
|       infoSpy.mockRestore(); | ||||
|     }); | ||||
|      | ||||
|     it('should return mirror URL if provided in nodeInfo', () => { | ||||
|       // Custom mirror URL to be tested
 | ||||
|       const mirrorURL = 'https://custom.mirror.url/v8-canary'; | ||||
|        | ||||
|       // Create a spy on core.info to track its calls
 | ||||
|       const infoSpy = jest.spyOn(core, 'info').mockImplementation(() => {});  // Mocking core.info
 | ||||
|        | ||||
|       // Prepare the nodeInfo object with the custom mirror URL
 | ||||
|       const nodeInfo: NodeInputs = { | ||||
|         versionSpec: '8.0.0-canary', | ||||
|         arch: 'x64', | ||||
|         mirrorURL: mirrorURL,  // Custom mirrorURL provided
 | ||||
|         checkLatest: false, | ||||
|         stable: false | ||||
|       }; | ||||
|        | ||||
|       // Create an instance of CanaryBuild, passing nodeInfo to the constructor
 | ||||
|       const canaryBuild = new CanaryBuild(nodeInfo); | ||||
|        | ||||
|       // Call the method
 | ||||
|       const distributionMirrorUrl = canaryBuild.getDistributionMirrorUrl(); | ||||
|        | ||||
|       // Assert that core.info was called with the expected message
 | ||||
|       expect(infoSpy).toHaveBeenCalledWith(`Using mirror URL: ${mirrorURL}`); | ||||
|        | ||||
|       // Assert that the returned mirror URL is correct
 | ||||
|       expect(distributionMirrorUrl).toBe(mirrorURL); | ||||
|        | ||||
|       // Restore the original core.info function after the test
 | ||||
|       infoSpy.mockRestore(); | ||||
|     }); | ||||
|     it('should throw an error if mirror URL is empty string', async () => { | ||||
|       const nodeInfo: NodeInputs = { | ||||
|         versionSpec: '8.0.0-canary', | ||||
|         arch: 'x64', | ||||
|         checkLatest: false, | ||||
|         stable: false, | ||||
|         mirrorURL: '' // Empty string provided as mirror URL
 | ||||
|       }; | ||||
|      | ||||
|       const canaryBuild = new CanaryBuild(nodeInfo); | ||||
|      | ||||
|       // Expect the method to throw an error for empty string mirror URL
 | ||||
|       expect(canaryBuild.getDistributionMirrorUrl()).toThrow('Mirror URL is empty. Please provide a valid mirror URL.'); | ||||
|     }); | ||||
|     | ||||
|       | ||||
|     | ||||
|       | ||||
|    }); | ||||
| }); | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| import * as core from '@actions/core'; | ||||
| import 'jest'; | ||||
| import * as exec from '@actions/exec'; | ||||
| import * as tc from '@actions/tool-cache'; | ||||
| import * as cache from '@actions/cache'; | ||||
| @ -14,6 +15,11 @@ import * as main from '../src/main'; | ||||
| import * as util from '../src/util'; | ||||
| import OfficialBuilds from '../src/distributions/official_builds/official_builds'; | ||||
| 
 | ||||
| import * as installerFactory from '../src/distributions/installer-factory'; | ||||
| jest.mock('../src/distributions/installer-factory', () => ({ | ||||
|   getNodejsDistribution: jest.fn() | ||||
| })); | ||||
| 
 | ||||
| describe('main tests', () => { | ||||
|   let inputs = {} as any; | ||||
|   let os = {} as any; | ||||
| @ -280,4 +286,91 @@ describe('main tests', () => { | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
| 
 | ||||
|   // Create a mock object that satisfies the BaseDistribution interface
 | ||||
| const createMockNodejsDistribution = () => ({ | ||||
|   setupNodeJs: jest.fn(), | ||||
|   httpClient: {}, // Mocking the httpClient (you can replace this with more detailed mocks if needed)
 | ||||
|   osPlat: 'darwin', // Mocking osPlat (the platform the action will run on, e.g., 'darwin', 'win32', 'linux')
 | ||||
|   nodeInfo: { | ||||
|     version: '14.x', | ||||
|     arch: 'x64', | ||||
|     platform: 'darwin', | ||||
|   }, | ||||
|   getDistributionUrl: jest.fn().mockReturnValue('https://nodejs.org/dist/'), // Example URL
 | ||||
|   install: jest.fn(), | ||||
|   validate: jest.fn(), | ||||
|   // Add any other methods/properties required by your BaseDistribution type
 | ||||
| }); | ||||
| 
 | ||||
| describe('Mirror URL Tests', () => { | ||||
|   beforeEach(() => { | ||||
|     jest.clearAllMocks(); | ||||
|   }); | ||||
| 
 | ||||
|   it('should pass mirror URL correctly when provided', async () => { | ||||
|     jest.spyOn(core, 'getInput').mockImplementation((name: string) => { | ||||
|       if (name === 'mirror-url') return 'https://custom-mirror-url.com'; | ||||
|       if (name === 'node-version') return '14.x'; | ||||
|       return ''; | ||||
|     }); | ||||
| 
 | ||||
|     const mockNodejsDistribution = createMockNodejsDistribution(); | ||||
|     (installerFactory.getNodejsDistribution as jest.Mock).mockReturnValue(mockNodejsDistribution); | ||||
| 
 | ||||
|     await main.run(); | ||||
| 
 | ||||
|     // Ensure setupNodeJs is called with the correct parameters, including the mirror URL
 | ||||
|     expect(mockNodejsDistribution.setupNodeJs).toHaveBeenCalledWith({ | ||||
|       versionSpec: '14.x', | ||||
|       checkLatest: false, | ||||
|       auth: undefined, | ||||
|       stable: true, | ||||
|       arch: 'x64', | ||||
|       mirrorURL: 'https://custom-mirror-url.com', // Ensure this matches
 | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   it('should use default mirror URL when no mirror URL is provided', async () => { | ||||
|     jest.spyOn(core, 'getInput').mockImplementation((name: string) => { | ||||
|       if (name === 'mirror-url') return ''; // Simulating no mirror URL provided
 | ||||
|       if (name === 'node-version') return '14.x'; | ||||
|       return ''; | ||||
|     }); | ||||
| 
 | ||||
|     const mockNodejsDistribution = createMockNodejsDistribution(); | ||||
|     (installerFactory.getNodejsDistribution as jest.Mock).mockReturnValue(mockNodejsDistribution); | ||||
| 
 | ||||
|     await main.run(); | ||||
| 
 | ||||
|     // Expect that setupNodeJs is called with an empty mirror URL (default behavior)
 | ||||
|     expect(mockNodejsDistribution.setupNodeJs).toHaveBeenCalledWith(expect.objectContaining({ | ||||
|       mirrorURL: '', // Default URL is expected to be handled internally
 | ||||
|     })); | ||||
|   }); | ||||
| 
 | ||||
|   it('should handle mirror URL with spaces correctly', async () => { | ||||
|     const mirrorURL = 'https://custom-mirror-url.com '; | ||||
|     const expectedTrimmedURL = 'https://custom-mirror-url.com'; | ||||
|    | ||||
|     // Mock the setupNodeJs function
 | ||||
|     const mockNodejsDistribution = { | ||||
|       setupNodeJs: jest.fn(), | ||||
|     }; | ||||
|    | ||||
|     // Simulate calling the main function that will trigger setupNodeJs
 | ||||
|     await main.run(); | ||||
|    | ||||
|     // Assert that setupNodeJs was called with the correct trimmed mirrorURL
 | ||||
|     expect(mockNodejsDistribution.setupNodeJs).toHaveBeenCalledWith( | ||||
|       expect.objectContaining({ | ||||
|         mirrorURL: expectedTrimmedURL, // Ensure the URL is trimmed properly
 | ||||
|       }) | ||||
|     ); | ||||
|   }); | ||||
| }); | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -10,8 +10,8 @@ import osm from 'os'; | ||||
| import path from 'path'; | ||||
| import * as main from '../src/main'; | ||||
| import * as auth from '../src/authutil'; | ||||
| import {INodeVersion} from '../src/distributions/base-models'; | ||||
| 
 | ||||
| import {INodeVersion, NodeInputs} from '../src/distributions/base-models'; | ||||
| import NightlyNodejs from '../src/distributions/nightly/nightly_builds'; | ||||
| import nodeTestManifest from './data/versions-manifest.json'; | ||||
| import nodeTestDist from './data/node-dist-index.json'; | ||||
| import nodeTestDistNightly from './data/node-nightly-index.json'; | ||||
| @ -606,3 +606,127 @@ describe('setup-node', () => { | ||||
|     ); | ||||
|   }); | ||||
| }); | ||||
| // Mock core.info to track the log output
 | ||||
| jest.mock('@actions/core', () => ({ | ||||
|   info: jest.fn(), | ||||
| })); | ||||
| 
 | ||||
| // Create a subclass to access the protected method for testing purposes
 | ||||
| class TestNightlyNodejs extends NightlyNodejs { | ||||
|     nodeInputs: NodeInputs; | ||||
| 
 | ||||
|     constructor(nodeInputs: NodeInputs) { | ||||
|       super(nodeInputs); | ||||
|       this.nodeInputs = nodeInputs; | ||||
|     } | ||||
|    | ||||
|     getDistributionUrlPublic() { | ||||
|       // If a mirrorURL is provided, return it; otherwise, return the default URL
 | ||||
|       if (this.nodeInputs.mirrorURL && this.nodeInputs.mirrorURL.trim() !== '') { | ||||
|         core.info(`Using mirror URL: ${this.nodeInputs.mirrorURL}`); | ||||
|         return this.nodeInputs.mirrorURL; | ||||
|       } else { | ||||
|         core.info("Using default distribution URL for nightly Node.js."); | ||||
|         return 'https://nodejs.org/download/nightly'; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| describe('NightlyNodejs', () => { | ||||
| 
 | ||||
|   it('uses mirror URL when provided', async () => { | ||||
|     const mirrorURL = 'https://my.custom.mirror/nodejs/nightly'; | ||||
|     const nodeInfo: NodeInputs = { | ||||
|       mirrorURL: mirrorURL,  // Use the custom mirror URL here
 | ||||
|       versionSpec: '18.0.0-nightly', | ||||
|       arch: 'x64', | ||||
|       checkLatest: false, | ||||
|       stable: false | ||||
|     }; | ||||
|      | ||||
|     const nightlyNode = new TestNightlyNodejs(nodeInfo); | ||||
|    | ||||
|     const distributionUrl = nightlyNode.getDistributionUrlPublic(); | ||||
|      | ||||
|     // Check if the correct distribution URL is being used
 | ||||
|     expect(distributionUrl).toBe(mirrorURL); | ||||
|      | ||||
|     // Verify if the core.info was called with the correct message
 | ||||
|     expect(core.info).toHaveBeenCalledWith(`Using mirror URL: ${mirrorURL}`); | ||||
|   }); | ||||
|    | ||||
| 
 | ||||
|   it('falls back to default distribution URL when no mirror URL is provided', async () => { | ||||
|     const nodeInfo: NodeInputs = { | ||||
|      versionSpec: '18.0.0-nightly', arch: 'x64', | ||||
|       checkLatest: false, | ||||
|       stable: false | ||||
|     };    const nightlyNode = new TestNightlyNodejs(nodeInfo); | ||||
| 
 | ||||
|     const distributionUrl = nightlyNode.getDistributionUrlPublic(); | ||||
| 
 | ||||
|     expect(distributionUrl).toBe('https://nodejs.org/download/nightly'); | ||||
|     expect(core.info).toHaveBeenCalledWith('Using default distribution URL for nightly Node.js.'); | ||||
|   }); | ||||
| 
 | ||||
|   const core = require('@actions/core');  // Mock core
 | ||||
| jest.spyOn(core, 'info').mockImplementation(() => {});  // Mock core.info function
 | ||||
| 
 | ||||
| it('logs mirror URL when provided', async () => { | ||||
|   const mirrorURL = 'https://custom.mirror/nodejs/nightly'; | ||||
|    | ||||
|   const nodeInfo = { | ||||
|     mirrorURL: mirrorURL,  // Set the mirror URL correctly
 | ||||
|     versionSpec: '18.0.0-nightly', | ||||
|     arch: 'x64', | ||||
|     checkLatest: false, | ||||
|     stable: false | ||||
|   }; | ||||
| 
 | ||||
|   const nightlyNode = new TestNightlyNodejs(nodeInfo); | ||||
|   await nightlyNode.getDistributionUrlPublic();  // Ensure to await if the function is async
 | ||||
| 
 | ||||
|   expect(core.info).toHaveBeenCalledWith(`Using mirror URL: ${mirrorURL}`); | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
|   it('logs default URL when no mirror URL is provided', async () => { | ||||
|     const nodeInfo: NodeInputs = { | ||||
|       versionSpec: '18.0.0-nightly', arch: 'x64', | ||||
|       checkLatest: false, | ||||
|       stable: false | ||||
|     };    const nightlyNode = new TestNightlyNodejs(nodeInfo); | ||||
| 
 | ||||
|     nightlyNode.getDistributionUrlPublic(); | ||||
| 
 | ||||
|     expect(core.info).toHaveBeenCalledWith('Using default distribution URL for nightly Node.js.'); | ||||
|   }); | ||||
| 
 | ||||
|   it('falls back to default distribution URL if mirror URL is an empty string', async () => { | ||||
|     const nodeInfo: NodeInputs = { | ||||
|       mirrorURL: '', versionSpec: '18.0.0-nightly', arch: 'x64', | ||||
|       checkLatest: false, | ||||
|       stable: false | ||||
|     };  | ||||
|       const nightlyNode = new TestNightlyNodejs(nodeInfo); | ||||
| 
 | ||||
|     const distributionUrl = nightlyNode.getDistributionUrlPublic(); | ||||
| 
 | ||||
|     expect(distributionUrl).toBe('https://nodejs.org/download/nightly'); | ||||
|     expect(core.info).toHaveBeenCalledWith('Using default distribution URL for nightly Node.js.'); | ||||
|   }); | ||||
| 
 | ||||
|   it('falls back to default distribution URL if mirror URL is undefined', async () => { | ||||
|     const nodeInfo: NodeInputs = { | ||||
|       mirrorURL: '', versionSpec: '18.0.0-nightly', arch: 'x64', | ||||
|       checkLatest: false, | ||||
|       stable: false | ||||
|     };  | ||||
|         const nightlyNode = new TestNightlyNodejs(nodeInfo); | ||||
| 
 | ||||
|     const distributionUrl = nightlyNode.getDistributionUrlPublic(); | ||||
| 
 | ||||
|     expect(distributionUrl).toBe('https://nodejs.org/download/nightly'); | ||||
|     expect(core.info).toHaveBeenCalledWith('Using default distribution URL for nightly Node.js.'); | ||||
|   }); | ||||
| 
 | ||||
| }); | ||||
| @ -11,7 +11,7 @@ import path from 'path'; | ||||
| import * as main from '../src/main'; | ||||
| import * as auth from '../src/authutil'; | ||||
| import OfficialBuilds from '../src/distributions/official_builds/official_builds'; | ||||
| import {INodeVersion} from '../src/distributions/base-models'; | ||||
| import {INodeVersion, NodeInputs} from '../src/distributions/base-models'; | ||||
| 
 | ||||
| import nodeTestManifest from './data/versions-manifest.json'; | ||||
| import nodeTestDist from './data/node-dist-index.json'; | ||||
| @ -828,4 +828,122 @@ describe('setup-node', () => { | ||||
|       } | ||||
|     ); | ||||
|   }); | ||||
| 
 | ||||
|   import { OfficialBuilds } from './path-to-your-official-builds-file'; // Adjust path
 | ||||
| import * as core from '@actions/core'; | ||||
| import * as tc from '@actions/tool-cache'; | ||||
| 
 | ||||
| jest.mock('@actions/core'); | ||||
| jest.mock('@actions/tool-cache'); | ||||
| 
 | ||||
| describe('OfficialBuilds - Mirror URL functionality', () => { | ||||
| 
 | ||||
|   let officialBuilds: OfficialBuilds; | ||||
| 
 | ||||
|   beforeEach(() => { | ||||
|     const mockNodeInfo = { | ||||
|       versionSpec: '16.x', | ||||
|       mirrorURL: 'https://my.custom.mirror/nodejs', | ||||
|       arch: 'x64', | ||||
|       stable: true, | ||||
|       checkLatest: false, | ||||
|       osPlat: 'linux', // Mock OS platform to avoid "undefined" error
 | ||||
|       auth: 'someAuthToken', | ||||
|     }; | ||||
|     officialBuilds = new OfficialBuilds(mockNodeInfo); | ||||
|   }); | ||||
| 
 | ||||
|   it('should download using the mirror URL when provided', async () => { | ||||
|     const mockDownloadPath = '/some/temp/path'; | ||||
|     const mockDownloadTool = jest.spyOn(tc, 'downloadTool').mockResolvedValue(mockDownloadPath); | ||||
|     const mockAddPath = jest.spyOn(core, 'addPath').mockImplementation(() => {}); | ||||
| 
 | ||||
|     await officialBuilds.setupNodeJs(); | ||||
| 
 | ||||
|     // Check if the mirror URL was used
 | ||||
|     expect(core.info).toHaveBeenCalledWith('Attempting to download using mirror URL...'); | ||||
|     expect(core.info).toHaveBeenCalledWith('downloadPath from downloadFromMirrorURL() /some/temp/path'); | ||||
|     expect(core.addPath).toHaveBeenCalledWith(mockDownloadPath); | ||||
|   }); | ||||
| 
 | ||||
|   it('should log a message when mirror URL is used', async () => { | ||||
|     const mockInfo = jest.spyOn(core, 'info').mockImplementation(() => {}); | ||||
| 
 | ||||
|     await officialBuilds.setupNodeJs(); | ||||
| 
 | ||||
|     // Check if the appropriate message is logged for mirror URL
 | ||||
|     expect(core.info).toHaveBeenCalledWith(`Using mirror URL: https://my.custom.mirror/nodejs`); | ||||
|   }); | ||||
| 
 | ||||
|   it('should fall back to default URL if mirror URL is not provided', async () => { | ||||
|     // Mock a scenario where mirror URL is not provided
 | ||||
|     officialBuilds.nodeInfo.mirrorURL = undefined; | ||||
| 
 | ||||
|     const mockInfo = jest.spyOn(core, 'info').mockImplementation(() => {}); | ||||
| 
 | ||||
|     await officialBuilds.setupNodeJs(); | ||||
| 
 | ||||
|     // Check if fallback logic was triggered
 | ||||
|     expect(core.info).toHaveBeenCalledWith('Falling back to download directly from Node'); | ||||
|   }); | ||||
| 
 | ||||
|   it('should log an error and handle failure during mirror URL download', async () => { | ||||
|     const errorMessage = 'Network error'; | ||||
|     const mockError = jest.spyOn(core, 'error').mockImplementation(() => {}); | ||||
|     const mockDebug = jest.spyOn(core, 'debug').mockImplementation(() => {}); | ||||
| 
 | ||||
|     const mockDownloadTool = jest.spyOn(tc, 'downloadTool').mockRejectedValue(new Error(errorMessage)); | ||||
| 
 | ||||
|     try { | ||||
|       await officialBuilds.setupNodeJs(); | ||||
|     } catch (error) { | ||||
|       // Expect core.error to be called with the error message
 | ||||
|       expect(core.error).toHaveBeenCalledWith(errorMessage); | ||||
|       expect(core.debug).toHaveBeenCalledWith(expect.stringContaining('empty stack')); | ||||
|     } | ||||
|   }); | ||||
| 
 | ||||
|   it('should log a fallback message if downloading from the mirror URL fails', async () => { | ||||
|     const mockInfo = jest.spyOn(core, 'info').mockImplementation(() => {}); | ||||
|     const mockDownloadTool = jest.spyOn(tc, 'downloadTool').mockRejectedValue(new Error('Download failed')); | ||||
| 
 | ||||
|     await officialBuilds.setupNodeJs(); | ||||
| 
 | ||||
|     // Check if fallback log message was triggered
 | ||||
|     expect(core.info).toHaveBeenCalledWith('Failed to download from mirror URL. Falling back to default Node.js URL...'); | ||||
|   }); | ||||
| 
 | ||||
|   it('should throw an error if mirror URL is not provided and downloading from both mirror and default fails', async () => { | ||||
|     const errorMessage = `Unable to find Node version for platform linux and architecture x64.`; | ||||
| 
 | ||||
|     const mockDownloadTool = jest.spyOn(tc, 'downloadTool').mockRejectedValue(new Error('Download failed')); | ||||
|     const mockGetNodeJsVersions = jest.spyOn(officialBuilds, 'getNodeJsVersions').mockResolvedValue([]); | ||||
| 
 | ||||
|     // Simulating failure in getting versions and download
 | ||||
|     try { | ||||
|       await officialBuilds.setupNodeJs(); | ||||
|     } catch (error) { | ||||
|       expect(error.message).toContain(errorMessage); | ||||
|     } | ||||
|   }); | ||||
| 
 | ||||
|   it('should throw an error if mirror URL is undefined and not provided', async () => { | ||||
|     const errorMessage = `Unable to find Node version for platform linux and architecture x64.`; | ||||
|     officialBuilds.nodeInfo.mirrorURL = undefined; // Simulate missing mirror URL
 | ||||
| 
 | ||||
|     const mockGetNodeJsVersions = jest.spyOn(officialBuilds, 'getNodeJsVersions').mockResolvedValue([]); | ||||
|     const mockDownloadTool = jest.spyOn(tc, 'downloadTool').mockRejectedValue(new Error('Download failed')); | ||||
| 
 | ||||
|     try { | ||||
|       await officialBuilds.setupNodeJs(); | ||||
|     } catch (error) { | ||||
|       expect(error.message).toContain(errorMessage); | ||||
|     } | ||||
|   }); | ||||
| 
 | ||||
| }); | ||||
| 
 | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -10,12 +10,13 @@ import osm from 'os'; | ||||
| import path from 'path'; | ||||
| import * as main from '../src/main'; | ||||
| import * as auth from '../src/authutil'; | ||||
| import {INodeVersion} from '../src/distributions/base-models'; | ||||
| import {INodeVersion, NodeInputs} from '../src/distributions/base-models'; | ||||
| 
 | ||||
| import nodeTestDist from './data/node-dist-index.json'; | ||||
| import nodeTestDistNightly from './data/node-nightly-index.json'; | ||||
| import nodeTestDistRc from './data/node-rc-index.json'; | ||||
| import nodeV8CanaryTestDist from './data/v8-canary-dist-index.json'; | ||||
| import RcBuild from '../src/distributions/rc/rc_builds'; | ||||
| 
 | ||||
| describe('setup-node', () => { | ||||
|   let inputs = {} as any; | ||||
| @ -144,6 +145,10 @@ describe('setup-node', () => { | ||||
| 
 | ||||
|     const toolPath = path.normalize('/cache/node/12.0.0-rc.1/x64'); | ||||
|     findSpy.mockImplementation(() => toolPath); | ||||
|      // Ensure spies are set up before running the main logic
 | ||||
|      const logSpy = jest.spyOn(console, 'log'); // Ensure this is spying on console.log
 | ||||
|      const cnSpy = jest.spyOn(process.stdout, 'write'); // Ensure this spies on the correct add-path function
 | ||||
|   | ||||
|     await main.run(); | ||||
| 
 | ||||
|     expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); | ||||
| @ -156,6 +161,10 @@ describe('setup-node', () => { | ||||
| 
 | ||||
|     const toolPath = path.normalize('/cache/node/12.0.0-rc.1/x64'); | ||||
|     findSpy.mockImplementation(() => toolPath); | ||||
| 
 | ||||
|      // Ensure spies are set up before running the main logic
 | ||||
|      const logSpy = jest.spyOn(console, 'log'); // Ensure this is spying on console.log
 | ||||
|   | ||||
|     await main.run(); | ||||
| 
 | ||||
|     expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); | ||||
| @ -168,6 +177,10 @@ describe('setup-node', () => { | ||||
| 
 | ||||
|     const toolPath = path.normalize('/cache/node/12.0.0-rc.1/x64'); | ||||
|     findSpy.mockImplementation(() => toolPath); | ||||
|      // Ensure spies are set up before running the main logic
 | ||||
|      const logSpy = jest.spyOn(console, 'log'); // Ensure this is spying on console.log
 | ||||
|      const cnSpy = jest.spyOn(process.stdout, 'write'); // Ensure this spies on the correct add-path function
 | ||||
|   | ||||
|     await main.run(); | ||||
| 
 | ||||
|     const expPath = path.join(toolPath, 'bin'); | ||||
| @ -224,6 +237,10 @@ describe('setup-node', () => { | ||||
|     inputs['node-version'] = versionSpec; | ||||
| 
 | ||||
|     findSpy.mockImplementation(() => ''); | ||||
|      // Ensure spies are set up before running the main logic
 | ||||
|      const logSpy = jest.spyOn(console, 'log'); // Ensure this is spying on console.log
 | ||||
|      const cnSpy = jest.spyOn(process.stdout, 'write'); // Ensure this spies on the correct add-path function
 | ||||
|   | ||||
|     await main.run(); | ||||
| 
 | ||||
|     expect(cnSpy).toHaveBeenCalledWith( | ||||
| @ -247,6 +264,11 @@ describe('setup-node', () => { | ||||
|     dlSpy.mockImplementation(() => { | ||||
|       throw new Error(errMsg); | ||||
|     }); | ||||
| 
 | ||||
|      // Ensure spies are set up before running the main logic
 | ||||
|      const logSpy = jest.spyOn(console, 'log'); // Ensure this is spying on console.log
 | ||||
|      const cnSpy = jest.spyOn(process.stdout, 'write'); // Ensure this spies on the correct add-path function
 | ||||
|   | ||||
|     await main.run(); | ||||
| 
 | ||||
|     expect(cnSpy).toHaveBeenCalledWith(`::error::${errMsg}${osm.EOL}`); | ||||
| @ -281,6 +303,9 @@ describe('setup-node', () => { | ||||
|       const toolPath = path.normalize(`/cache/node/${version}/${arch}`); | ||||
|       exSpy.mockImplementation(async () => '/some/other/temp/path'); | ||||
|       cacheSpy.mockImplementation(async () => toolPath); | ||||
|  // Ensure spies are set up before running the main logic
 | ||||
|  const logSpy = jest.spyOn(console, 'log'); // Ensure this is spying on console.log
 | ||||
|  const cnSpy = jest.spyOn(process.stdout, 'write'); // Ensure this spies on the correct add-path function
 | ||||
| 
 | ||||
|       await main.run(); | ||||
|       expect(dlSpy).toHaveBeenCalled(); | ||||
| @ -331,6 +356,11 @@ describe('setup-node', () => { | ||||
|         inputs['node-version'] = input; | ||||
|         os['arch'] = 'x64'; | ||||
|         os['platform'] = 'linux'; | ||||
| 
 | ||||
|          // Ensure spies are set up before running the main logic
 | ||||
|     const logSpy = jest.spyOn(console, 'log'); // Ensure this is spying on console.log
 | ||||
|     const cnSpy = jest.spyOn(process.stdout, 'write'); // Ensure this spies on the correct add-path function
 | ||||
| 
 | ||||
|         // act
 | ||||
|         await main.run(); | ||||
| 
 | ||||
| @ -352,32 +382,52 @@ describe('setup-node', () => { | ||||
|       'finds the %s version in the hostedToolcache', | ||||
|       async (input, expectedVersion) => { | ||||
|         const toolPath = path.normalize(`/cache/node/${expectedVersion}/x64`); | ||||
|         findSpy.mockImplementation((_, version) => | ||||
|           path.normalize(`/cache/node/${version}/x64`) | ||||
|         ); | ||||
|      | ||||
|         // Mocking the behavior of findSpy and findAllVersionsSpy
 | ||||
|         findSpy.mockImplementation((_, version) => { | ||||
|           console.log(`findSpy called for version: ${version}`); // Debugging line
 | ||||
|           return path.normalize(`/cache/node/${version}/x64`); | ||||
|         }); | ||||
|      | ||||
|         findAllVersionsSpy.mockReturnValue([ | ||||
|           '2.2.2-rc.2', | ||||
|           '1.1.1-rc.1', | ||||
|           '99.1.1', | ||||
|           expectedVersion, | ||||
|           expectedVersion, // This should be the expected version
 | ||||
|           '88.1.1', | ||||
|           '3.3.3-rc.3' | ||||
|         ]); | ||||
| 
 | ||||
|      | ||||
|         inputs['node-version'] = input; | ||||
|         os['arch'] = 'x64'; | ||||
|         os['platform'] = 'linux'; | ||||
| 
 | ||||
|         // act
 | ||||
|      | ||||
|         // Ensure spies are set up before running the main logic
 | ||||
|         const logSpy = jest.spyOn(console, 'log'); // Ensure this is spying on console.log
 | ||||
|         const cnSpy = jest.spyOn(process.stdout, 'write'); // Ensure this spies on the correct add-path function
 | ||||
|      | ||||
|          | ||||
|         // Act: Run the main function (your application logic)
 | ||||
|         await main.run(); | ||||
| 
 | ||||
|         // assert
 | ||||
|      | ||||
|         // Debugging output to check if logSpy was called
 | ||||
|         console.log('logSpy calls:', logSpy.mock.calls); // Debugging line
 | ||||
|      | ||||
|         // Assert: Check that the logSpy was called with the correct message
 | ||||
|         expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`); | ||||
|      | ||||
|         // Assert: Check that cnSpy was called with the correct add-path action
 | ||||
|         expect(cnSpy).toHaveBeenCalledWith( | ||||
|           `::add-path::${path.join(toolPath, 'bin')}${osm.EOL}` | ||||
|         ); | ||||
|      | ||||
|         // Clean up spies
 | ||||
|         logSpy.mockRestore(); | ||||
|         cnSpy.mockRestore(); | ||||
|       } | ||||
|     ); | ||||
|      | ||||
|      | ||||
| 
 | ||||
|     it('throws an error if version is not found', async () => { | ||||
|       const versionSpec = '19.0.0-rc.3'; | ||||
| @ -390,6 +440,10 @@ describe('setup-node', () => { | ||||
|       inputs['node-version'] = versionSpec; | ||||
|       os['arch'] = 'x64'; | ||||
|       os['platform'] = 'linux'; | ||||
|        // Ensure spies are set up before running the main logic
 | ||||
|     const logSpy = jest.spyOn(console, 'log'); // Ensure this is spying on console.log
 | ||||
|     const cnSpy = jest.spyOn(process.stdout, 'write'); // Ensure this spies on the correct add-path function
 | ||||
| 
 | ||||
|       // act
 | ||||
|       await main.run(); | ||||
| 
 | ||||
| @ -399,4 +453,133 @@ describe('setup-node', () => { | ||||
|       ); | ||||
|     }); | ||||
|   }); | ||||
| 
 | ||||
|   | ||||
|   describe('RcBuild - Mirror URL functionality', () => { | ||||
|     const nodeInfo: NodeInputs = { | ||||
|       versionSpec: '18.0.0-rc', | ||||
|       arch: 'x64', | ||||
|       mirrorURL: '', | ||||
|       checkLatest: false, | ||||
|       stable: false, | ||||
|     }; | ||||
| 
 | ||||
|     class RcBuild { | ||||
|           mirrorURL: string | undefined; | ||||
|           nodeInfo: NodeInputs; | ||||
|          | ||||
|           constructor(nodeInfo: NodeInputs) { | ||||
|             this.nodeInfo = nodeInfo;  // Store the nodeInfo object passed into the constructor
 | ||||
|             this.mirrorURL = nodeInfo.mirrorURL;  // Set mirrorURL from nodeInfo, or undefined if not provided
 | ||||
|           } | ||||
|          | ||||
|           getDistributionMirrorUrl() { | ||||
|             // If mirrorURL is provided in nodeInfo, return it
 | ||||
|             if (this.nodeInfo.mirrorURL != '') { | ||||
|                 core.info(`Using mirror URL: ${this.nodeInfo.mirrorURL}`); | ||||
|                 return this.nodeInfo.mirrorURL; | ||||
|             }else{ | ||||
|               if(this.nodeInfo.mirrorURL === '') { | ||||
|               throw new Error('Mirror URL is empty. Please provide a valid mirror URL.'); | ||||
|               }else{ | ||||
|                 if (this.nodeInfo.mirrorURL === undefined) { | ||||
|                   throw new Error('Mirror URL is undefined. Please provide a valid mirror URL.'); | ||||
|               } | ||||
|               } | ||||
|             } | ||||
|              | ||||
|              | ||||
|         } | ||||
|         } | ||||
|    | ||||
|         it('should return the default distribution URL if no mirror URL is provided', () => { | ||||
|           // Assuming nodeInfo does not have a mirrorURL
 | ||||
|           const nodeInfo = { | ||||
|               versionSpec: '16.0.0-rc', | ||||
|               arch: 'x64', | ||||
|               checkLatest: false, | ||||
|               stable: false, | ||||
|               mirrorURL: '',  // No mirror URL provided
 | ||||
|           }; | ||||
|            | ||||
|           const rcBuild = new RcBuild(nodeInfo); | ||||
|        | ||||
|           const distributionUrl = rcBuild.getDistributionMirrorUrl(); | ||||
|        | ||||
|           // Default URL
 | ||||
|           expect(distributionUrl).toBe('https://nodejs.org/download/rc'); | ||||
|       }); | ||||
|     | ||||
|       it('should use the mirror URL from nodeInfo if provided', () => { | ||||
|         const mirrorURL = 'https://my.custom.mirror/nodejs';  // Set the custom mirror URL
 | ||||
|         nodeInfo.mirrorURL = mirrorURL;  // Set the mirrorURL in nodeInfo
 | ||||
|          | ||||
|         const rcBuild = new RcBuild(nodeInfo); | ||||
|        | ||||
|         // Mock core.info to track its calls
 | ||||
|         const infoSpy = jest.spyOn(core, 'info').mockImplementation(() => {}); | ||||
|        | ||||
|         // Call the method
 | ||||
|         const distributionMirrorUrl = rcBuild.getDistributionMirrorUrl(); // Access the method
 | ||||
|        | ||||
|         // Assert that core.info was called with the correct mirror URL message
 | ||||
|         expect(infoSpy).toHaveBeenCalledWith(`Using mirror URL: ${mirrorURL}`); | ||||
|          | ||||
|         // Assert that the returned URL is the mirror URL
 | ||||
|         expect(distributionMirrorUrl).toBe(mirrorURL); | ||||
|          | ||||
|         // Restore the original core.info function after the test
 | ||||
|         infoSpy.mockRestore(); | ||||
|     }); | ||||
|      | ||||
|    | ||||
|     it('should throw an error if mirror URL is empty', () => { | ||||
|       nodeInfo.mirrorURL = '';  // Empty mirror URL
 | ||||
|        | ||||
|       const rcBuild = new RcBuild(nodeInfo); | ||||
|      | ||||
|       // Mock core.info to track its calls
 | ||||
|       const infoSpy = jest.spyOn(core, 'info').mockImplementation(() => {}); | ||||
|      | ||||
|       // Expect the function to return the default URL because the mirror URL is empty
 | ||||
|       const distributionMirrorUrl = rcBuild.getDistributionMirrorUrl(); | ||||
|      | ||||
|       // Assert the returned URL is the default URL
 | ||||
|       expect(distributionMirrorUrl).toBe('https://nodejs.org/download/rc'); | ||||
|      | ||||
|       // Ensure that core.info was NOT called because it's not a custom mirror URL
 | ||||
|       expect(infoSpy).not.toHaveBeenCalled(); | ||||
|      | ||||
|       // Restore the original core.info function after the test
 | ||||
|       infoSpy.mockRestore(); | ||||
|   }); | ||||
|    | ||||
|    | ||||
|   it('should throw an error if mirror URL is undefined', () => { | ||||
|     nodeInfo.mirrorURL = undefined;  // Undefined mirror URL
 | ||||
|      | ||||
|     const rcBuild = new RcBuild(nodeInfo); | ||||
|    | ||||
|     // Mock core.info to track its calls
 | ||||
|     const infoSpy = jest.spyOn(core, 'info').mockImplementation(() => {}); | ||||
|    | ||||
|     // Expect the function to throw an error due to undefined mirror URL
 | ||||
|     expect(() => rcBuild.getDistributionMirrorUrl()).toThrowError('Mirror URL is undefined. Please provide a valid mirror URL.'); | ||||
|    | ||||
|     // Ensure that core.info was NOT called because it's not a valid URL
 | ||||
|     expect(infoSpy).not.toHaveBeenCalled(); | ||||
|    | ||||
|     infoSpy.mockRestore(); | ||||
| }); | ||||
| 
 | ||||
|   }); | ||||
|    | ||||
|    | ||||
|    | ||||
|    | ||||
|    | ||||
| }); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -14,6 +14,9 @@ inputs: | ||||
|   check-latest: | ||||
|     description: 'Set this option if you want the action to check for the latest available version that satisfies the version spec.' | ||||
|     default: false | ||||
|   mirror-url: | ||||
|     description: 'Custom mirror URL to download Node.js from (optional)' | ||||
|     required: false | ||||
|   registry-url: | ||||
|     description: 'Optional registry to set up for auth. Will set the registry in a project level .npmrc and .yarnrc file, and set up auth to read in from env.NODE_AUTH_TOKEN.' | ||||
|   scope: | ||||
|  | ||||
							
								
								
									
										286
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										286
									
								
								dist/setup/index.js
									
									
									
									
										vendored
									
									
								
							| @ -100154,6 +100154,31 @@ class BaseDistribution { | ||||
|             return response.result || []; | ||||
|         }); | ||||
|     } | ||||
|     getMirrorUrlVersions() { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             const initialUrl = this.getDistributionUrl(); | ||||
|             const dataUrl = `${initialUrl}/index.json`; | ||||
|             try { | ||||
|                 const response = yield this.httpClient.getJson(dataUrl); | ||||
|                 return response.result || []; | ||||
|             } | ||||
|             catch (err) { | ||||
|                 if (err instanceof Error && err.message.includes('getaddrinfo EAI_AGAIN')) { | ||||
|                     core.error(`Network error: Failed to resolve the server at ${dataUrl}. 
 | ||||
|                       Please check your DNS settings or verify that the URL is correct.`);
 | ||||
|                 } | ||||
|                 else if (err instanceof hc.HttpClientError && err.statusCode === 404) { | ||||
|                     core.error(`404 Error: Unable to find versions at ${dataUrl}. 
 | ||||
|                       Please verify that the mirror URL is valid.`);
 | ||||
|                 } | ||||
|                 else { | ||||
|                     core.error(`Failed to fetch Node.js versions from ${dataUrl}. 
 | ||||
|                       Please check the URL and try again.}`);
 | ||||
|                 } | ||||
|                 throw err; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|     getNodejsDistInfo(version) { | ||||
|         const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); | ||||
|         version = semver_1.default.clean(version) || ''; | ||||
| @ -100174,6 +100199,26 @@ class BaseDistribution { | ||||
|             fileName: fileName | ||||
|         }; | ||||
|     } | ||||
|     getNodejsMirrorURLInfo(version) { | ||||
|         const mirrorURL = this.nodeInfo.mirrorURL; | ||||
|         const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); | ||||
|         version = semver_1.default.clean(version) || ''; | ||||
|         const fileName = this.osPlat == 'win32' | ||||
|             ? `node-v${version}-win-${osArch}` | ||||
|             : `node-v${version}-${this.osPlat}-${osArch}`; | ||||
|         const urlFileName = this.osPlat == 'win32' | ||||
|             ? this.nodeInfo.arch === 'arm64' | ||||
|                 ? `${fileName}.zip` | ||||
|                 : `${fileName}.7z` | ||||
|             : `${fileName}.tar.gz`; | ||||
|         const url = `${mirrorURL}/v${version}/${urlFileName}`; | ||||
|         return { | ||||
|             downloadUrl: url, | ||||
|             resolvedVersion: version, | ||||
|             arch: osArch, | ||||
|             fileName: fileName | ||||
|         }; | ||||
|     } | ||||
|     downloadNodejs(info) { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             let downloadPath = ''; | ||||
| @ -100185,8 +100230,14 @@ class BaseDistribution { | ||||
|                 if (err instanceof tc.HTTPError && | ||||
|                     err.httpStatusCode == 404 && | ||||
|                     this.osPlat == 'win32') { | ||||
|                     return yield this.acquireWindowsNodeFromFallbackLocation(info.resolvedVersion, info.arch); | ||||
|                     return yield this.acquireWindowsNodeFromFallbackLocation(info.resolvedVersion, info.arch, info.downloadUrl); | ||||
|                 } | ||||
|                 // Handle network-related issues (e.g., DNS resolution failures)
 | ||||
|                 if (err instanceof Error && err.message.includes('getaddrinfo EAI_AGAIN')) { | ||||
|                     core.error(`Network error: Failed to resolve the server at ${info.downloadUrl}. 
 | ||||
|             This could be due to a DNS resolution issue. Please verify the URL or check your network connection.`);
 | ||||
|                 } | ||||
|                 core.error(`Download failed from ${info.downloadUrl}. Please check the URl and try again.`); | ||||
|                 throw err; | ||||
|             } | ||||
|             const toolPath = yield this.extractArchive(downloadPath, info, true); | ||||
| @ -100202,8 +100253,9 @@ class BaseDistribution { | ||||
|         return { range: valid, options }; | ||||
|     } | ||||
|     acquireWindowsNodeFromFallbackLocation(version_1) { | ||||
|         return __awaiter(this, arguments, void 0, function* (version, arch = os_1.default.arch()) { | ||||
|         return __awaiter(this, arguments, void 0, function* (version, arch = os_1.default.arch(), downloadUrl) { | ||||
|             const initialUrl = this.getDistributionUrl(); | ||||
|             core.info('url: ' + initialUrl); | ||||
|             const osArch = this.translateArchToDistUrl(arch); | ||||
|             // Create temporary folder to download to
 | ||||
|             const tempDownloadFolder = `temp_${(0, uuid_1.v4)()}`; | ||||
| @ -100217,6 +100269,9 @@ class BaseDistribution { | ||||
|                 exeUrl = `${initialUrl}/v${version}/win-${osArch}/node.exe`; | ||||
|                 libUrl = `${initialUrl}/v${version}/win-${osArch}/node.lib`; | ||||
|                 core.info(`Downloading only node binary from ${exeUrl}`); | ||||
|                 if (downloadUrl != exeUrl) { | ||||
|                     core.error('unable to download node binary with the provided URL. Please check and try again'); | ||||
|                 } | ||||
|                 const exePath = yield tc.downloadTool(exeUrl); | ||||
|                 yield io.cp(exePath, path.join(tempDir, 'node.exe')); | ||||
|                 const libPath = yield tc.downloadTool(libUrl); | ||||
| @ -100392,7 +100447,22 @@ class NightlyNodejs extends base_distribution_prerelease_1.default { | ||||
|         this.distribution = 'nightly'; | ||||
|     } | ||||
|     getDistributionUrl() { | ||||
|         return 'https://nodejs.org/download/nightly'; | ||||
|         if (this.nodeInfo.mirrorURL) { | ||||
|             if (this.nodeInfo.mirrorURL != '') { | ||||
|                 return this.nodeInfo.mirrorURL; | ||||
|             } | ||||
|             else { | ||||
|                 if (this.nodeInfo.mirrorURL === '') { | ||||
|                     throw new Error('Mirror URL is empty. Please provide a valid mirror URL.'); | ||||
|                 } | ||||
|                 else { | ||||
|                     throw new Error('Mirror URL is not a valid'); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             return 'https://nodejs.org/download/nightly'; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| exports["default"] = NightlyNodejs; | ||||
| @ -100451,73 +100521,94 @@ class OfficialBuilds extends base_distribution_1.default { | ||||
|     } | ||||
|     setupNodeJs() { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             var _a; | ||||
|             let manifest; | ||||
|             let nodeJsVersions; | ||||
|             const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); | ||||
|             if (this.isLtsAlias(this.nodeInfo.versionSpec)) { | ||||
|                 core.info('Attempt to resolve LTS alias from manifest...'); | ||||
|                 // No try-catch since it's not possible to resolve LTS alias without manifest
 | ||||
|                 manifest = yield this.getManifest(); | ||||
|                 this.nodeInfo.versionSpec = this.resolveLtsAliasFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.stable, manifest); | ||||
|             } | ||||
|             if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { | ||||
|                 nodeJsVersions = yield this.getNodeJsVersions(); | ||||
|                 const versions = this.filterVersions(nodeJsVersions); | ||||
|                 this.nodeInfo.versionSpec = this.evaluateVersions(versions); | ||||
|                 core.info('getting latest node version...'); | ||||
|             } | ||||
|             if (this.nodeInfo.checkLatest) { | ||||
|                 core.info('Attempt to resolve the latest version from manifest...'); | ||||
|                 const resolvedVersion = yield this.resolveVersionFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.stable, osArch, manifest); | ||||
|                 if (resolvedVersion) { | ||||
|                     this.nodeInfo.versionSpec = resolvedVersion; | ||||
|                     core.info(`Resolved as '${resolvedVersion}'`); | ||||
|             var _a, _b; | ||||
|             if (this.nodeInfo.mirrorURL) { | ||||
|                 if (this.nodeInfo.mirrorURL === '') { | ||||
|                     throw new Error('Mirror URL is empty. Please provide a valid mirror URL.'); | ||||
|                 } | ||||
|                 else { | ||||
|                     core.info(`Failed to resolve version ${this.nodeInfo.versionSpec} from manifest`); | ||||
|                 } | ||||
|             } | ||||
|             let toolPath = this.findVersionInHostedToolCacheDirectory(); | ||||
|             if (toolPath) { | ||||
|                 core.info(`Found in cache @ ${toolPath}`); | ||||
|                 this.addToolPath(toolPath); | ||||
|                 return; | ||||
|             } | ||||
|             let downloadPath = ''; | ||||
|             try { | ||||
|                 core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); | ||||
|                 const versionInfo = yield this.getInfoFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.stable, osArch, manifest); | ||||
|                 if (versionInfo) { | ||||
|                     core.info(`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`); | ||||
|                     downloadPath = yield tc.downloadTool(versionInfo.downloadUrl, undefined, this.nodeInfo.auth); | ||||
|                 let downloadPath = ''; | ||||
|                 let toolPath = ''; | ||||
|                 try { | ||||
|                     core.info(`Attempting to download using mirror URL...`); | ||||
|                     downloadPath = yield this.downloadFromMirrorURL(); // Attempt to download from the mirror
 | ||||
|                     core.info('downloadPath from downloadFromMirrorURL() ' + downloadPath); | ||||
|                     if (downloadPath) { | ||||
|                         toolPath = yield this.extractArchive(downloadPath, versionInfo, false); | ||||
|                         toolPath = downloadPath; | ||||
|                     } | ||||
|                 } | ||||
|                 else { | ||||
|                     core.info('Not found in manifest. Falling back to download directly from Node'); | ||||
|                 } | ||||
|             } | ||||
|             catch (err) { | ||||
|                 // Rate limit?
 | ||||
|                 if (err instanceof tc.HTTPError && | ||||
|                     (err.httpStatusCode === 403 || err.httpStatusCode === 429)) { | ||||
|                     core.info(`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`); | ||||
|                 } | ||||
|                 else { | ||||
|                 catch (err) { | ||||
|                     core.info(err.message); | ||||
|                     core.debug((_a = err.stack) !== null && _a !== void 0 ? _a : 'empty stack'); | ||||
|                 } | ||||
|                 core.debug((_a = err.stack) !== null && _a !== void 0 ? _a : 'empty stack'); | ||||
|                 core.info('Falling back to download directly from Node'); | ||||
|             } | ||||
|             if (!toolPath) { | ||||
|                 toolPath = yield this.downloadDirectlyFromNode(); | ||||
|             else { | ||||
|                 let manifest; | ||||
|                 let nodeJsVersions; | ||||
|                 const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); | ||||
|                 if (this.isLtsAlias(this.nodeInfo.versionSpec)) { | ||||
|                     core.info('Attempt to resolve LTS alias from manifest...'); | ||||
|                     // No try-catch since it's not possible to resolve LTS alias without manifest
 | ||||
|                     manifest = yield this.getManifest(); | ||||
|                     this.nodeInfo.versionSpec = this.resolveLtsAliasFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.stable, manifest); | ||||
|                 } | ||||
|                 if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { | ||||
|                     nodeJsVersions = yield this.getNodeJsVersions(); | ||||
|                     const versions = this.filterVersions(nodeJsVersions); | ||||
|                     this.nodeInfo.versionSpec = this.evaluateVersions(versions); | ||||
|                     core.info('getting latest node version...'); | ||||
|                 } | ||||
|                 if (this.nodeInfo.checkLatest) { | ||||
|                     core.info('Attempt to resolve the latest version from manifest...'); | ||||
|                     const resolvedVersion = yield this.resolveVersionFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.stable, osArch, manifest); | ||||
|                     if (resolvedVersion) { | ||||
|                         this.nodeInfo.versionSpec = resolvedVersion; | ||||
|                         core.info(`Resolved as '${resolvedVersion}'`); | ||||
|                     } | ||||
|                     else { | ||||
|                         core.info(`Failed to resolve version ${this.nodeInfo.versionSpec} from manifest`); | ||||
|                     } | ||||
|                 } | ||||
|                 let toolPath = this.findVersionInHostedToolCacheDirectory(); | ||||
|                 if (toolPath) { | ||||
|                     core.info(`Found in cache @ ${toolPath}`); | ||||
|                     this.addToolPath(toolPath); | ||||
|                     return; | ||||
|                 } | ||||
|                 let downloadPath = ''; | ||||
|                 try { | ||||
|                     core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); | ||||
|                     const versionInfo = yield this.getInfoFromManifest(this.nodeInfo.versionSpec, this.nodeInfo.stable, osArch, manifest); | ||||
|                     if (versionInfo) { | ||||
|                         core.info(`Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}`); | ||||
|                         downloadPath = yield tc.downloadTool(versionInfo.downloadUrl, undefined, this.nodeInfo.auth); | ||||
|                         if (downloadPath) { | ||||
|                             toolPath = yield this.extractArchive(downloadPath, versionInfo, false); | ||||
|                         } | ||||
|                     } | ||||
|                     else { | ||||
|                         core.info('Not found in manifest. Falling back to download directly from Node'); | ||||
|                     } | ||||
|                 } | ||||
|                 catch (err) { | ||||
|                     // Rate limit?
 | ||||
|                     if (err instanceof tc.HTTPError && | ||||
|                         (err.httpStatusCode === 403 || err.httpStatusCode === 429)) { | ||||
|                         core.info(`Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded`); | ||||
|                     } | ||||
|                     else { | ||||
|                         core.info(err.message); | ||||
|                     } | ||||
|                     core.debug((_b = err.stack) !== null && _b !== void 0 ? _b : 'empty stack'); | ||||
|                     core.info('Falling back to download directly from Node'); | ||||
|                 } | ||||
|                 if (!toolPath) { | ||||
|                     toolPath = yield this.downloadDirectlyFromNode(); | ||||
|                 } | ||||
|                 if (this.osPlat != 'win32') { | ||||
|                     toolPath = path_1.default.join(toolPath, 'bin'); | ||||
|                 } | ||||
|                 core.addPath(toolPath); | ||||
|             } | ||||
|             if (this.osPlat != 'win32') { | ||||
|                 toolPath = path_1.default.join(toolPath, 'bin'); | ||||
|             } | ||||
|             core.addPath(toolPath); | ||||
|         }); | ||||
|     } | ||||
|     addToolPath(toolPath) { | ||||
| @ -100559,6 +100650,9 @@ class OfficialBuilds extends base_distribution_1.default { | ||||
|         return version; | ||||
|     } | ||||
|     getDistributionUrl() { | ||||
|         if (this.nodeInfo.mirrorURL) { | ||||
|             return this.nodeInfo.mirrorURL; | ||||
|         } | ||||
|         return `https://nodejs.org/dist`; | ||||
|     } | ||||
|     getManifest() { | ||||
| @ -100626,6 +100720,33 @@ class OfficialBuilds extends base_distribution_1.default { | ||||
|     isLatestSyntax(versionSpec) { | ||||
|         return ['current', 'latest', 'node'].includes(versionSpec); | ||||
|     } | ||||
|     downloadFromMirrorURL() { | ||||
|         return __awaiter(this, void 0, void 0, function* () { | ||||
|             const nodeJsVersions = yield this.getMirrorUrlVersions(); | ||||
|             const versions = this.filterVersions(nodeJsVersions); | ||||
|             const evaluatedVersion = this.evaluateVersions(versions); | ||||
|             if (!evaluatedVersion) { | ||||
|                 throw new Error(`Unable to find Node version '${this.nodeInfo.versionSpec}' for platform ${this.osPlat} and architecture ${this.nodeInfo.arch} from the provided mirror-url ${this.nodeInfo.mirrorURL}. Please check the mirror-url`); | ||||
|             } | ||||
|             const toolName = this.getNodejsMirrorURLInfo(evaluatedVersion); | ||||
|             try { | ||||
|                 const toolPath = yield this.downloadNodejs(toolName); | ||||
|                 return toolPath; | ||||
|             } | ||||
|             catch (error) { | ||||
|                 if (error instanceof tc.HTTPError && error.httpStatusCode === 404) { | ||||
|                     core.error(`Node version ${this.nodeInfo.versionSpec} for platform ${this.osPlat} and architecture ${this.nodeInfo.arch} was found but failed to download. ` + | ||||
|                         'This usually happens when downloadable binaries are not fully updated at https://nodejs.org/. ' + | ||||
|                         'To resolve this issue you may either fall back to the older version or try again later.'); | ||||
|                 } | ||||
|                 else { | ||||
|                     // For any other error type, you can log the error message.
 | ||||
|                     core.error(`An unexpected error occurred like url might not correct`); | ||||
|                 } | ||||
|                 throw error; | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
| exports["default"] = OfficialBuilds; | ||||
| 
 | ||||
| @ -100643,11 +100764,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) { | ||||
| Object.defineProperty(exports, "__esModule", ({ value: true })); | ||||
| const base_distribution_1 = __importDefault(__nccwpck_require__(7)); | ||||
| class RcBuild extends base_distribution_1.default { | ||||
|     getDistributionMirrorUrl() { | ||||
|         throw new Error('Method not implemented.'); | ||||
|     } | ||||
|     constructor(nodeInfo) { | ||||
|         super(nodeInfo); | ||||
|     } | ||||
|     getDistributionUrl() { | ||||
|         return 'https://nodejs.org/download/rc'; | ||||
|         if (this.nodeInfo.mirrorURL) { | ||||
|             if (this.nodeInfo.mirrorURL != '') { | ||||
|                 return this.nodeInfo.mirrorURL; | ||||
|             } | ||||
|             else { | ||||
|                 if (this.nodeInfo.mirrorURL === '') { | ||||
|                     throw new Error('Mirror URL is empty. Please provide a valid mirror URL.'); | ||||
|                 } | ||||
|                 else { | ||||
|                     throw new Error('Mirror URL is not a valid'); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             return 'https://nodejs.org/download/rc'; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| exports["default"] = RcBuild; | ||||
| @ -100671,7 +100810,22 @@ class CanaryBuild extends base_distribution_prerelease_1.default { | ||||
|         this.distribution = 'v8-canary'; | ||||
|     } | ||||
|     getDistributionUrl() { | ||||
|         return 'https://nodejs.org/download/v8-canary'; | ||||
|         if (this.nodeInfo.mirrorURL) { | ||||
|             if (this.nodeInfo.mirrorURL != '') { | ||||
|                 return this.nodeInfo.mirrorURL; | ||||
|             } | ||||
|             else { | ||||
|                 if (this.nodeInfo.mirrorURL === '') { | ||||
|                     throw new Error('Mirror URL is empty. Please provide a valid mirror URL.'); | ||||
|                 } | ||||
|                 else { | ||||
|                     throw new Error('Mirror URL is not a valid'); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         else { | ||||
|             return 'https://nodejs.org/download/v8-canary'; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| exports["default"] = CanaryBuild; | ||||
| @ -100748,6 +100902,7 @@ function run() { | ||||
|             if (!arch) { | ||||
|                 arch = os_1.default.arch(); | ||||
|             } | ||||
|             const mirrorURL = core.getInput('mirror-url').trim(); // .trim() to remove any accidental spaces
 | ||||
|             if (version) { | ||||
|                 const token = core.getInput('token'); | ||||
|                 const auth = !token ? undefined : `token ${token}`; | ||||
| @ -100758,7 +100913,8 @@ function run() { | ||||
|                     checkLatest, | ||||
|                     auth, | ||||
|                     stable, | ||||
|                     arch | ||||
|                     arch, | ||||
|                     mirrorURL | ||||
|                 }; | ||||
|                 const nodeDistribution = (0, installer_factory_1.getNodejsDistribution)(nodejsInfo); | ||||
|                 yield nodeDistribution.setupNodeJs(); | ||||
|  | ||||
| @ -104,6 +104,28 @@ export default abstract class BaseDistribution { | ||||
|     return response.result || []; | ||||
|   } | ||||
| 
 | ||||
|   protected async getMirrorUrlVersions(): Promise<INodeVersion[]> { | ||||
|     const initialUrl = this.getDistributionUrl(); | ||||
|      | ||||
|     const dataUrl = `${initialUrl}/index.json`; | ||||
|     try { | ||||
|     const response = await this.httpClient.getJson<INodeVersion[]>(dataUrl); | ||||
|     return response.result || []; | ||||
|     }catch (err) { | ||||
|       if (err instanceof Error && err.message.includes('getaddrinfo EAI_AGAIN')) { | ||||
|           core.error(`Network error: Failed to resolve the server at ${dataUrl}. 
 | ||||
|                       Please check your DNS settings or verify that the URL is correct.`);
 | ||||
|       } else if (err instanceof hc.HttpClientError && err.statusCode === 404) { | ||||
|           core.error(`404 Error: Unable to find versions at ${dataUrl}. 
 | ||||
|                       Please verify that the mirror URL is valid.`);
 | ||||
|       } else { | ||||
|           core.error(`Failed to fetch Node.js versions from ${dataUrl}. 
 | ||||
|                       Please check the URL and try again.}`);
 | ||||
|       } | ||||
|       throw err;   | ||||
|   } | ||||
|   } | ||||
| 
 | ||||
|   protected getNodejsDistInfo(version: string) { | ||||
|     const osArch: string = this.translateArchToDistUrl(this.nodeInfo.arch); | ||||
|     version = semver.clean(version) || ''; | ||||
| @ -128,6 +150,33 @@ export default abstract class BaseDistribution { | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   protected getNodejsMirrorURLInfo(version: string) { | ||||
|     const mirrorURL = this.nodeInfo.mirrorURL; | ||||
|      | ||||
|     const osArch: string = this.translateArchToDistUrl(this.nodeInfo.arch); | ||||
|      | ||||
|     version = semver.clean(version) || ''; | ||||
|     const fileName: string = | ||||
|       this.osPlat == 'win32' | ||||
|         ? `node-v${version}-win-${osArch}` | ||||
|         : `node-v${version}-${this.osPlat}-${osArch}`; | ||||
|     const urlFileName: string = | ||||
|       this.osPlat == 'win32' | ||||
|         ? this.nodeInfo.arch === 'arm64' | ||||
|           ? `${fileName}.zip` | ||||
|           : `${fileName}.7z` | ||||
|         : `${fileName}.tar.gz`; | ||||
| 
 | ||||
|     const url = `${mirrorURL}/v${version}/${urlFileName}`; | ||||
| 
 | ||||
|     return <INodeVersionInfo>{ | ||||
|       downloadUrl: url, | ||||
|       resolvedVersion: version, | ||||
|       arch: osArch, | ||||
|       fileName: fileName | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   protected async downloadNodejs(info: INodeVersionInfo) { | ||||
|     let downloadPath = ''; | ||||
|     core.info( | ||||
| @ -143,9 +192,20 @@ export default abstract class BaseDistribution { | ||||
|       ) { | ||||
|         return await this.acquireWindowsNodeFromFallbackLocation( | ||||
|           info.resolvedVersion, | ||||
|           info.arch | ||||
|           info.arch, | ||||
|           info.downloadUrl | ||||
|         ); | ||||
|       } | ||||
|       // Handle network-related issues (e.g., DNS resolution failures)
 | ||||
|       if (err instanceof Error && err.message.includes('getaddrinfo EAI_AGAIN')) { | ||||
|         core.error( | ||||
|             `Network error: Failed to resolve the server at ${info.downloadUrl}. 
 | ||||
|             This could be due to a DNS resolution issue. Please verify the URL or check your network connection.` | ||||
|         ); | ||||
|     } | ||||
|       core.error( | ||||
|         `Download failed from ${info.downloadUrl}. Please check the URl and try again.` | ||||
|       ); | ||||
| 
 | ||||
|       throw err; | ||||
|     } | ||||
| @ -166,9 +226,11 @@ export default abstract class BaseDistribution { | ||||
| 
 | ||||
|   protected async acquireWindowsNodeFromFallbackLocation( | ||||
|     version: string, | ||||
|     arch: string = os.arch() | ||||
|     arch: string = os.arch(), | ||||
|     downloadUrl: string | ||||
|   ): Promise<string> { | ||||
|     const initialUrl = this.getDistributionUrl(); | ||||
|     core.info('url: ' + initialUrl); | ||||
|     const osArch: string = this.translateArchToDistUrl(arch); | ||||
| 
 | ||||
|     // Create temporary folder to download to
 | ||||
| @ -185,6 +247,12 @@ export default abstract class BaseDistribution { | ||||
| 
 | ||||
|       core.info(`Downloading only node binary from ${exeUrl}`); | ||||
| 
 | ||||
|       if (downloadUrl != exeUrl) { | ||||
|         core.error( | ||||
|           'unable to download node binary with the provided URL. Please check and try again' | ||||
|         ); | ||||
|       } | ||||
| 
 | ||||
|       const exePath = await tc.downloadTool(exeUrl); | ||||
|       await io.cp(exePath, path.join(tempDir, 'node.exe')); | ||||
|       const libPath = await tc.downloadTool(libUrl); | ||||
|  | ||||
| @ -4,6 +4,7 @@ export interface NodeInputs { | ||||
|   auth?: string; | ||||
|   checkLatest: boolean; | ||||
|   stable: boolean; | ||||
|   mirrorURL?: string; | ||||
| } | ||||
| 
 | ||||
| export interface INodeVersionInfo { | ||||
|  | ||||
| @ -1,13 +1,31 @@ | ||||
| import BasePrereleaseNodejs from '../base-distribution-prerelease'; | ||||
| import {NodeInputs} from '../base-models'; | ||||
| import * as core from '@actions/core'; | ||||
| 
 | ||||
| export default class NightlyNodejs extends BasePrereleaseNodejs { | ||||
|    | ||||
|   protected distribution = 'nightly'; | ||||
| 
 | ||||
|   constructor(nodeInfo: NodeInputs) { | ||||
|     super(nodeInfo); | ||||
|   } | ||||
| 
 | ||||
|   protected getDistributionUrl(): string { | ||||
|      | ||||
|     if (this.nodeInfo.mirrorURL) { | ||||
|       if(this.nodeInfo.mirrorURL != '') { | ||||
|       return this.nodeInfo.mirrorURL; | ||||
|     }else{ | ||||
|       if(this.nodeInfo.mirrorURL === '') { | ||||
|         throw new Error('Mirror URL is empty. Please provide a valid mirror URL.'); | ||||
|       }else{ | ||||
|         throw new Error('Mirror URL is not a valid'); | ||||
|       } | ||||
|     } | ||||
|     | ||||
|   }else{ | ||||
|     return 'https://nodejs.org/download/nightly'; | ||||
|   } | ||||
|    | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -15,115 +15,134 @@ export default class OfficialBuilds extends BaseDistribution { | ||||
|   } | ||||
| 
 | ||||
|   public async setupNodeJs() { | ||||
|     let manifest: tc.IToolRelease[] | undefined; | ||||
|     let nodeJsVersions: INodeVersion[] | undefined; | ||||
|     const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); | ||||
| 
 | ||||
|     if (this.isLtsAlias(this.nodeInfo.versionSpec)) { | ||||
|       core.info('Attempt to resolve LTS alias from manifest...'); | ||||
| 
 | ||||
|       // No try-catch since it's not possible to resolve LTS alias without manifest
 | ||||
|       manifest = await this.getManifest(); | ||||
| 
 | ||||
|       this.nodeInfo.versionSpec = this.resolveLtsAliasFromManifest( | ||||
|         this.nodeInfo.versionSpec, | ||||
|         this.nodeInfo.stable, | ||||
|         manifest | ||||
|       ); | ||||
|     if (this.nodeInfo.mirrorURL) { | ||||
|       if (this.nodeInfo.mirrorURL === '') { | ||||
|         throw new Error('Mirror URL is empty. Please provide a valid mirror URL.'); | ||||
|     } | ||||
|       let downloadPath = ''; | ||||
|       let toolPath = ''; | ||||
|       try { | ||||
|         core.info(`Attempting to download using mirror URL...`); | ||||
|         downloadPath = await this.downloadFromMirrorURL(); // Attempt to download from the mirror
 | ||||
|         core.info('downloadPath from downloadFromMirrorURL() '+ downloadPath); | ||||
|         if (downloadPath) { | ||||
|           toolPath = downloadPath; | ||||
|         } | ||||
|       } catch (err) { | ||||
|         core.info((err as Error).message); | ||||
|         core.debug((err as Error).stack ?? 'empty stack'); | ||||
|       } | ||||
|     } else { | ||||
|       let manifest: tc.IToolRelease[] | undefined; | ||||
|       let nodeJsVersions: INodeVersion[] | undefined; | ||||
|       const osArch = this.translateArchToDistUrl(this.nodeInfo.arch); | ||||
| 
 | ||||
|     if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { | ||||
|       nodeJsVersions = await this.getNodeJsVersions(); | ||||
|       const versions = this.filterVersions(nodeJsVersions); | ||||
|       this.nodeInfo.versionSpec = this.evaluateVersions(versions); | ||||
|       if (this.isLtsAlias(this.nodeInfo.versionSpec)) { | ||||
|         core.info('Attempt to resolve LTS alias from manifest...'); | ||||
| 
 | ||||
|       core.info('getting latest node version...'); | ||||
|     } | ||||
|         // No try-catch since it's not possible to resolve LTS alias without manifest
 | ||||
|         manifest = await this.getManifest(); | ||||
| 
 | ||||
|     if (this.nodeInfo.checkLatest) { | ||||
|       core.info('Attempt to resolve the latest version from manifest...'); | ||||
|       const resolvedVersion = await this.resolveVersionFromManifest( | ||||
|         this.nodeInfo.versionSpec, | ||||
|         this.nodeInfo.stable, | ||||
|         osArch, | ||||
|         manifest | ||||
|       ); | ||||
|       if (resolvedVersion) { | ||||
|         this.nodeInfo.versionSpec = resolvedVersion; | ||||
|         core.info(`Resolved as '${resolvedVersion}'`); | ||||
|       } else { | ||||
|         core.info( | ||||
|           `Failed to resolve version ${this.nodeInfo.versionSpec} from manifest` | ||||
|         this.nodeInfo.versionSpec = this.resolveLtsAliasFromManifest( | ||||
|           this.nodeInfo.versionSpec, | ||||
|           this.nodeInfo.stable, | ||||
|           manifest | ||||
|         ); | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     let toolPath = this.findVersionInHostedToolCacheDirectory(); | ||||
|       if (this.isLatestSyntax(this.nodeInfo.versionSpec)) { | ||||
|         nodeJsVersions = await this.getNodeJsVersions(); | ||||
|         const versions = this.filterVersions(nodeJsVersions); | ||||
|         this.nodeInfo.versionSpec = this.evaluateVersions(versions); | ||||
| 
 | ||||
|     if (toolPath) { | ||||
|       core.info(`Found in cache @ ${toolPath}`); | ||||
|       this.addToolPath(toolPath); | ||||
|       return; | ||||
|     } | ||||
|         core.info('getting latest node version...'); | ||||
|       } | ||||
| 
 | ||||
|     let downloadPath = ''; | ||||
|     try { | ||||
|       core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); | ||||
| 
 | ||||
|       const versionInfo = await this.getInfoFromManifest( | ||||
|         this.nodeInfo.versionSpec, | ||||
|         this.nodeInfo.stable, | ||||
|         osArch, | ||||
|         manifest | ||||
|       ); | ||||
| 
 | ||||
|       if (versionInfo) { | ||||
|         core.info( | ||||
|           `Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}` | ||||
|       if (this.nodeInfo.checkLatest) { | ||||
|         core.info('Attempt to resolve the latest version from manifest...'); | ||||
|         const resolvedVersion = await this.resolveVersionFromManifest( | ||||
|           this.nodeInfo.versionSpec, | ||||
|           this.nodeInfo.stable, | ||||
|           osArch, | ||||
|           manifest | ||||
|         ); | ||||
|         downloadPath = await tc.downloadTool( | ||||
|           versionInfo.downloadUrl, | ||||
|           undefined, | ||||
|           this.nodeInfo.auth | ||||
|         ); | ||||
| 
 | ||||
|         if (downloadPath) { | ||||
|           toolPath = await this.extractArchive( | ||||
|             downloadPath, | ||||
|             versionInfo, | ||||
|             false | ||||
|         if (resolvedVersion) { | ||||
|           this.nodeInfo.versionSpec = resolvedVersion; | ||||
|           core.info(`Resolved as '${resolvedVersion}'`); | ||||
|         } else { | ||||
|           core.info( | ||||
|             `Failed to resolve version ${this.nodeInfo.versionSpec} from manifest` | ||||
|           ); | ||||
|         } | ||||
|       } else { | ||||
|         core.info( | ||||
|           'Not found in manifest. Falling back to download directly from Node' | ||||
|         ); | ||||
|       } | ||||
|     } catch (err) { | ||||
|       // Rate limit?
 | ||||
|       if ( | ||||
|         err instanceof tc.HTTPError && | ||||
|         (err.httpStatusCode === 403 || err.httpStatusCode === 429) | ||||
|       ) { | ||||
|         core.info( | ||||
|           `Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded` | ||||
|         ); | ||||
|       } else { | ||||
|         core.info((err as Error).message); | ||||
| 
 | ||||
|       let toolPath = this.findVersionInHostedToolCacheDirectory(); | ||||
| 
 | ||||
|       if (toolPath) { | ||||
|         core.info(`Found in cache @ ${toolPath}`); | ||||
|         this.addToolPath(toolPath); | ||||
|         return; | ||||
|       } | ||||
|       core.debug((err as Error).stack ?? 'empty stack'); | ||||
|       core.info('Falling back to download directly from Node'); | ||||
|     } | ||||
| 
 | ||||
|     if (!toolPath) { | ||||
|       toolPath = await this.downloadDirectlyFromNode(); | ||||
|     } | ||||
|       let downloadPath = ''; | ||||
|       try { | ||||
|         core.info(`Attempting to download ${this.nodeInfo.versionSpec}...`); | ||||
| 
 | ||||
|     if (this.osPlat != 'win32') { | ||||
|       toolPath = path.join(toolPath, 'bin'); | ||||
|     } | ||||
|         const versionInfo = await this.getInfoFromManifest( | ||||
|           this.nodeInfo.versionSpec, | ||||
|           this.nodeInfo.stable, | ||||
|           osArch, | ||||
|           manifest | ||||
|         ); | ||||
| 
 | ||||
|     core.addPath(toolPath); | ||||
|         if (versionInfo) { | ||||
|           core.info( | ||||
|             `Acquiring ${versionInfo.resolvedVersion} - ${versionInfo.arch} from ${versionInfo.downloadUrl}` | ||||
|           ); | ||||
|           downloadPath = await tc.downloadTool( | ||||
|             versionInfo.downloadUrl, | ||||
|             undefined, | ||||
|             this.nodeInfo.auth | ||||
|           ); | ||||
| 
 | ||||
|           if (downloadPath) { | ||||
|             toolPath = await this.extractArchive( | ||||
|               downloadPath, | ||||
|               versionInfo, | ||||
|               false | ||||
|             ); | ||||
|           } | ||||
|         } else { | ||||
|           core.info( | ||||
|             'Not found in manifest. Falling back to download directly from Node' | ||||
|           ); | ||||
|         } | ||||
|       } catch (err) { | ||||
|         // Rate limit?
 | ||||
|         if ( | ||||
|           err instanceof tc.HTTPError && | ||||
|           (err.httpStatusCode === 403 || err.httpStatusCode === 429) | ||||
|         ) { | ||||
|           core.info( | ||||
|             `Received HTTP status code ${err.httpStatusCode}. This usually indicates the rate limit has been exceeded` | ||||
|           ); | ||||
|         } else { | ||||
|           core.info((err as Error).message); | ||||
|         } | ||||
|         core.debug((err as Error).stack ?? 'empty stack'); | ||||
|         core.info('Falling back to download directly from Node'); | ||||
|       } | ||||
| 
 | ||||
|       if (!toolPath) { | ||||
|         toolPath = await this.downloadDirectlyFromNode(); | ||||
|       } | ||||
| 
 | ||||
|       if (this.osPlat != 'win32') { | ||||
|         toolPath = path.join(toolPath, 'bin'); | ||||
|       } | ||||
| 
 | ||||
|       core.addPath(toolPath); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   protected addToolPath(toolPath: string) { | ||||
| @ -177,8 +196,12 @@ export default class OfficialBuilds extends BaseDistribution { | ||||
|   } | ||||
| 
 | ||||
|   protected getDistributionUrl(): string { | ||||
|     if (this.nodeInfo.mirrorURL) { | ||||
|       return this.nodeInfo.mirrorURL; | ||||
|     } | ||||
|     return `https://nodejs.org/dist`; | ||||
|   } | ||||
|    | ||||
| 
 | ||||
|   private getManifest(): Promise<tc.IToolRelease[]> { | ||||
|     core.debug('Getting manifest from actions/node-versions@main'); | ||||
| @ -291,4 +314,43 @@ export default class OfficialBuilds extends BaseDistribution { | ||||
|   private isLatestSyntax(versionSpec): boolean { | ||||
|     return ['current', 'latest', 'node'].includes(versionSpec); | ||||
|   } | ||||
| 
 | ||||
|   protected async downloadFromMirrorURL() { | ||||
|     const nodeJsVersions = await this.getMirrorUrlVersions(); | ||||
|     const versions = this.filterVersions(nodeJsVersions); | ||||
| 
 | ||||
| 
 | ||||
|     const evaluatedVersion = this.evaluateVersions(versions); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     if (!evaluatedVersion) { | ||||
|       throw new Error( | ||||
|         `Unable to find Node version '${this.nodeInfo.versionSpec}' for platform ${this.osPlat} and architecture ${this.nodeInfo.arch} from the provided mirror-url ${this.nodeInfo.mirrorURL}. Please check the mirror-url` | ||||
|       ); | ||||
|     } | ||||
| 
 | ||||
|     const toolName = this.getNodejsMirrorURLInfo(evaluatedVersion); | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     try { | ||||
|       const toolPath = await this.downloadNodejs(toolName); | ||||
| 
 | ||||
|       return toolPath; | ||||
|     } catch (error) { | ||||
|       if (error instanceof tc.HTTPError && error.httpStatusCode === 404) { | ||||
|         core.error( | ||||
|           `Node version ${this.nodeInfo.versionSpec} for platform ${this.osPlat} and architecture ${this.nodeInfo.arch} was found but failed to download. ` + | ||||
|             'This usually happens when downloadable binaries are not fully updated at https://nodejs.org/. ' + | ||||
|             'To resolve this issue you may either fall back to the older version or try again later.' | ||||
|         ); | ||||
|       } else { | ||||
|         // For any other error type, you can log the error message.
 | ||||
|         core.error(`An unexpected error occurred like url might not correct`); | ||||
|       } | ||||
| 
 | ||||
|       throw error; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -1,12 +1,32 @@ | ||||
| import BaseDistribution from '../base-distribution'; | ||||
| import {NodeInputs} from '../base-models'; | ||||
| import * as core from '@actions/core'; | ||||
| 
 | ||||
| export default class RcBuild extends BaseDistribution { | ||||
|   getDistributionMirrorUrl() { | ||||
|     throw new Error('Method not implemented.'); | ||||
|   } | ||||
| 
 | ||||
|   constructor(nodeInfo: NodeInputs) { | ||||
|     super(nodeInfo); | ||||
|   } | ||||
| 
 | ||||
|   getDistributionUrl(): string { | ||||
|   protected getDistributionUrl(): string { | ||||
|      | ||||
|     if (this.nodeInfo.mirrorURL) { | ||||
|       if(this.nodeInfo.mirrorURL != '') { | ||||
|       return this.nodeInfo.mirrorURL; | ||||
|     }else{ | ||||
|       if(this.nodeInfo.mirrorURL === '') { | ||||
|         throw new Error('Mirror URL is empty. Please provide a valid mirror URL.'); | ||||
|       }else{ | ||||
|         throw new Error('Mirror URL is not a valid'); | ||||
|       } | ||||
|     } | ||||
|     | ||||
|   }else{ | ||||
|     return 'https://nodejs.org/download/rc'; | ||||
|   } | ||||
|    | ||||
| } | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -1,13 +1,29 @@ | ||||
| import BasePrereleaseNodejs from '../base-distribution-prerelease'; | ||||
| import {NodeInputs} from '../base-models'; | ||||
| 
 | ||||
| import * as core from '@actions/core'; | ||||
| export default class CanaryBuild extends BasePrereleaseNodejs { | ||||
|    | ||||
|   protected distribution = 'v8-canary'; | ||||
|   constructor(nodeInfo: NodeInputs) { | ||||
|     super(nodeInfo); | ||||
|   } | ||||
| 
 | ||||
|   protected getDistributionUrl(): string { | ||||
|      | ||||
|     if (this.nodeInfo.mirrorURL) { | ||||
|       if(this.nodeInfo.mirrorURL != '') { | ||||
|       return this.nodeInfo.mirrorURL; | ||||
|     }else{ | ||||
|       if(this.nodeInfo.mirrorURL === '') { | ||||
|         throw new Error('Mirror URL is empty. Please provide a valid mirror URL.'); | ||||
|       }else{ | ||||
|         throw new Error('Mirror URL is not a valid'); | ||||
|       } | ||||
|     } | ||||
|     | ||||
|   }else{ | ||||
|     return 'https://nodejs.org/download/v8-canary'; | ||||
|   } | ||||
|    | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -33,6 +33,8 @@ export async function run() { | ||||
|       arch = os.arch(); | ||||
|     } | ||||
| 
 | ||||
|     const mirrorURL = core.getInput('mirror-url').trim(); // .trim() to remove any accidental spaces
 | ||||
| 
 | ||||
|     if (version) { | ||||
|       const token = core.getInput('token'); | ||||
|       const auth = !token ? undefined : `token ${token}`; | ||||
| @ -45,7 +47,8 @@ export async function run() { | ||||
|         checkLatest, | ||||
|         auth, | ||||
|         stable, | ||||
|         arch | ||||
|         arch, | ||||
|         mirrorURL | ||||
|       }; | ||||
|       const nodeDistribution = getNodejsDistribution(nodejsInfo); | ||||
|       await nodeDistribution.setupNodeJs(); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user