diff --git a/.gitattributes b/.gitattributes index 541fd55..f6ac05f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1 @@ -.licenses/** -diff linguist-generated=true \ No newline at end of file +.licenses/** -diff linguist-generated=true diff --git a/.licenses/npm/@actions/core.dep.yml b/.licenses/npm/@actions/core.dep.yml index 2e0762e..a2682b8 100644 Binary files a/.licenses/npm/@actions/core.dep.yml and b/.licenses/npm/@actions/core.dep.yml differ diff --git a/.prettierrc.json b/.prettierrc.json index f6736bc..ca09262 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -7,5 +7,6 @@ "trailingComma": "none", "bracketSpacing": false, "arrowParens": "avoid", - "parser": "typescript" + "parser": "typescript", + "endOfLine": "auto" } \ No newline at end of file diff --git a/README.md b/README.md index c802711..cec68e9 100644 --- a/README.md +++ b/README.md @@ -195,16 +195,24 @@ Some environment variables may be necessary for your particular case or to impro | **Env.variable** | **Description** | **Default value** | | ----------- | ----------- | ----------- | +| DOTNET_INSTALL_DIR |Specifies a directory where .NET SDKs should be installed by the action.|*default value for each OS* | | DOTNET_NOLOGO |Removes logo and telemetry message from first run of dotnet cli|*false*| | DOTNET_CLI_TELEMETRY_OPTOUT |Opt-out of telemetry being sent to Microsoft|*false*| | DOTNET_MULTILEVEL_LOOKUP |Configures whether the global install location is used as a fall-back|*true*| +The default value of the `DOTNET_INSTALL_DIR` environment variable depends on the operation system which is used on a runner: +| **Operation system** | **Default value** | +| ----------- | ----------- | +| **Windows** | `C:\Program Files\dotnet` | +| **Ubuntu** | `/usr/share/dotnet` | +| **macOS** | `/Users/runner/.dotnet` | + **Example usage**: ```yml build: runs-on: ubuntu-latest env: - DOTNET_NOLOGO: true + DOTNET_INSTALL_DIR: "path/to/directory" steps: - uses: actions/checkout@main - uses: actions/setup-dotnet@v3 diff --git a/__tests__/authutil.test.ts b/__tests__/authutil.test.ts index ce02533..595682e 100644 --- a/__tests__/authutil.test.ts +++ b/__tests__/authutil.test.ts @@ -5,11 +5,7 @@ import path from 'path'; const fakeSourcesDirForTesting = path.join( __dirname, 'runner', - path.join( - Math.random() - .toString(36) - .substring(7) - ), + path.join(Math.random().toString(36).substring(7)), 's' ); diff --git a/dist/index.js b/dist/index.js index f3bd463..2bc407a 100644 --- a/dist/index.js +++ b/dist/index.js @@ -8,7 +8,11 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -21,7 +25,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -31,7 +35,8 @@ const fs = __importStar(__nccwpck_require__(7147)); const path = __importStar(__nccwpck_require__(1017)); const core = __importStar(__nccwpck_require__(2186)); const github = __importStar(__nccwpck_require__(5438)); -const fast_xml_parser_1 = __nccwpck_require__(2603); +const xmlbuilder = __importStar(__nccwpck_require__(2958)); +const xmlParser = __importStar(__nccwpck_require__(7448)); function configAuthentication(feedUrl, existingFileLocation = '', processRoot = process.cwd()) { const existingNuGetConfig = path.resolve(processRoot, existingFileLocation === '' ? getExistingNugetConfig(processRoot) @@ -54,8 +59,8 @@ function getExistingNugetConfig(processRoot) { return defaultConfigName; } function writeFeedToFile(feedUrl, existingFileLocation, tempFileLocation) { - var _a, _b; core.info(`dotnet-auth: Finding any source references in ${existingFileLocation}, writing a new temporary configuration file with credentials to ${tempFileLocation}`); + let xml; let sourceKeys = []; let owner = core.getInput('owner'); let sourceUrl = feedUrl; @@ -68,117 +73,76 @@ function writeFeedToFile(feedUrl, existingFileLocation, tempFileLocation) { if (fs.existsSync(existingFileLocation)) { // get key from existing NuGet.config so NuGet/dotnet can match credentials const curContents = fs.readFileSync(existingFileLocation, 'utf8'); - const parserOptions = { - ignoreAttributes: false - }; - const parser = new fast_xml_parser_1.XMLParser(parserOptions); - const json = parser.parse(curContents); + const json = xmlParser.parse(curContents, { ignoreAttributes: false }); if (typeof json.configuration === 'undefined') { throw new Error(`The provided NuGet.config seems invalid.`); } - if ((_b = (_a = json.configuration) === null || _a === void 0 ? void 0 : _a.packageSources) === null || _b === void 0 ? void 0 : _b.add) { - const packageSources = json.configuration.packageSources.add; - if (Array.isArray(packageSources)) { - packageSources.forEach(source => { - const value = source['@_value']; - core.debug(`source '${value}'`); - if (value.toLowerCase().includes(feedUrl.toLowerCase())) { - const key = source['@_key']; + if (typeof json.configuration.packageSources != 'undefined') { + if (typeof json.configuration.packageSources.add != 'undefined') { + // file has at least one + if (typeof json.configuration.packageSources.add[0] === 'undefined') { + // file has only one + if (json.configuration.packageSources.add['@_value'] + .toLowerCase() + .includes(feedUrl.toLowerCase())) { + const key = json.configuration.packageSources.add['@_key']; sourceKeys.push(key); core.debug(`Found a URL with key ${key}`); } - }); - } - else { - if (packageSources['@_value'] - .toLowerCase() - .includes(feedUrl.toLowerCase())) { - const key = packageSources['@_key']; - sourceKeys.push(key); - core.debug(`Found a URL with key ${key}`); } - } - } - } - const xmlSource = [ - { - '?xml': [ - { - '#text': '' - } - ], - ':@': { - '@_version': '1.0' - } - }, - { - configuration: [ - { - config: [ - { - add: [], - ':@': { - '@_key': 'defaultPushSource', - '@_value': sourceUrl - } + else { + // file has 2+ + for (let i = 0; i < json.configuration.packageSources.add.length; i++) { + const source = json.configuration.packageSources.add[i]; + const value = source['@_value']; + core.debug(`source '${value}'`); + if (value.toLowerCase().includes(feedUrl.toLowerCase())) { + const key = source['@_key']; + sourceKeys.push(key); + core.debug(`Found a URL with key ${key}`); } - ] - } - ] - } - ]; - if (!sourceKeys.length) { - let keystring = 'Source'; - xmlSource[1].configuration.push({ - packageSources: [ - { - add: [], - ':@': { - '@_key': keystring, - '@_value': sourceUrl } } - ] - }); + } + } + } + xml = xmlbuilder + .create('configuration') + .ele('config') + .ele('add', { key: 'defaultPushSource', value: sourceUrl }) + .up() + .up(); + if (!sourceKeys.length) { + let keystring = 'Source'; + xml = xml + .ele('packageSources') + .ele('add', { key: keystring, value: sourceUrl }) + .up() + .up(); sourceKeys.push(keystring); } - const packageSourceCredentials = []; + xml = xml.ele('packageSourceCredentials'); sourceKeys.forEach(key => { if (!isValidKey(key)) { throw new Error("Source name can contain letters, numbers, and '-', '_', '.' symbols only. Please, fix source name in NuGet.config and try again."); } - packageSourceCredentials.push({ - [key]: [ - { - add: [], - ':@': { - '@_key': 'Username', - '@_value': owner - } - }, - { - add: [], - ':@': { - '@_key': 'ClearTextPassword', - '@_value': process.env.NUGET_AUTH_TOKEN - } - } - ] - }); + xml = xml + .ele(key) + .ele('add', { key: 'Username', value: owner }) + .up() + .ele('add', { + key: 'ClearTextPassword', + value: process.env.NUGET_AUTH_TOKEN + }) + .up() + .up(); }); - xmlSource[1].configuration.push({ - packageSourceCredentials - }); - const xmlBuilderOptions = { - format: true, - ignoreAttributes: false, - preserveOrder: true, - allowBooleanAttributes: true, - suppressBooleanAttributes: true, - suppressEmptyNode: true - }; - const builder = new fast_xml_parser_1.XMLBuilder(xmlBuilderOptions); - const output = builder.build(xmlSource).trim(); + // If NuGet fixes itself such that on Linux it can look for environment variables in the config file (it doesn't seem to work today), + // use this for the value above + // process.platform == 'win32' + // ? '%NUGET_AUTH_TOKEN%' + // : '$NUGET_AUTH_TOKEN' + const output = xml.end({ pretty: true }); fs.writeFileSync(tempFileLocation, output); } @@ -192,7 +156,11 @@ function writeFeedToFile(feedUrl, existingFileLocation, tempFileLocation) { var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -205,7 +173,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -221,6 +189,7 @@ 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; // Load tempDirectory before it gets wiped by tool-cache @@ -231,6 +200,7 @@ const hc = __importStar(__nccwpck_require__(6255)); const fs_1 = __nccwpck_require__(7147); const promises_1 = __nccwpck_require__(3292); const path_1 = __importDefault(__nccwpck_require__(1017)); +const os_1 = __importDefault(__nccwpck_require__(2037)); const semver_1 = __importDefault(__nccwpck_require__(5911)); const utils_1 = __nccwpck_require__(918); class DotnetVersionResolver { @@ -309,26 +279,21 @@ class DotnetCoreInstaller { this.version = version; this.quality = quality; } - static addToPath() { - if (process.env['DOTNET_INSTALL_DIR']) { - core.addPath(process.env['DOTNET_INSTALL_DIR']); - core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']); + static convertInstallPathToAbsolute(installDir) { + let transformedPath; + if (path_1.default.isAbsolute(installDir)) { + transformedPath = installDir; } else { - if (utils_1.IS_WINDOWS) { - core.addPath(DotnetCoreInstaller.installationDirectoryWindows); - core.exportVariable('DOTNET_ROOT', DotnetCoreInstaller.installationDirectoryWindows); - } - else if (utils_1.IS_LINUX) { - core.addPath(DotnetCoreInstaller.installationDirectoryLinux); - core.exportVariable('DOTNET_ROOT', DotnetCoreInstaller.installationDirectoryLinux); - } - else { - // This is the default set in install-dotnet.sh - core.addPath(DotnetCoreInstaller.installationDirectoryMac); - core.exportVariable('DOTNET_ROOT', DotnetCoreInstaller.installationDirectoryMac); - } + 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'; @@ -373,14 +338,12 @@ class DotnetCoreInstaller { if (process.env['no_proxy'] != null) { scriptArguments.push(`-ProxyBypassList ${process.env['no_proxy']}`); } - scriptArguments.push('-InstallDir', `'${DotnetCoreInstaller.installationDirectoryWindows}'`); - // process.env must be explicitly passed in for DOTNET_INSTALL_DIR to be used scriptPath = (yield io.which('pwsh', false)) || (yield io.which('powershell', true)); scriptArguments = windowsDefaultOptions.concat(scriptArguments); } else { - fs_1.chmodSync(escapedScript, '777'); + (0, fs_1.chmodSync)(escapedScript, '777'); scriptPath = yield io.which(escapedScript, true); scriptArguments = []; if (dotnetVersion.type) { @@ -389,23 +352,23 @@ class DotnetCoreInstaller { if (this.quality) { this.setQuality(dotnetVersion, scriptArguments); } - if (utils_1.IS_LINUX) { - scriptArguments.push('--install-dir', DotnetCoreInstaller.installationDirectoryLinux); - } - if (utils_1.IS_MAC) { - scriptArguments.push('--install-dir', DotnetCoreInstaller.installationDirectoryMac); - } } - const { exitCode, stdout } = yield exec.getExecOutput(`"${scriptPath}"`, scriptArguments, { ignoreReturnCode: true }); + // process.env must be explicitly passed in for DOTNET_INSTALL_DIR to be used + const getExecOutputOptions = { + ignoreReturnCode: true, + env: process.env + }; + const { exitCode, stdout } = yield exec.getExecOutput(`"${scriptPath}"`, scriptArguments, getExecOutputOptions); if (exitCode) { throw new Error(`Failed to install dotnet ${exitCode}. ${stdout}`); } - return this.outputDotnetVersion(dotnetVersion.value, scriptArguments[scriptArguments.length - 1]); + return this.outputDotnetVersion(dotnetVersion.value); }); } - outputDotnetVersion(version, installationPath) { + outputDotnetVersion(version) { return __awaiter(this, void 0, void 0, function* () { - let versionsOnRunner = yield promises_1.readdir(path_1.default.join(installationPath.replace(/'/g, ''), 'sdk')); + const installationPath = process.env['DOTNET_INSTALL_DIR']; + let versionsOnRunner = yield (0, promises_1.readdir)(path_1.default.join(installationPath.replace(/'/g, ''), 'sdk')); let installedVersion = semver_1.default.maxSatisfying(versionsOnRunner, version, { includePrerelease: true }); @@ -414,9 +377,27 @@ class DotnetCoreInstaller { } } exports.DotnetCoreInstaller = DotnetCoreInstaller; -DotnetCoreInstaller.installationDirectoryWindows = path_1.default.join(process.env['PROGRAMFILES'] + '', 'dotnet'); -DotnetCoreInstaller.installationDirectoryLinux = '/usr/share/dotnet'; -DotnetCoreInstaller.installationDirectoryMac = path_1.default.join(process.env['HOME'] + '', '.dotnet'); +_a = DotnetCoreInstaller; +(() => { + 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; + } + } +})(); /***/ }), @@ -428,7 +409,11 @@ DotnetCoreInstaller.installationDirectoryMac = path_1.default.join(process.env[' var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; - Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; @@ -441,7 +426,7 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? ( var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; @@ -563,10 +548,9 @@ run(); "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.IS_MAC = exports.IS_LINUX = exports.IS_WINDOWS = void 0; +exports.IS_LINUX = exports.IS_WINDOWS = void 0; exports.IS_WINDOWS = process.platform === 'win32'; exports.IS_LINUX = process.platform === 'linux'; -exports.IS_MAC = process.platform === 'darwin'; /***/ }), @@ -710,7 +694,6 @@ const file_command_1 = __nccwpck_require__(717); const utils_1 = __nccwpck_require__(5278); const os = __importStar(__nccwpck_require__(2037)); const path = __importStar(__nccwpck_require__(1017)); -const uuid_1 = __nccwpck_require__(5840); const oidc_utils_1 = __nccwpck_require__(8041); /** * The code to exit an action @@ -740,20 +723,9 @@ function exportVariable(name, val) { process.env[name] = convertedVal; const filePath = process.env['GITHUB_ENV'] || ''; if (filePath) { - const delimiter = `ghadelimiter_${uuid_1.v4()}`; - // These should realistically never happen, but just in case someone finds a way to exploit uuid generation let's not allow keys or values that contain the delimiter. - if (name.includes(delimiter)) { - throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); - } - if (convertedVal.includes(delimiter)) { - throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); - } - const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`; - file_command_1.issueCommand('ENV', commandValue); - } - else { - command_1.issueCommand('set-env', { name }, convertedVal); + return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); } + command_1.issueCommand('set-env', { name }, convertedVal); } exports.exportVariable = exportVariable; /** @@ -771,7 +743,7 @@ exports.setSecret = setSecret; function addPath(inputPath) { const filePath = process.env['GITHUB_PATH'] || ''; if (filePath) { - file_command_1.issueCommand('PATH', inputPath); + file_command_1.issueFileCommand('PATH', inputPath); } else { command_1.issueCommand('add-path', {}, inputPath); @@ -811,7 +783,10 @@ function getMultilineInput(name, options) { const inputs = getInput(name, options) .split('\n') .filter(x => x !== ''); - return inputs; + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map(input => input.trim()); } exports.getMultilineInput = getMultilineInput; /** @@ -844,8 +819,12 @@ exports.getBooleanInput = getBooleanInput; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function setOutput(name, value) { + const filePath = process.env['GITHUB_OUTPUT'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); + } process.stdout.write(os.EOL); - command_1.issueCommand('set-output', { name }, value); + command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); } exports.setOutput = setOutput; /** @@ -974,7 +953,11 @@ exports.group = group; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function saveState(name, value) { - command_1.issueCommand('save-state', { name }, value); + const filePath = process.env['GITHUB_STATE'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); + } + command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); } exports.saveState = saveState; /** @@ -1040,13 +1023,14 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.issueCommand = void 0; +exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ const fs = __importStar(__nccwpck_require__(7147)); const os = __importStar(__nccwpck_require__(2037)); +const uuid_1 = __nccwpck_require__(5840); const utils_1 = __nccwpck_require__(5278); -function issueCommand(command, message) { +function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; if (!filePath) { throw new Error(`Unable to find environment variable for file command ${command}`); @@ -1058,7 +1042,22 @@ function issueCommand(command, message) { encoding: 'utf8' }); } -exports.issueCommand = issueCommand; +exports.issueFileCommand = issueFileCommand; +function prepareKeyValueMessage(key, value) { + const delimiter = `ghadelimiter_${uuid_1.v4()}`; + const convertedValue = utils_1.toCommandValue(value); + // These should realistically never happen, but just in case someone finds a + // way to exploit uuid generation let's not allow keys or values that contain + // the delimiter. + if (key.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedValue.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; +} +exports.prepareKeyValueMessage = prepareKeyValueMessage; //# sourceMappingURL=file-command.js.map /***/ }), diff --git a/package-lock.json b/package-lock.json index 6f2d42e..7f8095f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "setup-dotnet", - "version": "3.0.0", + "version": "3.0.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "setup-dotnet", - "version": "3.0.0", + "version": "3.0.2", "license": "MIT", "dependencies": { - "@actions/core": "^1.9.1", + "@actions/core": "^1.10.0", "@actions/exec": "^1.0.4", "@actions/github": "^1.1.0", "@actions/http-client": "^2.0.1", @@ -25,16 +25,16 @@ "husky": "^8.0.1", "jest": "^27.2.5", "jest-circus": "^27.2.5", - "prettier": "^1.19.1", + "prettier": "^2.7.1", "ts-jest": "^27.0.5", - "typescript": "^3.9.7", + "typescript": "^4.8.4", "wget-improved": "^3.2.1" } }, "node_modules/@actions/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", - "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz", + "integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==", "dependencies": { "@actions/http-client": "^2.0.1", "uuid": "^8.3.2" @@ -3884,15 +3884,18 @@ } }, "node_modules/prettier": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", - "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "dev": true, "bin": { "prettier": "bin-prettier.js" }, "engines": { - "node": ">=4" + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" } }, "node_modules/pretty-format": { @@ -4436,9 +4439,9 @@ } }, "node_modules/typescript": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", - "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -4723,9 +4726,9 @@ }, "dependencies": { "@actions/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", - "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz", + "integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==", "requires": { "@actions/http-client": "^2.0.1", "uuid": "^8.3.2" @@ -7724,9 +7727,9 @@ "dev": true }, "prettier": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", - "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "dev": true }, "pretty-format": { @@ -8129,9 +8132,9 @@ } }, "typescript": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", - "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true }, "universal-user-agent": { diff --git a/package.json b/package.json index e178bfc..6e80f1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "setup-dotnet", - "version": "3.0.0", + "version": "3.0.2", "private": true, "description": "setup dotnet action", "main": "lib/setup-dotnet.js", @@ -24,7 +24,7 @@ "author": "GitHub", "license": "MIT", "dependencies": { - "@actions/core": "^1.9.1", + "@actions/core": "^1.10.0", "@actions/exec": "^1.0.4", "@actions/github": "^1.1.0", "@actions/http-client": "^2.0.1", @@ -40,9 +40,9 @@ "husky": "^8.0.1", "jest": "^27.2.5", "jest-circus": "^27.2.5", - "prettier": "^1.19.1", + "prettier": "^2.7.1", "ts-jest": "^27.0.5", - "typescript": "^3.9.7", + "typescript": "^4.8.4", "wget-improved": "^3.2.1" }, "jest": { diff --git a/src/installer.ts b/src/installer.ts index 041b655..be0444f 100644 --- a/src/installer.ts +++ b/src/installer.ts @@ -6,8 +6,9 @@ import * as hc from '@actions/http-client'; import {chmodSync} from 'fs'; import {readdir} from 'fs/promises'; import path from 'path'; +import os from 'os'; import semver from 'semver'; -import {IS_LINUX, IS_WINDOWS, IS_MAC} from './utils'; +import {IS_LINUX, IS_WINDOWS} from './utils'; import {QualityOptions} from './setup-dotnet'; export interface DotnetVersion { @@ -112,40 +113,29 @@ export class DotnetVersionResolver { export class DotnetCoreInstaller { private version: string; private quality: QualityOptions; - private static readonly installationDirectoryWindows = path.join( - process.env['PROGRAMFILES'] + '', - 'dotnet' - ); - private static readonly installationDirectoryLinux = '/usr/share/dotnet'; - private static readonly installationDirectoryMac = path.join( - process.env['HOME'] + '', - '.dotnet' - ); - static addToPath() { - if (process.env['DOTNET_INSTALL_DIR']) { - core.addPath(process.env['DOTNET_INSTALL_DIR']); - core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']); + static { + const installationDirectoryWindows = path.join( + process.env['PROGRAMFILES'] + '', + 'dotnet' + ); + const installationDirectoryLinux = '/usr/share/dotnet'; + const installationDirectoryMac = path.join( + process.env['HOME'] + '', + '.dotnet' + ); + const dotnetInstallDir: string | undefined = + process.env['DOTNET_INSTALL_DIR']; + if (dotnetInstallDir) { + process.env['DOTNET_INSTALL_DIR'] = + this.convertInstallPathToAbsolute(dotnetInstallDir); } else { if (IS_WINDOWS) { - core.addPath(DotnetCoreInstaller.installationDirectoryWindows); - core.exportVariable( - 'DOTNET_ROOT', - DotnetCoreInstaller.installationDirectoryWindows - ); - } else if (IS_LINUX) { - core.addPath(DotnetCoreInstaller.installationDirectoryLinux); - core.exportVariable( - 'DOTNET_ROOT', - DotnetCoreInstaller.installationDirectoryLinux - ); + process.env['DOTNET_INSTALL_DIR'] = installationDirectoryWindows; } else { - // This is the default set in install-dotnet.sh - core.addPath(DotnetCoreInstaller.installationDirectoryMac); - core.exportVariable( - 'DOTNET_ROOT', - DotnetCoreInstaller.installationDirectoryMac - ); + process.env['DOTNET_INSTALL_DIR'] = IS_LINUX + ? installationDirectoryLinux + : installationDirectoryMac; } } } @@ -155,6 +145,23 @@ export class DotnetCoreInstaller { this.quality = quality; } + private static convertInstallPathToAbsolute(installDir: string): string { + let transformedPath; + if (path.isAbsolute(installDir)) { + transformedPath = installDir; + } else { + transformedPath = installDir.startsWith('~') + ? path.join(os.homedir(), installDir.slice(1)) + : (transformedPath = path.join(process.cwd(), installDir)); + } + return path.normalize(transformedPath); + } + + static addToPath() { + core.addPath(process.env['DOTNET_INSTALL_DIR']!); + core.exportVariable('DOTNET_ROOT', process.env['DOTNET_INSTALL_DIR']); + } + private setQuality( dotnetVersion: DotnetVersion, scriptArguments: string[] @@ -208,11 +215,6 @@ export class DotnetCoreInstaller { scriptArguments.push(`-ProxyBypassList ${process.env['no_proxy']}`); } - scriptArguments.push( - '-InstallDir', - `'${DotnetCoreInstaller.installationDirectoryWindows}'` - ); - // process.env must be explicitly passed in for DOTNET_INSTALL_DIR to be used scriptPath = (await io.which('pwsh', false)) || (await io.which('powershell', true)); scriptArguments = windowsDefaultOptions.concat(scriptArguments); @@ -228,40 +230,26 @@ export class DotnetCoreInstaller { if (this.quality) { this.setQuality(dotnetVersion, scriptArguments); } - - if (IS_LINUX) { - scriptArguments.push( - '--install-dir', - DotnetCoreInstaller.installationDirectoryLinux - ); - } - - if (IS_MAC) { - scriptArguments.push( - '--install-dir', - DotnetCoreInstaller.installationDirectoryMac - ); - } } + // process.env must be explicitly passed in for DOTNET_INSTALL_DIR to be used + const getExecOutputOptions = { + ignoreReturnCode: true, + env: process.env as {string: string} + }; const {exitCode, stdout} = await exec.getExecOutput( `"${scriptPath}"`, scriptArguments, - {ignoreReturnCode: true} + getExecOutputOptions ); if (exitCode) { throw new Error(`Failed to install dotnet ${exitCode}. ${stdout}`); } - return this.outputDotnetVersion( - dotnetVersion.value, - scriptArguments[scriptArguments.length - 1] - ); + return this.outputDotnetVersion(dotnetVersion.value); } - private async outputDotnetVersion( - version, - installationPath - ): Promise { + private async outputDotnetVersion(version): Promise { + const installationPath = process.env['DOTNET_INSTALL_DIR']!; let versionsOnRunner: string[] = await readdir( path.join(installationPath.replace(/'/g, ''), 'sdk') ); diff --git a/src/utils.ts b/src/utils.ts index ff20ee3..77886ce 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,3 +1,2 @@ export const IS_WINDOWS = process.platform === 'win32'; export const IS_LINUX = process.platform === 'linux'; -export const IS_MAC = process.platform === 'darwin'; diff --git a/tsconfig.json b/tsconfig.json index 5adbcc5..8bd57d4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -35,6 +35,7 @@ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ /* Additional Checks */ + "useUnknownInCatchVariables": false, /* Type catch clause variables as 'unknown' instead of 'any'. */ // "noUnusedLocals": true, /* Report errors on unused locals. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */