Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mirror-url parameter to allow downloading Node.js from a custom URL #1211

Draft
wants to merge 24 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 83 additions & 1 deletion __tests__/canary-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ 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;
Expand Down Expand Up @@ -529,3 +530,84 @@ describe('setup-node', () => {
});
});
});
describe('CanaryBuild - Mirror URL functionality', () => {
const nodeInfo: NodeInputs = {
versionSpec: '18.0.0-rc', arch: 'x64', mirrorURL: '',
checkLatest: false,
stable: false
};
it('should return the default distribution URL if no mirror URL is provided', () => {
const canaryBuild = new CanaryBuild(nodeInfo);

// @ts-ignore: Accessing protected method for testing purposes
const distributionMirrorUrl = canaryBuild.getDistributionMirrorUrl();
expect(distributionMirrorUrl).toBe('https://nodejs.org/download/v8-canary');
});

it('should use the mirror URL from nodeInfo if provided', () => {
const mirrorURL = 'https://custom.mirror.url/v8-canary';
nodeInfo.mirrorURL = mirrorURL;
const canaryBuild = new CanaryBuild(nodeInfo);

// @ts-ignore: Accessing protected method for testing purposes
const distributionMirrorUrl = canaryBuild.getDistributionMirrorUrl();
expect(core.info).toHaveBeenCalledWith(`Using mirror URL: ${mirrorURL}`);
expect(distributionMirrorUrl).toBe(mirrorURL);
});

it('should fall back to the default distribution URL if mirror URL is not provided', () => {
nodeInfo.mirrorURL = ''; // No mirror URL
const canaryBuild = new CanaryBuild(nodeInfo);

// @ts-ignore: Accessing protected method for testing purposes
const distributionMirrorUrl = canaryBuild.getDistributionMirrorUrl();
expect(core.info).toHaveBeenCalledWith('Using mirror URL: https://nodejs.org/download/v8-canary');
expect(distributionMirrorUrl).toBe('https://nodejs.org/download/v8-canary');
});

it('should log the correct info when mirror URL is not provided', () => {
nodeInfo.mirrorURL = ''; // No mirror URL
const canaryBuild = new CanaryBuild(nodeInfo);

// @ts-ignore: Accessing protected method for testing purposes
canaryBuild.getDistributionMirrorUrl();
expect(core.info).toHaveBeenCalledWith('Using mirror URL: https://nodejs.org/download/v8-canary');
});

it('should return mirror URL if provided in nodeInfo', () => {
const mirrorURL = 'https://custom.mirror.url/v8-canary';
nodeInfo.mirrorURL = mirrorURL;

const canaryBuild = new CanaryBuild(nodeInfo);
// @ts-ignore: Accessing protected method for testing purposes
const distributionMirrorUrl = canaryBuild.getDistributionMirrorUrl();
expect(core.info).toHaveBeenCalledWith(`Using mirror URL: ${mirrorURL}`);
expect(distributionMirrorUrl).toBe(mirrorURL);
});

it('should use the default URL if mirror URL is empty string', () => {
nodeInfo.mirrorURL = ''; // Empty string for mirror URL
const canaryBuild = new CanaryBuild(nodeInfo);

// @ts-ignore: Accessing protected method for testing purposes
const distributionMirrorUrl = canaryBuild.getDistributionMirrorUrl();
expect(core.info).toHaveBeenCalledWith('Using mirror URL: https://nodejs.org/download/v8-canary');
expect(distributionMirrorUrl).toBe('https://nodejs.org/download/v8-canary');
});

it('should return the default URL if mirror URL is undefined', async () => {
// Create a spy on core.info
const infoSpy = jest.spyOn(core, 'info').mockImplementation(() => {}); // Mocking with empty implementation

// @ts-ignore: Accessing protected method for testing purposes
const distributionMirrorUrl = await canaryBuild.getDistributionMirrorUrl(); // Use await here

// Assert that core.info was called with the expected message
expect(infoSpy).toHaveBeenCalledWith('Using mirror URL: https://nodejs.org/download/v8-canary');
expect(distributionMirrorUrl).toBe('https://nodejs.org/download/v8-canary');

// Optional: Restore the original function after the test
infoSpy.mockRestore();
});

});
118 changes: 118 additions & 0 deletions __tests__/main.test.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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;
Expand Down Expand Up @@ -281,3 +287,115 @@ 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',
});
});

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 '';
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
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({ mirrorURL });

// Debugging: Log the arguments that setupNodeJs was called with
console.log('setupNodeJs calls:', mockNodejsDistribution.setupNodeJs.mock.calls);

// Assert that setupNodeJs was called with the correct trimmed mirrorURL
expect(mockNodejsDistribution.setupNodeJs).toHaveBeenCalledWith(
expect.objectContaining({
mirrorURL: expectedTrimmedURL,
})
);
});



it('should warn if architecture is provided but node-version is missing', async () => {
jest.spyOn(core, 'getInput').mockImplementation((name: string) => {
if (name === 'architecture') return 'x64';
if (name === 'node-version') return '';
return '';
});

const mockWarning = jest.spyOn(core, 'warning');
const mockNodejsDistribution = createMockNodejsDistribution();
(installerFactory.getNodejsDistribution as jest.Mock).mockReturnValue(mockNodejsDistribution);

await main.run();

expect(mockWarning).toHaveBeenCalledWith(
"`architecture` is provided but `node-version` is missing. In this configuration, the version/architecture of Node will not be changed. To fix this, provide `architecture` in combination with `node-version`"
);

expect(mockNodejsDistribution.setupNodeJs).not.toHaveBeenCalled(); // Setup Node should not be called
});
});

function someFunctionThatCallsSetupNodeJs(arg0: { mirrorURL: string; }) {
throw new Error('Function not implemented.');
}
101 changes: 99 additions & 2 deletions __tests__/nightly-installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -606,3 +606,100 @@ 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 {
public getDistributionUrlPublic() {
return this.getDistributionUrl(); // This allows us to call the protected method
}
}

describe('NightlyNodejs', () => {

it('uses mirror URL when provided', async () => {
const mirrorURL = 'https://my.custom.mirror/nodejs/nightly';
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(mirrorURL);
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.');
});

it('logs mirror URL when provided', async () => {
const mirrorURL = 'https://custom.mirror/nodejs/nightly';
const nodeInfo: NodeInputs = {
mirrorURL: '', versionSpec: '18.0.0-nightly', arch: 'x64',
checkLatest: false,
stable: false
};
const nightlyNode = new TestNightlyNodejs(nodeInfo);

nightlyNode.getDistributionUrlPublic();

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.');
});

});
Loading
Loading