From 2042c96b2f6d4d8d2ff00d707d746bcbdf30ac26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Sj=C3=B6berg?= <samuel.sjoberg@extendaretail.com> Date: Mon, 20 Jun 2022 17:20:03 +0200 Subject: [PATCH 1/5] feat(sonar-scanner): Allow users to specify the dotnet-scanner version --- sonar-scanner/action.yml | 2 ++ sonar-scanner/dist/index.js | 20 ++++++++++++++------ sonar-scanner/src/index.js | 4 ++-- sonar-scanner/src/scan-msbuild.js | 16 ++++++++++++---- sonar-scanner/test/index.test.js | 2 +- sonar-scanner/test/scan-msbuild.test.js | 15 ++++++++++----- 6 files changed, 41 insertions(+), 18 deletions(-) diff --git a/sonar-scanner/action.yml b/sonar-scanner/action.yml index e7325200c..dc9e7568b 100644 --- a/sonar-scanner/action.yml +++ b/sonar-scanner/action.yml @@ -8,6 +8,8 @@ inputs: description: | The sonar scanner to use. Valid values are 'auto', 'maven', 'gradle', 'node' and 'dotnet'. The default value 'auto' will attempt to perform auto-discovery. Auto-discovery does not work for 'dotnet'. + For 'dotnet' it is possible to pin the scanner to a specific version, for example 'dotnet-5.6.0'. Only pin the + dotnet scanner version if you are using an old dotnet version that is no longer supported by the latest version. required: true default: auto main-branch: diff --git a/sonar-scanner/dist/index.js b/sonar-scanner/dist/index.js index 40f550e7a..9204cdb7f 100644 --- a/sonar-scanner/dist/index.js +++ b/sonar-scanner/dist/index.js @@ -60967,9 +60967,9 @@ const action = async () => { let waitForQualityGate = false; - if (sonarScanner === 'dotnet') { + if (sonarScanner.startsWith('dotnet')) { // MSBuild scanning - waitForQualityGate = await scanMsBuild(hostUrl, mainBranch, scanCommands.dotnet); + waitForQualityGate = await scanMsBuild(hostUrl, mainBranch, sonarScanner, scanCommands.dotnet); } else { // Perform the scanning for everything else. await core.group('Run Sonar analysis', async () => scan(hostUrl, mainBranch, sonarScanner, scanCommands)); @@ -61128,9 +61128,17 @@ const scanWithJavaHome = async (args) => { return exec.exec(scanner, args, { env }); }; -const beginScan = async (hostUrl, mainBranch, customArgs = '') => { +const beginScan = async (hostUrl, mainBranch, sonarScanner, customArgs = '') => { await core.group('Install dotnet-sonarscanner', async () => { - await exec.exec(`dotnet tool install -g dotnet-sonarscanner ${hostUrl.startsWith('https://sonar.extenda.io') ? '--version 4.10.0' : ''}`); + const [, version = ''] = sonarScanner.split('-'); + let versionArg = ''; + if (version !== '') { + core.warning(`Using pinned dotnet-scanner version ${version}`); + versionArg = `--version ${version}`; + } else if (hostUrl.startsWith('https://sonar.extenda.io')) { + versionArg = '--version 4.10.0'; + } + await exec.exec(`dotnet tool install -g dotnet-sonarscanner ${versionArg}`); }); const version = await getBuildVersion(`-${process.env.GITHUB_SHA}`); @@ -61154,11 +61162,11 @@ const finishScan = async (hostUrl) => { }); }; -const scanMsBuild = async (hostUrl, mainBranch, customArgs = '') => { +const scanMsBuild = async (hostUrl, mainBranch, sonarScanner, customArgs = '') => { if (!fs.existsSync(markerFile)) { // Create marker and begin scan fs.closeSync(fs.openSync(markerFile, 'w')); - await beginScan(hostUrl, mainBranch, customArgs); + await beginScan(hostUrl, mainBranch, sonarScanner, customArgs); return false; } diff --git a/sonar-scanner/src/index.js b/sonar-scanner/src/index.js index b239bae0b..c025b86cf 100644 --- a/sonar-scanner/src/index.js +++ b/sonar-scanner/src/index.js @@ -51,9 +51,9 @@ const action = async () => { let waitForQualityGate = false; - if (sonarScanner === 'dotnet') { + if (sonarScanner.startsWith('dotnet')) { // MSBuild scanning - waitForQualityGate = await scanMsBuild(hostUrl, mainBranch, scanCommands.dotnet); + waitForQualityGate = await scanMsBuild(hostUrl, mainBranch, sonarScanner, scanCommands.dotnet); } else { // Perform the scanning for everything else. await core.group('Run Sonar analysis', async () => scan(hostUrl, mainBranch, sonarScanner, scanCommands)); diff --git a/sonar-scanner/src/scan-msbuild.js b/sonar-scanner/src/scan-msbuild.js index 298b5c9a9..68a6aabb9 100644 --- a/sonar-scanner/src/scan-msbuild.js +++ b/sonar-scanner/src/scan-msbuild.js @@ -40,9 +40,17 @@ const scanWithJavaHome = async (args) => { return exec.exec(scanner, args, { env }); }; -const beginScan = async (hostUrl, mainBranch, customArgs = '') => { +const beginScan = async (hostUrl, mainBranch, sonarScanner, customArgs = '') => { await core.group('Install dotnet-sonarscanner', async () => { - await exec.exec(`dotnet tool install -g dotnet-sonarscanner ${hostUrl.startsWith('https://sonar.extenda.io') ? '--version 4.10.0' : ''}`); + const [, version = ''] = sonarScanner.split('-'); + let versionArg = ''; + if (version !== '') { + core.warning(`Using pinned dotnet-scanner version ${version}`); + versionArg = `--version ${version}`; + } else if (hostUrl.startsWith('https://sonar.extenda.io')) { + versionArg = '--version 4.10.0'; + } + await exec.exec(`dotnet tool install -g dotnet-sonarscanner ${versionArg}`); }); const version = await getBuildVersion(`-${process.env.GITHUB_SHA}`); @@ -66,11 +74,11 @@ const finishScan = async (hostUrl) => { }); }; -const scanMsBuild = async (hostUrl, mainBranch, customArgs = '') => { +const scanMsBuild = async (hostUrl, mainBranch, sonarScanner, customArgs = '') => { if (!fs.existsSync(markerFile)) { // Create marker and begin scan fs.closeSync(fs.openSync(markerFile, 'w')); - await beginScan(hostUrl, mainBranch, customArgs); + await beginScan(hostUrl, mainBranch, sonarScanner, customArgs); return false; } diff --git a/sonar-scanner/test/index.test.js b/sonar-scanner/test/index.test.js index b8265cd62..c55d70226 100644 --- a/sonar-scanner/test/index.test.js +++ b/sonar-scanner/test/index.test.js @@ -112,7 +112,7 @@ describe('Sonar-Scanner Action', () => { checkQualityGate.mockResolvedValueOnce(0); scanMsBuild.mockResolvedValueOnce(true); await action(); - expect(scanMsBuild).toHaveBeenCalledWith('https://sonarcloud.io', 'master', ''); + expect(scanMsBuild).toHaveBeenCalledWith('https://sonarcloud.io', 'master', 'dotnet', ''); expect(checkQualityGate).toHaveBeenCalled(); }); diff --git a/sonar-scanner/test/scan-msbuild.test.js b/sonar-scanner/test/scan-msbuild.test.js index cbc980141..a9c0baf07 100644 --- a/sonar-scanner/test/scan-msbuild.test.js +++ b/sonar-scanner/test/scan-msbuild.test.js @@ -31,7 +31,7 @@ describe('Scan MSBuild', () => { }); test('It begins to scan when marker file is missing', async () => { - const output = await scanMsBuild('https://sonar.extenda.io', 'master'); + const output = await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); expect(output).toEqual(false); expect(fs.existsSync(markerFile)).toEqual(true); expect(exec.exec.mock.calls.length).toEqual(2); @@ -40,11 +40,16 @@ describe('Scan MSBuild', () => { expect(exec.exec.mock.calls[1][0]).toContain('begin'); }); + test('It can install a pinned dotnet-scanner version', async () => { + await scanMsBuild('https://sonarcloud.io', 'master', 'dotnet-5.6.0'); + expect(exec.exec.mock.calls[0][0]).toEqual('dotnet tool install -g dotnet-sonarscanner --version 5.6.0'); + }); + test('It ends scan when marker file exists', async () => { // Create marker file fs.closeSync(fs.openSync(markerFile, 'w')); - const output = await scanMsBuild('https://sonar.extenda.io', 'master'); + const output = await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); expect(output).toEqual(true); expect(exec.exec.mock.calls.length).toEqual(1); @@ -57,7 +62,7 @@ describe('Scan MSBuild', () => { fs.closeSync(fs.openSync(markerFile, 'w')); const platformSpy = jest.spyOn(os, 'platform').mockReturnValue('win32'); - await scanMsBuild('https://sonar.extenda.io', 'master'); + await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); expect(Object.keys(exec.exec.mock.calls[0][2].env)).not.toContain('JAVA_HOME'); platformSpy.mockRestore(); }); @@ -68,7 +73,7 @@ describe('Scan MSBuild', () => { process.env.JDK_BASEDIR = '/tmp/missing'; const platformSpy = jest.spyOn(os, 'platform').mockReturnValue('linux'); - await scanMsBuild('https://sonar.extenda.io', 'master'); + await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); expect(Object.keys(exec.exec.mock.calls[0][2].env)).not.toContain('JAVA_HOME'); platformSpy.mockRestore(); }); @@ -77,7 +82,7 @@ describe('Scan MSBuild', () => { test('It can set JAVA_HOME', async () => { fs.closeSync(fs.openSync(markerFile, 'w')); const platformSpy = jest.spyOn(os, 'platform').mockReturnValue('linux'); - await scanMsBuild('https://sonar.extenda.io', 'master'); + await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); expect(Object.keys(exec.exec.mock.calls[0][2].env)).toContain('JAVA_HOME'); expect(exec.exec.mock.calls[0][2].env).toMatchObject({ JAVA_HOME: '/usr/lib/jvm/adoptopenjdk-11-hotspot-amd64', From a76f68f65aec6278114c785c5a2b0894e81321ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Sj=C3=B6berg?= <samuel.sjoberg@extendaretail.com> Date: Mon, 20 Jun 2022 18:42:37 +0200 Subject: [PATCH 2/5] fix: Modify os jest spy --- sonar-scanner/test/scan-msbuild.test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sonar-scanner/test/scan-msbuild.test.js b/sonar-scanner/test/scan-msbuild.test.js index a9c0baf07..6c06827b1 100644 --- a/sonar-scanner/test/scan-msbuild.test.js +++ b/sonar-scanner/test/scan-msbuild.test.js @@ -61,7 +61,7 @@ describe('Scan MSBuild', () => { // Create marker file fs.closeSync(fs.openSync(markerFile, 'w')); - const platformSpy = jest.spyOn(os, 'platform').mockReturnValue('win32'); + const platformSpy = jest.spyOn(os, 'platform').mockReturnValueOnce('win32'); await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); expect(Object.keys(exec.exec.mock.calls[0][2].env)).not.toContain('JAVA_HOME'); platformSpy.mockRestore(); @@ -72,7 +72,7 @@ describe('Scan MSBuild', () => { fs.closeSync(fs.openSync(markerFile, 'w')); process.env.JDK_BASEDIR = '/tmp/missing'; - const platformSpy = jest.spyOn(os, 'platform').mockReturnValue('linux'); + const platformSpy = jest.spyOn(os, 'platform').mockReturnValueOnce('linux'); await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); expect(Object.keys(exec.exec.mock.calls[0][2].env)).not.toContain('JAVA_HOME'); platformSpy.mockRestore(); @@ -81,7 +81,7 @@ describe('Scan MSBuild', () => { if (fs.existsSync('/usr/lib/jvm')) { test('It can set JAVA_HOME', async () => { fs.closeSync(fs.openSync(markerFile, 'w')); - const platformSpy = jest.spyOn(os, 'platform').mockReturnValue('linux'); + const platformSpy = jest.spyOn(os, 'platform').mockReturnValueOnce('linux'); await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); expect(Object.keys(exec.exec.mock.calls[0][2].env)).toContain('JAVA_HOME'); expect(exec.exec.mock.calls[0][2].env).toMatchObject({ From d4a6b3ce367250a3d79e79c3b99e683bd2ec2bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Sj=C3=B6berg?= <samuel.sjoberg@extendaretail.com> Date: Mon, 20 Jun 2022 18:57:53 +0200 Subject: [PATCH 3/5] fix: Use mock-fs is scan-msbuild test --- sonar-scanner/test/scan-msbuild.test.js | 32 ++++++++++++++++++------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/sonar-scanner/test/scan-msbuild.test.js b/sonar-scanner/test/scan-msbuild.test.js index 6c06827b1..cfe19cd10 100644 --- a/sonar-scanner/test/scan-msbuild.test.js +++ b/sonar-scanner/test/scan-msbuild.test.js @@ -1,12 +1,14 @@ +const mockFs = require('mock-fs'); const exec = require('@actions/exec'); const path = require('path'); const fs = require('fs'); const os = require('os'); +const { getBuildVersion } = require('../../utils/src/versions'); jest.mock('@actions/exec'); - jest.mock('../src/sonar-credentials'); jest.mock('../../utils/src/pull-request-info'); +jest.mock('../../utils/src/versions'); const { scanMsBuild, markerFile } = require('../src/scan-msbuild'); @@ -20,17 +22,17 @@ describe('Scan MSBuild', () => { process.env.GITHUB_REPOSITORY = 'extenda/actions'; process.env.SONAR_TOKEN = 'x'; process.env.GITHUB_EVENT_PATH = path.join(__dirname, 'push-event.json'); + getBuildVersion.mockReturnValueOnce('0.0.1-local'); }); afterEach(() => { - if (fs.existsSync(markerFile)) { - fs.unlinkSync(markerFile); - } + mockFs.restore(); process.env = orgEnv; jest.resetAllMocks(); }); test('It begins to scan when marker file is missing', async () => { + mockFs({}); const output = await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); expect(output).toEqual(false); expect(fs.existsSync(markerFile)).toEqual(true); @@ -41,13 +43,16 @@ describe('Scan MSBuild', () => { }); test('It can install a pinned dotnet-scanner version', async () => { + mockFs({}); await scanMsBuild('https://sonarcloud.io', 'master', 'dotnet-5.6.0'); expect(exec.exec.mock.calls[0][0]).toEqual('dotnet tool install -g dotnet-sonarscanner --version 5.6.0'); }); test('It ends scan when marker file exists', async () => { // Create marker file - fs.closeSync(fs.openSync(markerFile, 'w')); + const files = {}; + files[markerFile] = ''; + mockFs(files); const output = await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); @@ -59,7 +64,9 @@ describe('Scan MSBuild', () => { test('It will skip JAVA_HOME on Windows', async () => { // Create marker file - fs.closeSync(fs.openSync(markerFile, 'w')); + const files = {}; + files[markerFile] = ''; + mockFs(files); const platformSpy = jest.spyOn(os, 'platform').mockReturnValueOnce('win32'); await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); @@ -68,8 +75,11 @@ describe('Scan MSBuild', () => { }); test('It can handle missing JDK', async () => { - // Create marker fil - fs.closeSync(fs.openSync(markerFile, 'w')); + // Create marker file + const files = {}; + files[markerFile] = ''; + mockFs(files); + process.env.JDK_BASEDIR = '/tmp/missing'; const platformSpy = jest.spyOn(os, 'platform').mockReturnValueOnce('linux'); @@ -80,7 +90,11 @@ describe('Scan MSBuild', () => { if (fs.existsSync('/usr/lib/jvm')) { test('It can set JAVA_HOME', async () => { - fs.closeSync(fs.openSync(markerFile, 'w')); + // Create marker file + const files = {}; + files[markerFile] = ''; + mockFs(files); + const platformSpy = jest.spyOn(os, 'platform').mockReturnValueOnce('linux'); await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); expect(Object.keys(exec.exec.mock.calls[0][2].env)).toContain('JAVA_HOME'); From c94717bdb1846473b9df0e6e757f5db81e9214c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Sj=C3=B6berg?= <samuel.sjoberg@extendaretail.com> Date: Mon, 20 Jun 2022 19:22:15 +0200 Subject: [PATCH 4/5] chore: Rewrite conditional test --- sonar-scanner/dist/index.js | 8 +++---- sonar-scanner/src/scan-msbuild.js | 8 +++---- sonar-scanner/test/scan-msbuild.test.js | 30 ++++++++++++------------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/sonar-scanner/dist/index.js b/sonar-scanner/dist/index.js index 9204cdb7f..a816689cb 100644 --- a/sonar-scanner/dist/index.js +++ b/sonar-scanner/dist/index.js @@ -61130,11 +61130,11 @@ const scanWithJavaHome = async (args) => { const beginScan = async (hostUrl, mainBranch, sonarScanner, customArgs = '') => { await core.group('Install dotnet-sonarscanner', async () => { - const [, version = ''] = sonarScanner.split('-'); + const [, scannerVersion = ''] = sonarScanner.split('-'); let versionArg = ''; - if (version !== '') { - core.warning(`Using pinned dotnet-scanner version ${version}`); - versionArg = `--version ${version}`; + if (scannerVersion !== '') { + core.warning(`Using pinned dotnet-scanner version ${scannerVersion}`); + versionArg = `--version ${scannerVersion}`; } else if (hostUrl.startsWith('https://sonar.extenda.io')) { versionArg = '--version 4.10.0'; } diff --git a/sonar-scanner/src/scan-msbuild.js b/sonar-scanner/src/scan-msbuild.js index 68a6aabb9..9063d9721 100644 --- a/sonar-scanner/src/scan-msbuild.js +++ b/sonar-scanner/src/scan-msbuild.js @@ -42,11 +42,11 @@ const scanWithJavaHome = async (args) => { const beginScan = async (hostUrl, mainBranch, sonarScanner, customArgs = '') => { await core.group('Install dotnet-sonarscanner', async () => { - const [, version = ''] = sonarScanner.split('-'); + const [, scannerVersion = ''] = sonarScanner.split('-'); let versionArg = ''; - if (version !== '') { - core.warning(`Using pinned dotnet-scanner version ${version}`); - versionArg = `--version ${version}`; + if (scannerVersion !== '') { + core.warning(`Using pinned dotnet-scanner version ${scannerVersion}`); + versionArg = `--version ${scannerVersion}`; } else if (hostUrl.startsWith('https://sonar.extenda.io')) { versionArg = '--version 4.10.0'; } diff --git a/sonar-scanner/test/scan-msbuild.test.js b/sonar-scanner/test/scan-msbuild.test.js index cfe19cd10..ac48459fa 100644 --- a/sonar-scanner/test/scan-msbuild.test.js +++ b/sonar-scanner/test/scan-msbuild.test.js @@ -88,20 +88,20 @@ describe('Scan MSBuild', () => { platformSpy.mockRestore(); }); - if (fs.existsSync('/usr/lib/jvm')) { - test('It can set JAVA_HOME', async () => { - // Create marker file - const files = {}; - files[markerFile] = ''; - mockFs(files); - - const platformSpy = jest.spyOn(os, 'platform').mockReturnValueOnce('linux'); - await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); - expect(Object.keys(exec.exec.mock.calls[0][2].env)).toContain('JAVA_HOME'); - expect(exec.exec.mock.calls[0][2].env).toMatchObject({ - JAVA_HOME: '/usr/lib/jvm/adoptopenjdk-11-hotspot-amd64', - }); - platformSpy.mockRestore(); + test('It can set JAVA_HOME', async () => { + // Create marker file + const files = { + '/usr/lib/jvm/adoptopenjdk-11-hotspot-amd64/bin': '', + }; + files[markerFile] = ''; + mockFs(files); + + const platformSpy = jest.spyOn(os, 'platform').mockReturnValueOnce('linux'); + await scanMsBuild('https://sonar.extenda.io', 'master', 'dotnet'); + expect(Object.keys(exec.exec.mock.calls[0][2].env)).toContain('JAVA_HOME'); + expect(exec.exec.mock.calls[0][2].env).toMatchObject({ + JAVA_HOME: '/usr/lib/jvm/adoptopenjdk-11-hotspot-amd64', }); - } + platformSpy.mockRestore(); + }); }); From ce741b52495c9e681bf4cd791d7ea7ce19debb17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20Sj=C3=B6berg?= <samuel.sjoberg@extendaretail.com> Date: Mon, 20 Jun 2022 20:03:36 +0200 Subject: [PATCH 5/5] fix: Remove dependecy on os module --- setup-gcloud/test/setup-gcloud.test.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/setup-gcloud/test/setup-gcloud.test.js b/setup-gcloud/test/setup-gcloud.test.js index b64a3c521..f89b5ed8d 100644 --- a/setup-gcloud/test/setup-gcloud.test.js +++ b/setup-gcloud/test/setup-gcloud.test.js @@ -1,3 +1,5 @@ +const path = require('path'); + const mockFs = require('mock-fs'); // Mock out tools download @@ -10,7 +12,6 @@ jest.mock('@actions/core'); const core = require('@actions/core'); const exec = require('@actions/exec'); -const os = require('os'); const setupGcloud = require('../src/setup-gcloud'); const jsonKey = { @@ -72,10 +73,6 @@ describe('Setup Gcloud', () => { exec.exec.mockResolvedValueOnce(0); await setupGcloud(base64Key, 'latest', true); expect(core.exportVariable.mock.calls[0][0]).toEqual('GOOGLE_APPLICATION_CREDENTIALS'); - if (os.platform() === 'win32') { - expect(core.exportVariable.mock.calls[0][1]).toContain('\\workspace\\'); - } else { - expect(core.exportVariable.mock.calls[0][1]).toContain('/workspace/'); - } + expect(core.exportVariable.mock.calls[0][1]).toContain(`${path.sep}workspace${path.sep}`); }); });