From 6801cd626b2bec1f747c183a8d4a3fd87a6f83e8 Mon Sep 17 00:00:00 2001 From: Pavel Zwerschke Date: Tue, 5 Dec 2023 11:31:50 +0100 Subject: [PATCH] Add download-micromamba --- .github/workflows/test.yml | 36 +++++ README.md | 34 ++++- action.yml | 3 + dist/index.js | 299 +++++++++++++++++++++++++++++++++++-- dist/post.js | 295 ++++++++++++++++++++++++++++++++++-- package.json | 2 + pnpm-lock.yaml | 23 +++ src/main.ts | 8 +- src/options.ts | 13 +- src/post.ts | 4 + tsup.config.js | 3 +- 11 files changed, 683 insertions(+), 37 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index aefe85b..4a5754b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -287,6 +287,42 @@ jobs: which micromamba-shell | grep /home/runner/micromamba-bin/micromamba-shell shell: bash -el {0} + use-micromamba-from-path: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Download micromamba + run: | + curl -Ls https://github.com/mamba-org/micromamba-releases/releases/latest/download/micromamba-linux-64 -o /usr/local/bin/micromamba + chmod +x /usr/local/bin/micromamba + which micromamba + - uses: ./ + with: + environment-file: test/environment.yml + download-micromamba: false + - run: | + micromamba info | grep -q "environment : env-name" + shell: bash -elo pipefail {0} + + no-download-with-custom-path: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Download micromamba + run: | + mkdir -p "$HOME/not-on-path/bin" + curl -Ls https://github.com/mamba-org/micromamba-releases/releases/latest/download/micromamba-linux-64 -o "$HOME/not-on-path/bin/micromamba" + chmod +x "$HOME/not-on-path/bin/micromamba" + - uses: ./ + with: + environment-file: test/environment.yml + download-micromamba: false + micromamba-binary-path: ~/not-on-path/bin/micromamba + - run: | + micromamba info | grep -q "environment : env-name" + which micromamba | grep not-on-path/bin + shell: bash -elo pipefail {0} + # not properly testable # https://github.com/actions/runner/issues/2347 # https://github.com/orgs/community/discussions/15452 diff --git a/README.md b/README.md index af664e2..c516341 100644 --- a/README.md +++ b/README.md @@ -257,13 +257,17 @@ This can be specified by setting the `log-level` input. If nothing is specified, `setup-micromamba` will default to `warning` or `debug` depending on if [debug logging is enabled for the action](#debug-logging-of-the-action). -### Post action cleanup +### Self-hosted runners -On self hosted runners, it may happen that some files are persisted between jobs. +On self-hosted runners, it may happen that some files are persisted between jobs. This can lead to problems when the next job is run. -To avoid this, you can use the `post-cleanup` input to specify the post cleanup behavior of the action (i.e., what happens _after_ all your commands have been executed). + +#### Post-action cleanup + +To avoid persistence between jobs, you can use the `post-cleanup` input to specify the post cleanup behavior of the action (i.e., what happens _after_ all your commands have been executed). There is a total of 4 options: + - `none`: No cleanup is performed. - `shell-init`: The shell initialization files are removed by executing `micromamba shell deinit -s `. - `environment`: Shell initialization files and the installed environment are removed. @@ -278,6 +282,30 @@ If nothing is specified, `setup-micromamba` will default to `shell-init`. post-cleanup: environment ``` +#### Specify the path of the micromamba binary + +You also might want to alter the default micromamba installation location to a temporary location. You can use `micromamba-binary-path: ${{ runner.temp }}/bin/micromamba` to do this. + +```yml +- uses: mamba-org/setup-micromamba@v1 + with: + environment-file: environment.yml + # ${{ runner.temp }}\Scripts\micromamba.exe on Windows + micromamba-binary-path: ${{ runner.temp }}/bin/micromamba +``` + +You can also use a pre-installed micromamba binary by setting `micromamba-binary-path` to the path of the binary and specifying `download-micromamba: false`. + +```yml +- uses: mamba-org/setup-micromamba@v1 + with: + environment-file: environment.yml + download-micromamba: false + # you don't need to specify this if micromamba is already on PATH + micromamba-binary-path: /usr/local/bin/micromamba + generate-run-shell: false # this would generate a file next to the micromamba binary +``` + ## More examples If you want to see more examples, you can take a look at the [GitHub Workflows of this repository](.github/workflows/). diff --git a/action.yml b/action.yml index 8b598bf..753a38c 100644 --- a/action.yml +++ b/action.yml @@ -41,6 +41,9 @@ inputs: micromamba-url: description: | URL to download micromamba from. + download-micromamba: + description: | + If you already have micromamba installed, you can set this to `false`. init-shell: description: | Which shells to initialize micromamba in. diff --git a/dist/index.js b/dist/index.js index e5d2023..1319102 100644 --- a/dist/index.js +++ b/dist/index.js @@ -2567,13 +2567,13 @@ var require_io = __commonJS({ }); } exports.mkdirP = mkdirP; - function which2(tool, check) { + function which3(tool, check) { return __awaiter(this, void 0, void 0, function* () { if (!tool) { throw new Error("parameter 'tool' is required"); } if (check) { - const result = yield which2(tool, false); + const result = yield which3(tool, false); if (!result) { if (ioUtil.IS_WINDOWS) { 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.`); @@ -2590,7 +2590,7 @@ var require_io = __commonJS({ return ""; }); } - exports.which = which2; + exports.which = which3; function findInPath(tool) { return __awaiter(this, void 0, void 0, function* () { if (!tool) { @@ -7009,6 +7009,262 @@ var require_Either = __commonJS({ } }); +// node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/posix.js +var require_posix = __commonJS({ + "node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/posix.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.sync = exports.isexe = void 0; + var fs_1 = require("fs"); + var promises_1 = require("fs/promises"); + var isexe = async (path5, options2 = {}) => { + const { ignoreErrors = false } = options2; + try { + return checkStat(await (0, promises_1.stat)(path5), options2); + } catch (e) { + const er = e; + if (ignoreErrors || er.code === "EACCES") + return false; + throw er; + } + }; + exports.isexe = isexe; + var sync = (path5, options2 = {}) => { + const { ignoreErrors = false } = options2; + try { + return checkStat((0, fs_1.statSync)(path5), options2); + } catch (e) { + const er = e; + if (ignoreErrors || er.code === "EACCES") + return false; + throw er; + } + }; + exports.sync = sync; + var checkStat = (stat2, options2) => stat2.isFile() && checkMode(stat2, options2); + var checkMode = (stat2, options2) => { + const myUid = options2.uid ?? process.getuid?.(); + const myGroups = options2.groups ?? process.getgroups?.() ?? []; + const myGid = options2.gid ?? process.getgid?.() ?? myGroups[0]; + if (myUid === void 0 || myGid === void 0) { + throw new Error("cannot get uid or gid"); + } + const groups = /* @__PURE__ */ new Set([myGid, ...myGroups]); + const mod = stat2.mode; + const uid = stat2.uid; + const gid = stat2.gid; + const u = parseInt("100", 8); + const g = parseInt("010", 8); + const o = parseInt("001", 8); + const ug = u | g; + return !!(mod & o || mod & g && groups.has(gid) || mod & u && uid === myUid || mod & ug && myUid === 0); + }; + } +}); + +// node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/win32.js +var require_win32 = __commonJS({ + "node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/win32.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.sync = exports.isexe = void 0; + var fs_1 = require("fs"); + var promises_1 = require("fs/promises"); + var isexe = async (path5, options2 = {}) => { + const { ignoreErrors = false } = options2; + try { + return checkStat(await (0, promises_1.stat)(path5), path5, options2); + } catch (e) { + const er = e; + if (ignoreErrors || er.code === "EACCES") + return false; + throw er; + } + }; + exports.isexe = isexe; + var sync = (path5, options2 = {}) => { + const { ignoreErrors = false } = options2; + try { + return checkStat((0, fs_1.statSync)(path5), path5, options2); + } catch (e) { + const er = e; + if (ignoreErrors || er.code === "EACCES") + return false; + throw er; + } + }; + exports.sync = sync; + var checkPathExt = (path5, options2) => { + const { pathExt = process.env.PATHEXT || "" } = options2; + const peSplit = pathExt.split(";"); + if (peSplit.indexOf("") !== -1) { + return true; + } + for (let i = 0; i < peSplit.length; i++) { + const p = peSplit[i].toLowerCase(); + const ext = path5.substring(path5.length - p.length).toLowerCase(); + if (p && ext === p) { + return true; + } + } + return false; + }; + var checkStat = (stat2, path5, options2) => stat2.isFile() && checkPathExt(path5, options2); + } +}); + +// node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/options.js +var require_options = __commonJS({ + "node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/options.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + } +}); + +// node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/index.js +var require_cjs = __commonJS({ + "node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/index.js"(exports) { + "use strict"; + var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) { + if (k2 === void 0) + k2 = 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 === void 0) + k2 = k; + o[k2] = m[k]; + }); + var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } : function(o, v) { + o["default"] = v; + }); + var __importStar = exports && exports.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + 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; + }; + var __exportStar = exports && exports.__exportStar || function(m, exports2) { + for (var p in m) + if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) + __createBinding(exports2, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.sync = exports.isexe = exports.posix = exports.win32 = void 0; + var posix = __importStar(require_posix()); + exports.posix = posix; + var win32 = __importStar(require_win32()); + exports.win32 = win32; + __exportStar(require_options(), exports); + var platform4 = process.env._ISEXE_TEST_PLATFORM_ || process.platform; + var impl = platform4 === "win32" ? win32 : posix; + exports.isexe = impl.isexe; + exports.sync = impl.sync; + } +}); + +// node_modules/.pnpm/which@4.0.0/node_modules/which/lib/index.js +var require_lib2 = __commonJS({ + "node_modules/.pnpm/which@4.0.0/node_modules/which/lib/index.js"(exports, module2) { + "use strict"; + var { isexe, sync: isexeSync } = require_cjs(); + var { join: join2, delimiter: delimiter2, sep, posix } = require("path"); + var isWindows = process.platform === "win32"; + var rSlash = new RegExp(`[${posix.sep}${sep === posix.sep ? "" : sep}]`.replace(/(\\)/g, "\\$1")); + var rRel = new RegExp(`^\\.${rSlash.source}`); + var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" }); + var getPathInfo = (cmd, { + path: optPath = process.env.PATH, + pathExt: optPathExt = process.env.PATHEXT, + delimiter: optDelimiter = delimiter2 + }) => { + const pathEnv = cmd.match(rSlash) ? [""] : [ + // windows always checks the cwd first + ...isWindows ? [process.cwd()] : [], + ...(optPath || /* istanbul ignore next: very unusual */ + "").split(optDelimiter) + ]; + if (isWindows) { + const pathExtExe = optPathExt || [".EXE", ".CMD", ".BAT", ".COM"].join(optDelimiter); + const pathExt = pathExtExe.split(optDelimiter).flatMap((item) => [item, item.toLowerCase()]); + if (cmd.includes(".") && pathExt[0] !== "") { + pathExt.unshift(""); + } + return { pathEnv, pathExt, pathExtExe }; + } + return { pathEnv, pathExt: [""] }; + }; + var getPathPart = (raw, cmd) => { + const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw; + const prefix2 = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : ""; + return prefix2 + join2(pathPart, cmd); + }; + var which3 = async (cmd, opt = {}) => { + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt); + const found = []; + for (const envPart of pathEnv) { + const p = getPathPart(envPart, cmd); + for (const ext of pathExt) { + const withExt = p + ext; + const is = await isexe(withExt, { pathExt: pathExtExe, ignoreErrors: true }); + if (is) { + if (!opt.all) { + return withExt; + } + found.push(withExt); + } + } + } + if (opt.all && found.length) { + return found; + } + if (opt.nothrow) { + return null; + } + throw getNotFoundError(cmd); + }; + var whichSync = (cmd, opt = {}) => { + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt); + const found = []; + for (const pathEnvPart of pathEnv) { + const p = getPathPart(pathEnvPart, cmd); + for (const ext of pathExt) { + const withExt = p + ext; + const is = isexeSync(withExt, { pathExt: pathExtExe, ignoreErrors: true }); + if (is) { + if (!opt.all) { + return withExt; + } + found.push(withExt); + } + } + } + if (opt.all && found.length) { + return found; + } + if (opt.nothrow) { + return null; + } + throw getNotFoundError(cmd); + }; + module2.exports = which3; + which3.sync = whichSync; + } +}); + // node_modules/.pnpm/@actions+glob@0.1.2/node_modules/@actions/glob/lib/internal-glob-options-helper.js var require_internal_glob_options_helper = __commonJS({ "node_modules/.pnpm/@actions+glob@0.1.2/node_modules/@actions/glob/lib/internal-glob-options-helper.js"(exports) { @@ -25981,7 +26237,7 @@ var require_undici = __commonJS({ }); // node_modules/.pnpm/@actions+http-client@2.2.0/node_modules/@actions/http-client/lib/index.js -var require_lib2 = __commonJS({ +var require_lib3 = __commonJS({ "node_modules/.pnpm/@actions+http-client@2.2.0/node_modules/@actions/http-client/lib/index.js"(exports) { "use strict"; var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) { @@ -38484,7 +38740,7 @@ var init_log2 = __esm({ }); // node_modules/.pnpm/webidl-conversions@3.0.1/node_modules/webidl-conversions/lib/index.js -var require_lib3 = __commonJS({ +var require_lib4 = __commonJS({ "node_modules/.pnpm/webidl-conversions@3.0.1/node_modules/webidl-conversions/lib/index.js"(exports, module2) { "use strict"; var conversions = {}; @@ -40063,7 +40319,7 @@ var require_URL_impl = __commonJS({ var require_URL = __commonJS({ "node_modules/.pnpm/whatwg-url@5.0.0/node_modules/whatwg-url/lib/URL.js"(exports, module2) { "use strict"; - var conversions = require_lib3(); + var conversions = require_lib4(); var utils = require_utils3(); var Impl = require_URL_impl(); var impl = utils.implSymbol; @@ -45818,7 +46074,7 @@ var require_XMLStreamWriter = __commonJS({ }); // node_modules/.pnpm/xmlbuilder@11.0.1/node_modules/xmlbuilder/lib/index.js -var require_lib4 = __commonJS({ +var require_lib5 = __commonJS({ "node_modules/.pnpm/xmlbuilder@11.0.1/node_modules/xmlbuilder/lib/index.js"(exports, module2) { "use strict"; (function() { @@ -45879,7 +46135,7 @@ var require_builder = __commonJS({ (function() { "use strict"; var builder, defaults, escapeCDATA, requiresCDATA, wrapCDATA, hasProp = {}.hasOwnProperty; - builder = require_lib4(); + builder = require_lib5(); defaults = require_defaults().defaults; requiresCDATA = function(entry) { return typeof entry === "string" && (entry.indexOf("&") >= 0 || entry.indexOf(">") >= 0 || entry.indexOf("<") >= 0); @@ -75362,7 +75618,7 @@ var require_requestUtils = __commonJS({ Object.defineProperty(exports, "__esModule", { value: true }); exports.retryHttpClientResponse = exports.retryTypedResponse = exports.retry = exports.isRetryableStatusCode = exports.isServerErrorStatusCode = exports.isSuccessStatusCode = void 0; var core7 = __importStar(require_core()); - var http_client_1 = require_lib2(); + var http_client_1 = require_lib3(); var constants_1 = require_constants(); function isSuccessStatusCode(statusCode) { if (!statusCode) { @@ -75535,7 +75791,7 @@ var require_downloadUtils = __commonJS({ Object.defineProperty(exports, "__esModule", { value: true }); exports.downloadCacheStorageSDK = exports.downloadCacheHttpClientConcurrent = exports.downloadCacheHttpClient = exports.DownloadProgress = void 0; var core7 = __importStar(require_core()); - var http_client_1 = require_lib2(); + var http_client_1 = require_lib3(); var storage_blob_1 = (init_src12(), __toCommonJS(src_exports3)); var buffer = __importStar(require("buffer")); var fs6 = __importStar(require("fs")); @@ -75835,7 +76091,7 @@ var require_downloadUtils = __commonJS({ }); // node_modules/.pnpm/@actions+cache@3.2.2/node_modules/@actions/cache/lib/options.js -var require_options = __commonJS({ +var require_options2 = __commonJS({ "node_modules/.pnpm/@actions+cache@3.2.2/node_modules/@actions/cache/lib/options.js"(exports) { "use strict"; var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) { @@ -76002,14 +76258,14 @@ var require_cacheHttpClient = __commonJS({ Object.defineProperty(exports, "__esModule", { value: true }); exports.saveCache = exports.reserveCache = exports.downloadCache = exports.getCacheEntry = exports.getCacheVersion = void 0; var core7 = __importStar(require_core()); - var http_client_1 = require_lib2(); + var http_client_1 = require_lib3(); var auth_1 = require_auth2(); var crypto4 = __importStar(require("crypto")); var fs6 = __importStar(require("fs")); var url_1 = require("url"); var utils = __importStar(require_cacheUtils()); var downloadUtils_1 = require_downloadUtils(); - var options_1 = require_options(); + var options_1 = require_options2(); var requestUtils_1 = require_requestUtils(); var versionSalt = "1.0"; function getCacheApiUrl(resource) { @@ -76685,7 +76941,6 @@ var require_cache2 = __commonJS({ // src/main.ts var import_promises = __toESM(require("fs/promises")); -var import_fs = require("fs"); var import_os2 = __toESM(require("os")); var import_path3 = __toESM(require("path")); var import_process2 = require("process"); @@ -83148,6 +83403,7 @@ function untildify(pathWithTilde) { } // src/options.ts +var import_which = __toESM(require_lib2()); var core2 = process.env.MOCKING ? coreMocked : coreDefault; var PATHS = { micromambaBin: path.join(os2.homedir(), "micromamba-bin", `micromamba${os2.platform() === "win32" ? ".exe" : ""}`), @@ -83192,7 +83448,8 @@ var inferOptions = (inputs) => { const micromambaSource = inputs.micromambaUrl ? (0, import_Either.right)(inputs.micromambaUrl) : (0, import_Either.left)(inputs.micromambaVersion || "latest"); const writeToCondarc = inputs.condarcFile === void 0; const initShell = !inputs.initShell ? ["bash"] : inputs.initShell.includes("none") ? [] : inputs.initShell; - const micromambaBinPath = inputs.micromambaBinPath ? path.resolve(untildify(inputs.micromambaBinPath)) : PATHS.micromambaBin; + const downloadMicromamba2 = inputs.downloadMicromamba !== void 0 ? inputs.downloadMicromamba : true; + const micromambaBinPath = inputs.micromambaBinPath ? path.resolve(untildify(inputs.micromambaBinPath)) : inputs.downloadMicromamba === false ? import_which.default.sync("micromamba") : PATHS.micromambaBin; return { ...inputs, writeToCondarc, @@ -83200,6 +83457,7 @@ var inferOptions = (inputs) => { createArgs: inputs.createArgs || [], logLevel, micromambaSource, + downloadMicromamba: downloadMicromamba2, initShell, generateRunShell: inputs.generateRunShell !== void 0 ? inputs.generateRunShell : createEnvironment2, cacheEnvironmentKey: inputs.cacheEnvironmentKey || (inputs.cacheEnvironment ? `micromamba-environment-` : void 0), @@ -83218,6 +83476,9 @@ var validateInputs = (inputs) => { if (inputs.micromambaUrl && inputs.micromambaVersion) { throw new Error("You must specify either a micromamba URL or a micromamba version, not both."); } + if (inputs.downloadMicromamba === false && (inputs.micromambaUrl || inputs.micromambaVersion)) { + throw new Error("You cannot specify micromamba-url or micromamba-version when download-micromamba is false."); + } if (inputs.generateRunShell && !createEnvironment2) { throw new Error("You must create an environment to use 'generate-run-shell'."); } @@ -83283,6 +83544,7 @@ var getOptions = () => { "micromamba-version must be either `latest` or a version matching `1.2.3-0`." ), micromambaUrl: parseOrUndefined("micromamba-url", stringType().url()), + downloadMicromamba: parseOrUndefinedJSON("download-micromamba", booleanType()), initShell: parseOrUndefinedList("init-shell", shellSchema), generateRunShell: parseOrUndefinedJSON("generate-run-shell", booleanType()), cacheDownloads: parseOrUndefinedJSON("cache-downloads", booleanType()), @@ -83550,6 +83812,11 @@ var restoreCacheDownloads = () => { // src/main.ts var core6 = process.env.MOCKING ? coreMocked : coreDefault5; var downloadMicromamba = (url2) => { + if (options.downloadMicromamba === false) { + core6.info("Skipping micromamba download."); + core6.addPath(import_path3.default.dirname(options.micromambaBinPath)); + return Promise.resolve(); + } core6.startGroup("Install micromamba"); core6.debug(`Downloading micromamba from ${url2} ...`); return import_promises.default.mkdir(import_path3.default.dirname(options.micromambaBinPath), { recursive: true }).then(() => (0, import_tool_cache.downloadTool)(url2, options.micromambaBinPath)).then((_downloadPath) => import_promises.default.chmod(options.micromambaBinPath, 493)).then(() => core6.addPath(import_path3.default.dirname(options.micromambaBinPath))).then(() => core6.info(`micromamba installed to ${options.micromambaBinPath}`)).catch((err) => { @@ -83560,7 +83827,7 @@ var downloadMicromamba = (url2) => { var generateCondarc = () => { if (!options.writeToCondarc) { core6.debug(`Using condarc file ${options.condarcFile} ...`); - return import_promises.default.access(options.condarcFile, import_fs.constants.R_OK); + return import_promises.default.access(options.condarcFile, import_promises.default.constants.R_OK); } core6.debug(`Using ${options.condarcFile} as condarc file.`); const mkDir = import_promises.default.mkdir(import_path3.default.dirname(options.condarcFile), { recursive: true }); diff --git a/dist/post.js b/dist/post.js index 77c21c7..b83103f 100644 --- a/dist/post.js +++ b/dist/post.js @@ -3975,6 +3975,262 @@ var require_Either = __commonJS({ } }); +// node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/posix.js +var require_posix = __commonJS({ + "node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/posix.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.sync = exports.isexe = void 0; + var fs_1 = require("fs"); + var promises_1 = require("fs/promises"); + var isexe = async (path5, options2 = {}) => { + const { ignoreErrors = false } = options2; + try { + return checkStat(await (0, promises_1.stat)(path5), options2); + } catch (e) { + const er = e; + if (ignoreErrors || er.code === "EACCES") + return false; + throw er; + } + }; + exports.isexe = isexe; + var sync = (path5, options2 = {}) => { + const { ignoreErrors = false } = options2; + try { + return checkStat((0, fs_1.statSync)(path5), options2); + } catch (e) { + const er = e; + if (ignoreErrors || er.code === "EACCES") + return false; + throw er; + } + }; + exports.sync = sync; + var checkStat = (stat2, options2) => stat2.isFile() && checkMode(stat2, options2); + var checkMode = (stat2, options2) => { + const myUid = options2.uid ?? process.getuid?.(); + const myGroups = options2.groups ?? process.getgroups?.() ?? []; + const myGid = options2.gid ?? process.getgid?.() ?? myGroups[0]; + if (myUid === void 0 || myGid === void 0) { + throw new Error("cannot get uid or gid"); + } + const groups = /* @__PURE__ */ new Set([myGid, ...myGroups]); + const mod = stat2.mode; + const uid = stat2.uid; + const gid = stat2.gid; + const u = parseInt("100", 8); + const g = parseInt("010", 8); + const o = parseInt("001", 8); + const ug = u | g; + return !!(mod & o || mod & g && groups.has(gid) || mod & u && uid === myUid || mod & ug && myUid === 0); + }; + } +}); + +// node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/win32.js +var require_win32 = __commonJS({ + "node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/win32.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.sync = exports.isexe = void 0; + var fs_1 = require("fs"); + var promises_1 = require("fs/promises"); + var isexe = async (path5, options2 = {}) => { + const { ignoreErrors = false } = options2; + try { + return checkStat(await (0, promises_1.stat)(path5), path5, options2); + } catch (e) { + const er = e; + if (ignoreErrors || er.code === "EACCES") + return false; + throw er; + } + }; + exports.isexe = isexe; + var sync = (path5, options2 = {}) => { + const { ignoreErrors = false } = options2; + try { + return checkStat((0, fs_1.statSync)(path5), path5, options2); + } catch (e) { + const er = e; + if (ignoreErrors || er.code === "EACCES") + return false; + throw er; + } + }; + exports.sync = sync; + var checkPathExt = (path5, options2) => { + const { pathExt = process.env.PATHEXT || "" } = options2; + const peSplit = pathExt.split(";"); + if (peSplit.indexOf("") !== -1) { + return true; + } + for (let i = 0; i < peSplit.length; i++) { + const p = peSplit[i].toLowerCase(); + const ext = path5.substring(path5.length - p.length).toLowerCase(); + if (p && ext === p) { + return true; + } + } + return false; + }; + var checkStat = (stat2, path5, options2) => stat2.isFile() && checkPathExt(path5, options2); + } +}); + +// node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/options.js +var require_options = __commonJS({ + "node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/options.js"(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + } +}); + +// node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/index.js +var require_cjs = __commonJS({ + "node_modules/.pnpm/isexe@3.1.1/node_modules/isexe/dist/cjs/index.js"(exports) { + "use strict"; + var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) { + if (k2 === void 0) + k2 = 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 === void 0) + k2 = k; + o[k2] = m[k]; + }); + var __setModuleDefault = exports && exports.__setModuleDefault || (Object.create ? function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); + } : function(o, v) { + o["default"] = v; + }); + var __importStar = exports && exports.__importStar || function(mod) { + if (mod && mod.__esModule) + return mod; + var result = {}; + 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; + }; + var __exportStar = exports && exports.__exportStar || function(m, exports2) { + for (var p in m) + if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) + __createBinding(exports2, m, p); + }; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.sync = exports.isexe = exports.posix = exports.win32 = void 0; + var posix = __importStar(require_posix()); + exports.posix = posix; + var win32 = __importStar(require_win32()); + exports.win32 = win32; + __exportStar(require_options(), exports); + var platform5 = process.env._ISEXE_TEST_PLATFORM_ || process.platform; + var impl = platform5 === "win32" ? win32 : posix; + exports.isexe = impl.isexe; + exports.sync = impl.sync; + } +}); + +// node_modules/.pnpm/which@4.0.0/node_modules/which/lib/index.js +var require_lib2 = __commonJS({ + "node_modules/.pnpm/which@4.0.0/node_modules/which/lib/index.js"(exports, module2) { + "use strict"; + var { isexe, sync: isexeSync } = require_cjs(); + var { join: join2, delimiter: delimiter2, sep, posix } = require("path"); + var isWindows = process.platform === "win32"; + var rSlash = new RegExp(`[${posix.sep}${sep === posix.sep ? "" : sep}]`.replace(/(\\)/g, "\\$1")); + var rRel = new RegExp(`^\\.${rSlash.source}`); + var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" }); + var getPathInfo = (cmd, { + path: optPath = process.env.PATH, + pathExt: optPathExt = process.env.PATHEXT, + delimiter: optDelimiter = delimiter2 + }) => { + const pathEnv = cmd.match(rSlash) ? [""] : [ + // windows always checks the cwd first + ...isWindows ? [process.cwd()] : [], + ...(optPath || /* istanbul ignore next: very unusual */ + "").split(optDelimiter) + ]; + if (isWindows) { + const pathExtExe = optPathExt || [".EXE", ".CMD", ".BAT", ".COM"].join(optDelimiter); + const pathExt = pathExtExe.split(optDelimiter).flatMap((item) => [item, item.toLowerCase()]); + if (cmd.includes(".") && pathExt[0] !== "") { + pathExt.unshift(""); + } + return { pathEnv, pathExt, pathExtExe }; + } + return { pathEnv, pathExt: [""] }; + }; + var getPathPart = (raw, cmd) => { + const pathPart = /^".*"$/.test(raw) ? raw.slice(1, -1) : raw; + const prefix2 = !pathPart && rRel.test(cmd) ? cmd.slice(0, 2) : ""; + return prefix2 + join2(pathPart, cmd); + }; + var which2 = async (cmd, opt = {}) => { + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt); + const found = []; + for (const envPart of pathEnv) { + const p = getPathPart(envPart, cmd); + for (const ext of pathExt) { + const withExt = p + ext; + const is = await isexe(withExt, { pathExt: pathExtExe, ignoreErrors: true }); + if (is) { + if (!opt.all) { + return withExt; + } + found.push(withExt); + } + } + } + if (opt.all && found.length) { + return found; + } + if (opt.nothrow) { + return null; + } + throw getNotFoundError(cmd); + }; + var whichSync = (cmd, opt = {}) => { + const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt); + const found = []; + for (const pathEnvPart of pathEnv) { + const p = getPathPart(pathEnvPart, cmd); + for (const ext of pathExt) { + const withExt = p + ext; + const is = isexeSync(withExt, { pathExt: pathExtExe, ignoreErrors: true }); + if (is) { + if (!opt.all) { + return withExt; + } + found.push(withExt); + } + } + } + if (opt.all && found.length) { + return found; + } + if (opt.nothrow) { + return null; + } + throw getNotFoundError(cmd); + }; + module2.exports = which2; + which2.sync = whichSync; + } +}); + // node_modules/.pnpm/@actions+io@1.1.3/node_modules/@actions/io/lib/io-util.js var require_io_util = __commonJS({ "node_modules/.pnpm/@actions+io@1.1.3/node_modules/@actions/io/lib/io-util.js"(exports) { @@ -4292,13 +4548,13 @@ var require_io = __commonJS({ }); } exports.mkdirP = mkdirP; - function which(tool, check) { + function which2(tool, check) { return __awaiter(this, void 0, void 0, function* () { if (!tool) { throw new Error("parameter 'tool' is required"); } if (check) { - const result = yield which(tool, false); + const result = yield which2(tool, false); if (!result) { if (ioUtil.IS_WINDOWS) { 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.`); @@ -4315,7 +4571,7 @@ var require_io = __commonJS({ return ""; }); } - exports.which = which; + exports.which = which2; function findInPath(tool) { return __awaiter(this, void 0, void 0, function* () { if (!tool) { @@ -24056,7 +24312,7 @@ var require_undici = __commonJS({ }); // node_modules/.pnpm/@actions+http-client@2.2.0/node_modules/@actions/http-client/lib/index.js -var require_lib2 = __commonJS({ +var require_lib3 = __commonJS({ "node_modules/.pnpm/@actions+http-client@2.2.0/node_modules/@actions/http-client/lib/index.js"(exports) { "use strict"; var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) { @@ -36559,7 +36815,7 @@ var init_log2 = __esm({ }); // node_modules/.pnpm/webidl-conversions@3.0.1/node_modules/webidl-conversions/lib/index.js -var require_lib3 = __commonJS({ +var require_lib4 = __commonJS({ "node_modules/.pnpm/webidl-conversions@3.0.1/node_modules/webidl-conversions/lib/index.js"(exports, module2) { "use strict"; var conversions = {}; @@ -38138,7 +38394,7 @@ var require_URL_impl = __commonJS({ var require_URL = __commonJS({ "node_modules/.pnpm/whatwg-url@5.0.0/node_modules/whatwg-url/lib/URL.js"(exports, module2) { "use strict"; - var conversions = require_lib3(); + var conversions = require_lib4(); var utils = require_utils3(); var Impl = require_URL_impl(); var impl = utils.implSymbol; @@ -43893,7 +44149,7 @@ var require_XMLStreamWriter = __commonJS({ }); // node_modules/.pnpm/xmlbuilder@11.0.1/node_modules/xmlbuilder/lib/index.js -var require_lib4 = __commonJS({ +var require_lib5 = __commonJS({ "node_modules/.pnpm/xmlbuilder@11.0.1/node_modules/xmlbuilder/lib/index.js"(exports, module2) { "use strict"; (function() { @@ -43954,7 +44210,7 @@ var require_builder = __commonJS({ (function() { "use strict"; var builder, defaults, escapeCDATA, requiresCDATA, wrapCDATA, hasProp = {}.hasOwnProperty; - builder = require_lib4(); + builder = require_lib5(); defaults = require_defaults().defaults; requiresCDATA = function(entry) { return typeof entry === "string" && (entry.indexOf("&") >= 0 || entry.indexOf(">") >= 0 || entry.indexOf("<") >= 0); @@ -73437,7 +73693,7 @@ var require_requestUtils = __commonJS({ Object.defineProperty(exports, "__esModule", { value: true }); exports.retryHttpClientResponse = exports.retryTypedResponse = exports.retry = exports.isRetryableStatusCode = exports.isServerErrorStatusCode = exports.isSuccessStatusCode = void 0; var core7 = __importStar(require_core()); - var http_client_1 = require_lib2(); + var http_client_1 = require_lib3(); var constants_1 = require_constants(); function isSuccessStatusCode(statusCode) { if (!statusCode) { @@ -73610,7 +73866,7 @@ var require_downloadUtils = __commonJS({ Object.defineProperty(exports, "__esModule", { value: true }); exports.downloadCacheStorageSDK = exports.downloadCacheHttpClientConcurrent = exports.downloadCacheHttpClient = exports.DownloadProgress = void 0; var core7 = __importStar(require_core()); - var http_client_1 = require_lib2(); + var http_client_1 = require_lib3(); var storage_blob_1 = (init_src12(), __toCommonJS(src_exports3)); var buffer = __importStar(require("buffer")); var fs6 = __importStar(require("fs")); @@ -73910,7 +74166,7 @@ var require_downloadUtils = __commonJS({ }); // node_modules/.pnpm/@actions+cache@3.2.2/node_modules/@actions/cache/lib/options.js -var require_options = __commonJS({ +var require_options2 = __commonJS({ "node_modules/.pnpm/@actions+cache@3.2.2/node_modules/@actions/cache/lib/options.js"(exports) { "use strict"; var __createBinding = exports && exports.__createBinding || (Object.create ? function(o, m, k, k2) { @@ -74077,14 +74333,14 @@ var require_cacheHttpClient = __commonJS({ Object.defineProperty(exports, "__esModule", { value: true }); exports.saveCache = exports.reserveCache = exports.downloadCache = exports.getCacheEntry = exports.getCacheVersion = void 0; var core7 = __importStar(require_core()); - var http_client_1 = require_lib2(); + var http_client_1 = require_lib3(); var auth_1 = require_auth2(); var crypto4 = __importStar(require("crypto")); var fs6 = __importStar(require("fs")); var url_1 = require("url"); var utils = __importStar(require_cacheUtils()); var downloadUtils_1 = require_downloadUtils(); - var options_1 = require_options(); + var options_1 = require_options2(); var requestUtils_1 = require_requestUtils(); var versionSalt = "1.0"; function getCacheApiUrl(resource) { @@ -78411,6 +78667,7 @@ function untildify(pathWithTilde) { } // src/options.ts +var import_which = __toESM(require_lib2()); var core = process.env.MOCKING ? coreMocked : coreDefault; var PATHS = { micromambaBin: path.join(os2.homedir(), "micromamba-bin", `micromamba${os2.platform() === "win32" ? ".exe" : ""}`), @@ -78455,7 +78712,8 @@ var inferOptions = (inputs) => { const micromambaSource = inputs.micromambaUrl ? (0, import_Either.right)(inputs.micromambaUrl) : (0, import_Either.left)(inputs.micromambaVersion || "latest"); const writeToCondarc = inputs.condarcFile === void 0; const initShell = !inputs.initShell ? ["bash"] : inputs.initShell.includes("none") ? [] : inputs.initShell; - const micromambaBinPath = inputs.micromambaBinPath ? path.resolve(untildify(inputs.micromambaBinPath)) : PATHS.micromambaBin; + const downloadMicromamba = inputs.downloadMicromamba !== void 0 ? inputs.downloadMicromamba : true; + const micromambaBinPath = inputs.micromambaBinPath ? path.resolve(untildify(inputs.micromambaBinPath)) : inputs.downloadMicromamba === false ? import_which.default.sync("micromamba") : PATHS.micromambaBin; return { ...inputs, writeToCondarc, @@ -78463,6 +78721,7 @@ var inferOptions = (inputs) => { createArgs: inputs.createArgs || [], logLevel, micromambaSource, + downloadMicromamba, initShell, generateRunShell: inputs.generateRunShell !== void 0 ? inputs.generateRunShell : createEnvironment, cacheEnvironmentKey: inputs.cacheEnvironmentKey || (inputs.cacheEnvironment ? `micromamba-environment-` : void 0), @@ -78481,6 +78740,9 @@ var validateInputs = (inputs) => { if (inputs.micromambaUrl && inputs.micromambaVersion) { throw new Error("You must specify either a micromamba URL or a micromamba version, not both."); } + if (inputs.downloadMicromamba === false && (inputs.micromambaUrl || inputs.micromambaVersion)) { + throw new Error("You cannot specify micromamba-url or micromamba-version when download-micromamba is false."); + } if (inputs.generateRunShell && !createEnvironment) { throw new Error("You must create an environment to use 'generate-run-shell'."); } @@ -78546,6 +78808,7 @@ var getOptions = () => { "micromamba-version must be either `latest` or a version matching `1.2.3-0`." ), micromambaUrl: parseOrUndefined("micromamba-url", stringType().url()), + downloadMicromamba: parseOrUndefinedJSON("download-micromamba", booleanType()), initShell: parseOrUndefinedList("init-shell", shellSchema), generateRunShell: parseOrUndefinedJSON("generate-run-shell", booleanType()), cacheDownloads: parseOrUndefinedJSON("cache-downloads", booleanType()), @@ -81445,6 +81708,10 @@ var removeMicromambaBinaryParentIfEmpty = () => { }; var removeMicromambaBinary = () => { core6.info("Removing micromamba binary ..."); + if (options.downloadMicromamba === false) { + core6.debug("Skipping micromamba binary removal."); + return Promise.resolve(); + } core6.debug(`Deleting ${options.micromambaBinPath}`); return fs5.rm(options.micromambaBinPath, { force: false }); }; diff --git a/package.json b/package.json index a1ba43a..151db30 100644 --- a/package.json +++ b/package.json @@ -31,11 +31,13 @@ "fp-ts": "^2.16.1", "js-yaml": "^4.1.0", "untildify": "^5.0.0", + "which": "^4.0.0", "zod": "^3.22.4" }, "devDependencies": { "@types/js-yaml": "^4.0.9", "@types/node": "^20.10.3", + "@types/which": "^3.0.3", "@typescript-eslint/eslint-plugin": "^6.13.2", "@typescript-eslint/parser": "^6.13.2", "eslint": "^8.55.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c00e5f7..cd9256a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ dependencies: untildify: specifier: ^5.0.0 version: 5.0.0 + which: + specifier: ^4.0.0 + version: 4.0.0 zod: specifier: ^3.22.4 version: 3.22.4 @@ -40,6 +43,9 @@ devDependencies: '@types/node': specifier: ^20.10.3 version: 20.10.3 + '@types/which': + specifier: ^3.0.3 + version: 3.0.3 '@typescript-eslint/eslint-plugin': specifier: ^6.13.2 version: 6.13.2(@typescript-eslint/parser@6.13.2)(eslint@8.55.0)(typescript@5.3.2) @@ -720,6 +726,10 @@ packages: '@types/node': 20.10.3 dev: false + /@types/which@3.0.3: + resolution: {integrity: sha512-2C1+XoY0huExTbs8MQv1DuS5FS86+SEjdM9F/+GS61gg5Hqbtj8ZiDSx8MfWcyei907fIPbfPGCOrNUTnVHY1g==} + dev: true + /@typescript-eslint/eslint-plugin@6.13.2(@typescript-eslint/parser@6.13.2)(eslint@8.55.0)(typescript@5.3.2): resolution: {integrity: sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==} engines: {node: ^16.0.0 || >=18.0.0} @@ -2120,6 +2130,11 @@ packages: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true + /isexe@3.1.1: + resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} + engines: {node: '>=16'} + dev: false + /joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -3051,6 +3066,14 @@ packages: isexe: 2.0.0 dev: true + /which@4.0.0: + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + isexe: 3.1.1 + dev: false + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: true diff --git a/src/main.ts b/src/main.ts index 9b32944..69582c2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,4 @@ import fs from 'fs/promises' -import { constants as fsConstants } from 'fs' // fs.constants is not available in fs/promises for node < 18.4.0 import os from 'os' import path from 'path' import { exit } from 'process' @@ -15,6 +14,11 @@ import { restoreCacheDownloads, restoreCacheEnvironment, saveCacheEnvironment } const core = process.env.MOCKING ? coreMocked : coreDefault const downloadMicromamba = (url: string) => { + if (options.downloadMicromamba === false) { + core.info('Skipping micromamba download.') + core.addPath(path.dirname(options.micromambaBinPath)) + return Promise.resolve() + } core.startGroup('Install micromamba') core.debug(`Downloading micromamba from ${url} ...`) @@ -34,7 +38,7 @@ const downloadMicromamba = (url: string) => { const generateCondarc = () => { if (!options.writeToCondarc) { core.debug(`Using condarc file ${options.condarcFile} ...`) - return fs.access(options.condarcFile, fsConstants.R_OK) + return fs.access(options.condarcFile, fs.constants.R_OK) } core.debug(`Using ${options.condarcFile} as condarc file.`) const mkDir = fs.mkdir(path.dirname(options.condarcFile), { recursive: true }) diff --git a/src/options.ts b/src/options.ts index 14d3010..1cdd7d9 100644 --- a/src/options.ts +++ b/src/options.ts @@ -6,6 +6,7 @@ import * as z from 'zod' import { left, right } from 'fp-ts/lib/Either' import type { Either } from 'fp-ts/lib/Either' import untildify from 'untildify' +import which from 'which' import { coreMocked } from './mocking' const core = process.env.MOCKING ? coreMocked : coreDefault @@ -26,6 +27,7 @@ type Inputs = Readonly<{ logLevel?: LogLevelType micromambaVersion?: string micromambaUrl?: string + downloadMicromamba?: boolean initShell?: ShellTypeWithNone[] generateRunShell?: boolean cacheDownloads?: boolean @@ -47,6 +49,7 @@ export type Options = Readonly<{ createArgs: string[] logLevel: LogLevelType micromambaSource: MicromambaSourceType + downloadMicromamba: boolean initShell: ShellType[] generateRunShell: boolean cacheDownloadsKey?: string // undefined if cacheDownloads is false @@ -126,9 +129,12 @@ const inferOptions = (inputs: Inputs): Options => { : inputs.initShell.includes('none') ? [] : (inputs.initShell as ShellType[]) + const downloadMicromamba = inputs.downloadMicromamba !== undefined ? inputs.downloadMicromamba : true const micromambaBinPath = inputs.micromambaBinPath ? path.resolve(untildify(inputs.micromambaBinPath)) - : PATHS.micromambaBin + : inputs.downloadMicromamba === false + ? which.sync('micromamba') + : PATHS.micromambaBin return { ...inputs, @@ -137,6 +143,7 @@ const inferOptions = (inputs: Inputs): Options => { createArgs: inputs.createArgs || [], logLevel, micromambaSource, + downloadMicromamba, initShell, generateRunShell: inputs.generateRunShell !== undefined ? inputs.generateRunShell : createEnvironment, cacheEnvironmentKey: @@ -160,6 +167,9 @@ const validateInputs = (inputs: Inputs): void => { if (inputs.micromambaUrl && inputs.micromambaVersion) { throw new Error('You must specify either a micromamba URL or a micromamba version, not both.') } + if (inputs.downloadMicromamba === false && (inputs.micromambaUrl || inputs.micromambaVersion)) { + throw new Error('You cannot specify micromamba-url or micromamba-version when download-micromamba is false.') + } if (inputs.generateRunShell && !createEnvironment) { throw new Error("You must create an environment to use 'generate-run-shell'.") } @@ -234,6 +244,7 @@ const getOptions = () => { 'micromamba-version must be either `latest` or a version matching `1.2.3-0`.' ), micromambaUrl: parseOrUndefined('micromamba-url', z.string().url()), + downloadMicromamba: parseOrUndefinedJSON('download-micromamba', z.boolean()), initShell: parseOrUndefinedList('init-shell', shellSchema), generateRunShell: parseOrUndefinedJSON('generate-run-shell', z.boolean()), cacheDownloads: parseOrUndefinedJSON('cache-downloads', z.boolean()), diff --git a/src/post.ts b/src/post.ts index 6a9f7e3..8ae2559 100644 --- a/src/post.ts +++ b/src/post.ts @@ -56,6 +56,10 @@ const removeMicromambaBinaryParentIfEmpty = () => { const removeMicromambaBinary = () => { core.info('Removing micromamba binary ...') + if (options.downloadMicromamba === false) { + core.debug('Skipping micromamba binary removal.') + return Promise.resolve() + } core.debug(`Deleting ${options.micromambaBinPath}`) return fs.rm(options.micromambaBinPath, { force: false }) } diff --git a/tsup.config.js b/tsup.config.js index 7af0aa6..f1d52bf 100644 --- a/tsup.config.js +++ b/tsup.config.js @@ -21,6 +21,7 @@ export default defineConfig({ 'untildify', 'zod', 'fp-ts', - 'js-yaml' + 'js-yaml', + 'which' ] })