Skip to content
30 changes: 30 additions & 0 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -320,3 +320,33 @@ jobs:
- name: Verify dotnet
shell: pwsh
run: __tests__/verify-dotnet.ps1 -Patterns "^3.1.201$" -CheckNugetConfig

test-sequential-version-installation:
runs-on: ${{ matrix.operating-system }}
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-latest, windows-latest, macOS-latest]
lower-version: ['2.2.402', '3.0.103', '3.1.426', '6.0.408', '7.0.100']
higher-version: ['6.0.408', '7.0.203']
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Clear toolcache
shell: pwsh
run: __tests__/clear-toolcache.ps1 ${{ runner.os }}
# Install one version, use it for something, then switch to next version
- name: Setup dotnet (lower version)
uses: ./
with:
dotnet-version: ${{ matrix.lower-version }}
- name: Verify dotnet (lower version)
shell: pwsh
run: __tests__/verify-dotnet.ps1 -Patterns "^${{ matrix.lower-version }}$"
- name: Setup dotnet (higher version)
uses: ./
with:
dotnet-version: ${{ matrix.higher-version }}
- name: Verify dotnet (higher version)
shell: pwsh
run: __tests__/verify-dotnet.ps1 -Patterns "^${{ matrix.lower-version }}$", "^${{ matrix.higher-version }}$"
12 changes: 6 additions & 6 deletions __tests__/installer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ describe('DotnetVersionResolver tests', () => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject = await dotnetVersionResolver.createDotNetVersion();
const versionObject = await dotnetVersionResolver.createDotnetVersion();

expect(!!versionObject.value).toBe(true);
}
Expand Down Expand Up @@ -216,7 +216,7 @@ describe('DotnetVersionResolver tests', () => {
);

await expect(
async () => await dotnetVersionResolver.createDotNetVersion()
async () => await dotnetVersionResolver.createDotnetVersion()
).rejects.toThrow();
}
);
Expand All @@ -227,7 +227,7 @@ describe('DotnetVersionResolver tests', () => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject = await dotnetVersionResolver.createDotNetVersion();
const versionObject = await dotnetVersionResolver.createDotnetVersion();

expect(versionObject.type.toLowerCase().includes('channel')).toBe(true);
}
Expand All @@ -239,7 +239,7 @@ describe('DotnetVersionResolver tests', () => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject = await dotnetVersionResolver.createDotNetVersion();
const versionObject = await dotnetVersionResolver.createDotnetVersion();

expect(versionObject.type.toLowerCase().includes('channel')).toBe(true);
expect(versionObject.qualityFlag).toBe(true);
Expand All @@ -252,7 +252,7 @@ describe('DotnetVersionResolver tests', () => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject = await dotnetVersionResolver.createDotNetVersion();
const versionObject = await dotnetVersionResolver.createDotnetVersion();

expect(versionObject.type.toLowerCase().includes('version')).toBe(true);
expect(versionObject.qualityFlag).toBe(false);
Expand All @@ -265,7 +265,7 @@ describe('DotnetVersionResolver tests', () => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject = await dotnetVersionResolver.createDotNetVersion();
const versionObject = await dotnetVersionResolver.createDotnetVersion();
const windowsRegEx = new RegExp(/^-[VC]/);
const nonWindowsRegEx = new RegExp(/^--[vc]/);

Expand Down
227 changes: 133 additions & 94 deletions dist/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,9 +229,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
var _a;
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.DotnetCoreInstaller = exports.DotnetVersionResolver = void 0;
exports.DotnetCoreInstaller = exports.DotnetInstallDir = exports.DotnetInstallScript = exports.DotnetVersionResolver = void 0;
// Load tempDirectory before it gets wiped by tool-cache
const core = __importStar(__nccwpck_require__(2186));
const exec = __importStar(__nccwpck_require__(1514));
Expand Down Expand Up @@ -279,7 +278,7 @@ class DotnetVersionResolver {
isNumericTag(versionTag) {
return /^\d+$/.test(versionTag);
}
createDotNetVersion() {
createDotnetVersion() {
return __awaiter(this, void 0, void 0, function* () {
yield this.resolveVersionInput();
if (!this.resolvedArgument.type) {
Expand Down Expand Up @@ -314,39 +313,21 @@ class DotnetVersionResolver {
}
exports.DotnetVersionResolver = DotnetVersionResolver;
DotnetVersionResolver.DotNetCoreIndexUrl = 'https://dotnetcli.azureedge.net/dotnet/release-metadata/releases-index.json';
class DotnetCoreInstaller {
constructor(version, quality) {
this.version = version;
this.quality = quality;
}
static convertInstallPathToAbsolute(installDir) {
let transformedPath;
if (path_1.default.isAbsolute(installDir)) {
transformedPath = installDir;
}
else {
transformedPath = installDir.startsWith('~')
? path_1.default.join(os_1.default.homedir(), installDir.slice(1))
: (transformedPath = path_1.default.join(process.cwd(), installDir));
}
return path_1.default.normalize(transformedPath);
}
static addToPath() {
core.addPath(process.env['DOTNET_INSTALL_DIR']);
core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']);
}
setQuality(dotnetVersion, scriptArguments) {
const option = utils_1.IS_WINDOWS ? '-Quality' : '--quality';
if (dotnetVersion.qualityFlag) {
scriptArguments.push(option, this.quality);
}
else {
core.warning(`'dotnet-quality' input can be used only with .NET SDK version in A.B, A.B.x, A and A.x formats where the major tag is higher than 5. You specified: ${this.version}. 'dotnet-quality' input is ignored.`);
}
class DotnetInstallScript {
constructor() {
this.scriptName = utils_1.IS_WINDOWS ? 'install-dotnet.ps1' : 'install-dotnet.sh';
this.scriptArguments = [];
this.scriptPath = '';
this.escapedScript = path_1.default
.join(__dirname, '..', 'externals', this.scriptName)
.replace(/'/g, "''");
this.scriptReady = utils_1.IS_WINDOWS
? this.setupScriptPowershell()
: this.setupScriptBash();
}
installDotnet() {
setupScriptPowershell() {
return __awaiter(this, void 0, void 0, function* () {
const windowsDefaultOptions = [
this.scriptArguments = [
'-NoLogo',
'-Sta',
'-NoProfile',
Expand All @@ -355,52 +336,119 @@ class DotnetCoreInstaller {
'Unrestricted',
'-Command'
];
const scriptName = utils_1.IS_WINDOWS ? 'install-dotnet.ps1' : 'install-dotnet.sh';
const escapedScript = path_1.default
.join(__dirname, '..', 'externals', scriptName)
.replace(/'/g, "''");
let scriptArguments;
let scriptPath = '';
const versionResolver = new DotnetVersionResolver(this.version);
const dotnetVersion = yield versionResolver.createDotNetVersion();
if (utils_1.IS_WINDOWS) {
scriptArguments = ['&', `'${escapedScript}'`];
if (dotnetVersion.type) {
scriptArguments.push(dotnetVersion.type, dotnetVersion.value);
}
if (this.quality) {
this.setQuality(dotnetVersion, scriptArguments);
}
if (process.env['https_proxy'] != null) {
scriptArguments.push(`-ProxyAddress ${process.env['https_proxy']}`);
}
// This is not currently an option
if (process.env['no_proxy'] != null) {
scriptArguments.push(`-ProxyBypassList ${process.env['no_proxy']}`);
}
scriptPath =
(yield io.which('pwsh', false)) || (yield io.which('powershell', true));
scriptArguments = windowsDefaultOptions.concat(scriptArguments);
this.scriptArguments.push('&', `'${this.escapedScript}'`);
if (process.env['https_proxy'] != null) {
this.scriptArguments.push(`-ProxyAddress ${process.env['https_proxy']}`);
}
else {
(0, fs_1.chmodSync)(escapedScript, '777');
scriptPath = yield io.which(escapedScript, true);
scriptArguments = [];
if (dotnetVersion.type) {
scriptArguments.push(dotnetVersion.type, dotnetVersion.value);
}
if (this.quality) {
this.setQuality(dotnetVersion, scriptArguments);
}
// This is not currently an option
if (process.env['no_proxy'] != null) {
this.scriptArguments.push(`-ProxyBypassList ${process.env['no_proxy']}`);
}
// process.env must be explicitly passed in for DOTNET_INSTALL_DIR to be used
this.scriptPath =
(yield io.which('pwsh', false)) || (yield io.which('powershell', true));
});
}
setupScriptBash() {
return __awaiter(this, void 0, void 0, function* () {
(0, fs_1.chmodSync)(this.escapedScript, '777');
this.scriptPath = yield io.which(this.escapedScript, true);
});
}
useArguments(...args) {
this.scriptArguments.push(...args);
return this;
}
useVersion(dotnetVersion, quality) {
if (dotnetVersion.type) {
this.useArguments(dotnetVersion.type, dotnetVersion.value);
}
if (quality && !dotnetVersion.qualityFlag) {
core.warning(`'dotnet-quality' input can be used only with .NET SDK version in A.B, A.B.x, A and A.x formats where the major tag is higher than 5. You specified: ${dotnetVersion.value}. 'dotnet-quality' input is ignored.`);
return this;
}
if (quality) {
this.useArguments(utils_1.IS_WINDOWS ? '-Quality' : '--quality', quality);
}
return this;
}
execute() {
return __awaiter(this, void 0, void 0, function* () {
const getExecOutputOptions = {
ignoreReturnCode: true,
env: process.env
};
const { exitCode, stderr } = yield exec.getExecOutput(`"${scriptPath}"`, scriptArguments, getExecOutputOptions);
if (exitCode) {
throw new Error(`Failed to install dotnet, exit code: ${exitCode}. ${stderr}`);
yield this.scriptReady;
return exec.getExecOutput(`"${this.scriptPath}"`, this.scriptArguments, getExecOutputOptions);
});
}
}
exports.DotnetInstallScript = DotnetInstallScript;
class DotnetInstallDir {
static convertInstallPathToAbsolute(installDir) {
if (path_1.default.isAbsolute(installDir))
return path_1.default.normalize(installDir);
const transformedPath = installDir.startsWith('~')
? path_1.default.join(os_1.default.homedir(), installDir.slice(1))
: path_1.default.join(process.cwd(), installDir);
return path_1.default.normalize(transformedPath);
}
static addToPath() {
core.addPath(process.env['DOTNET_INSTALL_DIR']);
core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']);
}
static initialize() {
process.env['DOTNET_INSTALL_DIR'] = DotnetInstallDir.path;
}
}
exports.DotnetInstallDir = DotnetInstallDir;
DotnetInstallDir.default = {
linux: '/usr/share/dotnet',
mac: path_1.default.join(process.env['HOME'] + '', '.dotnet'),
windows: path_1.default.join(process.env['PROGRAMFILES'] + '', 'dotnet')
};
DotnetInstallDir.path = process.env['DOTNET_INSTALL_DIR']
? DotnetInstallDir.convertInstallPathToAbsolute(process.env['DOTNET_INSTALL_DIR'])
: DotnetInstallDir.default[(0, utils_1.getPlatform)()];
class DotnetCoreInstaller {
constructor(version, quality) {
this.version = version;
this.quality = quality;
}
installDotnet() {
return __awaiter(this, void 0, void 0, function* () {
const versionResolver = new DotnetVersionResolver(this.version);
const dotnetVersion = yield versionResolver.createDotnetVersion();
/**
* Install dotnet runitme first in order to get
* the latest stable version of dotnet CLI
*/
const runtimeInstallScript = new DotnetInstallScript()
// If dotnet CLI is already installed - avoid overwriting it
.useArguments(utils_1.IS_WINDOWS ? '-SkipNonVersionedFiles' : '--skip-non-versioned-files')
// Install only runtime + CLI
.useArguments(utils_1.IS_WINDOWS ? '-Runtime' : '--runtime', 'dotnet')
// Use latest stable version
.useArguments(utils_1.IS_WINDOWS ? '-Channel' : '--channel', 'LTS');
const runtimeInstall = yield runtimeInstallScript.execute();
if (runtimeInstall.exitCode) {
/**
* dotnetInstallScript will install CLI and runtime if previous script haven't succeded,
* so at this point it's too early to throw an error
*/
core.warning(`Failed to install dotnet runtime + cli, exit code: ${runtimeInstall.exitCode}. ${runtimeInstall.stderr}`);
}
/**
* Install dotnet over the latest version of
* dotnet CLI
*/
const dotnetInstallScript = new DotnetInstallScript()
// Don't overwrite CLI because it should be already installed
.useArguments(utils_1.IS_WINDOWS ? '-SkipNonVersionedFiles' : '--skip-non-versioned-files')
// Use version provided by user
.useVersion(dotnetVersion, this.quality);
const dotnetInstall = yield dotnetInstallScript.execute();
if (dotnetInstall.exitCode) {
throw new Error(`Failed to install dotnet, exit code: ${dotnetInstall.exitCode}. ${dotnetInstall.stderr}`);
}
return this.outputDotnetVersion(dotnetVersion.value);
});
Expand All @@ -417,26 +465,9 @@ class DotnetCoreInstaller {
}
}
exports.DotnetCoreInstaller = DotnetCoreInstaller;
_a = DotnetCoreInstaller;
DotnetCoreInstaller.addToPath = DotnetInstallDir.addToPath;
(() => {
const installationDirectoryWindows = path_1.default.join(process.env['PROGRAMFILES'] + '', 'dotnet');
const installationDirectoryLinux = '/usr/share/dotnet';
const installationDirectoryMac = path_1.default.join(process.env['HOME'] + '', '.dotnet');
const dotnetInstallDir = process.env['DOTNET_INSTALL_DIR'];
if (dotnetInstallDir) {
process.env['DOTNET_INSTALL_DIR'] =
_a.convertInstallPathToAbsolute(dotnetInstallDir);
}
else {
if (utils_1.IS_WINDOWS) {
process.env['DOTNET_INSTALL_DIR'] = installationDirectoryWindows;
}
else {
process.env['DOTNET_INSTALL_DIR'] = utils_1.IS_LINUX
? installationDirectoryLinux
: installationDirectoryMac;
}
}
DotnetInstallDir.initialize();
})();


Expand Down Expand Up @@ -591,9 +622,17 @@ run();
"use strict";

Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.IS_LINUX = exports.IS_WINDOWS = void 0;
exports.getPlatform = exports.IS_LINUX = exports.IS_WINDOWS = void 0;
exports.IS_WINDOWS = process.platform === 'win32';
exports.IS_LINUX = process.platform === 'linux';
const getPlatform = () => {
if (exports.IS_WINDOWS)
return 'windows';
if (exports.IS_LINUX)
return 'linux';
return 'mac';
};
exports.getPlatform = getPlatform;


/***/ }),
Expand Down
Loading