1
0

Migrate to ESM and upgrade dependencies (#752)

* Migrate to ESM and upgrade dependencies

* Address review: use type-only import for QualityOptions

* update version to 6.0.0 in package.json and package-lock.json

* Add ESM migration note to README for V6

* Update test imports for ESM and clean up devDependencies (ts-node, @types/jest)

* Pin @types/node to 24.x and refine tsconfig/README wording
This commit is contained in:
Priya Gupta
2026-07-16 02:11:57 +05:30
committed by GitHub
parent 26b0ec14cb
commit 6df8cefd14
78 changed files with 117103 additions and 102620 deletions
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
exports[`authutil tests existing config not in repo root, sets up a partial NuGet.config user/PAT for GPR 1`] = `
"<?xml version="1.0"?>
+5 -1
View File
@@ -1,6 +1,10 @@
import {afterAll, beforeEach, describe, expect, it} from '@jest/globals';
import * as io from '@actions/io';
import fs from 'fs';
import path from 'path';
import {fileURLToPath} from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const fakeSourcesDirForTesting = path.join(
__dirname,
@@ -71,7 +75,7 @@ const azureartifactsnugetorgNuGetConfig = `<?xml version="1.0" encoding="utf-8"?
const nugetConfigFile = path.join(fakeSourcesDirForTesting, '../nuget.config');
process.env['GITHUB_REPOSITORY'] = 'OwnerName/repo';
import * as auth from '../src/authutil';
import * as auth from '../src/authutil.js';
describe('authutil tests', () => {
beforeEach(async () => {
+39 -13
View File
@@ -1,16 +1,40 @@
import {readdir} from 'node:fs/promises';
import * as cache from '@actions/cache';
import * as core from '@actions/core';
import * as glob from '@actions/glob';
import {restoreCache} from '../src/cache-restore';
import {getNuGetFolderPath} from '../src/cache-utils';
import {lockFilePatterns} from '../src/constants';
import {
afterEach,
beforeAll,
beforeEach,
describe,
expect,
it,
jest
} from '@jest/globals';
jest.mock('node:fs/promises');
jest.mock('@actions/cache');
jest.mock('@actions/core');
jest.mock('@actions/glob');
jest.mock('../src/cache-utils');
jest.unstable_mockModule('node:fs/promises', () => ({
readdir: jest.fn()
}));
jest.unstable_mockModule('@actions/cache', () => ({
restoreCache: jest.fn()
}));
jest.unstable_mockModule('@actions/core', () => ({
saveState: jest.fn(),
setOutput: jest.fn(),
info: jest.fn(),
warning: jest.fn(),
debug: jest.fn()
}));
jest.unstable_mockModule('@actions/glob', () => ({
hashFiles: jest.fn()
}));
jest.unstable_mockModule('../src/cache-utils', () => ({
getNuGetFolderPath: jest.fn()
}));
const {readdir} = await import('node:fs/promises');
const cache = await import('@actions/cache');
const core = await import('@actions/core');
const glob = await import('@actions/glob');
const {restoreCache} = await import('../src/cache-restore.js');
const {getNuGetFolderPath} = await import('../src/cache-utils.js');
const {lockFilePatterns} = await import('../src/constants.js');
describe('cache-restore tests', () => {
describe.each(lockFilePatterns)('restoreCache("%s")', lockFilePattern => {
@@ -32,7 +56,9 @@ describe('cache-restore tests', () => {
jest.mocked(core.setOutput).mockClear();
jest.mocked(cache.restoreCache).mockClear();
});
afterEach(() => (process.env.GITHUB_WORKSPACE = githubWorkspace));
afterEach(() => {
process.env.GITHUB_WORKSPACE = githubWorkspace;
});
it('throws error when lock file is not found', async () => {
jest.mocked(glob.hashFiles).mockResolvedValue('');
+28 -10
View File
@@ -1,14 +1,32 @@
import * as cache from '@actions/cache';
import * as core from '@actions/core';
import fs from 'node:fs';
import {run} from '../src/cache-save';
import {getNuGetFolderPath} from '../src/cache-utils';
import {State} from '../src/constants';
import {beforeAll, beforeEach, describe, expect, it, jest} from '@jest/globals';
jest.mock('@actions/cache');
jest.mock('@actions/core');
jest.mock('node:fs');
jest.mock('../src/cache-utils');
jest.unstable_mockModule('@actions/cache', () => ({
saveCache: jest.fn()
}));
jest.unstable_mockModule('@actions/core', () => ({
setFailed: jest.fn(),
getState: jest.fn(),
setOutput: jest.fn(),
getBooleanInput: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
warning: jest.fn()
}));
jest.unstable_mockModule('node:fs', () => ({
default: {
existsSync: jest.fn()
}
}));
jest.unstable_mockModule('../src/cache-utils', () => ({
getNuGetFolderPath: jest.fn()
}));
const cache = await import('@actions/cache');
const core = await import('@actions/core');
const fs = (await import('node:fs')).default;
const {run} = await import('../src/cache-save.js');
const {getNuGetFolderPath} = await import('../src/cache-utils.js');
const {State} = await import('../src/constants.js');
describe('cache-save tests', () => {
beforeAll(() => {
+33 -9
View File
@@ -1,11 +1,29 @@
import * as cache from '@actions/cache';
import * as exec from '@actions/exec';
import {
afterEach,
beforeAll,
beforeEach,
describe,
expect,
it,
jest
} from '@jest/globals';
import {getNuGetFolderPath, isCacheFeatureAvailable} from '../src/cache-utils';
jest.unstable_mockModule('@actions/cache', () => ({
isFeatureAvailable: jest.fn()
}));
jest.unstable_mockModule('@actions/core', () => ({
warning: jest.fn(),
info: jest.fn(),
debug: jest.fn()
}));
jest.unstable_mockModule('@actions/exec', () => ({
getExecOutput: jest.fn()
}));
jest.mock('@actions/cache');
jest.mock('@actions/core');
jest.mock('@actions/exec');
const cache = await import('@actions/cache');
const exec = await import('@actions/exec');
const {getNuGetFolderPath, isCacheFeatureAvailable} =
await import('../src/cache-utils.js');
describe('cache-utils tests', () => {
describe('getNuGetFolderPath()', () => {
@@ -104,9 +122,15 @@ Options:
url => {
// Save & Restore env
let serverUrlEnv: string | undefined;
beforeAll(() => (serverUrlEnv = process.env['GITHUB_SERVER_URL']));
beforeEach(() => (process.env['GITHUB_SERVER_URL'] = url));
afterEach(() => (process.env['GITHUB_SERVER_URL'] = serverUrlEnv));
beforeAll(() => {
serverUrlEnv = process.env['GITHUB_SERVER_URL'];
});
beforeEach(() => {
process.env['GITHUB_SERVER_URL'] = url;
});
afterEach(() => {
process.env['GITHUB_SERVER_URL'] = serverUrlEnv;
});
it('returns true when cache.isFeatureAvailable() === true', () => {
jest.mocked(cache.isFeatureAvailable).mockReturnValue(true);
+3 -2
View File
@@ -1,4 +1,5 @@
import cscFile from '../.github/csc.json';
import {describe, expect, test} from '@jest/globals';
import cscFile from '../.github/csc.json' with {type: 'json'};
describe('csc tests', () => {
const regexPattern = cscFile['problemMatcher'][0]['pattern'][0]['regexp'];
const regexResultsMap = cscFile['problemMatcher'][0]['pattern'][0];
@@ -85,7 +86,7 @@ describe('csc tests', () => {
expect(matchedResultsArray).not.toBeNull();
for (const propName in results) {
const propertyIndex = regexResultsMap[propName];
const propertyIndex = (regexResultsMap as any)[propName];
const expectedPropValue = results[propName];
const matchedPropValue = matchedResultsArray![propertyIndex];
expect(matchedPropValue).toEqual(expectedPropValue);
+4
View File
@@ -1,7 +1,11 @@
import {describe, expect, it} from '@jest/globals';
import path from 'path';
import fs from 'fs';
import {fileURLToPath} from 'url';
import * as hc from '@actions/http-client';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const HTTP_CLIENT_OPTIONS = {allowRetries: true, maxRetries: 10} as const;
const TEST_TIMEOUT = 30000;
+58 -10
View File
@@ -1,14 +1,52 @@
import {
afterAll,
beforeAll,
beforeEach,
describe,
expect,
it,
jest
} from '@jest/globals';
import each from 'jest-each';
import semver from 'semver';
import fs from 'fs';
import fspromises from 'fs/promises';
import os from 'os';
import * as exec from '@actions/exec';
import * as core from '@actions/core';
import * as io from '@actions/io';
import * as installer from '../src/installer';
import path from 'path';
import {IS_WINDOWS} from '../src/utils';
jest.unstable_mockModule('@actions/exec', () => ({
getExecOutput: jest.fn()
}));
jest.unstable_mockModule('@actions/core', () => ({
warning: jest.fn(),
info: jest.fn(),
debug: jest.fn(),
setOutput: jest.fn(),
exportVariable: jest.fn((name: string, val: string) => {
process.env[name] = val;
}),
addPath: jest.fn((p: string) => {
process.env['PATH'] = `${p}${path.delimiter}${process.env['PATH']}`;
})
}));
jest.unstable_mockModule('@actions/io', () => ({
which: jest.fn()
}));
jest.unstable_mockModule('fs', () => {
const actual = jest.requireActual('fs') as typeof import('fs');
const chmodSync = jest.fn();
return {
...actual,
chmodSync,
default: {...actual, chmodSync}
};
});
const exec = await import('@actions/exec');
const core = await import('@actions/core');
const io = await import('@actions/io');
const fs = await import('fs');
const installer = await import('../src/installer.js');
const {IS_WINDOWS} = await import('../src/utils.js');
describe('installer tests', () => {
const env = process.env;
@@ -16,14 +54,24 @@ describe('installer tests', () => {
beforeEach(() => {
jest.resetModules();
process.env = {...env};
(core.exportVariable as jest.Mock).mockImplementation(
(...args: unknown[]) => {
const [name, val] = args as [string, string];
process.env[name] = val;
}
);
(core.addPath as jest.Mock).mockImplementation((...args: unknown[]) => {
const [p] = args as [string];
process.env['PATH'] = `${p}${path.delimiter}${process.env['PATH']}`;
});
});
describe('DotnetCoreInstaller tests', () => {
const getExecOutputSpy = jest.spyOn(exec, 'getExecOutput');
const warningSpy = jest.spyOn(core, 'warning');
const whichSpy = jest.spyOn(io, 'which');
const getExecOutputSpy = exec.getExecOutput as jest.Mock;
const warningSpy = core.warning as jest.Mock;
const whichSpy = io.which as jest.Mock;
const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying');
const chmodSyncSpy = jest.spyOn(fs, 'chmodSync');
const chmodSyncSpy = fs.chmodSync as jest.Mock;
const readdirSpy = jest.spyOn(fspromises, 'readdir');
describe('installDotnet() tests', () => {
+19 -10
View File
@@ -1,22 +1,31 @@
import {DotnetVersionResolver} from '../src/installer';
import * as hc from '@actions/http-client';
import * as core from '@actions/core';
import {afterEach, beforeEach, describe, expect, it, jest} from '@jest/globals';
// Mock http-client
jest.mock('@actions/http-client');
jest.unstable_mockModule('@actions/http-client', () => ({
HttpClient: jest.fn()
}));
jest.unstable_mockModule('@actions/core', () => ({
warning: jest.fn(),
info: jest.fn(),
debug: jest.fn()
}));
const hc = await import('@actions/http-client');
const core = await import('@actions/core');
const {DotnetVersionResolver} = await import('../src/installer.js');
describe('DotnetVersionResolver with latest', () => {
let getJsonMock: jest.Mock;
let warningSpy: jest.SpyInstance;
let getJsonMock: jest.Mock<(...args: any[]) => Promise<any>>;
let warningSpy: jest.Mock;
beforeEach(() => {
getJsonMock = jest.fn();
(hc.HttpClient as any).mockImplementation(() => {
getJsonMock = jest.fn<(...args: any[]) => Promise<any>>();
(hc.HttpClient as jest.Mock).mockImplementation(() => {
return {
getJson: getJsonMock
};
});
warningSpy = jest.spyOn(core, 'warning').mockImplementation(() => {});
warningSpy = core.warning as jest.Mock;
warningSpy.mockImplementation(() => {});
});
afterEach(() => {
+65 -22
View File
@@ -1,26 +1,71 @@
import * as core from '@actions/core';
import fs from 'fs';
import {
afterEach,
beforeEach,
describe,
expect,
it,
jest,
test
} from '@jest/globals';
import semver from 'semver';
import * as auth from '../src/authutil';
import os from 'os';
import * as setup from '../src/setup-dotnet';
import {DotnetCoreInstaller, DotnetInstallDir} from '../src/installer';
import * as cacheUtils from '../src/cache-utils';
import * as cacheRestore from '../src/cache-restore';
jest.unstable_mockModule('@actions/core', () => ({
getInput: jest.fn(),
getMultilineInput: jest.fn(),
getBooleanInput: jest.fn(),
setFailed: jest.fn(),
warning: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
setOutput: jest.fn(),
addPath: jest.fn(),
exportVariable: jest.fn()
}));
jest.unstable_mockModule('fs', () => {
const actual = jest.requireActual('fs') as typeof import('fs');
const existsSync = jest.fn(actual.existsSync);
const readFileSync = jest.fn(actual.readFileSync);
return {
...actual,
existsSync,
readFileSync,
default: {...actual, existsSync, readFileSync}
};
});
jest.unstable_mockModule('../src/authutil', () => ({
configAuthentication: jest.fn()
}));
jest.unstable_mockModule('../src/cache-utils', () => ({
isCacheFeatureAvailable: jest.fn(),
getNuGetFolderPath: jest.fn()
}));
jest.unstable_mockModule('../src/cache-restore', () => ({
restoreCache: jest.fn()
}));
const core = await import('@actions/core');
const fs = await import('fs');
const auth = await import('../src/authutil.js');
const cacheUtils = await import('../src/cache-utils.js');
const cacheRestore = await import('../src/cache-restore.js');
const setup = await import('../src/setup-dotnet.js');
const {DotnetCoreInstaller, DotnetInstallDir} =
await import('../src/installer.js');
describe('setup-dotnet tests', () => {
const inputs = {} as any;
const getInputSpy = jest.spyOn(core, 'getInput');
const getMultilineInputSpy = jest.spyOn(core, 'getMultilineInput');
const getBooleanInputSpy = jest.spyOn(core, 'getBooleanInput');
const setFailedSpy = jest.spyOn(core, 'setFailed');
const warningSpy = jest.spyOn(core, 'warning');
const debugSpy = jest.spyOn(core, 'debug');
const infoSpy = jest.spyOn(core, 'info');
const setOutputSpy = jest.spyOn(core, 'setOutput');
const getInputSpy = core.getInput as jest.Mock;
const getMultilineInputSpy = core.getMultilineInput as jest.Mock;
const getBooleanInputSpy = core.getBooleanInput as jest.Mock;
const setFailedSpy = core.setFailed as jest.Mock;
const warningSpy = core.warning as jest.Mock;
const debugSpy = core.debug as jest.Mock;
const infoSpy = core.info as jest.Mock;
const setOutputSpy = core.setOutput as jest.Mock;
const existsSyncSpy = jest.spyOn(fs, 'existsSync');
const existsSyncSpy = fs.existsSync as jest.Mock;
const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying');
@@ -29,12 +74,10 @@ describe('setup-dotnet tests', () => {
'installDotnet'
);
const isCacheFeatureAvailableSpy = jest.spyOn(
cacheUtils,
'isCacheFeatureAvailable'
);
const restoreCacheSpy = jest.spyOn(cacheRestore, 'restoreCache');
const configAuthenticationSpy = jest.spyOn(auth, 'configAuthentication');
const isCacheFeatureAvailableSpy =
cacheUtils.isCacheFeatureAvailable as jest.Mock;
const restoreCacheSpy = cacheRestore.restoreCache as jest.Mock;
const configAuthenticationSpy = auth.configAuthentication as jest.Mock;
const addToPathOriginal = DotnetInstallDir.addToPath;
describe('run() tests', () => {