From 351d39a82c8228025236714a9e22a5c6989b5663 Mon Sep 17 00:00:00 2001 From: Jan Stehlik Date: Thu, 12 Aug 2021 17:22:26 +0100 Subject: [PATCH 1/2] fix: read target framework from any PropertyGroup within project file --- .eslintrc.js | 1 + jest.config.js | 10 +++++ lib/nuget-parser/csproj-parser.ts | 38 +++++++++++-------- package.json | 5 ++- test/csproj.spec.ts | 32 ++++++++++++++++ test/csproj.test.ts | 16 ++------ .../example.csproj | 33 ++++++++++++++++ 7 files changed, 106 insertions(+), 29 deletions(-) create mode 100644 jest.config.js create mode 100644 test/csproj.spec.ts create mode 100644 test/stubs/target-framework-version-in-non-first-property-group/example.csproj diff --git a/.eslintrc.js b/.eslintrc.js index 7cc90bf6..10ef2bfb 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -8,6 +8,7 @@ module.exports = { env: { node: true, es6: true, + jest: true, }, plugins: ['@typescript-eslint'], extends: [ diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..3dd779db --- /dev/null +++ b/jest.config.js @@ -0,0 +1,10 @@ +module.exports = { + testEnvironment: 'node', + transform: { + '^.+\\.(ts)?$': 'ts-jest', + }, + testMatch: ['**/*.spec.ts'], + collectCoverage: false, + moduleFileExtensions: ['ts', 'js', 'json'], + forceExit: true, +}; diff --git a/lib/nuget-parser/csproj-parser.ts b/lib/nuget-parser/csproj-parser.ts index fe470b6e..11536260 100644 --- a/lib/nuget-parser/csproj-parser.ts +++ b/lib/nuget-parser/csproj-parser.ts @@ -24,39 +24,45 @@ export async function getTargetFrameworksFromProjFile( const csprojContents = fs.readFileSync(csprojPath); - let frameworks: (TargetFramework | undefined)[] = []; + let targetFrameworks: (TargetFramework | undefined)[] = []; parseXML.parseString(csprojContents, (err, parsedCsprojContents) => { if (err) { reject(new FileNotProcessableError(err)); return; } - const versionLoc = parsedCsprojContents?.Project?.PropertyGroup?.[0]; - const versions = [] - .concat( - ( - versionLoc?.TargetFrameworkVersion?.[0] || - versionLoc?.TargetFramework?.[0] || - versionLoc?.TargetFrameworks?.[0] || - '' - ).split(';'), - ) - .filter(Boolean); - if (versions.length < 1) { + const parsedTargetFrameworks = parsedCsprojContents?.Project?.PropertyGroup?.reduce( + (targetFrameworks, propertyGroup) => { + const targetFrameworkSource = + propertyGroup?.TargetFrameworkVersion?.[0] || + propertyGroup?.TargetFramework?.[0] || + propertyGroup?.TargetFrameworks?.[0] || + ''; + + return targetFrameworks + .concat(targetFrameworkSource.split(';')) + .filter(Boolean); + }, + [], + ); + + if (parsedTargetFrameworks.length < 1) { debug( 'Could not find TargetFrameworkVersion/TargetFramework' + '/TargetFrameworks defined in the Project.PropertyGroup field of ' + 'your .csproj file', ); } - frameworks = versions.map(toReadableFramework).filter(Boolean); - if (versions.length > 1 && frameworks.length < 1) { + targetFrameworks = parsedTargetFrameworks + .map(toReadableFramework) + .filter(Boolean); + if (parsedTargetFrameworks.length > 1 && targetFrameworks.length < 1) { debug( 'Could not find valid/supported .NET version in csproj file located at' + csprojPath, ); } - resolve(frameworks[0]); + resolve(targetFrameworks[0]); }); }); } diff --git a/package.json b/package.json index 0d2f3623..615b1a3f 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "main": "dist/index.js", "scripts": { "test": "npm run lint && npm run unit-test", - "unit-test": "tap --no-coverage test/*.test.ts --timeout=300", + "unit-test": "jest && tap --no-coverage test/*.test.ts --timeout=300", "lint": "prettier --check \"./lib/**/*.ts\" && eslint -c .eslintrc.js \"./lib/**/*\"", "lint:fix": "prettier --write \"./lib/**/*.ts\" && eslint -c .eslintrc.js --fix \"./lib/**/*\"", "build": "tsc", @@ -42,13 +42,16 @@ "xml2js": "^0.4.17" }, "devDependencies": { + "@types/jest": "^27.0.0", "@types/node": "^10", "@typescript-eslint/eslint-plugin": "^2.31.0", "@typescript-eslint/parser": "^2.31.0", "eslint": "^6.8.0", "eslint-config-prettier": "^6.15.0", + "jest": "^27.0.6", "prettier": "^1.19.1", "tap": "^14.10.7", + "ts-jest": "^27.0.4", "typescript": "^3.8.3" } } diff --git a/test/csproj.spec.ts b/test/csproj.spec.ts new file mode 100644 index 00000000..8f771f51 --- /dev/null +++ b/test/csproj.spec.ts @@ -0,0 +1,32 @@ +import { getTargetFrameworksFromProjFile } from '../lib/nuget-parser/csproj-parser'; + +const targetFrameworkInNonFirstPropertyGroup = + './test/stubs/target-framework-version-in-non-first-property-group'; +const multipleTargetFrameworksPath = + './test/stubs/target_framework/csproj_multiple'; + +describe('getTargetFrameworksFromProjFile', () => { + it('should parse target framework version even if it is in property group that is not first', async () => { + const targetFramework = await getTargetFrameworksFromProjFile( + targetFrameworkInNonFirstPropertyGroup, + ); + + expect(targetFramework).toMatchObject({ + framework: '.NETFramework', + original: 'v4.7.2', + version: '4.7.2', + }); + }); + + it('should return first target framwork if multiple ones are available', async () => { + const targetFramework = await getTargetFrameworksFromProjFile( + multipleTargetFrameworksPath, + ); + + expect(targetFramework).toMatchObject({ + framework: '.NETCore', + original: 'netcoreapp2.0', + version: '2.0', + }); + }); +}); diff --git a/test/csproj.test.ts b/test/csproj.test.ts index 7e51bb5b..ec4c0932 100644 --- a/test/csproj.test.ts +++ b/test/csproj.test.ts @@ -1,36 +1,28 @@ import * as tap from 'tap'; const test = tap.test; import * as plugin from '../lib/index'; -import {getTargetFrameworksFromProjFile} from '../lib/nuget-parser/csproj-parser'; -const multipleFrameworksPath = './test/stubs/target_framework/csproj_multiple/'; const noProjectPath = './test/stubs/target_framework/no_csproj/'; const noValidFrameworksPath = './test/stubs/target_framework/no_target_valid_framework'; const noDeps = './test/stubs/target_framework/no-dependencies/'; const manifestFile = 'obj/project.assets.json'; -test('parse dotnet with csproj containing multiple versions retrieves first one', async (t) => { - const dotnetVersions = await getTargetFrameworksFromProjFile( - multipleFrameworksPath); - t.equal('netcoreapp2.0', dotnetVersions!.original); -}); - -test('parse dotnet with vbproj', async (t) => { +test('parse dotnet with vbproj', async t => { const res = await plugin.inspect(noProjectPath, manifestFile); t.equal(res.package.name, 'no_csproj'); t.equal(res.plugin.targetRuntime, 'netcoreapp2.0'); }); -test('parse dotnet with no deps', async (t) => { +test('parse dotnet with no deps', async t => { const res = await plugin.inspect(noDeps, manifestFile); t.equal(Object.keys(res.package.dependencies).length, 0); }); -test('parse dotnet with no valid framework defined', async (t) => { +test('parse dotnet with no valid framework defined', async t => { try { await plugin.inspect(noValidFrameworksPath, manifestFile); t.fail('Expected error to be thrown!'); - } catch(err) { + } catch (err) { t.equal(err.message, 'No frameworks were found in project.assets.json', 'expected error'); } }); diff --git a/test/stubs/target-framework-version-in-non-first-property-group/example.csproj b/test/stubs/target-framework-version-in-non-first-property-group/example.csproj new file mode 100644 index 00000000..6c29b65a --- /dev/null +++ b/test/stubs/target-framework-version-in-non-first-property-group/example.csproj @@ -0,0 +1,33 @@ + + + + true + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + bin\ + TRACE;STANDARD;PRO; + + + bin\ + TRACE;STANDARD;PRO; + + + + Debug + AnyCPU + 9.0.30729 + v4.7.2 + + + true + + + pdbonly + + + bin\ + TRACE;STANDARD;PRO; + + \ No newline at end of file From 936f464aaa2dd4b9082394c89caa7b5ccc184da4 Mon Sep 17 00:00:00 2001 From: Jan Stehlik Date: Fri, 13 Aug 2021 11:20:30 +0100 Subject: [PATCH 2/2] chore: support node 10 --- .circleci/config.yml | 20 ++++++++++++++++++++ package.json | 4 ++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 39a8a06a..4b78f404 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -111,6 +111,16 @@ workflows: - master # UNIX tests + - test-unix: + name: Unix Tests for Node=10 + context: nodejs-install + node_version: '10' + requires: + - Lint + filters: + branches: + ignore: + - master - test-unix: name: Unix Tests for Node=12 context: nodejs-install @@ -133,6 +143,16 @@ workflows: - master # Windows tests + - test-windows: + name: Windows Tests for Node=10 + context: nodejs-install + node_version: '10.21.0' + requires: + - Lint + filters: + branches: + ignore: + - master - test-windows: name: Windows Tests for Node=12 context: nodejs-install diff --git a/package.json b/package.json index 72ca2c60..615b1a3f 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "author": "snyk.io", "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": ">=10" }, "files": [ "bin", @@ -43,7 +43,7 @@ }, "devDependencies": { "@types/jest": "^27.0.0", - "@types/node": "^12", + "@types/node": "^10", "@typescript-eslint/eslint-plugin": "^2.31.0", "@typescript-eslint/parser": "^2.31.0", "eslint": "^6.8.0",