diff --git a/.github/workflows/release-new-action-version.yml b/.github/workflows/release-new-action-version.yml index b14c183..6a29095 100644 --- a/.github/workflows/release-new-action-version.yml +++ b/.github/workflows/release-new-action-version.yml @@ -22,7 +22,7 @@ jobs: steps: - name: Update the ${{ env.TAG_NAME }} tag id: update-major-tag - uses: actions/publish-action@v0.1.0 + uses: actions/publish-action@v0.2.0 with: source-tag: ${{ env.TAG_NAME }} slack-webhook: ${{ secrets.SLACK_WEBHOOK }} \ No newline at end of file diff --git a/.github/workflows/workflow.yml b/.github/workflows/workflow.yml index 629d82a..58afa4a 100644 --- a/.github/workflows/workflow.yml +++ b/.github/workflows/workflow.yml @@ -78,7 +78,7 @@ jobs: uses: ./ with: dotnet-version: 3.1.201 - # We are including this veriable to force the generation of the nuget config file to verify that it is created in the correct place + # We are including this variable to force the generation of the nuget config file to verify that it is created in the correct place source-url: https://api.nuget.org/v3/index.json env: NUGET_AUTH_TOKEN: NOTATOKEN @@ -115,6 +115,30 @@ jobs: shell: pwsh run: __tests__/verify-dotnet.ps1 3.1 2.2 + test-setup-prerelease-version: + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest, windows-latest, macOS-latest] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Clear toolcache + shell: pwsh + run: __tests__/clear-toolcache.ps1 ${{ runner.os }} + - name: Setup dotnet '2.2' + uses: ./ + with: + dotnet-version: '2.2' + - name: Setup dotnet '3.1.100-preview1-014459' + uses: ./ + with: + dotnet-version: '3.1.100-preview1-014459' + - name: Verify dotnet + shell: pwsh + run: __tests__/verify-dotnet.ps1 3.1.100-preview1-014459 + test-setup-latest-patch-version: runs-on: ${{ matrix.operating-system }} strategy: @@ -131,13 +155,13 @@ jobs: uses: ./ with: dotnet-version: 3.1.x - - name: Setup dotnet 2.2.x + - name: Setup dotnet 2.2.X uses: ./ with: - dotnet-version: 2.2.x + dotnet-version: 2.2.X - name: Verify dotnet shell: pwsh - run: __tests__/verify-dotnet.ps1 3.1 2.2 + run: __tests__/verify-dotnet.ps1 '2.2' '3.1' test-setup-with-wildcard: runs-on: ${{ matrix.operating-system }} @@ -189,6 +213,31 @@ jobs: shell: pwsh run: __tests__/verify-dotnet.ps1 2.2 3.1 + test-setup-with-dotnet-quality: + runs-on: ${{ matrix.operating-system }} + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest, windows-latest, macOS-latest] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Clear toolcache + shell: pwsh + run: __tests__/clear-toolcache.ps1 ${{ runner.os }} + + - name: Setup dotnet 7.0 with preview quality + uses: ./ + with: + dotnet-version: "7.0" + dotnet-quality: "preview" + - name: Verify preview version + shell: pwsh + run: | + $version = & dotnet --version + Write-Host "Installed version: $version" + if (-not $version.Contains("preview")) { throw "Unexpected version" } + test-proxy: runs-on: ubuntu-latest container: diff --git a/__tests__/authutil.test.ts b/__tests__/authutil.test.ts index f2e82d8..ce02533 100644 --- a/__tests__/authutil.test.ts +++ b/__tests__/authutil.test.ts @@ -1,6 +1,6 @@ -import io = require('@actions/io'); -import fs = require('fs'); -import path = require('path'); +import * as io from '@actions/io'; +import fs from 'fs'; +import path from 'path'; const fakeSourcesDirForTesting = path.join( __dirname, diff --git a/__tests__/csc.test.ts b/__tests__/csc.test.ts index aa0d497..6862f78 100644 --- a/__tests__/csc.test.ts +++ b/__tests__/csc.test.ts @@ -1,5 +1,3 @@ -import fs = require('fs'); - describe('csc tests', () => { it('Valid regular expression', async () => { var cscFile = require('../.github/csc.json'); diff --git a/__tests__/installer.test.ts b/__tests__/installer.test.ts index 532da18..9304417 100644 --- a/__tests__/installer.test.ts +++ b/__tests__/installer.test.ts @@ -1,34 +1,54 @@ -import io = require('@actions/io'); -import fs = require('fs'); -import os = require('os'); -import path = require('path'); -import hc = require('@actions/http-client'); +import * as io from '@actions/io'; +import * as os from 'os'; +import fs from 'fs'; +import path from 'path'; +import each from 'jest-each'; +import * as hc from '@actions/core/node_modules/@actions/http-client'; +import * as installer from '../src/installer'; -const toolDir = path.join(__dirname, 'runner', 'tools'); +import {IS_WINDOWS} from '../src/utils'; +import {IS_LINUX} from '../src/utils'; + +let toolDir: string; + +if (IS_WINDOWS) { + toolDir = path.join(process.env['PROGRAMFILES'] + '', 'dotnet'); +} else if (IS_LINUX) { + toolDir = '/usr/share/dotnet'; +} else { + toolDir = path.join(process.env['HOME'] + '', '.dotnet'); +} const tempDir = path.join(__dirname, 'runner', 'temp'); process.env['RUNNER_TOOL_CACHE'] = toolDir; process.env['RUNNER_TEMP'] = tempDir; -import * as installer from '../src/installer'; -const IS_WINDOWS = process.platform === 'win32'; - -describe('installer tests', () => { +describe('DotnetCoreInstaller tests', () => { beforeAll(async () => { process.env.RUNNER_TOOL_CACHE = toolDir; process.env.DOTNET_INSTALL_DIR = toolDir; process.env.RUNNER_TEMP = tempDir; process.env.DOTNET_ROOT = ''; - await io.rmRF(toolDir); - await io.rmRF(tempDir); - }); - - afterAll(async () => { try { - await io.rmRF(toolDir); - await io.rmRF(tempDir); - } catch { - console.log('Failed to remove test directories'); + await io.rmRF(`${toolDir}/*`); + await io.rmRF(`${tempDir}/*`); + } catch (err) { + console.log( + `Failed to remove test directories, check the error message:${os.EOL}`, + err.message + ); + } + }, 30000); + + afterEach(async () => { + try { + await io.rmRF(`${toolDir}/*`); + await io.rmRF(`${tempDir}/*`); + } catch (err) { + console.log( + `Failed to remove test directories, check the error message:${os.EOL}`, + err.message + ); } }, 30000); @@ -87,13 +107,9 @@ describe('installer tests', () => { }, 600000); //This needs some time to download on "slower" internet connections it('Throws if no location contains correct dotnet version', async () => { - let thrown = false; - try { + await expect(async () => { await getDotnet('1000.0.0'); - } catch { - thrown = true; - } - expect(thrown).toBe(true); + }).rejects.toThrow(); }, 30000); it('Uses an up to date bash download script', async () => { @@ -137,6 +153,144 @@ describe('installer tests', () => { }, 30000); }); +describe('DotnetQualityValidator tests', () => { + it("returns quality if it's supplied and valid", () => { + const qualityInput = 'preview'; + const dotnetQualityValidator = new installer.DotnetQualityValidator( + qualityInput + ); + const result = dotnetQualityValidator.validateQuality(); + + expect(result).toBe('preview'); + }); + + each(['', undefined]).test( + "input value '%s' should be returned as it is", + version => { + const dotnetQualityValidator = new installer.DotnetQualityValidator( + version + ); + const result = dotnetQualityValidator.validateQuality(); + expect(result).toBe(version); + } + ); + + it('throws if quality is supplied and invalid', () => { + const qualityInput = 'invalid'; + const dotnetQualityValidator = new installer.DotnetQualityValidator( + qualityInput + ); + + expect(() => dotnetQualityValidator.validateQuality()).toThrow(); + }); +}); + +describe('DotnetVersionResolver tests', () => { + each([ + '3.1', + '3.x', + '3.1.x', + '3.1.*', + '3.1.X', + '3.1.2', + '3.1.0-preview1' + ]).test( + "if valid version: '%s' is supplied, it should return version object with some value", + async version => { + const dotnetVersionResolver = new installer.DotnetVersionResolver( + version + ); + const versionObject = await dotnetVersionResolver.createDotNetVersion(); + + expect(!!versionObject.value).toBeTruthy; + } + ); + + each([ + '.', + '..', + ' . ', + '. ', + ' .', + ' . . ', + ' .. ', + ' . ', + '-1.-1', + '-1', + '-1.-1.-1', + '..3', + '1..3', + '1..', + '.2.3', + '.2.x', + '*.', + '1.2.', + '1.2.-abc', + 'a.b', + 'a.b.c', + 'a.b.c-preview', + ' 0 . 1 . 2 ', + 'invalid' + ]).test( + "if invalid version: '%s' is supplied, it should throw", + async version => { + const dotnetVersionResolver = new installer.DotnetVersionResolver( + version + ); + + await expect( + async () => await dotnetVersionResolver.createDotNetVersion() + ).rejects.toThrow(); + } + ); + + each(['3.1', '3.1.x', '3.1.*', '3.1.X']).test( + "if version: '%s' that can be resolved to 'channel' option is supplied, it should set quality flag to 'true' and type to 'channel' in version object", + async version => { + const dotnetVersionResolver = new installer.DotnetVersionResolver( + version + ); + const versionObject = await dotnetVersionResolver.createDotNetVersion(); + + expect(versionObject.type.toLowerCase().includes('channel')).toBeTruthy; + expect(versionObject.qualityFlag).toBeTruthy; + } + ); + + each(['3.1.2', '3.1.0-preview1']).test( + "if version: '%s' that can be resolved to 'version' option is supplied, it should set quality flag to 'false' and type to 'version' in version object", + async version => { + const dotnetVersionResolver = new installer.DotnetVersionResolver( + version + ); + const versionObject = await dotnetVersionResolver.createDotNetVersion(); + + expect(versionObject.type.toLowerCase().includes('version')).toBeTruthy; + expect(versionObject.qualityFlag).toBeFalsy; + } + ); + + each(['3.1.2', '3.1']).test( + 'it should create proper line arguments for powershell/bash installation scripts', + async version => { + const dotnetVersionResolver = new installer.DotnetVersionResolver( + version + ); + const versionObject = await dotnetVersionResolver.createDotNetVersion(); + const windowsRegEx = new RegExp(/^-[VC]/); + const nonWindowsRegEx = new RegExp(/^--[vc]/); + + if (IS_WINDOWS) { + expect(windowsRegEx.test(versionObject.type)).toBeTruthy; + expect(nonWindowsRegEx.test(versionObject.type)).toBeFalsy; + } else { + expect(nonWindowsRegEx.test(versionObject.type)).toBeTruthy; + expect(windowsRegEx.test(versionObject.type)).toBeFalsy; + } + } + ); +}); + function normalizeFileContents(contents: string): string { return contents .trim() @@ -144,8 +298,8 @@ function normalizeFileContents(contents: string): string { .replace(new RegExp('\r', 'g'), '\n'); } -async function getDotnet(version: string): Promise { - const dotnetInstaller = new installer.DotnetCoreInstaller(version); +async function getDotnet(version: string, quality: string = ''): Promise { + const dotnetInstaller = new installer.DotnetCoreInstaller(version, quality); await dotnetInstaller.installDotnet(); installer.DotnetCoreInstaller.addToPath(); } diff --git a/__tests__/setup-dotnet.test.ts b/__tests__/setup-dotnet.test.ts index aa8e380..4cd84b6 100644 --- a/__tests__/setup-dotnet.test.ts +++ b/__tests__/setup-dotnet.test.ts @@ -1,32 +1,45 @@ -import io = require('@actions/io'); -import fs = require('fs'); -import os = require('os'); -import path = require('path'); - -const toolDir = path.join(__dirname, 'runner', 'tools2'); -const tempDir = path.join(__dirname, 'runner', 'temp2'); +import * as io from '@actions/io'; +import fs from 'fs'; +import os from 'os'; +import path from 'path'; import * as setup from '../src/setup-dotnet'; -import * as dotnetInstaller from '../src/installer'; +import {IS_WINDOWS} from '../src/utils'; +import {IS_LINUX} from '../src/utils'; -const IS_WINDOWS = process.platform === 'win32'; +let toolDir: string; + +if (IS_WINDOWS) { + toolDir = path.join(process.env['PROGRAMFILES'] + '', 'dotnet'); +} else if (IS_LINUX) { + toolDir = '/usr/share/dotnet'; +} else { + toolDir = path.join(process.env['HOME'] + '', '.dotnet'); +} + +const tempDir = path.join(__dirname, 'runner', 'temp2'); describe('setup-dotnet tests', () => { beforeAll(async () => { process.env.RUNNER_TOOL_CACHE = toolDir; process.env.DOTNET_INSTALL_DIR = toolDir; process.env.RUNNER_TEMP = tempDir; - process.env['INPUT_INCLUDE-PRERELEASE'] = 'false'; - await io.rmRF(toolDir); - await io.rmRF(tempDir); - }); + try { + await io.rmRF(`${toolDir}/*`); + await io.rmRF(`${tempDir}/*`); + } catch (err) { + console.log(err.message); + console.log('Failed to remove test directories'); + } + }, 30000); afterEach(async () => { try { await io.rmRF(path.join(process.cwd(), 'global.json')); - await io.rmRF(toolDir); - await io.rmRF(tempDir); - } catch { + await io.rmRF(`${toolDir}/*`); + await io.rmRF(`${tempDir}/*`); + } catch (err) { + console.log(err.message); console.log('Failed to remove test directories'); } }, 30000); @@ -46,26 +59,4 @@ describe('setup-dotnet tests', () => { expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true); } }, 400000); - - it('Acquires version of dotnet from global.json with rollForward option, install the latest patch', async () => { - const globalJsonPath = path.join(process.cwd(), 'global.json'); - const jsonContents = `{${os.EOL}"sdk": {${os.EOL}"version":"3.1.201",${os.EOL}"rollForward":"latestFeature"${os.EOL}}${os.EOL}}`; - if (!fs.existsSync(globalJsonPath)) { - fs.writeFileSync(globalJsonPath, jsonContents); - } - - const version = '3.1'; - const installer = new dotnetInstaller.DotnetCoreInstaller(version); - const patchVersion = await installer.resolveVersion( - new dotnetInstaller.DotNetVersionInfo(version) - ); - await setup.run(); - - expect(fs.existsSync(path.join(toolDir, 'sdk', patchVersion))).toBe(true); - if (IS_WINDOWS) { - expect(fs.existsSync(path.join(toolDir, 'dotnet.exe'))).toBe(true); - } else { - expect(fs.existsSync(path.join(toolDir, 'dotnet'))).toBe(true); - } - }, 400000); }); diff --git a/__tests__/verify-no-unstaged-changes.sh b/__tests__/verify-no-unstaged-changes.sh index f3260e3..15efefe 100755 --- a/__tests__/verify-no-unstaged-changes.sh +++ b/__tests__/verify-no-unstaged-changes.sh @@ -1,17 +1,7 @@ #!/bin/bash -if [[ "$(git status --porcelain)" != "" ]]; then - echo ---------------------------------------- - echo git status - echo ---------------------------------------- - git status - echo ---------------------------------------- - echo git diff - echo ---------------------------------------- +if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then + echo "Detected uncommitted changes after build. See status below:" git diff - echo ---------------------------------------- - echo Troubleshooting - echo ---------------------------------------- - echo "::error::Unstaged changes detected. Locally try running: git clean -ffdx && npm ci && npm run pre-checkin" exit 1 fi diff --git a/__tests__/versionutil.test.ts b/__tests__/versionutil.test.ts deleted file mode 100644 index 69681da..0000000 --- a/__tests__/versionutil.test.ts +++ /dev/null @@ -1,91 +0,0 @@ -import each from 'jest-each'; -import * as installer from '../src/installer'; - -describe('version tests', () => { - each(['3.1.999', '3.1.101-preview.3']).test( - "Exact version '%s' should be the same", - vers => { - let versInfo = new installer.DotNetVersionInfo(vers); - - expect(versInfo.isExactVersion()).toBe(true); - expect(versInfo.version()).toBe(vers); - } - ); - - each([ - ['3.x', '3.x'], - ['3.*', '3.*'], - ['3.1.x', '3.1'], - ['1.1.*', '1.1'], - ['2.0', '2.0'] - ]).test("Generic version '%s' should be '%s'", (vers, resVers) => { - let versInfo = new installer.DotNetVersionInfo(vers); - - expect(versInfo.isExactVersion()).toBe(false); - expect(versInfo.version()).toBe(resVers); - }); - - each([ - '', - '.', - '..', - ' . ', - '. ', - ' .', - ' . . ', - ' .. ', - ' . ', - '-1.-1', - '-1', - '-1.-1.-1', - '..3', - '1..3', - '1..', - '.2.3', - '.2.x', - '1', - '*.*.1', - '*.1', - '*.', - '1.2.', - '1.2.-abc', - 'a.b', - 'a.b.c', - 'a.b.c-preview', - ' 0 . 1 . 2 ' - ]).test("Malformed version '%s' should throw", vers => { - expect(() => new installer.DotNetVersionInfo(vers)).toThrow(); - }); - - each([ - ['3.1.x', '3.1.'], - ['3.1.*', '3.1.'], - ['3.1', '3.1.'], - ['5.0.0-preview.6', '5.0.0-preview.6'], - ['3.1.201', '3.1.201'] - ]).test( - "Resolving version '%s' as '%s'", - async (input, expectedVersion) => { - const dotnetInstaller = new installer.DotnetCoreInstaller(input); - let versInfo = await dotnetInstaller.resolveVersion( - new installer.DotNetVersionInfo(input) - ); - console.log(versInfo); - - expect(versInfo.startsWith(expectedVersion)); - }, - 100000 - ); - - it('Resolving a nonexistent generic version fails', async () => { - const dotnetInstaller = new installer.DotnetCoreInstaller('999.1.x'); - try { - await dotnetInstaller.resolveVersion( - new installer.DotNetVersionInfo('999.1.x') - ); - fail(); - } catch { - expect(true); - } - }, 100000); -});