├── .eslintignore ├── .eslintrc.json ├── .github └── workflows │ └── test.yml ├── .gitignore ├── .prettierignore ├── .prettierrc.json ├── LICENSE ├── README.md ├── __tests__ └── main.test.ts ├── action.yml ├── dist └── index.js ├── jest.config.js ├── package-lock.json ├── package.json ├── src └── main.ts └── tsconfig.json /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | lib/ 3 | node_modules/ -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": ["jest", "@typescript-eslint"], 3 | "extends": ["plugin:github/es6"], 4 | "parser": "@typescript-eslint/parser", 5 | "parserOptions": { 6 | "ecmaVersion": 9, 7 | "sourceType": "module", 8 | "project": "./tsconfig.json" 9 | }, 10 | "rules": { 11 | "no-console": "off", 12 | "eslint-comments/no-use": "off", 13 | "import/no-namespace": "off", 14 | "no-unused-vars": "off", 15 | "@typescript-eslint/no-unused-vars": "error", 16 | "@typescript-eslint/explicit-member-accessibility": ["error", {"accessibility": "no-public"}], 17 | "@typescript-eslint/no-require-imports": "error", 18 | "@typescript-eslint/array-type": "error", 19 | "@typescript-eslint/await-thenable": "error", 20 | "@typescript-eslint/ban-ts-ignore": "error", 21 | "camelcase": "off", 22 | "@typescript-eslint/camelcase": "error", 23 | "@typescript-eslint/class-name-casing": "error", 24 | "@typescript-eslint/explicit-function-return-type": ["error", {"allowExpressions": true}], 25 | "@typescript-eslint/func-call-spacing": ["error", "never"], 26 | "@typescript-eslint/generic-type-naming": ["error", "^[A-Z][A-Za-z]*$"], 27 | "@typescript-eslint/no-array-constructor": "error", 28 | "@typescript-eslint/no-empty-interface": "error", 29 | "@typescript-eslint/no-explicit-any": "error", 30 | "@typescript-eslint/no-extraneous-class": "error", 31 | "@typescript-eslint/no-for-in-array": "error", 32 | "@typescript-eslint/no-inferrable-types": "error", 33 | "@typescript-eslint/no-misused-new": "error", 34 | "@typescript-eslint/no-namespace": "error", 35 | "@typescript-eslint/no-non-null-assertion": "warn", 36 | "@typescript-eslint/no-object-literal-type-assertion": "error", 37 | "@typescript-eslint/no-unnecessary-qualifier": "error", 38 | "@typescript-eslint/no-unnecessary-type-assertion": "error", 39 | "@typescript-eslint/no-useless-constructor": "error", 40 | "@typescript-eslint/no-var-requires": "error", 41 | "@typescript-eslint/prefer-for-of": "warn", 42 | "@typescript-eslint/prefer-function-type": "warn", 43 | "@typescript-eslint/prefer-includes": "error", 44 | "@typescript-eslint/prefer-interface": "error", 45 | "@typescript-eslint/prefer-string-starts-ends-with": "error", 46 | "@typescript-eslint/promise-function-async": "error", 47 | "@typescript-eslint/require-array-sort-compare": "error", 48 | "@typescript-eslint/restrict-plus-operands": "error", 49 | "semi": "off", 50 | "@typescript-eslint/semi": ["error", "never"], 51 | "@typescript-eslint/type-annotation-spacing": "error", 52 | "@typescript-eslint/unbound-method": "error" 53 | }, 54 | "env": { 55 | "node": true, 56 | "es6": true, 57 | "jest/globals": true 58 | } 59 | } -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: "build-test" 2 | on: 3 | pull_request: 4 | push: 5 | branches: 6 | - master 7 | - 'releases/*' 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - run: | 15 | npm install 16 | npm run all 17 | 18 | test: 19 | runs-on: ${{ matrix.os }} 20 | 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | os: [ubuntu-latest, macos-latest] 25 | 26 | steps: 27 | - uses: actions/checkout@v2 28 | - uses: ./ 29 | - name: Install Python 30 | run: mamba install -y -c conda-forge python 31 | - name: Install Notebook and widgets 32 | run: mamba install -y -c notebook ipywidgets 33 | - name: List the packages 34 | run: mamba list 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependency directory 2 | node_modules 3 | 4 | # Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | yarn-debug.log* 10 | yarn-error.log* 11 | lerna-debug.log* 12 | 13 | # Diagnostic reports (https://nodejs.org/api/report.html) 14 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 15 | 16 | # Runtime data 17 | pids 18 | *.pid 19 | *.seed 20 | *.pid.lock 21 | 22 | # Directory for instrumented libs generated by jscoverage/JSCover 23 | lib-cov 24 | 25 | # Coverage directory used by tools like istanbul 26 | coverage 27 | *.lcov 28 | 29 | # nyc test coverage 30 | .nyc_output 31 | 32 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 33 | .grunt 34 | 35 | # Bower dependency directory (https://bower.io/) 36 | bower_components 37 | 38 | # node-waf configuration 39 | .lock-wscript 40 | 41 | # Compiled binary addons (https://nodejs.org/api/addons.html) 42 | build/Release 43 | 44 | # Dependency directories 45 | jspm_packages/ 46 | 47 | # TypeScript v1 declaration files 48 | typings/ 49 | 50 | # TypeScript cache 51 | *.tsbuildinfo 52 | 53 | # Optional npm cache directory 54 | .npm 55 | 56 | # Optional eslint cache 57 | .eslintcache 58 | 59 | # Optional REPL history 60 | .node_repl_history 61 | 62 | # Output of 'npm pack' 63 | *.tgz 64 | 65 | # Yarn Integrity file 66 | .yarn-integrity 67 | 68 | # dotenv environment variables file 69 | .env 70 | .env.test 71 | 72 | # parcel-bundler cache (https://parceljs.org/) 73 | .cache 74 | 75 | # next.js build output 76 | .next 77 | 78 | # nuxt.js build output 79 | .nuxt 80 | 81 | # vuepress build output 82 | .vuepress/dist 83 | 84 | # Serverless directories 85 | .serverless/ 86 | 87 | # FuseBox cache 88 | .fusebox/ 89 | 90 | # DynamoDB Local files 91 | .dynamodb/ 92 | 93 | # OS metadata 94 | .DS_Store 95 | Thumbs.db 96 | 97 | # Ignore built ts files 98 | __tests__/runner/* 99 | lib/**/* -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | lib/ 3 | node_modules/ -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "tabWidth": 2, 4 | "useTabs": false, 5 | "semi": false, 6 | "singleQuote": true, 7 | "trailingComma": "none", 8 | "bracketSpacing": false, 9 | "arrowParens": "avoid", 10 | "parser": "typescript" 11 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2018 GitHub, Inc. and contributors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # setup-mamba 2 | 3 | This project is archived. The GitHub Action setup-mamba is deprecated, please use [setup-micromamba](https://github.com/mamba-org/setup-micromamba) instead. 4 | 5 | -------------------------------------------------------------------------------- /__tests__/main.test.ts: -------------------------------------------------------------------------------- 1 | import * as process from 'process' 2 | import * as cp from 'child_process' 3 | import * as path from 'path' 4 | 5 | // shows how the runner will run a javascript action with env / stdout protocol 6 | test('test runs', () => { 7 | process.env['INPUT_MILLISECONDS'] = '500' 8 | const ip = path.join(__dirname, '..', 'lib', 'main.js') 9 | const options: cp.ExecSyncOptions = { 10 | env: process.env 11 | } 12 | console.log(cp.execSync(`node ${ip}`, options).toString()) 13 | }) 14 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: 'setup-mamba' 2 | description: 'GitHub action to setup mamba' 3 | author: 'TheSnakePit' 4 | runs: 5 | using: 'node12' 6 | main: 'dist/index.js' 7 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | module.exports = 2 | /******/ (function(modules, runtime) { // webpackBootstrap 3 | /******/ "use strict"; 4 | /******/ // The module cache 5 | /******/ var installedModules = {}; 6 | /******/ 7 | /******/ // The require function 8 | /******/ function __webpack_require__(moduleId) { 9 | /******/ 10 | /******/ // Check if module is in cache 11 | /******/ if(installedModules[moduleId]) { 12 | /******/ return installedModules[moduleId].exports; 13 | /******/ } 14 | /******/ // Create a new module (and put it into the cache) 15 | /******/ var module = installedModules[moduleId] = { 16 | /******/ i: moduleId, 17 | /******/ l: false, 18 | /******/ exports: {} 19 | /******/ }; 20 | /******/ 21 | /******/ // Execute the module function 22 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 23 | /******/ 24 | /******/ // Flag the module as loaded 25 | /******/ module.l = true; 26 | /******/ 27 | /******/ // Return the exports of the module 28 | /******/ return module.exports; 29 | /******/ } 30 | /******/ 31 | /******/ 32 | /******/ __webpack_require__.ab = __dirname + "/"; 33 | /******/ 34 | /******/ // the startup function 35 | /******/ function startup() { 36 | /******/ // Load entry module and return exports 37 | /******/ return __webpack_require__(198); 38 | /******/ }; 39 | /******/ 40 | /******/ // run startup 41 | /******/ return startup(); 42 | /******/ }) 43 | /************************************************************************/ 44 | /******/ ({ 45 | 46 | /***/ 1: 47 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 48 | 49 | "use strict"; 50 | 51 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 52 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 53 | return new (P || (P = Promise))(function (resolve, reject) { 54 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 55 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 56 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 57 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 58 | }); 59 | }; 60 | Object.defineProperty(exports, "__esModule", { value: true }); 61 | const childProcess = __webpack_require__(129); 62 | const path = __webpack_require__(622); 63 | const util_1 = __webpack_require__(669); 64 | const ioUtil = __webpack_require__(672); 65 | const exec = util_1.promisify(childProcess.exec); 66 | /** 67 | * Copies a file or folder. 68 | * Based off of shelljs - https://github.com/shelljs/shelljs/blob/9237f66c52e5daa40458f94f9565e18e8132f5a6/src/cp.js 69 | * 70 | * @param source source path 71 | * @param dest destination path 72 | * @param options optional. See CopyOptions. 73 | */ 74 | function cp(source, dest, options = {}) { 75 | return __awaiter(this, void 0, void 0, function* () { 76 | const { force, recursive } = readCopyOptions(options); 77 | const destStat = (yield ioUtil.exists(dest)) ? yield ioUtil.stat(dest) : null; 78 | // Dest is an existing file, but not forcing 79 | if (destStat && destStat.isFile() && !force) { 80 | return; 81 | } 82 | // If dest is an existing directory, should copy inside. 83 | const newDest = destStat && destStat.isDirectory() 84 | ? path.join(dest, path.basename(source)) 85 | : dest; 86 | if (!(yield ioUtil.exists(source))) { 87 | throw new Error(`no such file or directory: ${source}`); 88 | } 89 | const sourceStat = yield ioUtil.stat(source); 90 | if (sourceStat.isDirectory()) { 91 | if (!recursive) { 92 | throw new Error(`Failed to copy. ${source} is a directory, but tried to copy without recursive flag.`); 93 | } 94 | else { 95 | yield cpDirRecursive(source, newDest, 0, force); 96 | } 97 | } 98 | else { 99 | if (path.relative(source, newDest) === '') { 100 | // a file cannot be copied to itself 101 | throw new Error(`'${newDest}' and '${source}' are the same file`); 102 | } 103 | yield copyFile(source, newDest, force); 104 | } 105 | }); 106 | } 107 | exports.cp = cp; 108 | /** 109 | * Moves a path. 110 | * 111 | * @param source source path 112 | * @param dest destination path 113 | * @param options optional. See MoveOptions. 114 | */ 115 | function mv(source, dest, options = {}) { 116 | return __awaiter(this, void 0, void 0, function* () { 117 | if (yield ioUtil.exists(dest)) { 118 | let destExists = true; 119 | if (yield ioUtil.isDirectory(dest)) { 120 | // If dest is directory copy src into dest 121 | dest = path.join(dest, path.basename(source)); 122 | destExists = yield ioUtil.exists(dest); 123 | } 124 | if (destExists) { 125 | if (options.force == null || options.force) { 126 | yield rmRF(dest); 127 | } 128 | else { 129 | throw new Error('Destination already exists'); 130 | } 131 | } 132 | } 133 | yield mkdirP(path.dirname(dest)); 134 | yield ioUtil.rename(source, dest); 135 | }); 136 | } 137 | exports.mv = mv; 138 | /** 139 | * Remove a path recursively with force 140 | * 141 | * @param inputPath path to remove 142 | */ 143 | function rmRF(inputPath) { 144 | return __awaiter(this, void 0, void 0, function* () { 145 | if (ioUtil.IS_WINDOWS) { 146 | // Node doesn't provide a delete operation, only an unlink function. This means that if the file is being used by another 147 | // program (e.g. antivirus), it won't be deleted. To address this, we shell out the work to rd/del. 148 | try { 149 | if (yield ioUtil.isDirectory(inputPath, true)) { 150 | yield exec(`rd /s /q "${inputPath}"`); 151 | } 152 | else { 153 | yield exec(`del /f /a "${inputPath}"`); 154 | } 155 | } 156 | catch (err) { 157 | // if you try to delete a file that doesn't exist, desired result is achieved 158 | // other errors are valid 159 | if (err.code !== 'ENOENT') 160 | throw err; 161 | } 162 | // Shelling out fails to remove a symlink folder with missing source, this unlink catches that 163 | try { 164 | yield ioUtil.unlink(inputPath); 165 | } 166 | catch (err) { 167 | // if you try to delete a file that doesn't exist, desired result is achieved 168 | // other errors are valid 169 | if (err.code !== 'ENOENT') 170 | throw err; 171 | } 172 | } 173 | else { 174 | let isDir = false; 175 | try { 176 | isDir = yield ioUtil.isDirectory(inputPath); 177 | } 178 | catch (err) { 179 | // if you try to delete a file that doesn't exist, desired result is achieved 180 | // other errors are valid 181 | if (err.code !== 'ENOENT') 182 | throw err; 183 | return; 184 | } 185 | if (isDir) { 186 | yield exec(`rm -rf "${inputPath}"`); 187 | } 188 | else { 189 | yield ioUtil.unlink(inputPath); 190 | } 191 | } 192 | }); 193 | } 194 | exports.rmRF = rmRF; 195 | /** 196 | * Make a directory. Creates the full path with folders in between 197 | * Will throw if it fails 198 | * 199 | * @param fsPath path to create 200 | * @returns Promise 201 | */ 202 | function mkdirP(fsPath) { 203 | return __awaiter(this, void 0, void 0, function* () { 204 | yield ioUtil.mkdirP(fsPath); 205 | }); 206 | } 207 | exports.mkdirP = mkdirP; 208 | /** 209 | * Returns path of a tool had the tool actually been invoked. Resolves via paths. 210 | * If you check and the tool does not exist, it will throw. 211 | * 212 | * @param tool name of the tool 213 | * @param check whether to check if tool exists 214 | * @returns Promise path to tool 215 | */ 216 | function which(tool, check) { 217 | return __awaiter(this, void 0, void 0, function* () { 218 | if (!tool) { 219 | throw new Error("parameter 'tool' is required"); 220 | } 221 | // recursive when check=true 222 | if (check) { 223 | const result = yield which(tool, false); 224 | if (!result) { 225 | if (ioUtil.IS_WINDOWS) { 226 | throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also verify the file has a valid extension for an executable file.`); 227 | } 228 | else { 229 | throw new Error(`Unable to locate executable file: ${tool}. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable. Also check the file mode to verify the file is executable.`); 230 | } 231 | } 232 | } 233 | try { 234 | // build the list of extensions to try 235 | const extensions = []; 236 | if (ioUtil.IS_WINDOWS && process.env.PATHEXT) { 237 | for (const extension of process.env.PATHEXT.split(path.delimiter)) { 238 | if (extension) { 239 | extensions.push(extension); 240 | } 241 | } 242 | } 243 | // if it's rooted, return it if exists. otherwise return empty. 244 | if (ioUtil.isRooted(tool)) { 245 | const filePath = yield ioUtil.tryGetExecutablePath(tool, extensions); 246 | if (filePath) { 247 | return filePath; 248 | } 249 | return ''; 250 | } 251 | // if any path separators, return empty 252 | if (tool.includes('/') || (ioUtil.IS_WINDOWS && tool.includes('\\'))) { 253 | return ''; 254 | } 255 | // build the list of directories 256 | // 257 | // Note, technically "where" checks the current directory on Windows. From a toolkit perspective, 258 | // it feels like we should not do this. Checking the current directory seems like more of a use 259 | // case of a shell, and the which() function exposed by the toolkit should strive for consistency 260 | // across platforms. 261 | const directories = []; 262 | if (process.env.PATH) { 263 | for (const p of process.env.PATH.split(path.delimiter)) { 264 | if (p) { 265 | directories.push(p); 266 | } 267 | } 268 | } 269 | // return the first match 270 | for (const directory of directories) { 271 | const filePath = yield ioUtil.tryGetExecutablePath(directory + path.sep + tool, extensions); 272 | if (filePath) { 273 | return filePath; 274 | } 275 | } 276 | return ''; 277 | } 278 | catch (err) { 279 | throw new Error(`which failed with message ${err.message}`); 280 | } 281 | }); 282 | } 283 | exports.which = which; 284 | function readCopyOptions(options) { 285 | const force = options.force == null ? true : options.force; 286 | const recursive = Boolean(options.recursive); 287 | return { force, recursive }; 288 | } 289 | function cpDirRecursive(sourceDir, destDir, currentDepth, force) { 290 | return __awaiter(this, void 0, void 0, function* () { 291 | // Ensure there is not a run away recursive copy 292 | if (currentDepth >= 255) 293 | return; 294 | currentDepth++; 295 | yield mkdirP(destDir); 296 | const files = yield ioUtil.readdir(sourceDir); 297 | for (const fileName of files) { 298 | const srcFile = `${sourceDir}/${fileName}`; 299 | const destFile = `${destDir}/${fileName}`; 300 | const srcFileStat = yield ioUtil.lstat(srcFile); 301 | if (srcFileStat.isDirectory()) { 302 | // Recurse 303 | yield cpDirRecursive(srcFile, destFile, currentDepth, force); 304 | } 305 | else { 306 | yield copyFile(srcFile, destFile, force); 307 | } 308 | } 309 | // Change the mode for the newly created directory 310 | yield ioUtil.chmod(destDir, (yield ioUtil.stat(sourceDir)).mode); 311 | }); 312 | } 313 | // Buffered file copy 314 | function copyFile(srcFile, destFile, force) { 315 | return __awaiter(this, void 0, void 0, function* () { 316 | if ((yield ioUtil.lstat(srcFile)).isSymbolicLink()) { 317 | // unlink/re-link it 318 | try { 319 | yield ioUtil.lstat(destFile); 320 | yield ioUtil.unlink(destFile); 321 | } 322 | catch (e) { 323 | // Try to override file permission 324 | if (e.code === 'EPERM') { 325 | yield ioUtil.chmod(destFile, '0666'); 326 | yield ioUtil.unlink(destFile); 327 | } 328 | // other errors = it doesn't exist, no work to do 329 | } 330 | // Copy over symlink 331 | const symlinkFull = yield ioUtil.readlink(srcFile); 332 | yield ioUtil.symlink(symlinkFull, destFile, ioUtil.IS_WINDOWS ? 'junction' : null); 333 | } 334 | else if (!(yield ioUtil.exists(destFile)) || force) { 335 | yield ioUtil.copyFile(srcFile, destFile); 336 | } 337 | }); 338 | } 339 | //# sourceMappingURL=io.js.map 340 | 341 | /***/ }), 342 | 343 | /***/ 9: 344 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 345 | 346 | "use strict"; 347 | 348 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 349 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 350 | return new (P || (P = Promise))(function (resolve, reject) { 351 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 352 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 353 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 354 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 355 | }); 356 | }; 357 | var __importStar = (this && this.__importStar) || function (mod) { 358 | if (mod && mod.__esModule) return mod; 359 | var result = {}; 360 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; 361 | result["default"] = mod; 362 | return result; 363 | }; 364 | Object.defineProperty(exports, "__esModule", { value: true }); 365 | const os = __importStar(__webpack_require__(87)); 366 | const events = __importStar(__webpack_require__(614)); 367 | const child = __importStar(__webpack_require__(129)); 368 | const path = __importStar(__webpack_require__(622)); 369 | const io = __importStar(__webpack_require__(1)); 370 | const ioUtil = __importStar(__webpack_require__(672)); 371 | /* eslint-disable @typescript-eslint/unbound-method */ 372 | const IS_WINDOWS = process.platform === 'win32'; 373 | /* 374 | * Class for running command line tools. Handles quoting and arg parsing in a platform agnostic way. 375 | */ 376 | class ToolRunner extends events.EventEmitter { 377 | constructor(toolPath, args, options) { 378 | super(); 379 | if (!toolPath) { 380 | throw new Error("Parameter 'toolPath' cannot be null or empty."); 381 | } 382 | this.toolPath = toolPath; 383 | this.args = args || []; 384 | this.options = options || {}; 385 | } 386 | _debug(message) { 387 | if (this.options.listeners && this.options.listeners.debug) { 388 | this.options.listeners.debug(message); 389 | } 390 | } 391 | _getCommandString(options, noPrefix) { 392 | const toolPath = this._getSpawnFileName(); 393 | const args = this._getSpawnArgs(options); 394 | let cmd = noPrefix ? '' : '[command]'; // omit prefix when piped to a second tool 395 | if (IS_WINDOWS) { 396 | // Windows + cmd file 397 | if (this._isCmdFile()) { 398 | cmd += toolPath; 399 | for (const a of args) { 400 | cmd += ` ${a}`; 401 | } 402 | } 403 | // Windows + verbatim 404 | else if (options.windowsVerbatimArguments) { 405 | cmd += `"${toolPath}"`; 406 | for (const a of args) { 407 | cmd += ` ${a}`; 408 | } 409 | } 410 | // Windows (regular) 411 | else { 412 | cmd += this._windowsQuoteCmdArg(toolPath); 413 | for (const a of args) { 414 | cmd += ` ${this._windowsQuoteCmdArg(a)}`; 415 | } 416 | } 417 | } 418 | else { 419 | // OSX/Linux - this can likely be improved with some form of quoting. 420 | // creating processes on Unix is fundamentally different than Windows. 421 | // on Unix, execvp() takes an arg array. 422 | cmd += toolPath; 423 | for (const a of args) { 424 | cmd += ` ${a}`; 425 | } 426 | } 427 | return cmd; 428 | } 429 | _processLineBuffer(data, strBuffer, onLine) { 430 | try { 431 | let s = strBuffer + data.toString(); 432 | let n = s.indexOf(os.EOL); 433 | while (n > -1) { 434 | const line = s.substring(0, n); 435 | onLine(line); 436 | // the rest of the string ... 437 | s = s.substring(n + os.EOL.length); 438 | n = s.indexOf(os.EOL); 439 | } 440 | strBuffer = s; 441 | } 442 | catch (err) { 443 | // streaming lines to console is best effort. Don't fail a build. 444 | this._debug(`error processing line. Failed with error ${err}`); 445 | } 446 | } 447 | _getSpawnFileName() { 448 | if (IS_WINDOWS) { 449 | if (this._isCmdFile()) { 450 | return process.env['COMSPEC'] || 'cmd.exe'; 451 | } 452 | } 453 | return this.toolPath; 454 | } 455 | _getSpawnArgs(options) { 456 | if (IS_WINDOWS) { 457 | if (this._isCmdFile()) { 458 | let argline = `/D /S /C "${this._windowsQuoteCmdArg(this.toolPath)}`; 459 | for (const a of this.args) { 460 | argline += ' '; 461 | argline += options.windowsVerbatimArguments 462 | ? a 463 | : this._windowsQuoteCmdArg(a); 464 | } 465 | argline += '"'; 466 | return [argline]; 467 | } 468 | } 469 | return this.args; 470 | } 471 | _endsWith(str, end) { 472 | return str.endsWith(end); 473 | } 474 | _isCmdFile() { 475 | const upperToolPath = this.toolPath.toUpperCase(); 476 | return (this._endsWith(upperToolPath, '.CMD') || 477 | this._endsWith(upperToolPath, '.BAT')); 478 | } 479 | _windowsQuoteCmdArg(arg) { 480 | // for .exe, apply the normal quoting rules that libuv applies 481 | if (!this._isCmdFile()) { 482 | return this._uvQuoteCmdArg(arg); 483 | } 484 | // otherwise apply quoting rules specific to the cmd.exe command line parser. 485 | // the libuv rules are generic and are not designed specifically for cmd.exe 486 | // command line parser. 487 | // 488 | // for a detailed description of the cmd.exe command line parser, refer to 489 | // http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts/7970912#7970912 490 | // need quotes for empty arg 491 | if (!arg) { 492 | return '""'; 493 | } 494 | // determine whether the arg needs to be quoted 495 | const cmdSpecialChars = [ 496 | ' ', 497 | '\t', 498 | '&', 499 | '(', 500 | ')', 501 | '[', 502 | ']', 503 | '{', 504 | '}', 505 | '^', 506 | '=', 507 | ';', 508 | '!', 509 | "'", 510 | '+', 511 | ',', 512 | '`', 513 | '~', 514 | '|', 515 | '<', 516 | '>', 517 | '"' 518 | ]; 519 | let needsQuotes = false; 520 | for (const char of arg) { 521 | if (cmdSpecialChars.some(x => x === char)) { 522 | needsQuotes = true; 523 | break; 524 | } 525 | } 526 | // short-circuit if quotes not needed 527 | if (!needsQuotes) { 528 | return arg; 529 | } 530 | // the following quoting rules are very similar to the rules that by libuv applies. 531 | // 532 | // 1) wrap the string in quotes 533 | // 534 | // 2) double-up quotes - i.e. " => "" 535 | // 536 | // this is different from the libuv quoting rules. libuv replaces " with \", which unfortunately 537 | // doesn't work well with a cmd.exe command line. 538 | // 539 | // note, replacing " with "" also works well if the arg is passed to a downstream .NET console app. 540 | // for example, the command line: 541 | // foo.exe "myarg:""my val""" 542 | // is parsed by a .NET console app into an arg array: 543 | // [ "myarg:\"my val\"" ] 544 | // which is the same end result when applying libuv quoting rules. although the actual 545 | // command line from libuv quoting rules would look like: 546 | // foo.exe "myarg:\"my val\"" 547 | // 548 | // 3) double-up slashes that precede a quote, 549 | // e.g. hello \world => "hello \world" 550 | // hello\"world => "hello\\""world" 551 | // hello\\"world => "hello\\\\""world" 552 | // hello world\ => "hello world\\" 553 | // 554 | // technically this is not required for a cmd.exe command line, or the batch argument parser. 555 | // the reasons for including this as a .cmd quoting rule are: 556 | // 557 | // a) this is optimized for the scenario where the argument is passed from the .cmd file to an 558 | // external program. many programs (e.g. .NET console apps) rely on the slash-doubling rule. 559 | // 560 | // b) it's what we've been doing previously (by deferring to node default behavior) and we 561 | // haven't heard any complaints about that aspect. 562 | // 563 | // note, a weakness of the quoting rules chosen here, is that % is not escaped. in fact, % cannot be 564 | // escaped when used on the command line directly - even though within a .cmd file % can be escaped 565 | // by using %%. 566 | // 567 | // the saving grace is, on the command line, %var% is left as-is if var is not defined. this contrasts 568 | // the line parsing rules within a .cmd file, where if var is not defined it is replaced with nothing. 569 | // 570 | // one option that was explored was replacing % with ^% - i.e. %var% => ^%var^%. this hack would 571 | // often work, since it is unlikely that var^ would exist, and the ^ character is removed when the 572 | // variable is used. the problem, however, is that ^ is not removed when %* is used to pass the args 573 | // to an external program. 574 | // 575 | // an unexplored potential solution for the % escaping problem, is to create a wrapper .cmd file. 576 | // % can be escaped within a .cmd file. 577 | let reverse = '"'; 578 | let quoteHit = true; 579 | for (let i = arg.length; i > 0; i--) { 580 | // walk the string in reverse 581 | reverse += arg[i - 1]; 582 | if (quoteHit && arg[i - 1] === '\\') { 583 | reverse += '\\'; // double the slash 584 | } 585 | else if (arg[i - 1] === '"') { 586 | quoteHit = true; 587 | reverse += '"'; // double the quote 588 | } 589 | else { 590 | quoteHit = false; 591 | } 592 | } 593 | reverse += '"'; 594 | return reverse 595 | .split('') 596 | .reverse() 597 | .join(''); 598 | } 599 | _uvQuoteCmdArg(arg) { 600 | // Tool runner wraps child_process.spawn() and needs to apply the same quoting as 601 | // Node in certain cases where the undocumented spawn option windowsVerbatimArguments 602 | // is used. 603 | // 604 | // Since this function is a port of quote_cmd_arg from Node 4.x (technically, lib UV, 605 | // see https://github.com/nodejs/node/blob/v4.x/deps/uv/src/win/process.c for details), 606 | // pasting copyright notice from Node within this function: 607 | // 608 | // Copyright Joyent, Inc. and other Node contributors. All rights reserved. 609 | // 610 | // Permission is hereby granted, free of charge, to any person obtaining a copy 611 | // of this software and associated documentation files (the "Software"), to 612 | // deal in the Software without restriction, including without limitation the 613 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 614 | // sell copies of the Software, and to permit persons to whom the Software is 615 | // furnished to do so, subject to the following conditions: 616 | // 617 | // The above copyright notice and this permission notice shall be included in 618 | // all copies or substantial portions of the Software. 619 | // 620 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 621 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 622 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 623 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 624 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 625 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 626 | // IN THE SOFTWARE. 627 | if (!arg) { 628 | // Need double quotation for empty argument 629 | return '""'; 630 | } 631 | if (!arg.includes(' ') && !arg.includes('\t') && !arg.includes('"')) { 632 | // No quotation needed 633 | return arg; 634 | } 635 | if (!arg.includes('"') && !arg.includes('\\')) { 636 | // No embedded double quotes or backslashes, so I can just wrap 637 | // quote marks around the whole thing. 638 | return `"${arg}"`; 639 | } 640 | // Expected input/output: 641 | // input : hello"world 642 | // output: "hello\"world" 643 | // input : hello""world 644 | // output: "hello\"\"world" 645 | // input : hello\world 646 | // output: hello\world 647 | // input : hello\\world 648 | // output: hello\\world 649 | // input : hello\"world 650 | // output: "hello\\\"world" 651 | // input : hello\\"world 652 | // output: "hello\\\\\"world" 653 | // input : hello world\ 654 | // output: "hello world\\" - note the comment in libuv actually reads "hello world\" 655 | // but it appears the comment is wrong, it should be "hello world\\" 656 | let reverse = '"'; 657 | let quoteHit = true; 658 | for (let i = arg.length; i > 0; i--) { 659 | // walk the string in reverse 660 | reverse += arg[i - 1]; 661 | if (quoteHit && arg[i - 1] === '\\') { 662 | reverse += '\\'; 663 | } 664 | else if (arg[i - 1] === '"') { 665 | quoteHit = true; 666 | reverse += '\\'; 667 | } 668 | else { 669 | quoteHit = false; 670 | } 671 | } 672 | reverse += '"'; 673 | return reverse 674 | .split('') 675 | .reverse() 676 | .join(''); 677 | } 678 | _cloneExecOptions(options) { 679 | options = options || {}; 680 | const result = { 681 | cwd: options.cwd || process.cwd(), 682 | env: options.env || process.env, 683 | silent: options.silent || false, 684 | windowsVerbatimArguments: options.windowsVerbatimArguments || false, 685 | failOnStdErr: options.failOnStdErr || false, 686 | ignoreReturnCode: options.ignoreReturnCode || false, 687 | delay: options.delay || 10000 688 | }; 689 | result.outStream = options.outStream || process.stdout; 690 | result.errStream = options.errStream || process.stderr; 691 | return result; 692 | } 693 | _getSpawnOptions(options, toolPath) { 694 | options = options || {}; 695 | const result = {}; 696 | result.cwd = options.cwd; 697 | result.env = options.env; 698 | result['windowsVerbatimArguments'] = 699 | options.windowsVerbatimArguments || this._isCmdFile(); 700 | if (options.windowsVerbatimArguments) { 701 | result.argv0 = `"${toolPath}"`; 702 | } 703 | return result; 704 | } 705 | /** 706 | * Exec a tool. 707 | * Output will be streamed to the live console. 708 | * Returns promise with return code 709 | * 710 | * @param tool path to tool to exec 711 | * @param options optional exec options. See ExecOptions 712 | * @returns number 713 | */ 714 | exec() { 715 | return __awaiter(this, void 0, void 0, function* () { 716 | // root the tool path if it is unrooted and contains relative pathing 717 | if (!ioUtil.isRooted(this.toolPath) && 718 | (this.toolPath.includes('/') || 719 | (IS_WINDOWS && this.toolPath.includes('\\')))) { 720 | // prefer options.cwd if it is specified, however options.cwd may also need to be rooted 721 | this.toolPath = path.resolve(process.cwd(), this.options.cwd || process.cwd(), this.toolPath); 722 | } 723 | // if the tool is only a file name, then resolve it from the PATH 724 | // otherwise verify it exists (add extension on Windows if necessary) 725 | this.toolPath = yield io.which(this.toolPath, true); 726 | return new Promise((resolve, reject) => { 727 | this._debug(`exec tool: ${this.toolPath}`); 728 | this._debug('arguments:'); 729 | for (const arg of this.args) { 730 | this._debug(` ${arg}`); 731 | } 732 | const optionsNonNull = this._cloneExecOptions(this.options); 733 | if (!optionsNonNull.silent && optionsNonNull.outStream) { 734 | optionsNonNull.outStream.write(this._getCommandString(optionsNonNull) + os.EOL); 735 | } 736 | const state = new ExecState(optionsNonNull, this.toolPath); 737 | state.on('debug', (message) => { 738 | this._debug(message); 739 | }); 740 | const fileName = this._getSpawnFileName(); 741 | const cp = child.spawn(fileName, this._getSpawnArgs(optionsNonNull), this._getSpawnOptions(this.options, fileName)); 742 | const stdbuffer = ''; 743 | if (cp.stdout) { 744 | cp.stdout.on('data', (data) => { 745 | if (this.options.listeners && this.options.listeners.stdout) { 746 | this.options.listeners.stdout(data); 747 | } 748 | if (!optionsNonNull.silent && optionsNonNull.outStream) { 749 | optionsNonNull.outStream.write(data); 750 | } 751 | this._processLineBuffer(data, stdbuffer, (line) => { 752 | if (this.options.listeners && this.options.listeners.stdline) { 753 | this.options.listeners.stdline(line); 754 | } 755 | }); 756 | }); 757 | } 758 | const errbuffer = ''; 759 | if (cp.stderr) { 760 | cp.stderr.on('data', (data) => { 761 | state.processStderr = true; 762 | if (this.options.listeners && this.options.listeners.stderr) { 763 | this.options.listeners.stderr(data); 764 | } 765 | if (!optionsNonNull.silent && 766 | optionsNonNull.errStream && 767 | optionsNonNull.outStream) { 768 | const s = optionsNonNull.failOnStdErr 769 | ? optionsNonNull.errStream 770 | : optionsNonNull.outStream; 771 | s.write(data); 772 | } 773 | this._processLineBuffer(data, errbuffer, (line) => { 774 | if (this.options.listeners && this.options.listeners.errline) { 775 | this.options.listeners.errline(line); 776 | } 777 | }); 778 | }); 779 | } 780 | cp.on('error', (err) => { 781 | state.processError = err.message; 782 | state.processExited = true; 783 | state.processClosed = true; 784 | state.CheckComplete(); 785 | }); 786 | cp.on('exit', (code) => { 787 | state.processExitCode = code; 788 | state.processExited = true; 789 | this._debug(`Exit code ${code} received from tool '${this.toolPath}'`); 790 | state.CheckComplete(); 791 | }); 792 | cp.on('close', (code) => { 793 | state.processExitCode = code; 794 | state.processExited = true; 795 | state.processClosed = true; 796 | this._debug(`STDIO streams have closed for tool '${this.toolPath}'`); 797 | state.CheckComplete(); 798 | }); 799 | state.on('done', (error, exitCode) => { 800 | if (stdbuffer.length > 0) { 801 | this.emit('stdline', stdbuffer); 802 | } 803 | if (errbuffer.length > 0) { 804 | this.emit('errline', errbuffer); 805 | } 806 | cp.removeAllListeners(); 807 | if (error) { 808 | reject(error); 809 | } 810 | else { 811 | resolve(exitCode); 812 | } 813 | }); 814 | if (this.options.input) { 815 | if (!cp.stdin) { 816 | throw new Error('child process missing stdin'); 817 | } 818 | cp.stdin.end(this.options.input); 819 | } 820 | }); 821 | }); 822 | } 823 | } 824 | exports.ToolRunner = ToolRunner; 825 | /** 826 | * Convert an arg string to an array of args. Handles escaping 827 | * 828 | * @param argString string of arguments 829 | * @returns string[] array of arguments 830 | */ 831 | function argStringToArray(argString) { 832 | const args = []; 833 | let inQuotes = false; 834 | let escaped = false; 835 | let arg = ''; 836 | function append(c) { 837 | // we only escape double quotes. 838 | if (escaped && c !== '"') { 839 | arg += '\\'; 840 | } 841 | arg += c; 842 | escaped = false; 843 | } 844 | for (let i = 0; i < argString.length; i++) { 845 | const c = argString.charAt(i); 846 | if (c === '"') { 847 | if (!escaped) { 848 | inQuotes = !inQuotes; 849 | } 850 | else { 851 | append(c); 852 | } 853 | continue; 854 | } 855 | if (c === '\\' && escaped) { 856 | append(c); 857 | continue; 858 | } 859 | if (c === '\\' && inQuotes) { 860 | escaped = true; 861 | continue; 862 | } 863 | if (c === ' ' && !inQuotes) { 864 | if (arg.length > 0) { 865 | args.push(arg); 866 | arg = ''; 867 | } 868 | continue; 869 | } 870 | append(c); 871 | } 872 | if (arg.length > 0) { 873 | args.push(arg.trim()); 874 | } 875 | return args; 876 | } 877 | exports.argStringToArray = argStringToArray; 878 | class ExecState extends events.EventEmitter { 879 | constructor(options, toolPath) { 880 | super(); 881 | this.processClosed = false; // tracks whether the process has exited and stdio is closed 882 | this.processError = ''; 883 | this.processExitCode = 0; 884 | this.processExited = false; // tracks whether the process has exited 885 | this.processStderr = false; // tracks whether stderr was written to 886 | this.delay = 10000; // 10 seconds 887 | this.done = false; 888 | this.timeout = null; 889 | if (!toolPath) { 890 | throw new Error('toolPath must not be empty'); 891 | } 892 | this.options = options; 893 | this.toolPath = toolPath; 894 | if (options.delay) { 895 | this.delay = options.delay; 896 | } 897 | } 898 | CheckComplete() { 899 | if (this.done) { 900 | return; 901 | } 902 | if (this.processClosed) { 903 | this._setResult(); 904 | } 905 | else if (this.processExited) { 906 | this.timeout = setTimeout(ExecState.HandleTimeout, this.delay, this); 907 | } 908 | } 909 | _debug(message) { 910 | this.emit('debug', message); 911 | } 912 | _setResult() { 913 | // determine whether there is an error 914 | let error; 915 | if (this.processExited) { 916 | if (this.processError) { 917 | error = new Error(`There was an error when attempting to execute the process '${this.toolPath}'. This may indicate the process failed to start. Error: ${this.processError}`); 918 | } 919 | else if (this.processExitCode !== 0 && !this.options.ignoreReturnCode) { 920 | error = new Error(`The process '${this.toolPath}' failed with exit code ${this.processExitCode}`); 921 | } 922 | else if (this.processStderr && this.options.failOnStdErr) { 923 | error = new Error(`The process '${this.toolPath}' failed because one or more lines were written to the STDERR stream`); 924 | } 925 | } 926 | // clear the timeout 927 | if (this.timeout) { 928 | clearTimeout(this.timeout); 929 | this.timeout = null; 930 | } 931 | this.done = true; 932 | this.emit('done', error, this.processExitCode); 933 | } 934 | static HandleTimeout(state) { 935 | if (state.done) { 936 | return; 937 | } 938 | if (!state.processClosed && state.processExited) { 939 | const message = `The STDIO streams did not close within ${state.delay / 940 | 1000} seconds of the exit event from process '${state.toolPath}'. This may indicate a child process inherited the STDIO streams and has not yet exited.`; 941 | state._debug(message); 942 | } 943 | state._setResult(); 944 | } 945 | } 946 | //# sourceMappingURL=toolrunner.js.map 947 | 948 | /***/ }), 949 | 950 | /***/ 87: 951 | /***/ (function(module) { 952 | 953 | module.exports = require("os"); 954 | 955 | /***/ }), 956 | 957 | /***/ 129: 958 | /***/ (function(module) { 959 | 960 | module.exports = require("child_process"); 961 | 962 | /***/ }), 963 | 964 | /***/ 198: 965 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 966 | 967 | "use strict"; 968 | 969 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 970 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 971 | return new (P || (P = Promise))(function (resolve, reject) { 972 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 973 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 974 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 975 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 976 | }); 977 | }; 978 | var __importStar = (this && this.__importStar) || function (mod) { 979 | if (mod && mod.__esModule) return mod; 980 | var result = {}; 981 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; 982 | result["default"] = mod; 983 | return result; 984 | }; 985 | Object.defineProperty(exports, "__esModule", { value: true }); 986 | const path = __importStar(__webpack_require__(622)); 987 | const core = __importStar(__webpack_require__(470)); 988 | const exec = __importStar(__webpack_require__(986)); 989 | function fixPermissions(os) { 990 | return __awaiter(this, void 0, void 0, function* () { 991 | if (os === 'darwin') { 992 | const username = process.env.USER; 993 | yield exec.exec('sudo', [ 994 | 'chown', 995 | '-R', 996 | `${username}:staff`, 997 | process.env.CONDA 998 | ]); 999 | } 1000 | }); 1001 | } 1002 | function addPath(os) { 1003 | return __awaiter(this, void 0, void 0, function* () { 1004 | const basePath = process.env.CONDA; 1005 | if (os === 'darwin') { 1006 | const bin = path.join(basePath, 'condabin'); 1007 | core.addPath(bin); 1008 | } 1009 | else if (os === 'win32') { 1010 | const bin = path.join(basePath, 'Scripts'); 1011 | core.addPath(bin); 1012 | } 1013 | else { 1014 | const bin = path.join(basePath, 'bin'); 1015 | core.addPath(bin); 1016 | } 1017 | }); 1018 | } 1019 | function installMamba() { 1020 | return __awaiter(this, void 0, void 0, function* () { 1021 | yield exec.exec('conda', ['install', '-y', '-c', 'conda-forge', 'mamba']); 1022 | }); 1023 | } 1024 | function run() { 1025 | return __awaiter(this, void 0, void 0, function* () { 1026 | try { 1027 | const os = process.platform; 1028 | core.debug('Fix permissions'); 1029 | fixPermissions(os); 1030 | core.debug('Add conda to the path'); 1031 | yield addPath(os); 1032 | core.debug('Installing mamba'); 1033 | yield installMamba(); 1034 | } 1035 | catch (error) { 1036 | core.setFailed(error.message); 1037 | } 1038 | }); 1039 | } 1040 | run(); 1041 | 1042 | 1043 | /***/ }), 1044 | 1045 | /***/ 357: 1046 | /***/ (function(module) { 1047 | 1048 | module.exports = require("assert"); 1049 | 1050 | /***/ }), 1051 | 1052 | /***/ 431: 1053 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 1054 | 1055 | "use strict"; 1056 | 1057 | Object.defineProperty(exports, "__esModule", { value: true }); 1058 | const os = __webpack_require__(87); 1059 | /** 1060 | * Commands 1061 | * 1062 | * Command Format: 1063 | * ##[name key=value;key=value]message 1064 | * 1065 | * Examples: 1066 | * ##[warning]This is the user warning message 1067 | * ##[set-secret name=mypassword]definitelyNotAPassword! 1068 | */ 1069 | function issueCommand(command, properties, message) { 1070 | const cmd = new Command(command, properties, message); 1071 | process.stdout.write(cmd.toString() + os.EOL); 1072 | } 1073 | exports.issueCommand = issueCommand; 1074 | function issue(name, message = '') { 1075 | issueCommand(name, {}, message); 1076 | } 1077 | exports.issue = issue; 1078 | const CMD_STRING = '::'; 1079 | class Command { 1080 | constructor(command, properties, message) { 1081 | if (!command) { 1082 | command = 'missing.command'; 1083 | } 1084 | this.command = command; 1085 | this.properties = properties; 1086 | this.message = message; 1087 | } 1088 | toString() { 1089 | let cmdStr = CMD_STRING + this.command; 1090 | if (this.properties && Object.keys(this.properties).length > 0) { 1091 | cmdStr += ' '; 1092 | for (const key in this.properties) { 1093 | if (this.properties.hasOwnProperty(key)) { 1094 | const val = this.properties[key]; 1095 | if (val) { 1096 | // safely append the val - avoid blowing up when attempting to 1097 | // call .replace() if message is not a string for some reason 1098 | cmdStr += `${key}=${escape(`${val || ''}`)},`; 1099 | } 1100 | } 1101 | } 1102 | } 1103 | cmdStr += CMD_STRING; 1104 | // safely append the message - avoid blowing up when attempting to 1105 | // call .replace() if message is not a string for some reason 1106 | const message = `${this.message || ''}`; 1107 | cmdStr += escapeData(message); 1108 | return cmdStr; 1109 | } 1110 | } 1111 | function escapeData(s) { 1112 | return s.replace(/\r/g, '%0D').replace(/\n/g, '%0A'); 1113 | } 1114 | function escape(s) { 1115 | return s 1116 | .replace(/\r/g, '%0D') 1117 | .replace(/\n/g, '%0A') 1118 | .replace(/]/g, '%5D') 1119 | .replace(/;/g, '%3B'); 1120 | } 1121 | //# sourceMappingURL=command.js.map 1122 | 1123 | /***/ }), 1124 | 1125 | /***/ 470: 1126 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 1127 | 1128 | "use strict"; 1129 | 1130 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 1131 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 1132 | return new (P || (P = Promise))(function (resolve, reject) { 1133 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 1134 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 1135 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 1136 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 1137 | }); 1138 | }; 1139 | Object.defineProperty(exports, "__esModule", { value: true }); 1140 | const command_1 = __webpack_require__(431); 1141 | const os = __webpack_require__(87); 1142 | const path = __webpack_require__(622); 1143 | /** 1144 | * The code to exit an action 1145 | */ 1146 | var ExitCode; 1147 | (function (ExitCode) { 1148 | /** 1149 | * A code indicating that the action was successful 1150 | */ 1151 | ExitCode[ExitCode["Success"] = 0] = "Success"; 1152 | /** 1153 | * A code indicating that the action was a failure 1154 | */ 1155 | ExitCode[ExitCode["Failure"] = 1] = "Failure"; 1156 | })(ExitCode = exports.ExitCode || (exports.ExitCode = {})); 1157 | //----------------------------------------------------------------------- 1158 | // Variables 1159 | //----------------------------------------------------------------------- 1160 | /** 1161 | * Sets env variable for this action and future actions in the job 1162 | * @param name the name of the variable to set 1163 | * @param val the value of the variable 1164 | */ 1165 | function exportVariable(name, val) { 1166 | process.env[name] = val; 1167 | command_1.issueCommand('set-env', { name }, val); 1168 | } 1169 | exports.exportVariable = exportVariable; 1170 | /** 1171 | * Registers a secret which will get masked from logs 1172 | * @param secret value of the secret 1173 | */ 1174 | function setSecret(secret) { 1175 | command_1.issueCommand('add-mask', {}, secret); 1176 | } 1177 | exports.setSecret = setSecret; 1178 | /** 1179 | * Prepends inputPath to the PATH (for this action and future actions) 1180 | * @param inputPath 1181 | */ 1182 | function addPath(inputPath) { 1183 | command_1.issueCommand('add-path', {}, inputPath); 1184 | process.env['PATH'] = `${inputPath}${path.delimiter}${process.env['PATH']}`; 1185 | } 1186 | exports.addPath = addPath; 1187 | /** 1188 | * Gets the value of an input. The value is also trimmed. 1189 | * 1190 | * @param name name of the input to get 1191 | * @param options optional. See InputOptions. 1192 | * @returns string 1193 | */ 1194 | function getInput(name, options) { 1195 | const val = process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || ''; 1196 | if (options && options.required && !val) { 1197 | throw new Error(`Input required and not supplied: ${name}`); 1198 | } 1199 | return val.trim(); 1200 | } 1201 | exports.getInput = getInput; 1202 | /** 1203 | * Sets the value of an output. 1204 | * 1205 | * @param name name of the output to set 1206 | * @param value value to store 1207 | */ 1208 | function setOutput(name, value) { 1209 | command_1.issueCommand('set-output', { name }, value); 1210 | } 1211 | exports.setOutput = setOutput; 1212 | //----------------------------------------------------------------------- 1213 | // Results 1214 | //----------------------------------------------------------------------- 1215 | /** 1216 | * Sets the action status to failed. 1217 | * When the action exits it will be with an exit code of 1 1218 | * @param message add error issue message 1219 | */ 1220 | function setFailed(message) { 1221 | process.exitCode = ExitCode.Failure; 1222 | error(message); 1223 | } 1224 | exports.setFailed = setFailed; 1225 | //----------------------------------------------------------------------- 1226 | // Logging Commands 1227 | //----------------------------------------------------------------------- 1228 | /** 1229 | * Writes debug message to user log 1230 | * @param message debug message 1231 | */ 1232 | function debug(message) { 1233 | command_1.issueCommand('debug', {}, message); 1234 | } 1235 | exports.debug = debug; 1236 | /** 1237 | * Adds an error issue 1238 | * @param message error issue message 1239 | */ 1240 | function error(message) { 1241 | command_1.issue('error', message); 1242 | } 1243 | exports.error = error; 1244 | /** 1245 | * Adds an warning issue 1246 | * @param message warning issue message 1247 | */ 1248 | function warning(message) { 1249 | command_1.issue('warning', message); 1250 | } 1251 | exports.warning = warning; 1252 | /** 1253 | * Writes info to log with console.log. 1254 | * @param message info message 1255 | */ 1256 | function info(message) { 1257 | process.stdout.write(message + os.EOL); 1258 | } 1259 | exports.info = info; 1260 | /** 1261 | * Begin an output group. 1262 | * 1263 | * Output until the next `groupEnd` will be foldable in this group 1264 | * 1265 | * @param name The name of the output group 1266 | */ 1267 | function startGroup(name) { 1268 | command_1.issue('group', name); 1269 | } 1270 | exports.startGroup = startGroup; 1271 | /** 1272 | * End an output group. 1273 | */ 1274 | function endGroup() { 1275 | command_1.issue('endgroup'); 1276 | } 1277 | exports.endGroup = endGroup; 1278 | /** 1279 | * Wrap an asynchronous function call in a group. 1280 | * 1281 | * Returns the same type as the function itself. 1282 | * 1283 | * @param name The name of the group 1284 | * @param fn The function to wrap in the group 1285 | */ 1286 | function group(name, fn) { 1287 | return __awaiter(this, void 0, void 0, function* () { 1288 | startGroup(name); 1289 | let result; 1290 | try { 1291 | result = yield fn(); 1292 | } 1293 | finally { 1294 | endGroup(); 1295 | } 1296 | return result; 1297 | }); 1298 | } 1299 | exports.group = group; 1300 | //----------------------------------------------------------------------- 1301 | // Wrapper action state 1302 | //----------------------------------------------------------------------- 1303 | /** 1304 | * Saves state for current action, the state can only be retrieved by this action's post job execution. 1305 | * 1306 | * @param name name of the state to store 1307 | * @param value value to store 1308 | */ 1309 | function saveState(name, value) { 1310 | command_1.issueCommand('save-state', { name }, value); 1311 | } 1312 | exports.saveState = saveState; 1313 | /** 1314 | * Gets the value of an state set by this action's main execution. 1315 | * 1316 | * @param name name of the state to get 1317 | * @returns string 1318 | */ 1319 | function getState(name) { 1320 | return process.env[`STATE_${name}`] || ''; 1321 | } 1322 | exports.getState = getState; 1323 | //# sourceMappingURL=core.js.map 1324 | 1325 | /***/ }), 1326 | 1327 | /***/ 614: 1328 | /***/ (function(module) { 1329 | 1330 | module.exports = require("events"); 1331 | 1332 | /***/ }), 1333 | 1334 | /***/ 622: 1335 | /***/ (function(module) { 1336 | 1337 | module.exports = require("path"); 1338 | 1339 | /***/ }), 1340 | 1341 | /***/ 669: 1342 | /***/ (function(module) { 1343 | 1344 | module.exports = require("util"); 1345 | 1346 | /***/ }), 1347 | 1348 | /***/ 672: 1349 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 1350 | 1351 | "use strict"; 1352 | 1353 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 1354 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 1355 | return new (P || (P = Promise))(function (resolve, reject) { 1356 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 1357 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 1358 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 1359 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 1360 | }); 1361 | }; 1362 | var _a; 1363 | Object.defineProperty(exports, "__esModule", { value: true }); 1364 | const assert_1 = __webpack_require__(357); 1365 | const fs = __webpack_require__(747); 1366 | const path = __webpack_require__(622); 1367 | _a = fs.promises, exports.chmod = _a.chmod, exports.copyFile = _a.copyFile, exports.lstat = _a.lstat, exports.mkdir = _a.mkdir, exports.readdir = _a.readdir, exports.readlink = _a.readlink, exports.rename = _a.rename, exports.rmdir = _a.rmdir, exports.stat = _a.stat, exports.symlink = _a.symlink, exports.unlink = _a.unlink; 1368 | exports.IS_WINDOWS = process.platform === 'win32'; 1369 | function exists(fsPath) { 1370 | return __awaiter(this, void 0, void 0, function* () { 1371 | try { 1372 | yield exports.stat(fsPath); 1373 | } 1374 | catch (err) { 1375 | if (err.code === 'ENOENT') { 1376 | return false; 1377 | } 1378 | throw err; 1379 | } 1380 | return true; 1381 | }); 1382 | } 1383 | exports.exists = exists; 1384 | function isDirectory(fsPath, useStat = false) { 1385 | return __awaiter(this, void 0, void 0, function* () { 1386 | const stats = useStat ? yield exports.stat(fsPath) : yield exports.lstat(fsPath); 1387 | return stats.isDirectory(); 1388 | }); 1389 | } 1390 | exports.isDirectory = isDirectory; 1391 | /** 1392 | * On OSX/Linux, true if path starts with '/'. On Windows, true for paths like: 1393 | * \, \hello, \\hello\share, C:, and C:\hello (and corresponding alternate separator cases). 1394 | */ 1395 | function isRooted(p) { 1396 | p = normalizeSeparators(p); 1397 | if (!p) { 1398 | throw new Error('isRooted() parameter "p" cannot be empty'); 1399 | } 1400 | if (exports.IS_WINDOWS) { 1401 | return (p.startsWith('\\') || /^[A-Z]:/i.test(p) // e.g. \ or \hello or \\hello 1402 | ); // e.g. C: or C:\hello 1403 | } 1404 | return p.startsWith('/'); 1405 | } 1406 | exports.isRooted = isRooted; 1407 | /** 1408 | * Recursively create a directory at `fsPath`. 1409 | * 1410 | * This implementation is optimistic, meaning it attempts to create the full 1411 | * path first, and backs up the path stack from there. 1412 | * 1413 | * @param fsPath The path to create 1414 | * @param maxDepth The maximum recursion depth 1415 | * @param depth The current recursion depth 1416 | */ 1417 | function mkdirP(fsPath, maxDepth = 1000, depth = 1) { 1418 | return __awaiter(this, void 0, void 0, function* () { 1419 | assert_1.ok(fsPath, 'a path argument must be provided'); 1420 | fsPath = path.resolve(fsPath); 1421 | if (depth >= maxDepth) 1422 | return exports.mkdir(fsPath); 1423 | try { 1424 | yield exports.mkdir(fsPath); 1425 | return; 1426 | } 1427 | catch (err) { 1428 | switch (err.code) { 1429 | case 'ENOENT': { 1430 | yield mkdirP(path.dirname(fsPath), maxDepth, depth + 1); 1431 | yield exports.mkdir(fsPath); 1432 | return; 1433 | } 1434 | default: { 1435 | let stats; 1436 | try { 1437 | stats = yield exports.stat(fsPath); 1438 | } 1439 | catch (err2) { 1440 | throw err; 1441 | } 1442 | if (!stats.isDirectory()) 1443 | throw err; 1444 | } 1445 | } 1446 | } 1447 | }); 1448 | } 1449 | exports.mkdirP = mkdirP; 1450 | /** 1451 | * Best effort attempt to determine whether a file exists and is executable. 1452 | * @param filePath file path to check 1453 | * @param extensions additional file extensions to try 1454 | * @return if file exists and is executable, returns the file path. otherwise empty string. 1455 | */ 1456 | function tryGetExecutablePath(filePath, extensions) { 1457 | return __awaiter(this, void 0, void 0, function* () { 1458 | let stats = undefined; 1459 | try { 1460 | // test file exists 1461 | stats = yield exports.stat(filePath); 1462 | } 1463 | catch (err) { 1464 | if (err.code !== 'ENOENT') { 1465 | // eslint-disable-next-line no-console 1466 | console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); 1467 | } 1468 | } 1469 | if (stats && stats.isFile()) { 1470 | if (exports.IS_WINDOWS) { 1471 | // on Windows, test for valid extension 1472 | const upperExt = path.extname(filePath).toUpperCase(); 1473 | if (extensions.some(validExt => validExt.toUpperCase() === upperExt)) { 1474 | return filePath; 1475 | } 1476 | } 1477 | else { 1478 | if (isUnixExecutable(stats)) { 1479 | return filePath; 1480 | } 1481 | } 1482 | } 1483 | // try each extension 1484 | const originalFilePath = filePath; 1485 | for (const extension of extensions) { 1486 | filePath = originalFilePath + extension; 1487 | stats = undefined; 1488 | try { 1489 | stats = yield exports.stat(filePath); 1490 | } 1491 | catch (err) { 1492 | if (err.code !== 'ENOENT') { 1493 | // eslint-disable-next-line no-console 1494 | console.log(`Unexpected error attempting to determine if executable file exists '${filePath}': ${err}`); 1495 | } 1496 | } 1497 | if (stats && stats.isFile()) { 1498 | if (exports.IS_WINDOWS) { 1499 | // preserve the case of the actual file (since an extension was appended) 1500 | try { 1501 | const directory = path.dirname(filePath); 1502 | const upperName = path.basename(filePath).toUpperCase(); 1503 | for (const actualName of yield exports.readdir(directory)) { 1504 | if (upperName === actualName.toUpperCase()) { 1505 | filePath = path.join(directory, actualName); 1506 | break; 1507 | } 1508 | } 1509 | } 1510 | catch (err) { 1511 | // eslint-disable-next-line no-console 1512 | console.log(`Unexpected error attempting to determine the actual case of the file '${filePath}': ${err}`); 1513 | } 1514 | return filePath; 1515 | } 1516 | else { 1517 | if (isUnixExecutable(stats)) { 1518 | return filePath; 1519 | } 1520 | } 1521 | } 1522 | } 1523 | return ''; 1524 | }); 1525 | } 1526 | exports.tryGetExecutablePath = tryGetExecutablePath; 1527 | function normalizeSeparators(p) { 1528 | p = p || ''; 1529 | if (exports.IS_WINDOWS) { 1530 | // convert slashes on Windows 1531 | p = p.replace(/\//g, '\\'); 1532 | // remove redundant slashes 1533 | return p.replace(/\\\\+/g, '\\'); 1534 | } 1535 | // remove redundant slashes 1536 | return p.replace(/\/\/+/g, '/'); 1537 | } 1538 | // on Mac/Linux, test the execute bit 1539 | // R W X R W X R W X 1540 | // 256 128 64 32 16 8 4 2 1 1541 | function isUnixExecutable(stats) { 1542 | return ((stats.mode & 1) > 0 || 1543 | ((stats.mode & 8) > 0 && stats.gid === process.getgid()) || 1544 | ((stats.mode & 64) > 0 && stats.uid === process.getuid())); 1545 | } 1546 | //# sourceMappingURL=io-util.js.map 1547 | 1548 | /***/ }), 1549 | 1550 | /***/ 747: 1551 | /***/ (function(module) { 1552 | 1553 | module.exports = require("fs"); 1554 | 1555 | /***/ }), 1556 | 1557 | /***/ 986: 1558 | /***/ (function(__unusedmodule, exports, __webpack_require__) { 1559 | 1560 | "use strict"; 1561 | 1562 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 1563 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 1564 | return new (P || (P = Promise))(function (resolve, reject) { 1565 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 1566 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 1567 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 1568 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 1569 | }); 1570 | }; 1571 | var __importStar = (this && this.__importStar) || function (mod) { 1572 | if (mod && mod.__esModule) return mod; 1573 | var result = {}; 1574 | if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; 1575 | result["default"] = mod; 1576 | return result; 1577 | }; 1578 | Object.defineProperty(exports, "__esModule", { value: true }); 1579 | const tr = __importStar(__webpack_require__(9)); 1580 | /** 1581 | * Exec a command. 1582 | * Output will be streamed to the live console. 1583 | * Returns promise with return code 1584 | * 1585 | * @param commandLine command to execute (can include additional args). Must be correctly escaped. 1586 | * @param args optional arguments for tool. Escaping is handled by the lib. 1587 | * @param options optional exec options. See ExecOptions 1588 | * @returns Promise exit code 1589 | */ 1590 | function exec(commandLine, args, options) { 1591 | return __awaiter(this, void 0, void 0, function* () { 1592 | const commandArgs = tr.argStringToArray(commandLine); 1593 | if (commandArgs.length === 0) { 1594 | throw new Error(`Parameter 'commandLine' cannot be null or empty.`); 1595 | } 1596 | // Path to tool to execute should be first arg 1597 | const toolPath = commandArgs[0]; 1598 | args = commandArgs.slice(1).concat(args || []); 1599 | const runner = new tr.ToolRunner(toolPath, args, options); 1600 | return runner.exec(); 1601 | }); 1602 | } 1603 | exports.exec = exec; 1604 | //# sourceMappingURL=exec.js.map 1605 | 1606 | /***/ }) 1607 | 1608 | /******/ }); -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | clearMocks: true, 3 | moduleFileExtensions: ['js', 'ts'], 4 | testEnvironment: 'node', 5 | testMatch: ['**/*.test.ts'], 6 | testRunner: 'jest-circus/runner', 7 | transform: { 8 | '^.+\\.ts$': 'ts-jest' 9 | }, 10 | verbose: true 11 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "setup-mamba", 3 | "version": "0.0.0", 4 | "private": true, 5 | "description": "GitHub action to setup mamba", 6 | "main": "lib/main.js", 7 | "scripts": { 8 | "build": "tsc", 9 | "format": "prettier --write **/*.ts", 10 | "format-check": "prettier --check **/*.ts", 11 | "lint": "eslint src/**/*.ts", 12 | "pack": "ncc build", 13 | "test": "jest", 14 | "all": "npm run build && npm run format && npm run lint && npm run pack && npm test" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/TheSnakePit/setup-mamba.git" 19 | }, 20 | "keywords": [ 21 | "actions", 22 | "node", 23 | "setup" 24 | ], 25 | "author": "TheSnakePit", 26 | "license": "MIT", 27 | "dependencies": { 28 | "@actions/core": "^1.2.0", 29 | "@actions/exec": "^1.0.4" 30 | }, 31 | "devDependencies": { 32 | "@types/jest": "^24.0.23", 33 | "@types/node": "^12.7.12", 34 | "@typescript-eslint/parser": "^2.8.0", 35 | "@zeit/ncc": "^0.20.5", 36 | "eslint": "^5.16.0", 37 | "eslint-plugin-github": "^2.0.0", 38 | "eslint-plugin-jest": "^22.21.0", 39 | "jest": "^24.9.0", 40 | "jest-circus": "^24.9.0", 41 | "js-yaml": "^3.13.1", 42 | "prettier": "^1.19.1", 43 | "ts-jest": "^24.2.0", 44 | "typescript": "^3.6.4" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import * as path from 'path' 2 | 3 | import * as core from '@actions/core' 4 | 5 | import * as exec from '@actions/exec' 6 | 7 | async function fixPermissions(os: string): Promise { 8 | if (os === 'darwin') { 9 | const username = process.env.USER 10 | await exec.exec('sudo', [ 11 | 'chown', 12 | '-R', 13 | `${username}:staff`, 14 | process.env.CONDA as string 15 | ]) 16 | } 17 | } 18 | 19 | async function addPath(os: string): Promise { 20 | const basePath = process.env.CONDA as string 21 | if (os === 'darwin') { 22 | const bin = path.join(basePath, 'condabin') 23 | core.addPath(bin) 24 | } else if (os === 'win32') { 25 | const bin = path.join(basePath, 'Scripts') 26 | core.addPath(bin) 27 | } else { 28 | const bin = path.join(basePath, 'bin') 29 | core.addPath(bin) 30 | } 31 | } 32 | 33 | async function installMamba(): Promise { 34 | await exec.exec('conda', ['install', '-y', '-c', 'conda-forge', 'mamba']) 35 | } 36 | 37 | async function run(): Promise { 38 | try { 39 | const os = process.platform 40 | 41 | core.debug('Fix permissions') 42 | fixPermissions(os) 43 | 44 | core.debug('Add conda to the path') 45 | await addPath(os) 46 | 47 | core.debug('Installing mamba') 48 | await installMamba() 49 | } catch (error) { 50 | core.setFailed(error.message) 51 | } 52 | } 53 | 54 | run() 55 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ 4 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 5 | "outDir": "./lib", /* Redirect output structure to the directory. */ 6 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 7 | "strict": true, /* Enable all strict type-checking options. */ 8 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 9 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 10 | }, 11 | "exclude": ["node_modules", "**/*.test.ts"] 12 | } 13 | --------------------------------------------------------------------------------