From 3fc81bfec3110026732625bd14a7c6e150fec3ff Mon Sep 17 00:00:00 2001 From: Le Cong Date: Thu, 26 Jun 2025 12:10:25 -0400 Subject: [PATCH 1/2] evaluate import statement directly instead of running npm script --- package-lock.json | 138 +++++++++++------- package.json | 12 +- .../validate-npm-package.spec.ts | 11 ++ .../validate-npm-package.ts | 44 +++--- 4 files changed, 121 insertions(+), 84 deletions(-) diff --git a/package-lock.json b/package-lock.json index 51e0ac5..7fb0eaa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,20 +1,20 @@ { "name": "@checkdigit/github-actions", - "version": "2.4.2", + "version": "2.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@checkdigit/github-actions", - "version": "2.4.2", + "version": "2.5.0", "license": "MIT", "dependencies": { - "@actions/core": "^1.10.1", - "@actions/github": "^6.0.0", + "@actions/core": "^1.11.1", + "@actions/github": "^6.0.1", "@checkdigit/time": "^4.0.0", "@octokit/rest": "^20.1.1", - "debug": "^4.3.5", - "semver": "^7.6.2", + "debug": "^4.4.1", + "semver": "^7.7.2", "undici": "^6.18.2", "uuid": "^9.0.1" }, @@ -24,7 +24,7 @@ "@checkdigit/prettier-config": "^5.4.0", "@checkdigit/typescript-config": "^7.0.1", "@types/debug": "^4.1.12", - "@types/semver": "^7.5.8", + "@types/semver": "^7.7.0", "@types/uuid": "^9.0.8", "nock": "^14.0.0-beta.5", "rimraf": "^5.0.7" @@ -34,31 +34,49 @@ } }, "node_modules/@actions/core": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz", - "integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", + "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", + "license": "MIT", "dependencies": { - "@actions/http-client": "^2.0.1", - "uuid": "^8.3.2" + "@actions/exec": "^1.1.1", + "@actions/http-client": "^2.0.1" } }, - "node_modules/@actions/core/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "bin": { - "uuid": "dist/bin/uuid" + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "license": "MIT", + "dependencies": { + "@actions/io": "^1.0.1" } }, "node_modules/@actions/github": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.0.tgz", - "integrity": "sha512-alScpSVnYmjNEXboZjarjukQEzgCRmjMv6Xj47fsdnqGS73bjJNDpiiXmp8jr0UZLdUB6d9jW63IcmddUP+l0g==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.1.tgz", + "integrity": "sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw==", + "license": "MIT", "dependencies": { "@actions/http-client": "^2.2.0", "@octokit/core": "^5.0.1", - "@octokit/plugin-paginate-rest": "^9.0.0", - "@octokit/plugin-rest-endpoint-methods": "^10.0.0" + "@octokit/plugin-paginate-rest": "^9.2.2", + "@octokit/plugin-rest-endpoint-methods": "^10.4.0", + "@octokit/request": "^8.4.1", + "@octokit/request-error": "^5.1.1", + "undici": "^5.28.5" + } + }, + "node_modules/@actions/github/node_modules/undici": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" } }, "node_modules/@actions/http-client": { @@ -81,6 +99,12 @@ "node": ">=14.0" } }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", + "license": "MIT" + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -2004,9 +2028,10 @@ } }, "node_modules/@octokit/endpoint": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.5.tgz", - "integrity": "sha512-ekqR4/+PCLkEBF6qgj8WqJfvDq65RH85OAgrtnVp1mSxaXF03u2xW/hUdweGS5654IlC0wkNYC18Z50tSYTAFw==", + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", + "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", + "license": "MIT", "dependencies": { "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" @@ -2034,9 +2059,10 @@ "integrity": "sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==" }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.1.tgz", - "integrity": "sha512-wfGhE/TAkXZRLjksFXuDZdmGnJQHvtU/joFQdweXUgzo1XwvBCD4o4+75NtFfjfLK5IwLf9vHTfSiU3sLRYpRw==", + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz", + "integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==", + "license": "MIT", "dependencies": { "@octokit/types": "^12.6.0" }, @@ -2050,12 +2076,14 @@ "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { "version": "20.0.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", - "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==" + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "license": "MIT" }, "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { "version": "12.6.0", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "license": "MIT", "dependencies": { "@octokit/openapi-types": "^20.0.0" } @@ -2099,12 +2127,13 @@ } }, "node_modules/@octokit/request": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.0.tgz", - "integrity": "sha512-9Bb014e+m2TgBeEJGEbdplMVWwPmL1FPtggHQRkV+WVsMggPtEkLKPlcVYm/o8xKLkpJ7B+6N8WfQMtDLX2Dpw==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", + "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", + "license": "MIT", "dependencies": { - "@octokit/endpoint": "^9.0.1", - "@octokit/request-error": "^5.1.0", + "@octokit/endpoint": "^9.0.6", + "@octokit/request-error": "^5.1.1", "@octokit/types": "^13.1.0", "universal-user-agent": "^6.0.0" }, @@ -2113,9 +2142,10 @@ } }, "node_modules/@octokit/request-error": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.0.tgz", - "integrity": "sha512-GETXfE05J0+7H2STzekpKObFe765O5dlAKUTLNGeH+x47z7JjXHfsHKo5z21D/o/IOZTUEI6nyWyR+bZVP/n5Q==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", + "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", + "license": "MIT", "dependencies": { "@octokit/types": "^13.1.0", "deprecation": "^2.0.0", @@ -2341,10 +2371,11 @@ "peer": true }, "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", + "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/stack-utils": { "version": "2.0.3", @@ -3387,11 +3418,12 @@ } }, "node_modules/debug": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", - "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -6575,9 +6607,10 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/natural-compare": { "version": "1.4.0", @@ -7559,9 +7592,10 @@ } }, "node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "license": "ISC", "bin": { "semver": "bin/semver.js" }, diff --git a/package.json b/package.json index c0411cf..7339d47 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@checkdigit/github-actions", - "version": "2.4.2", + "version": "2.5.0", "description": " Provides supporting operations for github action builds.", "author": "Check Digit, LLC", "license": "MIT", @@ -18,12 +18,12 @@ "type": "module", "sideEffects": false, "dependencies": { - "@actions/core": "^1.10.1", - "@actions/github": "^6.0.0", + "@actions/core": "^1.11.1", + "@actions/github": "^6.0.1", "@checkdigit/time": "^4.0.0", "@octokit/rest": "^20.1.1", - "debug": "^4.3.5", - "semver": "^7.6.2", + "debug": "^4.4.1", + "semver": "^7.7.2", "undici": "^6.18.2", "uuid": "^9.0.1" }, @@ -33,7 +33,7 @@ "@checkdigit/prettier-config": "^5.4.0", "@checkdigit/typescript-config": "^7.0.1", "@types/debug": "^4.1.12", - "@types/semver": "^7.5.8", + "@types/semver": "^7.7.0", "@types/uuid": "^9.0.8", "nock": "^14.0.0-beta.5", "rimraf": "^5.0.7" diff --git a/src/validate-npm-package/validate-npm-package.spec.ts b/src/validate-npm-package/validate-npm-package.spec.ts index f8568cd..353c370 100644 --- a/src/validate-npm-package/validate-npm-package.spec.ts +++ b/src/validate-npm-package/validate-npm-package.spec.ts @@ -36,6 +36,17 @@ describe('validate-npm-package', () => { await verifyNpmPackage(); }, 300_000); + it('config only package exporting json entry point should work too', async () => { + actionsCoreSpy.mockImplementationOnce((name) => { + if (name === 'betaPackage') { + return '@checkdigit/prettier-config@7.1.0-PR.56-1e02'; + } + return ''; + }); + + await verifyNpmPackage(); + }, 300_000); + // Test uses a bad version of approval package // and requires skipLibCheck: false in tsconfig.json // we set it manually in validate npm package as diff --git a/src/validate-npm-package/validate-npm-package.ts b/src/validate-npm-package/validate-npm-package.ts index bb8feb2..518aa5c 100644 --- a/src/validate-npm-package/validate-npm-package.ts +++ b/src/validate-npm-package/validate-npm-package.ts @@ -16,8 +16,12 @@ interface PackageJson { name: string; version: string; engine?: Record; - devDependencies?: Record; - overrides?: Record; + main?: string; // for backward compatibility + exports?: { + '.'?: { + import?: string; + }; + }; } const exec = util.promisify(childProcess.exec); @@ -35,10 +39,6 @@ async function retrievePackageJson(workFolder: string, packageNameAndBetaVersion // create a minimal project with the package as a dependency async function generateProject(workFolder: string, packageJson: PackageJson): Promise { - // create index.ts to import the dependency - await fs.mkdir(`${workFolder}/src`); - await fs.writeFile(path.join(workFolder, 'src', 'index.ts'), `import '${packageJson.name}';\n`); - // create package.json with the dependency const projectPackageJson = { name: 'test', @@ -49,22 +49,8 @@ async function generateProject(workFolder: string, packageJson: PackageJson): Pr dependencies: { [packageJson.name]: packageJson.version, }, - devDependencies: packageJson.devDependencies, - ...(packageJson.overrides === undefined ? {} : { overrides: packageJson.overrides }), - scripts: { - compile: 'tsc --noEmit', - }, }; await fs.writeFile(`${workFolder}/package.json`, JSON.stringify(projectPackageJson, null, 2)); - - // create tsconfig.json - const tsconfigJson = { - extends: '@checkdigit/typescript-config', - compilerOptions: { - skipLibCheck: false, - }, - }; - await fs.writeFile(`${workFolder}/tsconfig.json`, JSON.stringify(tsconfigJson, null, 2)); } async function installDependencies(workFolder: string): Promise { @@ -75,12 +61,14 @@ async function installDependencies(workFolder: string): Promise { log('installNpmDependencies - execResult', execResult); } -async function verifyDefaultImport(workFolder: string): Promise { - const fullCommandLine = `npm run compile`; - log('verifyImportEntryPoints - fullCommandLine', fullCommandLine); +async function verifyDefaultImport(workFolder: string, packageName: string, importEntryPoint: string): Promise { + const importType = importEntryPoint.endsWith('.json') ? ` with { type: 'json' }` : ''; + const importStatement = `import '${packageName}'${importType};`; + const commandLine = `node -e "${importStatement}"`; + log('verifyDefaultImport - commandLine', commandLine); - const execResult = await exec(fullCommandLine, { cwd: workFolder }); - log('verifyImportEntryPoints - execResult', execResult); + const execResult = await exec(commandLine, { cwd: workFolder }); + log('verifyDefaultImport - execResult', execResult); } export default async function (): Promise { @@ -96,12 +84,16 @@ export default async function (): Promise { await addNPMRCFile(workFolder); const packageJson = await retrievePackageJson(workFolder, packageNameAndBetaVersion); + const importEntryPoint = packageJson.exports?.['.']?.import ?? packageJson.main; + if (typeof importEntryPoint !== 'string') { + throw new TypeError('no import entry point found, or not defined following our standards.'); + } await generateProject(workFolder, packageJson); await installDependencies(workFolder); - await verifyDefaultImport(workFolder); + await verifyDefaultImport(workFolder, packageJson.name, importEntryPoint); log('Action end'); } From a0d0114e264ed6376a3421b23b13a06f2caf71b5 Mon Sep 17 00:00:00 2001 From: Le Cong Date: Wed, 13 Aug 2025 17:55:26 -0400 Subject: [PATCH 2/2] added test case to verify that no dependency conflict occur for service without direct dependency with serve-runtime, e.g. connector --- src/validate-npm-package/validate-npm-package.spec.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/validate-npm-package/validate-npm-package.spec.ts b/src/validate-npm-package/validate-npm-package.spec.ts index 6d2265f..8bd6ff5 100644 --- a/src/validate-npm-package/validate-npm-package.spec.ts +++ b/src/validate-npm-package/validate-npm-package.spec.ts @@ -46,6 +46,17 @@ describe('validate-npm-package', async () => { await verifyNpmPackage(); }); + it('service without serve-runtime should not have dependency conflicts', { timeout: 300_000 }, async () => { + getInputMock.mock.mockImplementationOnce((name) => { + if (name === 'betaPackage') { + return '@checkdigit/connector@4.0.2-PR.141-c066'; + } + return ''; + }); + + await verifyNpmPackage(); + }); + // Test uses a bad version of approval package // and requires skipLibCheck: false in tsconfig.json // we set it manually in validate npm package as