From d828acb7046fe1b4ea76bef3cd5e32b0b49b1bd5 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Fri, 17 May 2024 17:55:54 -0300 Subject: [PATCH 01/27] Add strict mode --- action.yml | 4 ++++ dist/index.js | 25 ++++++++++++++++++++----- dist/index.js.map | 2 +- src/index.ts | 29 ++++++++++++++++++++++++----- 4 files changed, 49 insertions(+), 11 deletions(-) diff --git a/action.yml b/action.yml index 882f4eb..14fd3cc 100644 --- a/action.yml +++ b/action.yml @@ -51,6 +51,10 @@ inputs: source-url: description: A URL pointing to a `magic-nix-cache` binary. Overrides all other `source-*` options. required: false + strict-mode: + description: "Whether to fail when any errors are thrown. Used only to test the Action; do not set this in your own workflows." + default: false + required: false runs: using: "node20" diff --git a/dist/index.js b/dist/index.js index c0fc53b..cc8048d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -94810,6 +94810,7 @@ var MagicNixCacheAction = class { idsProjectName: "magic-nix-cache-closure", requireNix: "warn" }); + this.failMode = inputs_exports.getBool("fail-mode"); this.client = got_dist_source.extend({ retry: { limit: 1, @@ -94956,16 +94957,21 @@ var MagicNixCacheAction = class { notifyPromise.then((_value) => { resolve(); }).catch((err) => { - reject(new Error(`error in notifyPromise: ${err}`)); + const msg = `error in notifyPromise: ${err}`; + reject(new Error(msg)); + this.failInFailMode(msg); }); daemon.on("exit", async (code, signal) => { + let msg; if (signal) { - reject(new Error(`Daemon was killed by signal ${signal}`)); + msg = `Daemon was killed by signal ${signal}`; } else if (code) { - reject(new Error(`Daemon exited with code ${code}`)); + msg = `Daemon exited with code ${code}`; } else { - reject(new Error(`Daemon unexpectedly exited`)); + msg = "Daemon unexpectedly exited"; } + reject(new Error(msg)); + this.failInFailMode(msg); }); }); daemon.unref(); @@ -94996,6 +95002,7 @@ var MagicNixCacheAction = class { core.info(`Error marking the workflow as started:`); core.info((0,external_node_util_.inspect)(e)); core.info(`Magic Nix Cache may not be running for this workflow.`); + this.failInFailMode(`Magic Nix Cache failed to start: ${(0,external_node_util_.inspect)(e)}`); } } async tearDownAutoCache() { @@ -95007,7 +95014,9 @@ var MagicNixCacheAction = class { const pid = parseInt(await promises_namespaceObject.readFile(pidFile, { encoding: "ascii" })); core.debug(`found daemon pid: ${pid}`); if (!pid) { - throw new Error("magic-nix-cache did not start successfully"); + const msg = "magic-nix-cache did not start successfully"; + this.failInFailMode(msg); + throw new Error(msg); } const log = tailLog(this.daemonDir); try { @@ -95024,6 +95033,7 @@ var MagicNixCacheAction = class { process.kill(pid, "SIGTERM"); } catch (e) { if (typeof e === "object" && e && "code" in e && e.code !== "ESRCH") { + this.failInFailMode(e.toString()); throw e; } } finally { @@ -95034,6 +95044,11 @@ var MagicNixCacheAction = class { } } } + failInFailMode(msg) { + if (this.failMode) { + core.setFailed(`fail-mode error: ${msg}`); + } + } }; function main() { const cacheAction = new MagicNixCacheAction(); diff --git a/dist/index.js.map b/dist/index.js.map index 8b091c2..0b37ba7 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n reject(new Error(`error in notifyPromise: ${err}`));\n });\n daemon.on(\"exit\", async (code, signal) => {\n if (signal) {\n reject(new Error(`Daemon was killed by signal ${signal}`));\n } else if (code) {\n reject(new Error(`Daemon exited with code ${code}`));\n } else {\n reject(new Error(`Daemon unexpectedly exited`));\n }\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n throw new Error(\"magic-nix-cache did not start successfully\");\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-finish`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private failMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.failMode = inputs.getBool(\"fail-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInFailMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInFailMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInFailMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInFailMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-finish`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInFailMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInFailMode(msg: string): void {\n if (this.failMode) {\n actionsCore.setFailed(`fail-mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index da4c4a3..cc95046 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,6 +28,7 @@ const TEXT_TRUST_UNKNOWN = class MagicNixCacheAction { idslib: IdsToolbox; + private strictMode: boolean; private client: Got; noopMode: boolean; @@ -42,6 +43,8 @@ class MagicNixCacheAction { requireNix: "warn", }); + this.strictMode = inputs.getBool("strict-mode"); + this.client = got.extend({ retry: { limit: 1, @@ -224,16 +227,21 @@ class MagicNixCacheAction { }) // eslint-disable-next-line github/no-then .catch((err) => { - reject(new Error(`error in notifyPromise: ${err}`)); + const msg = `error in notifyPromise: ${err}`; + reject(new Error(msg)); + this.failInStrictMode(msg); }); daemon.on("exit", async (code, signal) => { + let msg: string; if (signal) { - reject(new Error(`Daemon was killed by signal ${signal}`)); + msg = `Daemon was killed by signal ${signal}`; } else if (code) { - reject(new Error(`Daemon exited with code ${code}`)); + msg = `Daemon exited with code ${code}`; } else { - reject(new Error(`Daemon unexpectedly exited`)); + msg = "Daemon unexpectedly exited"; } + reject(new Error(msg)); + this.failInStrictMode(msg); }); }); @@ -274,6 +282,8 @@ class MagicNixCacheAction { actionsCore.info(`Error marking the workflow as started:`); actionsCore.info(inspect(e)); actionsCore.info(`Magic Nix Cache may not be running for this workflow.`); + + this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`); } } @@ -287,7 +297,9 @@ class MagicNixCacheAction { const pid = parseInt(await fs.readFile(pidFile, { encoding: "ascii" })); actionsCore.debug(`found daemon pid: ${pid}`); if (!pid) { - throw new Error("magic-nix-cache did not start successfully"); + const msg = "magic-nix-cache did not start successfully"; + this.failInStrictMode(msg); + throw new Error(msg); } const log = tailLog(this.daemonDir); @@ -309,6 +321,7 @@ class MagicNixCacheAction { process.kill(pid, "SIGTERM"); } catch (e) { if (typeof e === "object" && e && "code" in e && e.code !== "ESRCH") { + this.failInStrictMode(e.toString()); throw e; } } finally { @@ -319,6 +332,12 @@ class MagicNixCacheAction { } } } + + private failInStrictMode(msg: string): void { + if (this.strictMode) { + actionsCore.setFailed(`strict mode error: ${msg}`); + } + } } function main(): void { From a0718e6822128db95db41fd41865dc67f0e5dc1b Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Fri, 17 May 2024 17:57:10 -0300 Subject: [PATCH 02/27] Set strict mode on all CI runs --- .github/workflows/ci.yml | 10 ++++++++++ action.yml | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6dd06bc..3db0982 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,6 +43,8 @@ jobs: - uses: actions/checkout@v4 - name: Cache the store uses: ./ + with: + strict-mode: true run-x86_64-linux-untrusted: name: Run x86_64 Linux, Untrusted @@ -63,6 +65,8 @@ jobs: trusted-users = root - name: Cache the store uses: ./ + with: + strict-mode: true - name: Check the cache isn't enabled run: | [ $(nix config show substituters) == "https://cache.nixos.org/" ] @@ -85,6 +89,8 @@ jobs: narinfo-cache-negative-ttl = 0 - name: Cache the store uses: ./ + with: + strict-mode: true - name: Check the cache for liveness run: | .github/workflows/cache-test.sh @@ -107,6 +113,8 @@ jobs: narinfo-cache-negative-ttl = 0 - name: Cache the store uses: ./ + with: + strict-mode: true - name: Check the cache for liveness run: | .github/workflows/cache-test.sh @@ -130,6 +138,8 @@ jobs: narinfo-cache-negative-ttl = 0 - name: Cache the store uses: ./ + with: + strict-mode: true - name: Check the cache for liveness run: | .github/workflows/cache-test.sh diff --git a/action.yml b/action.yml index 14fd3cc..442d900 100644 --- a/action.yml +++ b/action.yml @@ -52,7 +52,7 @@ inputs: description: A URL pointing to a `magic-nix-cache` binary. Overrides all other `source-*` options. required: false strict-mode: - description: "Whether to fail when any errors are thrown. Used only to test the Action; do not set this in your own workflows." + description: Whether to fail when any errors are thrown. Used only to test the Action; do not set this in your own workflows. default: false required: false From 73510dc45c28fcfac50fe8660b0b984766e2bef6 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Fri, 17 May 2024 17:59:56 -0300 Subject: [PATCH 03/27] Regenerate dist --- dist/index.js | 18 +++++++++--------- dist/index.js.map | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/dist/index.js b/dist/index.js index cc8048d..fe7d9e4 100644 --- a/dist/index.js +++ b/dist/index.js @@ -94810,7 +94810,7 @@ var MagicNixCacheAction = class { idsProjectName: "magic-nix-cache-closure", requireNix: "warn" }); - this.failMode = inputs_exports.getBool("fail-mode"); + this.strictMode = inputs_exports.getBool("strict-mode"); this.client = got_dist_source.extend({ retry: { limit: 1, @@ -94959,7 +94959,7 @@ var MagicNixCacheAction = class { }).catch((err) => { const msg = `error in notifyPromise: ${err}`; reject(new Error(msg)); - this.failInFailMode(msg); + this.failInStrictMode(msg); }); daemon.on("exit", async (code, signal) => { let msg; @@ -94971,7 +94971,7 @@ var MagicNixCacheAction = class { msg = "Daemon unexpectedly exited"; } reject(new Error(msg)); - this.failInFailMode(msg); + this.failInStrictMode(msg); }); }); daemon.unref(); @@ -95002,7 +95002,7 @@ var MagicNixCacheAction = class { core.info(`Error marking the workflow as started:`); core.info((0,external_node_util_.inspect)(e)); core.info(`Magic Nix Cache may not be running for this workflow.`); - this.failInFailMode(`Magic Nix Cache failed to start: ${(0,external_node_util_.inspect)(e)}`); + this.failInStrictMode(`Magic Nix Cache failed to start: ${(0,external_node_util_.inspect)(e)}`); } } async tearDownAutoCache() { @@ -95015,7 +95015,7 @@ var MagicNixCacheAction = class { core.debug(`found daemon pid: ${pid}`); if (!pid) { const msg = "magic-nix-cache did not start successfully"; - this.failInFailMode(msg); + this.failInStrictMode(msg); throw new Error(msg); } const log = tailLog(this.daemonDir); @@ -95033,7 +95033,7 @@ var MagicNixCacheAction = class { process.kill(pid, "SIGTERM"); } catch (e) { if (typeof e === "object" && e && "code" in e && e.code !== "ESRCH") { - this.failInFailMode(e.toString()); + this.failInStrictMode(e.toString()); throw e; } } finally { @@ -95044,9 +95044,9 @@ var MagicNixCacheAction = class { } } } - failInFailMode(msg) { - if (this.failMode) { - core.setFailed(`fail-mode error: ${msg}`); + failInStrictMode(msg) { + if (this.strictMode) { + core.setFailed(`strict mode error: ${msg}`); } } }; diff --git a/dist/index.js.map b/dist/index.js.map index 0b37ba7..7d06a4e 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private failMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.failMode = inputs.getBool(\"fail-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInFailMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInFailMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInFailMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInFailMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-finish`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInFailMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInFailMode(msg: string): void {\n if (this.failMode) {\n actionsCore.setFailed(`fail-mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-finish`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file From 79ca9d8642cbdee382d239f583b7be71a87f448a Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Sat, 18 May 2024 15:01:41 -0300 Subject: [PATCH 04/27] Apply matrix strategy --- .github/workflows/ci.yml | 66 ++++++++-------------------------------- 1 file changed, 13 insertions(+), 53 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3db0982..a2558a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -71,66 +71,26 @@ jobs: run: | [ $(nix config show substituters) == "https://cache.nixos.org/" ] - run-x86_64-linux: - name: Run x86_64 Linux - runs-on: ubuntu-22.04 - permissions: - id-token: "write" - contents: "read" - env: - ACTIONS_STEP_DEBUG: true - steps: - - uses: actions/checkout@v4 - - name: Install Nix - uses: DeterminateSystems/nix-installer-action@main - with: - flakehub: true - extra-conf: | - narinfo-cache-negative-ttl = 0 - - name: Cache the store - uses: ./ - with: - strict-mode: true - - name: Check the cache for liveness - run: | - .github/workflows/cache-test.sh - - run-x86_64-darwin: - name: Run x86_64 Darwin - runs-on: macos-12 + run-systems: + name: "Run ${{ matrix.systems.nix-system }}" + runs-on: "${{ matrix.systems.runner }}" permissions: id-token: "write" contents: "read" env: ACTIONS_STEP_DEBUG: true + strategy: + matrix: + systems: + - nix-system: "aarch64-darwin" + runner: "macos-latest-xlarge" + - nix-system: "x86_64-darwin" + runner: "macos-12" + - nix-system: "x86_64-linux" + runner: "ubuntu-22.04" steps: - uses: actions/checkout@v4 - - name: Install Nix - uses: DeterminateSystems/nix-installer-action@main - with: - flakehub: true - extra-conf: | - narinfo-cache-negative-ttl = 0 - - name: Cache the store - uses: ./ - with: - strict-mode: true - - name: Check the cache for liveness - run: | - .github/workflows/cache-test.sh - - run-aarch64-darwin: - name: Run aarch64 Darwin - concurrency: build-ARM64-macOS - runs-on: macos-latest-xlarge - permissions: - id-token: "write" - contents: "read" - env: - ACTIONS_STEP_DEBUG: true - steps: - - uses: actions/checkout@v4 - - name: Install Nix + - name: Install Nix on ${{ matrix.systems.nix-system }} system uses: DeterminateSystems/nix-installer-action@main with: flakehub: true From aa46387b46c58238a584ee6ddaa4748ab08b8c2e Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 07:57:19 -0300 Subject: [PATCH 05/27] Fail when workflow finish hook fails --- dist/index.js | 5 +++++ dist/index.js.map | 2 +- src/index.ts | 7 +++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/dist/index.js b/dist/index.js index fe7d9e4..4e74401 100644 --- a/dist/index.js +++ b/dist/index.js @@ -95023,6 +95023,11 @@ var MagicNixCacheAction = class { core.debug(`about to post to localhost`); const hostAndPort = inputs_exports.getString("listen"); const res = await this.client.post(`http://${hostAndPort}/api/workflow-finish`).json(); + if (res.status !== 200) { + this.failInStrictMode( + `Failed to trigger workflow finish hook; expected HTTP status 200 from POST to /api/workflow-finish but got ${res.status} instead` + ); + } core.debug(`back from post: ${res}`); } finally { core.debug(`unwatching the daemon log`); diff --git a/dist/index.js.map b/dist/index.js.map index 7d06a4e..7906623 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-finish`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-finish`)\n .json();\n\n if (res.status !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected HTTP status 200 from POST to /api/workflow-finish but got ${res.status} instead`,\n );\n }\n\n actionsCore.debug(`back from post: ${res}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index cc95046..0341814 100644 --- a/src/index.ts +++ b/src/index.ts @@ -310,6 +310,13 @@ class MagicNixCacheAction { const res: Response = await this.client .post(`http://${hostAndPort}/api/workflow-finish`) .json(); + + if (res.status !== 200) { + this.failInStrictMode( + `Failed to trigger workflow finish hook; expected HTTP status 200 from POST to /api/workflow-finish but got ${res.status} instead`, + ); + } + actionsCore.debug(`back from post: ${res}`); } finally { actionsCore.debug(`unwatching the daemon log`); From 643c369303f996e767483f2a6b31331b0fb53370 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 08:29:33 -0300 Subject: [PATCH 06/27] Add info statement about HTTP response --- src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/index.ts b/src/index.ts index 0341814..1f2c015 100644 --- a/src/index.ts +++ b/src/index.ts @@ -311,6 +311,8 @@ class MagicNixCacheAction { .post(`http://${hostAndPort}/api/workflow-finish`) .json(); + actionsCore.info(JSON.stringify(res)); + if (res.status !== 200) { this.failInStrictMode( `Failed to trigger workflow finish hook; expected HTTP status 200 from POST to /api/workflow-finish but got ${res.status} instead`, From c93080475704b181784f9e3cd03ad2c35269fe32 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 08:33:19 -0300 Subject: [PATCH 07/27] Move info statement --- src/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 1f2c015..c5af7e5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -311,9 +311,8 @@ class MagicNixCacheAction { .post(`http://${hostAndPort}/api/workflow-finish`) .json(); - actionsCore.info(JSON.stringify(res)); - if (res.status !== 200) { + actionsCore.info(JSON.stringify(res)); this.failInStrictMode( `Failed to trigger workflow finish hook; expected HTTP status 200 from POST to /api/workflow-finish but got ${res.status} instead`, ); From 39876685c835ff1420484fff8bf8782d87830725 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 08:36:04 -0300 Subject: [PATCH 08/27] Print JSON --- src/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index c5af7e5..d518755 100644 --- a/src/index.ts +++ b/src/index.ts @@ -312,9 +312,8 @@ class MagicNixCacheAction { .json(); if (res.status !== 200) { - actionsCore.info(JSON.stringify(res)); this.failInStrictMode( - `Failed to trigger workflow finish hook; expected HTTP status 200 from POST to /api/workflow-finish but got ${res.status} instead`, + `Failed to trigger workflow finish hook. Response: ${JSON.stringify(res)}`, ); } From 93f3ded0b4ec1ce848865b6dc8814ca84c0b896d Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 08:37:55 -0300 Subject: [PATCH 09/27] Regenerate dist --- dist/index.js | 2 +- dist/index.js.map | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 4e74401..976fc00 100644 --- a/dist/index.js +++ b/dist/index.js @@ -95025,7 +95025,7 @@ var MagicNixCacheAction = class { const res = await this.client.post(`http://${hostAndPort}/api/workflow-finish`).json(); if (res.status !== 200) { this.failInStrictMode( - `Failed to trigger workflow finish hook; expected HTTP status 200 from POST to /api/workflow-finish but got ${res.status} instead` + `Failed to trigger workflow finish hook. Response: ${JSON.stringify(res)}` ); } core.debug(`back from post: ${res}`); diff --git a/dist/index.js.map b/dist/index.js.map index 7906623..aba3ac8 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-finish`)\n .json();\n\n if (res.status !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected HTTP status 200 from POST to /api/workflow-finish but got ${res.status} instead`,\n );\n }\n\n actionsCore.debug(`back from post: ${res}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-finish`)\n .json();\n\n if (res.status !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook. Response: ${JSON.stringify(res)}`,\n );\n }\n\n actionsCore.debug(`back from post: ${res}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file From edc61c4d5a6ec4d67f304bbcbab5e6311aa42a63 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 09:20:03 -0300 Subject: [PATCH 10/27] Fix HTTP status code logic --- .github/workflows/ci.yml | 2 ++ dist/index.js | 21 +++++++++++++++------ dist/index.js.map | 2 +- src/index.ts | 29 ++++++++++++++++++----------- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2558a8..6c1f80a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,6 +32,7 @@ jobs: - run: git diff --exit-code test-no-nix: + needs: build name: "Test: Nix not installed" runs-on: ubuntu-22.04 permissions: @@ -47,6 +48,7 @@ jobs: strict-mode: true run-x86_64-linux-untrusted: + needs: build name: Run x86_64 Linux, Untrusted runs-on: ubuntu-22.04 permissions: diff --git a/dist/index.js b/dist/index.js index 976fc00..b263bba 100644 --- a/dist/index.js +++ b/dist/index.js @@ -94996,8 +94996,15 @@ var MagicNixCacheAction = class { try { core.debug(`Indicating workflow start`); const hostAndPort = inputs_exports.getString("listen"); - const res = await this.client.post(`http://${hostAndPort}/api/workflow-start`).json(); - core.debug(`back from post: ${res}`); + const res = await this.client.post( + `http://${hostAndPort}/api/workflow-start` + ); + if (res.statusCode !== 200) { + this.failInStrictMode( + `Failed to trigger workflow start hook. Expected status 200 but got ${res.statusCode}` + ); + } + core.debug(`back from post: ${JSON.stringify(res)}`); } catch (e) { core.info(`Error marking the workflow as started:`); core.info((0,external_node_util_.inspect)(e)); @@ -95022,13 +95029,15 @@ var MagicNixCacheAction = class { try { core.debug(`about to post to localhost`); const hostAndPort = inputs_exports.getString("listen"); - const res = await this.client.post(`http://${hostAndPort}/api/workflow-finish`).json(); - if (res.status !== 200) { + const res = await this.client.post( + `http://${hostAndPort}/api/workflow-finish` + ); + if (res.statusCode !== 200) { this.failInStrictMode( - `Failed to trigger workflow finish hook. Response: ${JSON.stringify(res)}` + `Failed to trigger workflow finish hook. Expected status 200 but got ${res.statusCode}` ); } - core.debug(`back from post: ${res}`); + core.debug(`back from post: ${JSON.stringify(res.body)}`); } finally { core.debug(`unwatching the daemon log`); log.unwatch(); diff --git a/dist/index.js.map b/dist/index.js.map index aba3ac8..d33342c 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n actionsCore.debug(`back from post: ${res}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-finish`)\n .json();\n\n if (res.status !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook. Response: ${JSON.stringify(res)}`,\n );\n }\n\n actionsCore.debug(`back from post: ${res}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client.post(\n `http://${hostAndPort}/api/workflow-start`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook. Expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${JSON.stringify(res)}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client.post(\n `http://${hostAndPort}/api/workflow-finish`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook. Expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${JSON.stringify(res.body)}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index d518755..16a141e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import { netrcPath, tailLog } from "./helpers.js"; import * as actionsCore from "@actions/core"; import { IdsToolbox, inputs } from "detsys-ts"; -import got, { Got } from "got"; +import got, { Got, Response } from "got"; import * as http from "http"; import { SpawnOptions, exec, spawn } from "node:child_process"; import { mkdirSync, openSync, readFileSync } from "node:fs"; @@ -274,10 +274,17 @@ class MagicNixCacheAction { try { actionsCore.debug(`Indicating workflow start`); const hostAndPort = inputs.getString("listen"); - const res: Response = await this.client - .post(`http://${hostAndPort}/api/workflow-start`) - .json(); - actionsCore.debug(`back from post: ${res}`); + const res: Response = await this.client.post( + `http://${hostAndPort}/api/workflow-start`, + ); + + if (res.statusCode !== 200) { + this.failInStrictMode( + `Failed to trigger workflow start hook. Expected status 200 but got ${res.statusCode}`, + ); + } + + actionsCore.debug(`back from post: ${JSON.stringify(res)}`); } catch (e) { actionsCore.info(`Error marking the workflow as started:`); actionsCore.info(inspect(e)); @@ -307,17 +314,17 @@ class MagicNixCacheAction { try { actionsCore.debug(`about to post to localhost`); const hostAndPort = inputs.getString("listen"); - const res: Response = await this.client - .post(`http://${hostAndPort}/api/workflow-finish`) - .json(); + const res: Response = await this.client.post( + `http://${hostAndPort}/api/workflow-finish`, + ); - if (res.status !== 200) { + if (res.statusCode !== 200) { this.failInStrictMode( - `Failed to trigger workflow finish hook. Response: ${JSON.stringify(res)}`, + `Failed to trigger workflow finish hook. Expected status 200 but got ${res.statusCode}`, ); } - actionsCore.debug(`back from post: ${res}`); + actionsCore.debug(`back from post: ${JSON.stringify(res.body)}`); } finally { actionsCore.debug(`unwatching the daemon log`); log.unwatch(); From a8b68ff5ba26f7064c46439c424cd27741b2fabb Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 09:25:51 -0300 Subject: [PATCH 11/27] Fix HTTP response stringify issue --- dist/index.js | 6 ++---- dist/index.js.map | 2 +- src/index.ts | 8 ++++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/dist/index.js b/dist/index.js index b263bba..e53e2b5 100644 --- a/dist/index.js +++ b/dist/index.js @@ -94996,15 +94996,13 @@ var MagicNixCacheAction = class { try { core.debug(`Indicating workflow start`); const hostAndPort = inputs_exports.getString("listen"); - const res = await this.client.post( - `http://${hostAndPort}/api/workflow-start` - ); + const res = await this.client.post(`http://${hostAndPort}/api/workflow-start`).json(); if (res.statusCode !== 200) { this.failInStrictMode( `Failed to trigger workflow start hook. Expected status 200 but got ${res.statusCode}` ); } - core.debug(`back from post: ${JSON.stringify(res)}`); + core.debug(`back from post: ${JSON.stringify(res.body)}`); } catch (e) { core.info(`Error marking the workflow as started:`); core.info((0,external_node_util_.inspect)(e)); diff --git a/dist/index.js.map b/dist/index.js.map index d33342c..75d4cfc 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client.post(\n `http://${hostAndPort}/api/workflow-start`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook. Expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${JSON.stringify(res)}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client.post(\n `http://${hostAndPort}/api/workflow-finish`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook. Expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${JSON.stringify(res.body)}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook. Expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${JSON.stringify(res.body)}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client.post(\n `http://${hostAndPort}/api/workflow-finish`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook. Expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${JSON.stringify(res.body)}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":";AAAA,YAAY,iBAAiB;AAC7B,YAAY,QAAQ;AACpB,YAAY,QAAQ;AACpB,OAAO,UAAU;AACjB,SAAS,YAAY;AAEd,SAAS,QAAQ,WAAyB;AAC/C,QAAM,MAAM,IAAI,KAAK,KAAK,KAAK,WAAW,YAAY,CAAC;AACvD,EAAY,kBAAM,uBAAuB;AACzC,MAAI,GAAG,QAAQ,CAAC,SAAS;AACvB,IAAY,iBAAK,IAAI;AAAA,EACvB,CAAC;AACD,SAAO;AACT;AAEA,eAAsB,YAA6B;AACjD,QAAM,oBAAoB,KAAK;AAAA,IAC7B,QAAQ,IAAI,aAAa,KAAQ,UAAO;AAAA,IACxC;AAAA,EACF;AACA,MAAI;AACF,UAAS,UAAO,iBAAiB;AACjC,WAAO;AAAA,EACT,QAAQ;AAEN,UAAM,oBAAoB,KAAK;AAAA,MAC7B,QAAQ,IAAI,aAAa,KAAQ,UAAO;AAAA,MACxC;AAAA,IACF;AACA,QAAI;AACF,YAAM,cAAc,iBAAiB;AAAA,IACvC,SAAS,GAAG;AACV,MAAY,iBAAK,0BAA0B;AAC3C,MAAY,kBAAM,sCAAsC,CAAC,EAAE;AAAA,IAC7D;AACA,WAAO;AAAA,EACT;AACF;AAEA,eAAe,cAAc,OAA8B;AACzD,QAAM,MAAM,MAAkB,uBAAW,kBAAkB;AAE3D,QAAS;AAAA,IACP;AAAA,IACA;AAAA,MACE,oDAAoD,GAAG;AAAA,MACvD,gDAAgD,GAAG;AAAA,MACnD,sDAAsD,GAAG;AAAA,IAC3D,EAAE,KAAK,IAAI;AAAA,EACb;AAEA,EAAY,iBAAK,wBAAwB;AAC3C;;;ACnDA,YAAYA,kBAAiB;AAC7B,SAAS,YAAY,cAAc;AACnC,OAAO,SAA4B;AACnC,YAAY,UAAU;AACtB,SAAuB,MAAM,aAAa;AAC1C,SAAS,WAAW,UAAU,oBAAoB;AAClD,YAAYC,SAAQ;AACpB,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AACtB,SAAS,SAAS,iBAAiB;AAKnC,IAAM,iBAAiB;AAEvB,IAAM,kBAAkB;AACxB,IAAM,gBAAgB;AACtB,IAAM,eAAe;AAErB,IAAM,YACJ;AACF,IAAM,uBACJ;AACF,IAAM,qBACJ;AAEF,IAAM,sBAAN,MAA0B;AAAA,EASxB,cAAc;AACZ,SAAK,SAAS,IAAI,WAAW;AAAA,MAC3B,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,YAAY;AAAA,IACd,CAAC;AAED,SAAK,aAAa,OAAO,QAAQ,aAAa;AAE9C,SAAK,SAAS,IAAI,OAAO;AAAA,MACvB,OAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS,CAAC,QAAQ,OAAO,OAAO,QAAQ,UAAU,WAAW,OAAO;AAAA,MACtE;AAAA,MACA,OAAO;AAAA,QACL,aAAa;AAAA,UACX,CAAC,OAAO,eAAe;AACrB,YAAY;AAAA,cACV,wBAAwB,MAAM,IAAI,cAAc,UAAU;AAAA,YAC5D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,SAAK,gBAA4B,sBAAS,aAAa,MAAM;AAE7D,QAAgB,sBAAS,eAAe,MAAM,IAAI;AAChD,WAAK,YAAwB,sBAAS,eAAe;AAAA,IACvD,OAAO;AACL,WAAK,YAAY,KAAK,OAAO,iBAAiB;AAC9C,gBAAU,KAAK,SAAS;AACxB,MAAY,uBAAU,iBAAiB,KAAK,SAAS;AAAA,IACvD;AAEA,QAAI,QAAQ,IAAI,cAAc,MAAM,QAAW;AAC7C,WAAK,WAAW;AAChB,MAAY,4BAAe,gBAAgB,KAAK,SAAS;AAAA,IAC3D,OAAO;AACL,WAAK,WAAW,QAAQ,IAAI,cAAc,MAAM,KAAK;AAAA,IACvD;AACA,SAAK,OAAO,QAAQ,aAAa,KAAK,QAAQ;AAE9C,SAAK,OAAO;AAAA,MACV;AAAA,MACK,WAAK,KAAK,WAAW,YAAY;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,MAAM,iBAAgC;AACpC,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI,aAAa;AACjB,eAAW,KAAK,aAAa;AAC3B,UAAI,CAAC,QAAQ,IAAI,eAAe,CAAC,GAAG;AAClC,qBAAa;AACb,QAAY;AAAA,UACV,0DAA0D,CAAC;AAAA,QAC7D;AAAA,MACF;AAAA,IACF;AAEA,SAAK,OAAO,QAAQ,qBAAqB,CAAC,UAAU;AACpD,QAAI,YAAY;AACd;AAAA,IACF;AAEA,QAAI,KAAK,eAAe;AACtB,MAAY,mBAAM,kBAAkB;AACpC;AAAA,IACF;AAEA,IAAY;AAAA,MACV,4BAA4B,QAAQ,IAAI,mBAAmB,CAAC;AAAA,IAC9D;AAEA,UAAM,eAAe,OAAO,gBAAgB,eAAe;AAC3D,UAAM,YACJ,iBAAiB,OAAO,eAAe,MAAM,KAAK,gBAAgB;AAEpE,QAAI;AACJ,QAAgB,qBAAQ,GAAG;AACzB,eAAS;AAAA,QACP,UAAU;AAAA,QACV,gBAAgB;AAAA,QAChB,GAAG,QAAQ;AAAA,MACb;AAAA,IACF,OAAO;AACL,eAAS,QAAQ;AAAA,IACnB;AAEA,UAAM,aAAa,OAAO,UAAU,2BAA2B;AAE/D,UAAM,gBAAgB,IAAI,QAAuB,CAAC,qBAAqB;AACrE,YAAM,UAAU,IAAI,QAAc,OAAO,gBAAgB;AACvD,cAAM,eAAoB,kBAAa,CAAC,KAAK,QAAQ;AACnD,cAAI,IAAI,WAAW,UAAU,IAAI,QAAQ,KAAK;AAC5C,YAAY,mBAAM,8BAA8B;AAChD,gBAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,gBAAI,IAAI,IAAI;AACZ,yBAAa,MAAM,MAAM;AACvB,0BAAY;AAAA,YACd,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AAED,qBAAa,OAAO,YAAY,MAAM;AACpC,UAAY,mBAAM,wBAAwB;AAC1C,2BAAiB,OAAO;AAAA,QAC1B,CAAC;AAAA,MACH,CAAC;AAAA,IACH,CAAC;AAGD,UAAM,aAAa,GAAG,KAAK,SAAS;AACpC,UAAM,SAAS,SAAS,YAAY,GAAG;AACvC,UAAM,MAAM,QAAQ,KAAK,SAAS;AAClC,UAAM,QAAQ,MAAM,UAAU;AAC9B,UAAM,cAAc,GAAG,QAAQ,IAAI,MAAM,CAAC;AAE1C,UAAM,cAAc,OAAO,UAAU,QAAQ;AAC7C,UAAM,gBAAgB,OAAO,UAAU,gBAAgB;AACvD,UAAM,qBAAqB,OAAO,UAAU,qBAAqB;AACjE,UAAM,cAAc,OAAO,QAAQ,cAAc;AACjD,UAAM,sBAAsB,OAAO,UAAU,uBAAuB;AACpE,UAAM,oBAAoB,OAAO,UAAU,qBAAqB;AAChE,UAAM,oBAAoB,OAAO,UAAU,qBAAqB;AAChE,UAAM,cAAc,OAAO,QAAQ,eAAe;AAElD,UAAM,iBAA2B;AAAA,MAC/B;AAAA,MACA,oBAAoB,UAAU;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EACG;AAAA,MACC,cACI;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,IACA,CAAC;AAAA,IACP,EACC,OAAO,cAAc,CAAC,iBAAiB,IAAI,CAAC,CAAC;AAEhD,UAAM,OAAqB;AAAA,MACzB,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,MAChC,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAGA,IAAY,mBAAM,4BAA4B;AAC9C,IAAY,mBAAM,GAAG,SAAS,IAAI,eAAe,KAAK,GAAG,CAAC,EAAE;AAG5D,UAAM,SAAS,MAAM,WAAW,gBAAgB,IAAI;AAEpD,SAAK,gBAAgB;AACrB,IAAY,uBAAU,eAAe,YAAY;AAEjD,UAAM,UAAe,WAAK,KAAK,WAAW,YAAY;AACtD,UAAS,cAAU,SAAS,GAAG,OAAO,GAAG,EAAE;AAE3C,IAAY,kBAAK,yCAAyC;AAE1D,UAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,oBAEG,KAAK,CAAC,WAAW;AAChB,gBAAQ;AAAA,MACV,CAAC,EAEA,MAAM,CAAC,QAAQ;AACd,cAAM,MAAM,2BAA2B,GAAG;AAC1C,eAAO,IAAI,MAAM,GAAG,CAAC;AACrB,aAAK,iBAAiB,GAAG;AAAA,MAC3B,CAAC;AACH,aAAO,GAAG,QAAQ,OAAO,MAAM,WAAW;AACxC,YAAI;AACJ,YAAI,QAAQ;AACV,gBAAM,+BAA+B,MAAM;AAAA,QAC7C,WAAW,MAAM;AACf,gBAAM,2BAA2B,IAAI;AAAA,QACvC,OAAO;AACL,gBAAM;AAAA,QACR;AACA,eAAO,IAAI,MAAM,GAAG,CAAC;AACrB,aAAK,iBAAiB,GAAG;AAAA,MAC3B,CAAC;AAAA,IACH,CAAC;AAED,WAAO,MAAM;AAEb,IAAY,kBAAK,0BAA0B;AAE3C,QAAI,QAAQ;AAAA,EACd;AAAA,EAEA,MAAc,kBAAmC;AAC/C,UAAM,cAAc,MAAM,KAAK,OAAO,MAAM;AAC5C,SAAK,OAAO,YAAY,cAAc;AACtC,UAAM,EAAE,OAAO,IAAI,MAAM,UAAU,IAAI;AAAA,MACrC,QAAQ,WAAW;AAAA,IACrB;AAEA,UAAM,QAAQ,OAAO,MAAS,OAAG;AAEjC,UAAM,WAAW,MAAM,GAAG,EAAE;AAC5B,WAAO,GAAG,QAAQ;AAAA,EACpB;AAAA,EAEA,MAAM,kBAAiC;AACrC,QAAI,CAAC,KAAK,eAAe;AACvB,MAAY,mBAAM,wCAAwC;AAC1D;AAAA,IACF;AAEA,QAAI;AACF,MAAY,mBAAM,2BAA2B;AAC7C,YAAM,cAAc,OAAO,UAAU,QAAQ;AAC7C,YAAM,MAAwB,MAAM,KAAK,OACtC,KAAK,UAAU,WAAW,qBAAqB,EAC/C,KAAK;AAER,UAAI,IAAI,eAAe,KAAK;AAC1B,aAAK;AAAA,UACH,sEAAsE,IAAI,UAAU;AAAA,QACtF;AAAA,MACF;AAEA,MAAY,mBAAM,mBAAmB,KAAK,UAAU,IAAI,IAAI,CAAC,EAAE;AAAA,IACjE,SAAS,GAAG;AACV,MAAY,kBAAK,wCAAwC;AACzD,MAAY,kBAAK,QAAQ,CAAC,CAAC;AAC3B,MAAY,kBAAK,uDAAuD;AAExE,WAAK,iBAAiB,oCAAoC,QAAQ,CAAC,CAAC,EAAE;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,MAAM,oBAAmC;AACvC,QAAI,CAAC,KAAK,eAAe;AACvB,MAAY,mBAAM,wCAAwC;AAC1D;AAAA,IACF;AAEA,UAAM,UAAe,WAAK,KAAK,WAAW,YAAY;AACtD,UAAM,MAAM,SAAS,MAAS,aAAS,SAAS,EAAE,UAAU,QAAQ,CAAC,CAAC;AACtE,IAAY,mBAAM,qBAAqB,GAAG,EAAE;AAC5C,QAAI,CAAC,KAAK;AACR,YAAM,MAAM;AACZ,WAAK,iBAAiB,GAAG;AACzB,YAAM,IAAI,MAAM,GAAG;AAAA,IACrB;AAEA,UAAM,MAAM,QAAQ,KAAK,SAAS;AAElC,QAAI;AACF,MAAY,mBAAM,4BAA4B;AAC9C,YAAM,cAAc,OAAO,UAAU,QAAQ;AAC7C,YAAM,MAAwB,MAAM,KAAK,OAAO;AAAA,QAC9C,UAAU,WAAW;AAAA,MACvB;AAEA,UAAI,IAAI,eAAe,KAAK;AAC1B,aAAK;AAAA,UACH,uEAAuE,IAAI,UAAU;AAAA,QACvF;AAAA,MACF;AAEA,MAAY,mBAAM,mBAAmB,KAAK,UAAU,IAAI,IAAI,CAAC,EAAE;AAAA,IACjE,UAAE;AACA,MAAY,mBAAM,2BAA2B;AAC7C,UAAI,QAAQ;AAAA,IACd;AAEA,IAAY,mBAAM,SAAS;AAC3B,QAAI;AACF,cAAQ,KAAK,KAAK,SAAS;AAAA,IAC7B,SAAS,GAAG;AACV,UAAI,OAAO,MAAM,YAAY,KAAK,UAAU,KAAK,EAAE,SAAS,SAAS;AACnE,aAAK,iBAAiB,EAAE,SAAS,CAAC;AAClC,cAAM;AAAA,MACR;AAAA,IACF,UAAE;AACA,UAAgB,qBAAQ,GAAG;AACzB,QAAY,kBAAK,aAAa;AAC9B,cAAM,YAAY,aAAkB,WAAK,KAAK,WAAW,YAAY,CAAC;AACtE,QAAY,kBAAK,UAAU,SAAS,CAAC;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,iBAAiB,KAAmB;AAC1C,QAAI,KAAK,YAAY;AACnB,MAAY,uBAAU,sBAAsB,GAAG,EAAE;AAAA,IACnD;AAAA,EACF;AACF;AAEA,SAAS,OAAa;AACpB,QAAM,cAAc,IAAI,oBAAoB;AAE5C,cAAY,OAAO,OAAO,YAAY;AACpC,QAAI,YAAY,UAAU;AACxB,MAAY,qBAAQ,SAAS;AAC7B;AAAA,IACF;AAEA,QAAI,YAAY,OAAO,kBAAkB,aAAa;AACpD,MAAY,qBAAQ,oBAAoB;AACxC;AAAA,IACF,WAAW,YAAY,OAAO,kBAAkB,WAAW;AACzD,MAAY,kBAAK,kBAAkB;AAAA,IACrC;AAEA,UAAM,YAAY,eAAe;AACjC,UAAM,YAAY,gBAAgB;AAAA,EACpC,CAAC;AACD,cAAY,OAAO,OAAO,YAAY;AACpC,QAAI,YAAY,UAAU;AACxB,MAAY,mBAAM,SAAS;AAC3B;AAAA,IACF;AAEA,QAAI,YAAY,OAAO,kBAAkB,aAAa;AACpD,MAAY,mBAAM,oBAAoB;AACtC;AAAA,IACF,WAAW,YAAY,OAAO,kBAAkB,WAAW;AACzD,MAAY,mBAAM,kBAAkB;AAAA,IACtC;AAEA,UAAM,YAAY,kBAAkB;AAAA,EACtC,CAAC;AAED,cAAY,OAAO,QAAQ;AAC7B;AAEA,KAAK;","names":["actionsCore","fs","os","path"]} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 16a141e..86daf49 100644 --- a/src/index.ts +++ b/src/index.ts @@ -274,9 +274,9 @@ class MagicNixCacheAction { try { actionsCore.debug(`Indicating workflow start`); const hostAndPort = inputs.getString("listen"); - const res: Response = await this.client.post( - `http://${hostAndPort}/api/workflow-start`, - ); + const res: Response = await this.client + .post(`http://${hostAndPort}/api/workflow-start`) + .json(); if (res.statusCode !== 200) { this.failInStrictMode( @@ -284,7 +284,7 @@ class MagicNixCacheAction { ); } - actionsCore.debug(`back from post: ${JSON.stringify(res)}`); + actionsCore.debug(`back from post: ${JSON.stringify(res.body)}`); } catch (e) { actionsCore.info(`Error marking the workflow as started:`); actionsCore.info(inspect(e)); From 7f10b5e63d7a0de43072b87e65a609931aba16c5 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 09:35:11 -0300 Subject: [PATCH 12/27] Fix HTTP handling logic --- dist/index.js | 13 ++++++------- dist/index.js.map | 2 +- src/index.ts | 15 ++++++++------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/dist/index.js b/dist/index.js index e53e2b5..fdb1b76 100644 --- a/dist/index.js +++ b/dist/index.js @@ -94816,6 +94816,7 @@ var MagicNixCacheAction = class { limit: 1, methods: ["POST", "GET", "PUT", "HEAD", "DELETE", "OPTIONS", "TRACE"] }, + resolveBodyOnly: false, hooks: { beforeRetry: [ (error, retryCount) => { @@ -94999,10 +95000,10 @@ var MagicNixCacheAction = class { const res = await this.client.post(`http://${hostAndPort}/api/workflow-start`).json(); if (res.statusCode !== 200) { this.failInStrictMode( - `Failed to trigger workflow start hook. Expected status 200 but got ${res.statusCode}` + `Failed to trigger workflow start hook; expected status 200 but got ${res.statusCode}` ); } - core.debug(`back from post: ${JSON.stringify(res.body)}`); + core.debug(`back from post: ${res.body}`); } catch (e) { core.info(`Error marking the workflow as started:`); core.info((0,external_node_util_.inspect)(e)); @@ -95027,15 +95028,13 @@ var MagicNixCacheAction = class { try { core.debug(`about to post to localhost`); const hostAndPort = inputs_exports.getString("listen"); - const res = await this.client.post( - `http://${hostAndPort}/api/workflow-finish` - ); + const res = await this.client.post(`http://${hostAndPort}/api/workflow-finish`).json(); if (res.statusCode !== 200) { this.failInStrictMode( - `Failed to trigger workflow finish hook. Expected status 200 but got ${res.statusCode}` + `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}` ); } - core.debug(`back from post: ${JSON.stringify(res.body)}`); + core.debug(`back from post: ${res.body}`); } finally { core.debug(`unwatching the daemon log`); log.unwatch(); diff --git a/dist/index.js.map b/dist/index.js.map index 75d4cfc..bd46c39 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook. Expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${JSON.stringify(res.body)}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client.post(\n `http://${hostAndPort}/api/workflow-finish`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook. Expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${JSON.stringify(res.body)}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n resolveBodyOnly: false,\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook; expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-finish`)\n .json();\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 86daf49..575d0b2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -50,6 +50,7 @@ class MagicNixCacheAction { limit: 1, methods: ["POST", "GET", "PUT", "HEAD", "DELETE", "OPTIONS", "TRACE"], }, + resolveBodyOnly: false, hooks: { beforeRetry: [ (error, retryCount) => { @@ -280,11 +281,11 @@ class MagicNixCacheAction { if (res.statusCode !== 200) { this.failInStrictMode( - `Failed to trigger workflow start hook. Expected status 200 but got ${res.statusCode}`, + `Failed to trigger workflow start hook; expected status 200 but got ${res.statusCode}`, ); } - actionsCore.debug(`back from post: ${JSON.stringify(res.body)}`); + actionsCore.debug(`back from post: ${res.body}`); } catch (e) { actionsCore.info(`Error marking the workflow as started:`); actionsCore.info(inspect(e)); @@ -314,17 +315,17 @@ class MagicNixCacheAction { try { actionsCore.debug(`about to post to localhost`); const hostAndPort = inputs.getString("listen"); - const res: Response = await this.client.post( - `http://${hostAndPort}/api/workflow-finish`, - ); + const res: Response = await this.client + .post(`http://${hostAndPort}/api/workflow-finish`) + .json(); if (res.statusCode !== 200) { this.failInStrictMode( - `Failed to trigger workflow finish hook. Expected status 200 but got ${res.statusCode}`, + `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}`, ); } - actionsCore.debug(`back from post: ${JSON.stringify(res.body)}`); + actionsCore.debug(`back from post: ${res.body}`); } finally { actionsCore.debug(`unwatching the daemon log`); log.unwatch(); From cfa539aa360d722c3f0071a1a1dbf0b2be6ac8f3 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 09:36:30 -0300 Subject: [PATCH 13/27] Remove .json() calls --- src/index.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/index.ts b/src/index.ts index 575d0b2..fece483 100644 --- a/src/index.ts +++ b/src/index.ts @@ -50,7 +50,6 @@ class MagicNixCacheAction { limit: 1, methods: ["POST", "GET", "PUT", "HEAD", "DELETE", "OPTIONS", "TRACE"], }, - resolveBodyOnly: false, hooks: { beforeRetry: [ (error, retryCount) => { @@ -275,9 +274,9 @@ class MagicNixCacheAction { try { actionsCore.debug(`Indicating workflow start`); const hostAndPort = inputs.getString("listen"); - const res: Response = await this.client - .post(`http://${hostAndPort}/api/workflow-start`) - .json(); + const res: Response = await this.client.post( + `http://${hostAndPort}/api/workflow-start`, + ); if (res.statusCode !== 200) { this.failInStrictMode( @@ -315,9 +314,9 @@ class MagicNixCacheAction { try { actionsCore.debug(`about to post to localhost`); const hostAndPort = inputs.getString("listen"); - const res: Response = await this.client - .post(`http://${hostAndPort}/api/workflow-finish`) - .json(); + const res: Response = await this.client.post( + `http://${hostAndPort}/api/workflow-finish`, + ); if (res.statusCode !== 200) { this.failInStrictMode( From 148bd72756e6866e5ce3a04550a01925926f1922 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 09:39:04 -0300 Subject: [PATCH 14/27] Regenerate dist --- dist/index.js | 9 ++++++--- dist/index.js.map | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/dist/index.js b/dist/index.js index fdb1b76..998a080 100644 --- a/dist/index.js +++ b/dist/index.js @@ -94816,7 +94816,6 @@ var MagicNixCacheAction = class { limit: 1, methods: ["POST", "GET", "PUT", "HEAD", "DELETE", "OPTIONS", "TRACE"] }, - resolveBodyOnly: false, hooks: { beforeRetry: [ (error, retryCount) => { @@ -94997,7 +94996,9 @@ var MagicNixCacheAction = class { try { core.debug(`Indicating workflow start`); const hostAndPort = inputs_exports.getString("listen"); - const res = await this.client.post(`http://${hostAndPort}/api/workflow-start`).json(); + const res = await this.client.post( + `http://${hostAndPort}/api/workflow-start` + ); if (res.statusCode !== 200) { this.failInStrictMode( `Failed to trigger workflow start hook; expected status 200 but got ${res.statusCode}` @@ -95028,7 +95029,9 @@ var MagicNixCacheAction = class { try { core.debug(`about to post to localhost`); const hostAndPort = inputs_exports.getString("listen"); - const res = await this.client.post(`http://${hostAndPort}/api/workflow-finish`).json(); + const res = await this.client.post( + `http://${hostAndPort}/api/workflow-finish` + ); if (res.statusCode !== 200) { this.failInStrictMode( `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}` diff --git a/dist/index.js.map b/dist/index.js.map index bd46c39..299da8e 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n resolveBodyOnly: false,\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-start`)\n .json();\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook; expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client\n .post(`http://${hostAndPort}/api/workflow-finish`)\n .json();\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client.post(\n `http://${hostAndPort}/api/workflow-start`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook; expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client.post(\n `http://${hostAndPort}/api/workflow-finish`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":";AAAA,YAAY,iBAAiB;AAC7B,YAAY,QAAQ;AACpB,YAAY,QAAQ;AACpB,OAAO,UAAU;AACjB,SAAS,YAAY;AAEd,SAAS,QAAQ,WAAyB;AAC/C,QAAM,MAAM,IAAI,KAAK,KAAK,KAAK,WAAW,YAAY,CAAC;AACvD,EAAY,kBAAM,uBAAuB;AACzC,MAAI,GAAG,QAAQ,CAAC,SAAS;AACvB,IAAY,iBAAK,IAAI;AAAA,EACvB,CAAC;AACD,SAAO;AACT;AAEA,eAAsB,YAA6B;AACjD,QAAM,oBAAoB,KAAK;AAAA,IAC7B,QAAQ,IAAI,aAAa,KAAQ,UAAO;AAAA,IACxC;AAAA,EACF;AACA,MAAI;AACF,UAAS,UAAO,iBAAiB;AACjC,WAAO;AAAA,EACT,QAAQ;AAEN,UAAM,oBAAoB,KAAK;AAAA,MAC7B,QAAQ,IAAI,aAAa,KAAQ,UAAO;AAAA,MACxC;AAAA,IACF;AACA,QAAI;AACF,YAAM,cAAc,iBAAiB;AAAA,IACvC,SAAS,GAAG;AACV,MAAY,iBAAK,0BAA0B;AAC3C,MAAY,kBAAM,sCAAsC,CAAC,EAAE;AAAA,IAC7D;AACA,WAAO;AAAA,EACT;AACF;AAEA,eAAe,cAAc,OAA8B;AACzD,QAAM,MAAM,MAAkB,uBAAW,kBAAkB;AAE3D,QAAS;AAAA,IACP;AAAA,IACA;AAAA,MACE,oDAAoD,GAAG;AAAA,MACvD,gDAAgD,GAAG;AAAA,MACnD,sDAAsD,GAAG;AAAA,IAC3D,EAAE,KAAK,IAAI;AAAA,EACb;AAEA,EAAY,iBAAK,wBAAwB;AAC3C;;;ACnDA,YAAYA,kBAAiB;AAC7B,SAAS,YAAY,cAAc;AACnC,OAAO,SAA4B;AACnC,YAAY,UAAU;AACtB,SAAuB,MAAM,aAAa;AAC1C,SAAS,WAAW,UAAU,oBAAoB;AAClD,YAAYC,SAAQ;AACpB,YAAYC,SAAQ;AACpB,YAAYC,WAAU;AACtB,SAAS,SAAS,iBAAiB;AAKnC,IAAM,iBAAiB;AAEvB,IAAM,kBAAkB;AACxB,IAAM,gBAAgB;AACtB,IAAM,eAAe;AAErB,IAAM,YACJ;AACF,IAAM,uBACJ;AACF,IAAM,qBACJ;AAEF,IAAM,sBAAN,MAA0B;AAAA,EASxB,cAAc;AACZ,SAAK,SAAS,IAAI,WAAW;AAAA,MAC3B,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,YAAY;AAAA,IACd,CAAC;AAED,SAAK,aAAa,OAAO,QAAQ,aAAa;AAE9C,SAAK,SAAS,IAAI,OAAO;AAAA,MACvB,OAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS,CAAC,QAAQ,OAAO,OAAO,QAAQ,UAAU,WAAW,OAAO;AAAA,MACtE;AAAA,MACA,OAAO;AAAA,QACL,aAAa;AAAA,UACX,CAAC,OAAO,eAAe;AACrB,YAAY;AAAA,cACV,wBAAwB,MAAM,IAAI,cAAc,UAAU;AAAA,YAC5D;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,SAAK,gBAA4B,sBAAS,aAAa,MAAM;AAE7D,QAAgB,sBAAS,eAAe,MAAM,IAAI;AAChD,WAAK,YAAwB,sBAAS,eAAe;AAAA,IACvD,OAAO;AACL,WAAK,YAAY,KAAK,OAAO,iBAAiB;AAC9C,gBAAU,KAAK,SAAS;AACxB,MAAY,uBAAU,iBAAiB,KAAK,SAAS;AAAA,IACvD;AAEA,QAAI,QAAQ,IAAI,cAAc,MAAM,QAAW;AAC7C,WAAK,WAAW;AAChB,MAAY,4BAAe,gBAAgB,KAAK,SAAS;AAAA,IAC3D,OAAO;AACL,WAAK,WAAW,QAAQ,IAAI,cAAc,MAAM,KAAK;AAAA,IACvD;AACA,SAAK,OAAO,QAAQ,aAAa,KAAK,QAAQ;AAE9C,SAAK,OAAO;AAAA,MACV;AAAA,MACK,WAAK,KAAK,WAAW,YAAY;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,MAAM,iBAAgC;AACpC,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI,aAAa;AACjB,eAAW,KAAK,aAAa;AAC3B,UAAI,CAAC,QAAQ,IAAI,eAAe,CAAC,GAAG;AAClC,qBAAa;AACb,QAAY;AAAA,UACV,0DAA0D,CAAC;AAAA,QAC7D;AAAA,MACF;AAAA,IACF;AAEA,SAAK,OAAO,QAAQ,qBAAqB,CAAC,UAAU;AACpD,QAAI,YAAY;AACd;AAAA,IACF;AAEA,QAAI,KAAK,eAAe;AACtB,MAAY,mBAAM,kBAAkB;AACpC;AAAA,IACF;AAEA,IAAY;AAAA,MACV,4BAA4B,QAAQ,IAAI,mBAAmB,CAAC;AAAA,IAC9D;AAEA,UAAM,eAAe,OAAO,gBAAgB,eAAe;AAC3D,UAAM,YACJ,iBAAiB,OAAO,eAAe,MAAM,KAAK,gBAAgB;AAEpE,QAAI;AACJ,QAAgB,qBAAQ,GAAG;AACzB,eAAS;AAAA,QACP,UAAU;AAAA,QACV,gBAAgB;AAAA,QAChB,GAAG,QAAQ;AAAA,MACb;AAAA,IACF,OAAO;AACL,eAAS,QAAQ;AAAA,IACnB;AAEA,UAAM,aAAa,OAAO,UAAU,2BAA2B;AAE/D,UAAM,gBAAgB,IAAI,QAAuB,CAAC,qBAAqB;AACrE,YAAM,UAAU,IAAI,QAAc,OAAO,gBAAgB;AACvD,cAAM,eAAoB,kBAAa,CAAC,KAAK,QAAQ;AACnD,cAAI,IAAI,WAAW,UAAU,IAAI,QAAQ,KAAK;AAC5C,YAAY,mBAAM,8BAA8B;AAChD,gBAAI,UAAU,KAAK,EAAE,gBAAgB,mBAAmB,CAAC;AACzD,gBAAI,IAAI,IAAI;AACZ,yBAAa,MAAM,MAAM;AACvB,0BAAY;AAAA,YACd,CAAC;AAAA,UACH;AAAA,QACF,CAAC;AAED,qBAAa,OAAO,YAAY,MAAM;AACpC,UAAY,mBAAM,wBAAwB;AAC1C,2BAAiB,OAAO;AAAA,QAC1B,CAAC;AAAA,MACH,CAAC;AAAA,IACH,CAAC;AAGD,UAAM,aAAa,GAAG,KAAK,SAAS;AACpC,UAAM,SAAS,SAAS,YAAY,GAAG;AACvC,UAAM,MAAM,QAAQ,KAAK,SAAS;AAClC,UAAM,QAAQ,MAAM,UAAU;AAC9B,UAAM,cAAc,GAAG,QAAQ,IAAI,MAAM,CAAC;AAE1C,UAAM,cAAc,OAAO,UAAU,QAAQ;AAC7C,UAAM,gBAAgB,OAAO,UAAU,gBAAgB;AACvD,UAAM,qBAAqB,OAAO,UAAU,qBAAqB;AACjE,UAAM,cAAc,OAAO,QAAQ,cAAc;AACjD,UAAM,sBAAsB,OAAO,UAAU,uBAAuB;AACpE,UAAM,oBAAoB,OAAO,UAAU,qBAAqB;AAChE,UAAM,oBAAoB,OAAO,UAAU,qBAAqB;AAChE,UAAM,cAAc,OAAO,QAAQ,eAAe;AAElD,UAAM,iBAA2B;AAAA,MAC/B;AAAA,MACA,oBAAoB,UAAU;AAAA,MAC9B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EACG;AAAA,MACC,cACI;AAAA,QACE;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,IACA,CAAC;AAAA,IACP,EACC,OAAO,cAAc,CAAC,iBAAiB,IAAI,CAAC,CAAC;AAEhD,UAAM,OAAqB;AAAA,MACzB,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,MAChC,KAAK;AAAA,MACL,UAAU;AAAA,IACZ;AAGA,IAAY,mBAAM,4BAA4B;AAC9C,IAAY,mBAAM,GAAG,SAAS,IAAI,eAAe,KAAK,GAAG,CAAC,EAAE;AAG5D,UAAM,SAAS,MAAM,WAAW,gBAAgB,IAAI;AAEpD,SAAK,gBAAgB;AACrB,IAAY,uBAAU,eAAe,YAAY;AAEjD,UAAM,UAAe,WAAK,KAAK,WAAW,YAAY;AACtD,UAAS,cAAU,SAAS,GAAG,OAAO,GAAG,EAAE;AAE3C,IAAY,kBAAK,yCAAyC;AAE1D,UAAM,IAAI,QAAc,CAAC,SAAS,WAAW;AAC3C,oBAEG,KAAK,CAAC,WAAW;AAChB,gBAAQ;AAAA,MACV,CAAC,EAEA,MAAM,CAAC,QAAQ;AACd,cAAM,MAAM,2BAA2B,GAAG;AAC1C,eAAO,IAAI,MAAM,GAAG,CAAC;AACrB,aAAK,iBAAiB,GAAG;AAAA,MAC3B,CAAC;AACH,aAAO,GAAG,QAAQ,OAAO,MAAM,WAAW;AACxC,YAAI;AACJ,YAAI,QAAQ;AACV,gBAAM,+BAA+B,MAAM;AAAA,QAC7C,WAAW,MAAM;AACf,gBAAM,2BAA2B,IAAI;AAAA,QACvC,OAAO;AACL,gBAAM;AAAA,QACR;AACA,eAAO,IAAI,MAAM,GAAG,CAAC;AACrB,aAAK,iBAAiB,GAAG;AAAA,MAC3B,CAAC;AAAA,IACH,CAAC;AAED,WAAO,MAAM;AAEb,IAAY,kBAAK,0BAA0B;AAE3C,QAAI,QAAQ;AAAA,EACd;AAAA,EAEA,MAAc,kBAAmC;AAC/C,UAAM,cAAc,MAAM,KAAK,OAAO,MAAM;AAC5C,SAAK,OAAO,YAAY,cAAc;AACtC,UAAM,EAAE,OAAO,IAAI,MAAM,UAAU,IAAI;AAAA,MACrC,QAAQ,WAAW;AAAA,IACrB;AAEA,UAAM,QAAQ,OAAO,MAAS,OAAG;AAEjC,UAAM,WAAW,MAAM,GAAG,EAAE;AAC5B,WAAO,GAAG,QAAQ;AAAA,EACpB;AAAA,EAEA,MAAM,kBAAiC;AACrC,QAAI,CAAC,KAAK,eAAe;AACvB,MAAY,mBAAM,wCAAwC;AAC1D;AAAA,IACF;AAEA,QAAI;AACF,MAAY,mBAAM,2BAA2B;AAC7C,YAAM,cAAc,OAAO,UAAU,QAAQ;AAC7C,YAAM,MAAwB,MAAM,KAAK,OAAO;AAAA,QAC9C,UAAU,WAAW;AAAA,MACvB;AAEA,UAAI,IAAI,eAAe,KAAK;AAC1B,aAAK;AAAA,UACH,sEAAsE,IAAI,UAAU;AAAA,QACtF;AAAA,MACF;AAEA,MAAY,mBAAM,mBAAmB,IAAI,IAAI,EAAE;AAAA,IACjD,SAAS,GAAG;AACV,MAAY,kBAAK,wCAAwC;AACzD,MAAY,kBAAK,QAAQ,CAAC,CAAC;AAC3B,MAAY,kBAAK,uDAAuD;AAExE,WAAK,iBAAiB,oCAAoC,QAAQ,CAAC,CAAC,EAAE;AAAA,IACxE;AAAA,EACF;AAAA,EAEA,MAAM,oBAAmC;AACvC,QAAI,CAAC,KAAK,eAAe;AACvB,MAAY,mBAAM,wCAAwC;AAC1D;AAAA,IACF;AAEA,UAAM,UAAe,WAAK,KAAK,WAAW,YAAY;AACtD,UAAM,MAAM,SAAS,MAAS,aAAS,SAAS,EAAE,UAAU,QAAQ,CAAC,CAAC;AACtE,IAAY,mBAAM,qBAAqB,GAAG,EAAE;AAC5C,QAAI,CAAC,KAAK;AACR,YAAM,MAAM;AACZ,WAAK,iBAAiB,GAAG;AACzB,YAAM,IAAI,MAAM,GAAG;AAAA,IACrB;AAEA,UAAM,MAAM,QAAQ,KAAK,SAAS;AAElC,QAAI;AACF,MAAY,mBAAM,4BAA4B;AAC9C,YAAM,cAAc,OAAO,UAAU,QAAQ;AAC7C,YAAM,MAAwB,MAAM,KAAK,OAAO;AAAA,QAC9C,UAAU,WAAW;AAAA,MACvB;AAEA,UAAI,IAAI,eAAe,KAAK;AAC1B,aAAK;AAAA,UACH,uEAAuE,IAAI,UAAU;AAAA,QACvF;AAAA,MACF;AAEA,MAAY,mBAAM,mBAAmB,IAAI,IAAI,EAAE;AAAA,IACjD,UAAE;AACA,MAAY,mBAAM,2BAA2B;AAC7C,UAAI,QAAQ;AAAA,IACd;AAEA,IAAY,mBAAM,SAAS;AAC3B,QAAI;AACF,cAAQ,KAAK,KAAK,SAAS;AAAA,IAC7B,SAAS,GAAG;AACV,UAAI,OAAO,MAAM,YAAY,KAAK,UAAU,KAAK,EAAE,SAAS,SAAS;AACnE,aAAK,iBAAiB,EAAE,SAAS,CAAC;AAClC,cAAM;AAAA,MACR;AAAA,IACF,UAAE;AACA,UAAgB,qBAAQ,GAAG;AACzB,QAAY,kBAAK,aAAa;AAC9B,cAAM,YAAY,aAAkB,WAAK,KAAK,WAAW,YAAY,CAAC;AACtE,QAAY,kBAAK,UAAU,SAAS,CAAC;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,iBAAiB,KAAmB;AAC1C,QAAI,KAAK,YAAY;AACnB,MAAY,uBAAU,sBAAsB,GAAG,EAAE;AAAA,IACnD;AAAA,EACF;AACF;AAEA,SAAS,OAAa;AACpB,QAAM,cAAc,IAAI,oBAAoB;AAE5C,cAAY,OAAO,OAAO,YAAY;AACpC,QAAI,YAAY,UAAU;AACxB,MAAY,qBAAQ,SAAS;AAC7B;AAAA,IACF;AAEA,QAAI,YAAY,OAAO,kBAAkB,aAAa;AACpD,MAAY,qBAAQ,oBAAoB;AACxC;AAAA,IACF,WAAW,YAAY,OAAO,kBAAkB,WAAW;AACzD,MAAY,kBAAK,kBAAkB;AAAA,IACrC;AAEA,UAAM,YAAY,eAAe;AACjC,UAAM,YAAY,gBAAgB;AAAA,EACpC,CAAC;AACD,cAAY,OAAO,OAAO,YAAY;AACpC,QAAI,YAAY,UAAU;AACxB,MAAY,mBAAM,SAAS;AAC3B;AAAA,IACF;AAEA,QAAI,YAAY,OAAO,kBAAkB,aAAa;AACpD,MAAY,mBAAM,oBAAoB;AACtC;AAAA,IACF,WAAW,YAAY,OAAO,kBAAkB,WAAW;AACzD,MAAY,mBAAM,kBAAkB;AAAA,IACtC;AAEA,UAAM,YAAY,kBAAkB;AAAA,EACtC,CAAC;AAED,cAAY,OAAO,QAAQ;AAC7B;AAEA,KAAK;","names":["actionsCore","fs","os","path"]} \ No newline at end of file From ec531ea91f298ace47f848e5749ef80f67781118 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 09:39:29 -0300 Subject: [PATCH 15/27] Make system-specific runs rely on success of build job --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6c1f80a..afe2dce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,6 +74,7 @@ jobs: [ $(nix config show substituters) == "https://cache.nixos.org/" ] run-systems: + needs: build name: "Run ${{ matrix.systems.nix-system }}" runs-on: "${{ matrix.systems.runner }}" permissions: From afefc2fc85ebc25f20724c6a6aed256ed085cbf9 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 11:19:46 -0300 Subject: [PATCH 16/27] Always log status code and body --- dist/index.js | 17 ++++++++++------- dist/index.js.map | 2 +- src/index.ts | 22 +++++++++++++--------- 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/dist/index.js b/dist/index.js index 998a080..2e3fad2 100644 --- a/dist/index.js +++ b/dist/index.js @@ -94811,6 +94811,7 @@ var MagicNixCacheAction = class { requireNix: "warn" }); this.strictMode = inputs_exports.getBool("strict-mode"); + this.hostAndPort = inputs_exports.getString("listen"); this.client = got_dist_source.extend({ retry: { limit: 1, @@ -94908,7 +94909,6 @@ var MagicNixCacheAction = class { const log = tailLog(this.daemonDir); const netrc = await netrcPath(); const nixConfPath = `${process.env["HOME"]}/.config/nix/nix.conf`; - const hostAndPort = inputs_exports.getString("listen"); const upstreamCache = inputs_exports.getString("upstream-cache"); const diagnosticEndpoint = inputs_exports.getString("diagnostic-endpoint"); const useFlakeHub = inputs_exports.getBool("use-flakehub"); @@ -94920,7 +94920,7 @@ var MagicNixCacheAction = class { "--startup-notification-url", `http://127.0.0.1:${notifyPort}`, "--listen", - hostAndPort, + this.hostAndPort, "--upstream", upstreamCache, "--diagnostic-endpoint", @@ -94995,9 +94995,11 @@ var MagicNixCacheAction = class { } try { core.debug(`Indicating workflow start`); - const hostAndPort = inputs_exports.getString("listen"); const res = await this.client.post( - `http://${hostAndPort}/api/workflow-start` + `http://${this.hostAndPort}/api/workflow-start` + ); + core.debug( + `post to /api/workflow-start (status: ${res.statusCode}, body: ${res.body})` ); if (res.statusCode !== 200) { this.failInStrictMode( @@ -95028,16 +95030,17 @@ var MagicNixCacheAction = class { const log = tailLog(this.daemonDir); try { core.debug(`about to post to localhost`); - const hostAndPort = inputs_exports.getString("listen"); const res = await this.client.post( - `http://${hostAndPort}/api/workflow-finish` + `http://${this.hostAndPort}/api/workflow-finish` + ); + core.debug( + `post to /api/workflow-finish (status: ${res.statusCode}, body: ${res.body})` ); if (res.statusCode !== 200) { this.failInStrictMode( `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}` ); } - core.debug(`back from post: ${res.body}`); } finally { core.debug(`unwatching the daemon log`); log.unwatch(); diff --git a/dist/index.js.map b/dist/index.js.map index 299da8e..7f51c8d 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n\n const hostAndPort = inputs.getString(\"listen\");\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client.post(\n `http://${hostAndPort}/api/workflow-start`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook; expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const hostAndPort = inputs.getString(\"listen\");\n const res: Response = await this.client.post(\n `http://${hostAndPort}/api/workflow-finish`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private hostAndPort: string;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n actionsCore.debug(\n `post to /api/workflow-start (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook; expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n actionsCore.debug(\n `post to /api/workflow-finish (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index fece483..bda18a7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -29,6 +29,7 @@ const TEXT_TRUST_UNKNOWN = class MagicNixCacheAction { idslib: IdsToolbox; private strictMode: boolean; + private hostAndPort: string; private client: Got; noopMode: boolean; @@ -44,6 +45,7 @@ class MagicNixCacheAction { }); this.strictMode = inputs.getBool("strict-mode"); + this.hostAndPort = inputs.getString("listen"); this.client = got.extend({ retry: { @@ -159,8 +161,6 @@ class MagicNixCacheAction { const log = tailLog(this.daemonDir); const netrc = await netrcPath(); const nixConfPath = `${process.env["HOME"]}/.config/nix/nix.conf`; - - const hostAndPort = inputs.getString("listen"); const upstreamCache = inputs.getString("upstream-cache"); const diagnosticEndpoint = inputs.getString("diagnostic-endpoint"); const useFlakeHub = inputs.getBool("use-flakehub"); @@ -173,7 +173,7 @@ class MagicNixCacheAction { "--startup-notification-url", `http://127.0.0.1:${notifyPort}`, "--listen", - hostAndPort, + this.hostAndPort, "--upstream", upstreamCache, "--diagnostic-endpoint", @@ -273,9 +273,12 @@ class MagicNixCacheAction { try { actionsCore.debug(`Indicating workflow start`); - const hostAndPort = inputs.getString("listen"); const res: Response = await this.client.post( - `http://${hostAndPort}/api/workflow-start`, + `http://${this.hostAndPort}/api/workflow-start`, + ); + + actionsCore.debug( + `post to /api/workflow-start (status: ${res.statusCode}, body: ${res.body})`, ); if (res.statusCode !== 200) { @@ -313,9 +316,12 @@ class MagicNixCacheAction { try { actionsCore.debug(`about to post to localhost`); - const hostAndPort = inputs.getString("listen"); const res: Response = await this.client.post( - `http://${hostAndPort}/api/workflow-finish`, + `http://${this.hostAndPort}/api/workflow-finish`, + ); + + actionsCore.debug( + `post to /api/workflow-finish (status: ${res.statusCode}, body: ${res.body})`, ); if (res.statusCode !== 200) { @@ -323,8 +329,6 @@ class MagicNixCacheAction { `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}`, ); } - - actionsCore.debug(`back from post: ${res.body}`); } finally { actionsCore.debug(`unwatching the daemon log`); log.unwatch(); From a181f8e6e8841e7ec0f9388093730678bb88ae8d Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 11:55:57 -0300 Subject: [PATCH 17/27] Pass HTTP body to failure log --- src/index.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/index.ts b/src/index.ts index bda18a7..11740e3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -277,13 +277,9 @@ class MagicNixCacheAction { `http://${this.hostAndPort}/api/workflow-start`, ); - actionsCore.debug( - `post to /api/workflow-start (status: ${res.statusCode}, body: ${res.body})`, - ); - if (res.statusCode !== 200) { this.failInStrictMode( - `Failed to trigger workflow start hook; expected status 200 but got ${res.statusCode}`, + `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`, ); } @@ -320,13 +316,9 @@ class MagicNixCacheAction { `http://${this.hostAndPort}/api/workflow-finish`, ); - actionsCore.debug( - `post to /api/workflow-finish (status: ${res.statusCode}, body: ${res.body})`, - ); - if (res.statusCode !== 200) { this.failInStrictMode( - `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}`, + `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`, ); } } finally { From 6551db427e7f5d4e0f7813e6f475d5be51ceddc2 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 11:57:41 -0300 Subject: [PATCH 18/27] Regenerate dist --- dist/index.js | 10 ++-------- dist/index.js.map | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/dist/index.js b/dist/index.js index 2e3fad2..db298b8 100644 --- a/dist/index.js +++ b/dist/index.js @@ -94998,12 +94998,9 @@ var MagicNixCacheAction = class { const res = await this.client.post( `http://${this.hostAndPort}/api/workflow-start` ); - core.debug( - `post to /api/workflow-start (status: ${res.statusCode}, body: ${res.body})` - ); if (res.statusCode !== 200) { this.failInStrictMode( - `Failed to trigger workflow start hook; expected status 200 but got ${res.statusCode}` + `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})` ); } core.debug(`back from post: ${res.body}`); @@ -95033,12 +95030,9 @@ var MagicNixCacheAction = class { const res = await this.client.post( `http://${this.hostAndPort}/api/workflow-finish` ); - core.debug( - `post to /api/workflow-finish (status: ${res.statusCode}, body: ${res.body})` - ); if (res.statusCode !== 200) { this.failInStrictMode( - `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}` + `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})` ); } } finally { diff --git a/dist/index.js.map b/dist/index.js.map index 7f51c8d..b35b408 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private hostAndPort: string;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n actionsCore.debug(\n `post to /api/workflow-start (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook; expected status 200 but got ${res.statusCode}`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n actionsCore.debug(\n `post to /api/workflow-finish (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected status 200 but got ${res.statusCode}`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private hostAndPort: string;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file From fe4aeab234ad45b830744f9883d387bd973de6b1 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 13:58:18 -0300 Subject: [PATCH 19/27] Reinstate debug statements --- src/index.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/index.ts b/src/index.ts index 11740e3..1784f47 100644 --- a/src/index.ts +++ b/src/index.ts @@ -277,6 +277,10 @@ class MagicNixCacheAction { `http://${this.hostAndPort}/api/workflow-start`, ); + actionsCore.debug( + `Response from POST to /api/workflow-start: (status: ${res.statusCode}, body: ${res.body})`, + ); + if (res.statusCode !== 200) { this.failInStrictMode( `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`, @@ -316,6 +320,10 @@ class MagicNixCacheAction { `http://${this.hostAndPort}/api/workflow-finish`, ); + actionsCore.debug( + `Response from POST to /api/workflow-finish: (status: ${res.statusCode}, body: ${res.body})`, + ); + if (res.statusCode !== 200) { this.failInStrictMode( `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`, From d53320e748ab1398a9f8ef057ba494bb886bff85 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 20 May 2024 13:58:36 -0300 Subject: [PATCH 20/27] Regenerate dist --- dist/index.js | 6 ++++++ dist/index.js.map | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/dist/index.js b/dist/index.js index db298b8..78417ab 100644 --- a/dist/index.js +++ b/dist/index.js @@ -94998,6 +94998,9 @@ var MagicNixCacheAction = class { const res = await this.client.post( `http://${this.hostAndPort}/api/workflow-start` ); + core.debug( + `Response from POST to /api/workflow-start: (status: ${res.statusCode}, body: ${res.body})` + ); if (res.statusCode !== 200) { this.failInStrictMode( `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})` @@ -95030,6 +95033,9 @@ var MagicNixCacheAction = class { const res = await this.client.post( `http://${this.hostAndPort}/api/workflow-finish` ); + core.debug( + `Response from POST to /api/workflow-finish: (status: ${res.statusCode}, body: ${res.body})` + ); if (res.statusCode !== 200) { this.failInStrictMode( `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})` diff --git a/dist/index.js.map b/dist/index.js.map index b35b408..e328ece 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private hostAndPort: string;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private hostAndPort: string;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-start: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-finish: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file From 69a317751693a7a4d6fdf2778a5e280b22037cdc Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Wed, 22 May 2024 13:23:30 -0300 Subject: [PATCH 21/27] Change variable name Co-authored-by: Graham Christensen --- action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/action.yml b/action.yml index 442d900..c7428ca 100644 --- a/action.yml +++ b/action.yml @@ -51,7 +51,7 @@ inputs: source-url: description: A URL pointing to a `magic-nix-cache` binary. Overrides all other `source-*` options. required: false - strict-mode: + _internal-strict-mode: description: Whether to fail when any errors are thrown. Used only to test the Action; do not set this in your own workflows. default: false required: false From 08f6eb41e5eac75e0bde8650160eb3215beca77d Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Wed, 22 May 2024 13:26:19 -0300 Subject: [PATCH 22/27] Update strict mode name in code --- .github/workflows/ci.yml | 6 +++--- dist/index.js | 2 +- dist/index.js.map | 2 +- src/index.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index afe2dce..5a98ed3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: - name: Cache the store uses: ./ with: - strict-mode: true + _internal-strict-mode: true run-x86_64-linux-untrusted: needs: build @@ -68,7 +68,7 @@ jobs: - name: Cache the store uses: ./ with: - strict-mode: true + _internal-strict-mode: true - name: Check the cache isn't enabled run: | [ $(nix config show substituters) == "https://cache.nixos.org/" ] @@ -102,7 +102,7 @@ jobs: - name: Cache the store uses: ./ with: - strict-mode: true + _internal-strict-mode: true - name: Check the cache for liveness run: | .github/workflows/cache-test.sh diff --git a/dist/index.js b/dist/index.js index 78417ab..f45b8c2 100644 --- a/dist/index.js +++ b/dist/index.js @@ -94810,7 +94810,7 @@ var MagicNixCacheAction = class { idsProjectName: "magic-nix-cache-closure", requireNix: "warn" }); - this.strictMode = inputs_exports.getBool("strict-mode"); + this.strictMode = inputs_exports.getBool("_internal-strict-mode"); this.hostAndPort = inputs_exports.getString("listen"); this.client = got_dist_source.extend({ retry: { diff --git a/dist/index.js.map b/dist/index.js.map index e328ece..fe4fb2e 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private hostAndPort: string;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"strict-mode\");\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-start: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-finish: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private hostAndPort: string;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"_internal-strict-mode\");\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-start: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-finish: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 1784f47..7bcf751 100644 --- a/src/index.ts +++ b/src/index.ts @@ -44,7 +44,7 @@ class MagicNixCacheAction { requireNix: "warn", }); - this.strictMode = inputs.getBool("strict-mode"); + this.strictMode = inputs.getBool("_internal-strict-mode"); this.hostAndPort = inputs.getString("listen"); this.client = got.extend({ From e1ac8233469595b9ca18adb8611993c1bcef1923 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Wed, 22 May 2024 15:01:28 -0300 Subject: [PATCH 23/27] Update strict mode logic --- action.yml | 1 - dist/index.js | 1236 +++++++++++++++++++++++++++++---------------- dist/index.js.map | 2 +- package.json | 6 +- pnpm-lock.yaml | 361 ++++++------- src/index.ts | 121 ++--- 6 files changed, 1036 insertions(+), 691 deletions(-) diff --git a/action.yml b/action.yml index c7428ca..cfd6954 100644 --- a/action.yml +++ b/action.yml @@ -54,7 +54,6 @@ inputs: _internal-strict-mode: description: Whether to fail when any errors are thrown. Used only to test the Action; do not set this in your own workflows. default: false - required: false runs: using: "node20" diff --git a/dist/index.js b/dist/index.js index f45b8c2..7a70a69 100644 --- a/dist/index.js +++ b/dist/index.js @@ -796,7 +796,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.downloadCacheStorageSDK = exports.downloadCacheHttpClientConcurrent = exports.downloadCacheHttpClient = exports.DownloadProgress = void 0; const core = __importStar(__nccwpck_require__(9093)); const http_client_1 = __nccwpck_require__(6372); -const storage_blob_1 = __nccwpck_require__(5542); +const storage_blob_1 = __nccwpck_require__(4883); const buffer = __importStar(__nccwpck_require__(4300)); const fs = __importStar(__nccwpck_require__(7147)); const stream = __importStar(__nccwpck_require__(2781)); @@ -11711,7 +11711,7 @@ exports.setSpanContext = setSpanContext; /***/ }), -/***/ 5542: +/***/ 4883: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { @@ -20223,7 +20223,7 @@ const timeoutInSeconds = { const version = { parameterPath: "version", mapper: { - defaultValue: "2023-11-03", + defaultValue: "2024-05-04", isConstant: true, serializedName: "x-ms-version", type: { @@ -25054,8 +25054,8 @@ const logger = logger$1.createClientLogger("storage-blob"); // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -const SDK_VERSION = "12.17.0"; -const SERVICE_VERSION = "2023-11-03"; +const SDK_VERSION = "12.18.0"; +const SERVICE_VERSION = "2024-05-04"; const BLOCK_BLOB_MAX_UPLOAD_BLOB_BYTES = 256 * 1024 * 1024; // 256MB const BLOCK_BLOB_MAX_STAGE_BLOCK_BYTES = 4000 * 1024 * 1024; // 4000MB const BLOCK_BLOB_MAX_BLOCKS = 50000; @@ -26915,7 +26915,7 @@ class StorageSharedKeyCredential extends Credential { * Changes may cause incorrect behavior and will be lost if the code is regenerated. */ const packageName = "azure-storage-blob"; -const packageVersion = "12.17.0"; +const packageVersion = "12.18.0"; class StorageClientContext extends coreHttp__namespace.ServiceClient { /** * Initializes a new instance of the StorageClientContext class. @@ -26941,7 +26941,7 @@ class StorageClientContext extends coreHttp__namespace.ServiceClient { // Parameter assignments this.url = url; // Assigning values to Constant parameters - this.version = options.version || "2023-11-03"; + this.version = options.version || "2024-05-04"; } } @@ -39513,7 +39513,7 @@ module.exports = { parallel : __nccwpck_require__(644), serial : __nccwpck_require__(4501), - serialOrdered : __nccwpck_require__(2362) + serialOrdered : __nccwpck_require__(3958) }; @@ -39844,7 +39844,7 @@ function parallel(list, iterator, callback) /***/ 4501: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -var serialOrdered = __nccwpck_require__(2362); +var serialOrdered = __nccwpck_require__(3958); // Public API module.exports = serial; @@ -39865,7 +39865,7 @@ function serial(list, iterator, callback) /***/ }), -/***/ 2362: +/***/ 3958: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { var iterate = __nccwpck_require__(5748) @@ -41215,133 +41215,6 @@ module.exports = function(dst, src) { }; -/***/ }), - -/***/ 1210: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - - -const {PassThrough: PassThroughStream} = __nccwpck_require__(2781); - -module.exports = options => { - options = {...options}; - - const {array} = options; - let {encoding} = options; - const isBuffer = encoding === 'buffer'; - let objectMode = false; - - if (array) { - objectMode = !(encoding || isBuffer); - } else { - encoding = encoding || 'utf8'; - } - - if (isBuffer) { - encoding = null; - } - - const stream = new PassThroughStream({objectMode}); - - if (encoding) { - stream.setEncoding(encoding); - } - - let length = 0; - const chunks = []; - - stream.on('data', chunk => { - chunks.push(chunk); - - if (objectMode) { - length = chunks.length; - } else { - length += chunk.length; - } - }); - - stream.getBufferedValue = () => { - if (array) { - return chunks; - } - - return isBuffer ? Buffer.concat(chunks, length) : chunks.join(''); - }; - - stream.getBufferedLength = () => length; - - return stream; -}; - - -/***/ }), - -/***/ 1798: -/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { - - -const {constants: BufferConstants} = __nccwpck_require__(4300); -const stream = __nccwpck_require__(2781); -const {promisify} = __nccwpck_require__(3837); -const bufferStream = __nccwpck_require__(1210); - -const streamPipelinePromisified = promisify(stream.pipeline); - -class MaxBufferError extends Error { - constructor() { - super('maxBuffer exceeded'); - this.name = 'MaxBufferError'; - } -} - -async function getStream(inputStream, options) { - if (!inputStream) { - throw new Error('Expected a stream'); - } - - options = { - maxBuffer: Infinity, - ...options - }; - - const {maxBuffer} = options; - const stream = bufferStream(options); - - await new Promise((resolve, reject) => { - const rejectPromise = error => { - // Don't retrieve an oversized buffer. - if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) { - error.bufferedData = stream.getBufferedValue(); - } - - reject(error); - }; - - (async () => { - try { - await streamPipelinePromisified(inputStream, stream); - resolve(); - } catch (error) { - rejectPromise(error); - } - })(); - - stream.on('data', () => { - if (stream.getBufferedLength() > maxBuffer) { - rejectPromise(new MaxBufferError()); - } - }); - }); - - return stream.getBufferedValue(); -} - -module.exports = getStream; -module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'}); -module.exports.array = (stream, options) => getStream(stream, {...options, array: true}); -module.exports.MaxBufferError = MaxBufferError; - - /***/ }), /***/ 7893: @@ -86799,7 +86672,7 @@ var external_os_ = __nccwpck_require__(2037); const external_node_crypto_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:crypto"); // EXTERNAL MODULE: ./node_modules/.pnpm/@actions+cache@3.2.4/node_modules/@actions/cache/lib/cache.js var cache = __nccwpck_require__(6878); -;// CONCATENATED MODULE: ./node_modules/.pnpm/@sindresorhus+is@6.3.0/node_modules/@sindresorhus/is/dist/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/@sindresorhus+is@6.3.1/node_modules/@sindresorhus/is/dist/index.js const typedArrayTypeNames = [ 'Int8Array', 'Uint8Array', @@ -88230,7 +88103,7 @@ class PCancelable { Object.setPrototypeOf(PCancelable.prototype, Promise.prototype); -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/errors.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/errors.js // A hacky check to prevent circular references. function isRequest(x) { @@ -88782,8 +88655,449 @@ function normalizeUrl(urlString, options) { return urlString; } -// EXTERNAL MODULE: ./node_modules/.pnpm/get-stream@6.0.1/node_modules/get-stream/index.js -var get_stream = __nccwpck_require__(1798); +;// CONCATENATED MODULE: ./node_modules/.pnpm/is-stream@4.0.1/node_modules/is-stream/index.js +function isStream(stream, {checkOpen = true} = {}) { + return stream !== null + && typeof stream === 'object' + && (stream.writable || stream.readable || !checkOpen || (stream.writable === undefined && stream.readable === undefined)) + && typeof stream.pipe === 'function'; +} + +function isWritableStream(stream, {checkOpen = true} = {}) { + return isStream(stream, {checkOpen}) + && (stream.writable || !checkOpen) + && typeof stream.write === 'function' + && typeof stream.end === 'function' + && typeof stream.writable === 'boolean' + && typeof stream.writableObjectMode === 'boolean' + && typeof stream.destroy === 'function' + && typeof stream.destroyed === 'boolean'; +} + +function isReadableStream(stream, {checkOpen = true} = {}) { + return isStream(stream, {checkOpen}) + && (stream.readable || !checkOpen) + && typeof stream.read === 'function' + && typeof stream.readable === 'boolean' + && typeof stream.readableObjectMode === 'boolean' + && typeof stream.destroy === 'function' + && typeof stream.destroyed === 'boolean'; +} + +function isDuplexStream(stream, options) { + return isWritableStream(stream, options) + && isReadableStream(stream, options); +} + +function isTransformStream(stream, options) { + return isDuplexStream(stream, options) + && typeof stream._transform === 'function'; +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/@sec-ant+readable-stream@0.4.1/node_modules/@sec-ant/readable-stream/dist/ponyfill/asyncIterator.js +const a = Object.getPrototypeOf( + Object.getPrototypeOf( + /* istanbul ignore next */ + async function* () { + } + ).prototype +); +class c { + #t; + #n; + #r = !1; + #e = void 0; + constructor(e, t) { + this.#t = e, this.#n = t; + } + next() { + const e = () => this.#s(); + return this.#e = this.#e ? this.#e.then(e, e) : e(), this.#e; + } + return(e) { + const t = () => this.#i(e); + return this.#e ? this.#e.then(t, t) : t(); + } + async #s() { + if (this.#r) + return { + done: !0, + value: void 0 + }; + let e; + try { + e = await this.#t.read(); + } catch (t) { + throw this.#e = void 0, this.#r = !0, this.#t.releaseLock(), t; + } + return e.done && (this.#e = void 0, this.#r = !0, this.#t.releaseLock()), e; + } + async #i(e) { + if (this.#r) + return { + done: !0, + value: e + }; + if (this.#r = !0, !this.#n) { + const t = this.#t.cancel(e); + return this.#t.releaseLock(), await t, { + done: !0, + value: e + }; + } + return this.#t.releaseLock(), { + done: !0, + value: e + }; + } +} +const n = Symbol(); +function i() { + return this[n].next(); +} +Object.defineProperty(i, "name", { value: "next" }); +function o(r) { + return this[n].return(r); +} +Object.defineProperty(o, "name", { value: "return" }); +const u = Object.create(a, { + next: { + enumerable: !0, + configurable: !0, + writable: !0, + value: i + }, + return: { + enumerable: !0, + configurable: !0, + writable: !0, + value: o + } +}); +function h({ preventCancel: r = !1 } = {}) { + const e = this.getReader(), t = new c( + e, + r + ), s = Object.create(u); + return s[n] = t, s; +} + + +;// CONCATENATED MODULE: ./node_modules/.pnpm/@sec-ant+readable-stream@0.4.1/node_modules/@sec-ant/readable-stream/dist/ponyfill/index.js + + + + +;// CONCATENATED MODULE: ./node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/stream.js + + + +const getAsyncIterable = stream => { + if (isReadableStream(stream, {checkOpen: false}) && nodeImports.on !== undefined) { + return getStreamIterable(stream); + } + + if (typeof stream?.[Symbol.asyncIterator] === 'function') { + return stream; + } + + // `ReadableStream[Symbol.asyncIterator]` support is missing in multiple browsers, so we ponyfill it + if (stream_toString.call(stream) === '[object ReadableStream]') { + return h.call(stream); + } + + throw new TypeError('The first argument must be a Readable, a ReadableStream, or an async iterable.'); +}; + +const {toString: stream_toString} = Object.prototype; + +// The default iterable for Node.js streams does not allow for multiple readers at once, so we re-implement it +const getStreamIterable = async function * (stream) { + const controller = new AbortController(); + const state = {}; + handleStreamEnd(stream, controller, state); + + try { + for await (const [chunk] of nodeImports.on(stream, 'data', {signal: controller.signal})) { + yield chunk; + } + } catch (error) { + // Stream failure, for example due to `stream.destroy(error)` + if (state.error !== undefined) { + throw state.error; + // `error` event directly emitted on stream + } else if (!controller.signal.aborted) { + throw error; + // Otherwise, stream completed successfully + } + // The `finally` block also runs when the caller throws, for example due to the `maxBuffer` option + } finally { + stream.destroy(); + } +}; + +const handleStreamEnd = async (stream, controller, state) => { + try { + await nodeImports.finished(stream, { + cleanup: true, + readable: true, + writable: false, + error: false, + }); + } catch (error) { + state.error = error; + } finally { + controller.abort(); + } +}; + +// Loaded by the Node entrypoint, but not by the browser one. +// This prevents using dynamic imports. +const nodeImports = {}; + +;// CONCATENATED MODULE: ./node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/contents.js + + +const contents_getStreamContents = async (stream, {init, convertChunk, getSize, truncateChunk, addChunk, getFinalChunk, finalize}, {maxBuffer = Number.POSITIVE_INFINITY} = {}) => { + const asyncIterable = getAsyncIterable(stream); + + const state = init(); + state.length = 0; + + try { + for await (const chunk of asyncIterable) { + const chunkType = getChunkType(chunk); + const convertedChunk = convertChunk[chunkType](chunk, state); + appendChunk({ + convertedChunk, + state, + getSize, + truncateChunk, + addChunk, + maxBuffer, + }); + } + + appendFinalChunk({ + state, + convertChunk, + getSize, + truncateChunk, + addChunk, + getFinalChunk, + maxBuffer, + }); + return finalize(state); + } catch (error) { + const normalizedError = typeof error === 'object' && error !== null ? error : new Error(error); + normalizedError.bufferedData = finalize(state); + throw normalizedError; + } +}; + +const appendFinalChunk = ({state, getSize, truncateChunk, addChunk, getFinalChunk, maxBuffer}) => { + const convertedChunk = getFinalChunk(state); + if (convertedChunk !== undefined) { + appendChunk({ + convertedChunk, + state, + getSize, + truncateChunk, + addChunk, + maxBuffer, + }); + } +}; + +const appendChunk = ({convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer}) => { + const chunkSize = getSize(convertedChunk); + const newLength = state.length + chunkSize; + + if (newLength <= maxBuffer) { + addNewChunk(convertedChunk, state, addChunk, newLength); + return; + } + + const truncatedChunk = truncateChunk(convertedChunk, maxBuffer - state.length); + + if (truncatedChunk !== undefined) { + addNewChunk(truncatedChunk, state, addChunk, maxBuffer); + } + + throw new MaxBufferError(); +}; + +const addNewChunk = (convertedChunk, state, addChunk, newLength) => { + state.contents = addChunk(convertedChunk, state, newLength); + state.length = newLength; +}; + +const getChunkType = chunk => { + const typeOfChunk = typeof chunk; + + if (typeOfChunk === 'string') { + return 'string'; + } + + if (typeOfChunk !== 'object' || chunk === null) { + return 'others'; + } + + if (globalThis.Buffer?.isBuffer(chunk)) { + return 'buffer'; + } + + const prototypeName = objectToString.call(chunk); + + if (prototypeName === '[object ArrayBuffer]') { + return 'arrayBuffer'; + } + + if (prototypeName === '[object DataView]') { + return 'dataView'; + } + + if ( + Number.isInteger(chunk.byteLength) + && Number.isInteger(chunk.byteOffset) + && objectToString.call(chunk.buffer) === '[object ArrayBuffer]' + ) { + return 'typedArray'; + } + + return 'others'; +}; + +const {toString: objectToString} = Object.prototype; + +class MaxBufferError extends Error { + name = 'MaxBufferError'; + + constructor() { + super('maxBuffer exceeded'); + } +} + +;// CONCATENATED MODULE: ./node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/utils.js +const identity = value => value; + +const noop = () => undefined; + +const getContentsProperty = ({contents}) => contents; + +const throwObjectStream = chunk => { + throw new Error(`Streams in object mode are not supported: ${String(chunk)}`); +}; + +const getLengthProperty = convertedChunk => convertedChunk.length; + +;// CONCATENATED MODULE: ./node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/array-buffer.js + + + +async function getStreamAsArrayBuffer(stream, options) { + return contents_getStreamContents(stream, arrayBufferMethods, options); +} + +const initArrayBuffer = () => ({contents: new ArrayBuffer(0)}); + +const useTextEncoder = chunk => textEncoder.encode(chunk); +const textEncoder = new TextEncoder(); + +const useUint8Array = chunk => new Uint8Array(chunk); + +const useUint8ArrayWithOffset = chunk => new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); + +const truncateArrayBufferChunk = (convertedChunk, chunkSize) => convertedChunk.slice(0, chunkSize); + +// `contents` is an increasingly growing `Uint8Array`. +const addArrayBufferChunk = (convertedChunk, {contents, length: previousLength}, length) => { + const newContents = hasArrayBufferResize() ? resizeArrayBuffer(contents, length) : resizeArrayBufferSlow(contents, length); + new Uint8Array(newContents).set(convertedChunk, previousLength); + return newContents; +}; + +// Without `ArrayBuffer.resize()`, `contents` size is always a power of 2. +// This means its last bytes are zeroes (not stream data), which need to be +// trimmed at the end with `ArrayBuffer.slice()`. +const resizeArrayBufferSlow = (contents, length) => { + if (length <= contents.byteLength) { + return contents; + } + + const arrayBuffer = new ArrayBuffer(getNewContentsLength(length)); + new Uint8Array(arrayBuffer).set(new Uint8Array(contents), 0); + return arrayBuffer; +}; + +// With `ArrayBuffer.resize()`, `contents` size matches exactly the size of +// the stream data. It does not include extraneous zeroes to trim at the end. +// The underlying `ArrayBuffer` does allocate a number of bytes that is a power +// of 2, but those bytes are only visible after calling `ArrayBuffer.resize()`. +const resizeArrayBuffer = (contents, length) => { + if (length <= contents.maxByteLength) { + contents.resize(length); + return contents; + } + + const arrayBuffer = new ArrayBuffer(length, {maxByteLength: getNewContentsLength(length)}); + new Uint8Array(arrayBuffer).set(new Uint8Array(contents), 0); + return arrayBuffer; +}; + +// Retrieve the closest `length` that is both >= and a power of 2 +const getNewContentsLength = length => SCALE_FACTOR ** Math.ceil(Math.log(length) / Math.log(SCALE_FACTOR)); + +const SCALE_FACTOR = 2; + +const finalizeArrayBuffer = ({contents, length}) => hasArrayBufferResize() ? contents : contents.slice(0, length); + +// `ArrayBuffer.slice()` is slow. When `ArrayBuffer.resize()` is available +// (Node >=20.0.0, Safari >=16.4 and Chrome), we can use it instead. +// eslint-disable-next-line no-warning-comments +// TODO: remove after dropping support for Node 20. +// eslint-disable-next-line no-warning-comments +// TODO: use `ArrayBuffer.transferToFixedLength()` instead once it is available +const hasArrayBufferResize = () => 'resize' in ArrayBuffer.prototype; + +const arrayBufferMethods = { + init: initArrayBuffer, + convertChunk: { + string: useTextEncoder, + buffer: useUint8Array, + arrayBuffer: useUint8Array, + dataView: useUint8ArrayWithOffset, + typedArray: useUint8ArrayWithOffset, + others: throwObjectStream, + }, + getSize: getLengthProperty, + truncateChunk: truncateArrayBufferChunk, + addChunk: addArrayBufferChunk, + getFinalChunk: noop, + finalize: finalizeArrayBuffer, +}; + +;// CONCATENATED MODULE: ./node_modules/.pnpm/get-stream@9.0.1/node_modules/get-stream/source/buffer.js + + +async function getStreamAsBuffer(stream, options) { + if (!('Buffer' in globalThis)) { + throw new Error('getStreamAsBuffer() is only supported in Node.js'); + } + + try { + return arrayBufferToNodeBuffer(await getStreamAsArrayBuffer(stream, options)); + } catch (error) { + if (error.bufferedData !== undefined) { + error.bufferedData = arrayBufferToNodeBuffer(error.bufferedData); + } + + throw error; + } +} + +const arrayBufferToNodeBuffer = arrayBuffer => globalThis.Buffer.from(arrayBuffer); + // EXTERNAL MODULE: ./node_modules/.pnpm/http-cache-semantics@4.1.1/node_modules/http-cache-semantics/index.js var http_cache_semantics = __nccwpck_require__(7893); ;// CONCATENATED MODULE: ./node_modules/.pnpm/lowercase-keys@3.0.0/node_modules/lowercase-keys/index.js @@ -88911,7 +89225,7 @@ function mimicResponse(fromStream, toStream) { return toStream; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/cacheable-request@10.2.14/node_modules/cacheable-request/dist/types.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/cacheable-request@12.0.1/node_modules/cacheable-request/dist/types.js // Type definitions for cacheable-request 6.0 // Project: https://github.com/lukechilds/cacheable-request#readme // Definitions by: BendingBender @@ -88931,7 +89245,7 @@ class types_CacheError extends Error { } } //# sourceMappingURL=types.js.map -;// CONCATENATED MODULE: ./node_modules/.pnpm/cacheable-request@10.2.14/node_modules/cacheable-request/dist/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/cacheable-request@12.0.1/node_modules/cacheable-request/dist/index.js @@ -88946,7 +89260,7 @@ class types_CacheError extends Error { class CacheableRequest { constructor(cacheRequest, cacheAdapter) { this.hooks = new Map(); - this.request = () => (options, cb) => { + this.request = () => (options, callback) => { let url; if (typeof options === 'string') { url = normalizeUrlObject(external_node_url_namespaceObject.parse(options)); @@ -88975,7 +89289,7 @@ class CacheableRequest { options.headers = Object.fromEntries(entries(options.headers).map(([key, value]) => [key.toLowerCase(), value])); const ee = new external_node_events_(); const normalizedUrlString = normalizeUrl(external_node_url_namespaceObject.format(url), { - stripWWW: false, + stripWWW: false, // eslint-disable-line @typescript-eslint/naming-convention removeTrailingSlash: false, stripAuthentication: false, }); @@ -89020,7 +89334,9 @@ class CacheableRequest { .once('end', resolve); }); const headers = convertHeaders(revalidatedPolicy.policy.responseHeaders()); - response = new Response({ statusCode: revalidate.statusCode, headers, body: revalidate.body, url: revalidate.url }); + response = new Response({ + statusCode: revalidate.statusCode, headers, body: revalidate.body, url: revalidate.url, + }); response.cachePolicy = revalidatedPolicy.policy; response.fromCache = true; } @@ -89034,10 +89350,10 @@ class CacheableRequest { clonedResponse = cloneResponse(response); (async () => { try { - const bodyPromise = get_stream.buffer(response); + const bodyPromise = getStreamAsBuffer(response); await Promise.race([ requestErrorPromise, - new Promise(resolve => response.once('end', resolve)), + new Promise(resolve => response.once('end', resolve)), // eslint-disable-line no-promise-executor-return new Promise(resolve => response.once('close', resolve)), // eslint-disable-line no-promise-executor-return ]); const body = await bodyPromise; @@ -89076,8 +89392,8 @@ class CacheableRequest { })(); } ee.emit('response', clonedResponse ?? response); - if (typeof cb === 'function') { - cb(clonedResponse ?? response); + if (typeof callback === 'function') { + callback(clonedResponse ?? response); } }; try { @@ -89102,12 +89418,14 @@ class CacheableRequest { const policy = http_cache_semantics.fromObject(cacheEntry.cachePolicy); if (policy.satisfiesWithoutRevalidation(options_) && !options_.forceRefresh) { const headers = convertHeaders(policy.responseHeaders()); - const response = new Response({ statusCode: cacheEntry.statusCode, headers, body: cacheEntry.body, url: cacheEntry.url }); + const response = new Response({ + statusCode: cacheEntry.statusCode, headers, body: cacheEntry.body, url: cacheEntry.url, + }); response.cachePolicy = policy; response.fromCache = true; ee.emit('response', response); - if (typeof cb === 'function') { - cb(response); + if (typeof callback === 'function') { + callback(response); } } else if (policy.satisfiesWithoutRevalidation(options_) && Date.now() >= policy.timeToLive() && options_.forceRefresh) { @@ -89140,14 +89458,14 @@ class CacheableRequest { })(); return ee; }; - this.addHook = (name, fn) => { + this.addHook = (name, function_) => { if (!this.hooks.has(name)) { - this.hooks.set(name, fn); + this.hooks.set(name, function_); } }; this.removeHook = (name) => this.hooks.delete(name); this.getHook = (name) => this.hooks.get(name); - this.runHook = async (name, ...args) => this.hooks.get(name)?.(...args); + this.runHook = async (name, ...arguments_) => this.hooks.get(name)?.(...arguments_); if (cacheAdapter instanceof src) { this.cache = cacheAdapter; } @@ -89210,7 +89528,7 @@ const onResponse = 'onResponse'; // EXTERNAL MODULE: ./node_modules/.pnpm/decompress-response@6.0.0/node_modules/decompress-response/index.js var decompress_response = __nccwpck_require__(7748); ;// CONCATENATED MODULE: ./node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/contents.js -const contents_getStreamContents = async (stream, {init, convertChunk, getSize, truncateChunk, addChunk, getFinalChunk, finalize}, {maxBuffer = Number.POSITIVE_INFINITY} = {}) => { +const source_contents_getStreamContents = async (stream, {init, convertChunk, getSize, truncateChunk, addChunk, getFinalChunk, finalize}, {maxBuffer = Number.POSITIVE_INFINITY} = {}) => { if (!contents_isAsyncIterable(stream)) { throw new Error('The first argument must be a Readable, a ReadableStream, or an async iterable.'); } @@ -89220,12 +89538,12 @@ const contents_getStreamContents = async (stream, {init, convertChunk, getSize, try { for await (const chunk of stream) { - const chunkType = getChunkType(chunk); + const chunkType = contents_getChunkType(chunk); const convertedChunk = convertChunk[chunkType](chunk, state); - appendChunk({convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer}); + contents_appendChunk({convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer}); } - appendFinalChunk({state, convertChunk, getSize, truncateChunk, addChunk, getFinalChunk, maxBuffer}); + contents_appendFinalChunk({state, convertChunk, getSize, truncateChunk, addChunk, getFinalChunk, maxBuffer}); return finalize(state); } catch (error) { error.bufferedData = finalize(state); @@ -89233,39 +89551,39 @@ const contents_getStreamContents = async (stream, {init, convertChunk, getSize, } }; -const appendFinalChunk = ({state, getSize, truncateChunk, addChunk, getFinalChunk, maxBuffer}) => { +const contents_appendFinalChunk = ({state, getSize, truncateChunk, addChunk, getFinalChunk, maxBuffer}) => { const convertedChunk = getFinalChunk(state); if (convertedChunk !== undefined) { - appendChunk({convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer}); + contents_appendChunk({convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer}); } }; -const appendChunk = ({convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer}) => { +const contents_appendChunk = ({convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer}) => { const chunkSize = getSize(convertedChunk); const newLength = state.length + chunkSize; if (newLength <= maxBuffer) { - addNewChunk(convertedChunk, state, addChunk, newLength); + contents_addNewChunk(convertedChunk, state, addChunk, newLength); return; } const truncatedChunk = truncateChunk(convertedChunk, maxBuffer - state.length); if (truncatedChunk !== undefined) { - addNewChunk(truncatedChunk, state, addChunk, maxBuffer); + contents_addNewChunk(truncatedChunk, state, addChunk, maxBuffer); } - throw new MaxBufferError(); + throw new contents_MaxBufferError(); }; -const addNewChunk = (convertedChunk, state, addChunk, newLength) => { +const contents_addNewChunk = (convertedChunk, state, addChunk, newLength) => { state.contents = addChunk(convertedChunk, state, newLength); state.length = newLength; }; const contents_isAsyncIterable = stream => typeof stream === 'object' && stream !== null && typeof stream[Symbol.asyncIterator] === 'function'; -const getChunkType = chunk => { +const contents_getChunkType = chunk => { const typeOfChunk = typeof chunk; if (typeOfChunk === 'string') { @@ -89281,7 +89599,7 @@ const getChunkType = chunk => { return 'buffer'; } - const prototypeName = objectToString.call(chunk); + const prototypeName = contents_objectToString.call(chunk); if (prototypeName === '[object ArrayBuffer]') { return 'arrayBuffer'; @@ -89294,7 +89612,7 @@ const getChunkType = chunk => { if ( Number.isInteger(chunk.byteLength) && Number.isInteger(chunk.byteOffset) - && objectToString.call(chunk.buffer) === '[object ArrayBuffer]' + && contents_objectToString.call(chunk.buffer) === '[object ArrayBuffer]' ) { return 'typedArray'; } @@ -89302,9 +89620,9 @@ const getChunkType = chunk => { return 'others'; }; -const {toString: objectToString} = Object.prototype; +const {toString: contents_objectToString} = Object.prototype; -class MaxBufferError extends Error { +class contents_MaxBufferError extends Error { name = 'MaxBufferError'; constructor() { @@ -89313,13 +89631,13 @@ class MaxBufferError extends Error { } ;// CONCATENATED MODULE: ./node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/utils.js -const identity = value => value; +const utils_identity = value => value; -const noop = () => undefined; +const utils_noop = () => undefined; const getContentsProp = ({contents}) => contents; -const throwObjectStream = chunk => { +const utils_throwObjectStream = chunk => { throw new Error(`Streams in object mode are not supported: ${String(chunk)}`); }; @@ -89345,17 +89663,17 @@ const addArrayChunk = (convertedChunk, {contents}) => { const arrayMethods = { init: initArray, convertChunk: { - string: identity, - buffer: identity, - arrayBuffer: identity, - dataView: identity, - typedArray: identity, - others: identity, + string: utils_identity, + buffer: utils_identity, + arrayBuffer: utils_identity, + dataView: utils_identity, + typedArray: utils_identity, + others: utils_identity, }, getSize: increment, - truncateChunk: noop, + truncateChunk: utils_noop, addChunk: addArrayChunk, - getFinalChunk: noop, + getFinalChunk: utils_noop, finalize: getContentsProp, }; @@ -89363,24 +89681,24 @@ const arrayMethods = { -async function getStreamAsArrayBuffer(stream, options) { - return contents_getStreamContents(stream, arrayBufferMethods, options); +async function array_buffer_getStreamAsArrayBuffer(stream, options) { + return source_contents_getStreamContents(stream, array_buffer_arrayBufferMethods, options); } -const initArrayBuffer = () => ({contents: new ArrayBuffer(0)}); +const array_buffer_initArrayBuffer = () => ({contents: new ArrayBuffer(0)}); -const useTextEncoder = chunk => textEncoder.encode(chunk); -const textEncoder = new TextEncoder(); +const array_buffer_useTextEncoder = chunk => array_buffer_textEncoder.encode(chunk); +const array_buffer_textEncoder = new TextEncoder(); -const useUint8Array = chunk => new Uint8Array(chunk); +const array_buffer_useUint8Array = chunk => new Uint8Array(chunk); -const useUint8ArrayWithOffset = chunk => new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); +const array_buffer_useUint8ArrayWithOffset = chunk => new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); -const truncateArrayBufferChunk = (convertedChunk, chunkSize) => convertedChunk.slice(0, chunkSize); +const array_buffer_truncateArrayBufferChunk = (convertedChunk, chunkSize) => convertedChunk.slice(0, chunkSize); // `contents` is an increasingly growing `Uint8Array`. -const addArrayBufferChunk = (convertedChunk, {contents, length: previousLength}, length) => { - const newContents = hasArrayBufferResize() ? resizeArrayBuffer(contents, length) : resizeArrayBufferSlow(contents, length); +const array_buffer_addArrayBufferChunk = (convertedChunk, {contents, length: previousLength}, length) => { + const newContents = array_buffer_hasArrayBufferResize() ? array_buffer_resizeArrayBuffer(contents, length) : array_buffer_resizeArrayBufferSlow(contents, length); new Uint8Array(newContents).set(convertedChunk, previousLength); return newContents; }; @@ -89388,12 +89706,12 @@ const addArrayBufferChunk = (convertedChunk, {contents, length: previousLength}, // Without `ArrayBuffer.resize()`, `contents` size is always a power of 2. // This means its last bytes are zeroes (not stream data), which need to be // trimmed at the end with `ArrayBuffer.slice()`. -const resizeArrayBufferSlow = (contents, length) => { +const array_buffer_resizeArrayBufferSlow = (contents, length) => { if (length <= contents.byteLength) { return contents; } - const arrayBuffer = new ArrayBuffer(getNewContentsLength(length)); + const arrayBuffer = new ArrayBuffer(array_buffer_getNewContentsLength(length)); new Uint8Array(arrayBuffer).set(new Uint8Array(contents), 0); return arrayBuffer; }; @@ -89402,23 +89720,23 @@ const resizeArrayBufferSlow = (contents, length) => { // the stream data. It does not include extraneous zeroes to trim at the end. // The underlying `ArrayBuffer` does allocate a number of bytes that is a power // of 2, but those bytes are only visible after calling `ArrayBuffer.resize()`. -const resizeArrayBuffer = (contents, length) => { +const array_buffer_resizeArrayBuffer = (contents, length) => { if (length <= contents.maxByteLength) { contents.resize(length); return contents; } - const arrayBuffer = new ArrayBuffer(length, {maxByteLength: getNewContentsLength(length)}); + const arrayBuffer = new ArrayBuffer(length, {maxByteLength: array_buffer_getNewContentsLength(length)}); new Uint8Array(arrayBuffer).set(new Uint8Array(contents), 0); return arrayBuffer; }; // Retrieve the closest `length` that is both >= and a power of 2 -const getNewContentsLength = length => SCALE_FACTOR ** Math.ceil(Math.log(length) / Math.log(SCALE_FACTOR)); +const array_buffer_getNewContentsLength = length => array_buffer_SCALE_FACTOR ** Math.ceil(Math.log(length) / Math.log(array_buffer_SCALE_FACTOR)); -const SCALE_FACTOR = 2; +const array_buffer_SCALE_FACTOR = 2; -const finalizeArrayBuffer = ({contents, length}) => hasArrayBufferResize() ? contents : contents.slice(0, length); +const array_buffer_finalizeArrayBuffer = ({contents, length}) => array_buffer_hasArrayBufferResize() ? contents : contents.slice(0, length); // `ArrayBuffer.slice()` is slow. When `ArrayBuffer.resize()` is available // (Node >=20.0.0, Safari >=16.4 and Chrome), we can use it instead. @@ -89426,38 +89744,38 @@ const finalizeArrayBuffer = ({contents, length}) => hasArrayBufferResize() ? con // TODO: remove after dropping support for Node 20. // eslint-disable-next-line no-warning-comments // TODO: use `ArrayBuffer.transferToFixedLength()` instead once it is available -const hasArrayBufferResize = () => 'resize' in ArrayBuffer.prototype; +const array_buffer_hasArrayBufferResize = () => 'resize' in ArrayBuffer.prototype; -const arrayBufferMethods = { - init: initArrayBuffer, +const array_buffer_arrayBufferMethods = { + init: array_buffer_initArrayBuffer, convertChunk: { - string: useTextEncoder, - buffer: useUint8Array, - arrayBuffer: useUint8Array, - dataView: useUint8ArrayWithOffset, - typedArray: useUint8ArrayWithOffset, - others: throwObjectStream, + string: array_buffer_useTextEncoder, + buffer: array_buffer_useUint8Array, + arrayBuffer: array_buffer_useUint8Array, + dataView: array_buffer_useUint8ArrayWithOffset, + typedArray: array_buffer_useUint8ArrayWithOffset, + others: utils_throwObjectStream, }, getSize: getLengthProp, - truncateChunk: truncateArrayBufferChunk, - addChunk: addArrayBufferChunk, - getFinalChunk: noop, - finalize: finalizeArrayBuffer, + truncateChunk: array_buffer_truncateArrayBufferChunk, + addChunk: array_buffer_addArrayBufferChunk, + getFinalChunk: utils_noop, + finalize: array_buffer_finalizeArrayBuffer, }; ;// CONCATENATED MODULE: ./node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/buffer.js -async function getStreamAsBuffer(stream, options) { +async function buffer_getStreamAsBuffer(stream, options) { if (!('Buffer' in globalThis)) { throw new Error('getStreamAsBuffer() is only supported in Node.js'); } try { - return arrayBufferToNodeBuffer(await getStreamAsArrayBuffer(stream, options)); + return buffer_arrayBufferToNodeBuffer(await array_buffer_getStreamAsArrayBuffer(stream, options)); } catch (error) { if (error.bufferedData !== undefined) { - error.bufferedData = arrayBufferToNodeBuffer(error.bufferedData); + error.bufferedData = buffer_arrayBufferToNodeBuffer(error.bufferedData); } throw error; @@ -89465,7 +89783,7 @@ async function getStreamAsBuffer(stream, options) { } // eslint-disable-next-line n/prefer-global/buffer -const arrayBufferToNodeBuffer = arrayBuffer => globalThis.Buffer.from(arrayBuffer); +const buffer_arrayBufferToNodeBuffer = arrayBuffer => globalThis.Buffer.from(arrayBuffer); ;// CONCATENATED MODULE: ./node_modules/.pnpm/get-stream@8.0.1/node_modules/get-stream/source/string.js @@ -89491,12 +89809,12 @@ const getFinalStringChunk = ({textDecoder}) => { const stringMethods = { init: initString, convertChunk: { - string: identity, + string: utils_identity, buffer: useTextDecoder, arrayBuffer: useTextDecoder, dataView: useTextDecoder, typedArray: useTextDecoder, - others: throwObjectStream, + others: utils_throwObjectStream, }, getSize: getLengthProp, truncateChunk: truncateStringChunk, @@ -89875,13 +90193,13 @@ getContentLength_fn = function() { }; -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/utils/is-form-data.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/is-form-data.js function is_form_data_isFormData(body) { return dist.nodeStream(body) && dist.function_(body.getBoundary); } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/utils/get-body-size.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/get-body-size.js @@ -89905,12 +90223,12 @@ async function getBodySize(body, headers) { return undefined; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/utils/proxy-events.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/proxy-events.js function proxyEvents(from, to, events) { const eventFunctions = {}; for (const event of events) { - const eventFunction = (...args) => { - to.emit(event, ...args); + const eventFunction = (...arguments_) => { + to.emit(event, ...arguments_); }; eventFunctions[event] = eventFunction; from.on(event, eventFunction); @@ -89924,7 +90242,7 @@ function proxyEvents(from, to, events) { ;// CONCATENATED MODULE: external "node:net" const external_node_net_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:net"); -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/utils/unhandle.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/unhandle.js // When attaching listeners, it's very easy to forget about them. // Especially if you do error handling and set timeouts. // So instead of checking if it's proper to throw an error on every timeout ever, @@ -89932,9 +90250,9 @@ const external_node_net_namespaceObject = __WEBPACK_EXTERNAL_createRequire(impor function unhandle() { const handlers = []; return { - once(origin, event, fn) { - origin.once(event, fn); - handlers.push({ origin, event, fn }); + once(origin, event, function_) { + origin.once(event, function_); + handlers.push({ origin, event, fn: function_ }); }, unhandleAll() { for (const handler of handlers) { @@ -89946,7 +90264,7 @@ function unhandle() { }; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/timed-out.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/timed-out.js const reentry = Symbol('reentry'); @@ -90077,7 +90395,7 @@ function timedOut(request, delays, options) { return cancelTimeouts; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/utils/url-to-options.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/url-to-options.js function urlToOptions(url) { // Cast to URL @@ -90101,7 +90419,7 @@ function urlToOptions(url) { return options; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/utils/weakable-map.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/weakable-map.js class WeakableMap { weakMap; map; @@ -90131,7 +90449,7 @@ class WeakableMap { } } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/calculate-retry-delay.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/calculate-retry-delay.js const calculateRetryDelay = ({ attemptCount, retryOptions, error, retryAfter, computedValue, }) => { if (error.name === 'RetryError') { return 1; @@ -90618,7 +90936,7 @@ class CacheableLookup { // EXTERNAL MODULE: ./node_modules/.pnpm/http2-wrapper@2.2.1/node_modules/http2-wrapper/source/index.js var http2_wrapper_source = __nccwpck_require__(9695); -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/parse-link-header.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/parse-link-header.js function parseLinkHeader(link) { const parsed = []; const items = link.split(','); @@ -90653,7 +90971,7 @@ function parseLinkHeader(link) { return parsed; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/options.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/options.js @@ -90830,7 +91148,7 @@ const defaultInternals = { shouldContinue: () => true, countLimit: Number.POSITIVE_INFINITY, backoff: 0, - requestLimit: 10000, + requestLimit: 10_000, stackAllItems: false, }, setHost: true, @@ -92290,7 +92608,7 @@ class Options { } } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/response.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/response.js const isResponseOk = (response) => { const { statusCode } = response; @@ -92333,19 +92651,19 @@ const parseBody = (response, responseType, parseJson, encoding) => { }, response); }; -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/utils/is-client-request.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/is-client-request.js function isClientRequest(clientRequest) { return clientRequest.writable && !clientRequest.writableEnded; } /* harmony default export */ const is_client_request = (isClientRequest); -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/utils/is-unix-socket-url.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/utils/is-unix-socket-url.js // eslint-disable-next-line @typescript-eslint/naming-convention function isUnixSocketURL(url) { return url.protocol === 'unix:' || url.hostname === 'unix'; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/core/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/core/index.js @@ -92975,7 +93293,7 @@ class Request extends external_node_stream_.Duplex { } try { // Errors are emitted via the `error` event - const rawBody = await getStreamAsBuffer(from); + const rawBody = await buffer_getStreamAsBuffer(from); // TODO: Switch to this: // let rawBody = await from.toArray(); // rawBody = Buffer.concat(rawBody); @@ -93172,9 +93490,7 @@ class Request extends external_node_stream_.Duplex { break; } } - if (!request) { - request = options.getRequestFunction(); - } + request ||= options.getRequestFunction(); const url = options.url; this._requestOptions = options.createNativeRequestOptions(); if (options.cache) { @@ -93184,11 +93500,11 @@ class Request extends external_node_stream_.Duplex { this._prepareCache(options.cache); } // Cache support - const fn = options.cache ? this._createCacheableRequest : request; + const function_ = options.cache ? this._createCacheableRequest : request; try { // We can't do `await fn(...)`, // because stream `error` event can be emitted before `Promise.resolve()`. - let requestOrResponse = fn(url, this._requestOptions); + let requestOrResponse = function_(url, this._requestOptions); if (dist.promise(requestOrResponse)) { requestOrResponse = await requestOrResponse; } @@ -93351,7 +93667,7 @@ class Request extends external_node_stream_.Duplex { } } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/as-promise/types.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/as-promise/types.js /** An error to be thrown when the request is aborted with `.cancel()`. @@ -93370,7 +93686,7 @@ class types_CancelError extends RequestError { } } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/as-promise/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/as-promise/index.js @@ -93503,12 +93819,12 @@ function asPromise(firstRequest) { }; makeRequest(0); }); - promise.on = (event, fn) => { - emitter.on(event, fn); + promise.on = (event, function_) => { + emitter.on(event, function_); return promise; }; - promise.off = (event, fn) => { - emitter.off(event, fn); + promise.off = (event, function_) => { + emitter.off(event, function_); return promise; }; const shortcut = (responseType) => { @@ -93536,7 +93852,7 @@ function asPromise(firstRequest) { return promise; } -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/create.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/create.js @@ -93577,9 +93893,7 @@ const create = (defaults) => { if (normalized.isStream) { return request; } - if (!promise) { - promise = asPromise(request); - } + promise ||= asPromise(request); return promise; }; let iteration = 0; @@ -93587,9 +93901,7 @@ const create = (defaults) => { const handler = defaults.handlers[iteration++] ?? lastHandler; const result = handler(newOptions, iterateHandlers); if (dist.promise(result) && !request.options.isStream) { - if (!promise) { - promise = asPromise(request); - } + promise ||= asPromise(request); if (result !== promise) { const descriptors = Object.getOwnPropertyDescriptors(promise); for (const key in descriptors) { @@ -93725,7 +94037,7 @@ const create = (defaults) => { }; /* harmony default export */ const source_create = (create); -;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.2.1/node_modules/got/dist/source/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/got@14.3.0/node_modules/got/dist/source/index.js const defaults = { @@ -93748,11 +94060,13 @@ const got = source_create(defaults); +;// CONCATENATED MODULE: external "node:child_process" +const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:child_process"); ;// CONCATENATED MODULE: external "node:stream/promises" const external_node_stream_promises_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:stream/promises"); ;// CONCATENATED MODULE: external "node:zlib" const external_node_zlib_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:zlib"); -;// CONCATENATED MODULE: ./node_modules/.pnpm/github.com+DeterminateSystems+detsys-ts@93a5166cd57eefcd448ea79923c11eb4b56d4563_rgjnyo4jd3kdijkrub73izga24/node_modules/detsys-ts/dist/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/github.com+DeterminateSystems+detsys-ts@ed02129aed8e4d6402d920152652877189bece70_3whmnlhrx56zhgtsjnkrhnutfu/node_modules/detsys-ts/dist/index.js var __defProp = Object.defineProperty; var __export = (target, all) => { for (var name in all) @@ -94056,45 +94370,6 @@ function hashEnvironmentVariables(prefix, variables) { return `${prefix}-${hash.digest("hex")}`; } -// src/platform.ts -var platform_exports = {}; -__export(platform_exports, { - getArchOs: () => getArchOs, - getNixPlatform: () => getNixPlatform -}); - -function getArchOs() { - const envArch = process.env.RUNNER_ARCH; - const envOs = process.env.RUNNER_OS; - if (envArch && envOs) { - return `${envArch}-${envOs}`; - } else { - core.error( - `Can't identify the platform: RUNNER_ARCH or RUNNER_OS undefined (${envArch}-${envOs})` - ); - throw new Error("RUNNER_ARCH and/or RUNNER_OS is not defined"); - } -} -function getNixPlatform(archOs) { - const archOsMap = /* @__PURE__ */ new Map([ - ["X64-macOS", "x86_64-darwin"], - ["ARM64-macOS", "aarch64-darwin"], - ["X64-Linux", "x86_64-linux"], - ["ARM64-Linux", "aarch64-linux"] - ]); - const mappedTo = archOsMap.get(archOs); - if (mappedTo) { - return mappedTo; - } else { - core.error( - `ArchOs (${archOs}) doesn't map to a supported Nix platform.` - ); - throw new Error( - `Cannot convert ArchOs (${archOs}) to a supported Nix platform.` - ); - } -} - // src/inputs.ts var inputs_exports = {}; __export(inputs_exports, { @@ -94159,38 +94434,77 @@ var getStringOrUndefined = (name) => { } }; +// src/platform.ts +var platform_exports = {}; +__export(platform_exports, { + getArchOs: () => getArchOs, + getNixPlatform: () => getNixPlatform +}); + +function getArchOs() { + const envArch = process.env.RUNNER_ARCH; + const envOs = process.env.RUNNER_OS; + if (envArch && envOs) { + return `${envArch}-${envOs}`; + } else { + core.error( + `Can't identify the platform: RUNNER_ARCH or RUNNER_OS undefined (${envArch}-${envOs})` + ); + throw new Error("RUNNER_ARCH and/or RUNNER_OS is not defined"); + } +} +function getNixPlatform(archOs) { + const archOsMap = /* @__PURE__ */ new Map([ + ["X64-macOS", "x86_64-darwin"], + ["ARM64-macOS", "aarch64-darwin"], + ["X64-Linux", "x86_64-linux"], + ["ARM64-Linux", "aarch64-linux"] + ]); + const mappedTo = archOsMap.get(archOs); + if (mappedTo) { + return mappedTo; + } else { + core.error( + `ArchOs (${archOs}) doesn't map to a supported Nix platform.` + ); + throw new Error( + `Cannot convert ArchOs (${archOs}) to a supported Nix platform.` + ); + } +} + // src/sourcedef.ts function constructSourceParameters(legacyPrefix) { - const noisilyGetInput = (suffix) => { - const preferredInput = getStringOrUndefined(`source-${suffix}`); - if (!legacyPrefix) { - return preferredInput; - } - const legacyInput = getStringOrUndefined(`${legacyPrefix}-${suffix}`); - if (preferredInput && legacyInput) { - core.warning( - `The supported option source-${suffix} and the legacy option ${legacyPrefix}-${suffix} are both set. Preferring source-${suffix}. Please stop setting ${legacyPrefix}-${suffix}.` - ); - return preferredInput; - } else if (legacyInput) { - core.warning( - `The legacy option ${legacyPrefix}-${suffix} is set. Please migrate to source-${suffix}.` - ); - return legacyInput; - } else { - return preferredInput; - } - }; return { - path: noisilyGetInput("path"), - url: noisilyGetInput("url"), - tag: noisilyGetInput("tag"), - pr: noisilyGetInput("pr"), - branch: noisilyGetInput("branch"), - revision: noisilyGetInput("revision") + path: noisilyGetInput("path", legacyPrefix), + url: noisilyGetInput("url", legacyPrefix), + tag: noisilyGetInput("tag", legacyPrefix), + pr: noisilyGetInput("pr", legacyPrefix), + branch: noisilyGetInput("branch", legacyPrefix), + revision: noisilyGetInput("revision", legacyPrefix) }; } +function noisilyGetInput(suffix, legacyPrefix) { + const preferredInput = getStringOrUndefined(`source-${suffix}`); + if (!legacyPrefix) { + return preferredInput; + } + const legacyInput = getStringOrUndefined(`${legacyPrefix}-${suffix}`); + if (preferredInput && legacyInput) { + core.warning( + `The supported option source-${suffix} and the legacy option ${legacyPrefix}-${suffix} are both set. Preferring source-${suffix}. Please stop setting ${legacyPrefix}-${suffix}.` + ); + return preferredInput; + } else if (legacyInput) { + core.warning( + `The legacy option ${legacyPrefix}-${suffix} is set. Please migrate to source-${suffix}.` + ); + return legacyInput; + } else { + return preferredInput; + } +} // src/index.ts @@ -94205,27 +94519,44 @@ function constructSourceParameters(legacyPrefix) { + + var DEFAULT_IDS_HOST = "https://install.determinate.systems"; var IDS_HOST = process.env["IDS_HOST"] ?? DEFAULT_IDS_HOST; var EVENT_EXCEPTION = "exception"; var EVENT_ARTIFACT_CACHE_HIT = "artifact_cache_hit"; var EVENT_ARTIFACT_CACHE_MISS = "artifact_cache_miss"; var EVENT_ARTIFACT_CACHE_PERSIST = "artifact_cache_persist"; +var EVENT_PREFLIGHT_REQUIRE_NIX_DENIED = "preflight-require-nix-denied"; var FACT_ENDED_WITH_EXCEPTION = "ended_with_exception"; var FACT_FINAL_EXCEPTION = "final_exception"; +var FACT_OS = "$os"; +var FACT_OS_VERSION = "$os_version"; var FACT_SOURCE_URL = "source_url"; var FACT_SOURCE_URL_ETAG = "source_url_etag"; +var FACT_NIX_LOCATION = "nix_location"; var FACT_NIX_STORE_TRUST = "nix_store_trusted"; var FACT_NIX_STORE_VERSION = "nix_store_version"; var FACT_NIX_STORE_CHECK_METHOD = "nix_store_check_method"; var FACT_NIX_STORE_CHECK_ERROR = "nix_store_check_error"; -var IdsToolbox = class { +var STATE_KEY_EXECUTION_PHASE = "detsys_action_execution_phase"; +var STATE_KEY_NIX_NOT_FOUND = "detsys_action_nix_not_found"; +var STATE_NOT_FOUND = "not-found"; +var DetSysAction = class { + determineExecutionPhase() { + const currentPhase = core.getState(STATE_KEY_EXECUTION_PHASE); + if (currentPhase === "") { + core.saveState(STATE_KEY_EXECUTION_PHASE, "post"); + return "main"; + } else { + return "post"; + } + } constructor(actionOptions) { this.actionOptions = makeOptionsConfident(actionOptions); - this.hookMain = void 0; - this.hookPost = void 0; this.exceptionAttachments = /* @__PURE__ */ new Map(); this.nixStoreTrust = "unknown"; + this.strictMode = getBool("_internal-strict-mode"); this.events = []; this.client = got_dist_source.extend({ retry: { @@ -94269,25 +94600,19 @@ var IdsToolbox = class { { getDetails().then((details) => { if (details.name !== "unknown") { - this.addFact("$os", details.name); + this.addFact(FACT_OS, details.name); } if (details.version !== "unknown") { - this.addFact("$os_version", details.version); + this.addFact(FACT_OS_VERSION, details.version); } }).catch((e) => { - core.debug(`Failure getting platform details: ${e}`); + core.debug( + `Failure getting platform details: ${stringifyError(e)}` + ); }); } - { - const phase = core.getState("idstoolbox_execution_phase"); - if (phase === "") { - core.saveState("idstoolbox_execution_phase", "post"); - this.executionPhase = "main"; - } else { - this.executionPhase = "post"; - } - this.facts.execution_phase = this.executionPhase; - } + this.executionPhase = this.determineExecutionPhase(); + this.facts.execution_phase = this.executionPhase; if (this.actionOptions.fetchStyle === "gh-env-style") { this.architectureFetchSuffix = this.archOs; } else if (this.actionOptions.fetchStyle === "nix-style") { @@ -94315,20 +94640,31 @@ var IdsToolbox = class { stapleFile(name, location) { this.exceptionAttachments.set(name, location); } - onMain(callback) { - this.hookMain = callback; - } - onPost(callback) { - this.hookPost = callback; + setExecutionPhase() { + const phase = core.getState(STATE_KEY_EXECUTION_PHASE); + if (phase === "") { + core.saveState(STATE_KEY_EXECUTION_PHASE, "post"); + this.executionPhase = "main"; + } else { + this.executionPhase = "post"; + } + this.facts.execution_phase = this.executionPhase; } + /** + * Execute the Action as defined. + */ execute() { this.executeAsync().catch((error2) => { console.log(error2); process.exitCode = 1; }); } - stringifyError(error2) { - return error2 instanceof Error || typeof error2 == "string" ? error2.toString() : JSON.stringify(error2); + // Whether the + get isMain() { + return this.executionPhase === "main"; + } + get isPost() { + return this.executionPhase === "post"; } async executeAsync() { try { @@ -94336,41 +94672,41 @@ var IdsToolbox = class { this.getCorrelationHashes() ); if (!await this.preflightRequireNix()) { - this.recordEvent("preflight-require-nix-denied"); + this.recordEvent(EVENT_PREFLIGHT_REQUIRE_NIX_DENIED); return; } else { await this.preflightNixStoreInfo(); this.addFact(FACT_NIX_STORE_TRUST, this.nixStoreTrust); } - if (this.executionPhase === "main" && this.hookMain) { - await this.hookMain(); - } else if (this.executionPhase === "post" && this.hookPost) { - await this.hookPost(); + if (this.isMain) { + await this.main(); + } else if (this.isPost) { + await this.post(); } this.addFact(FACT_ENDED_WITH_EXCEPTION, false); - } catch (error2) { + } catch (e) { this.addFact(FACT_ENDED_WITH_EXCEPTION, true); - const reportable = this.stringifyError(error2); + const reportable = stringifyError(e); this.addFact(FACT_FINAL_EXCEPTION, reportable); - if (this.executionPhase === "post") { + if (this.isPost) { core.warning(reportable); } else { core.setFailed(reportable); } - const do_gzip = (0,external_node_util_.promisify)(external_node_zlib_namespaceObject.gzip); + const doGzip = (0,external_node_util_.promisify)(external_node_zlib_namespaceObject.gzip); const exceptionContext = /* @__PURE__ */ new Map(); for (const [attachmentLabel, filePath] of this.exceptionAttachments) { try { const logText = (0,external_node_fs_namespaceObject.readFileSync)(filePath); - const buf = await do_gzip(logText); + const buf = await doGzip(logText); exceptionContext.set( `staple_value_${attachmentLabel}`, buf.toString("base64") ); - } catch (e) { + } catch (innerError) { exceptionContext.set( `staple_failure_${attachmentLabel}`, - this.stringifyError(e) + stringifyError(innerError) ); } } @@ -94401,7 +94737,24 @@ var IdsToolbox = class { uuid: (0,external_node_crypto_namespaceObject.randomUUID)() }); } - async fetch() { + /** + * Fetches a file in `.xz` format, imports its contents into the Nix store, + * and returns the path of the executable at `/nix/store/STORE_PATH/bin/${bin}`. + */ + async unpackClosure(bin) { + const artifact = this.fetchArtifact(); + const { stdout } = await (0,external_node_util_.promisify)(external_node_child_process_namespaceObject.exec)( + `cat "${artifact}" | xz -d | nix-store --import` + ); + const paths = stdout.split(external_node_os_.EOL); + const lastPath = paths.at(-2); + return `${lastPath}/bin/${bin}`; + } + /** + * Fetch an artifact, such as a tarball, from the URL determined by the `source-*` + * inputs and other factors. + */ + async fetchArtifact() { core.startGroup( `Downloading ${this.actionOptions.name} for ${this.architectureFetchSuffix}` ); @@ -94445,7 +94798,7 @@ var IdsToolbox = class { try { await this.saveCachedVersion(v, destFile); } catch (e) { - core.debug(`Error caching the artifact: ${e}`); + core.debug(`Error caching the artifact: ${stringifyError(e)}`); } } return destFile; @@ -94453,11 +94806,24 @@ var IdsToolbox = class { core.endGroup(); } } + /** + * Fetches the executable at the URL determined by the `source-*` inputs and + * other facts, `chmod`s it, and returns the path to the executable on disk. + */ async fetchExecutable() { - const binaryPath = await this.fetch(); + const binaryPath = await this.fetchArtifact(); await (0,promises_namespaceObject.chmod)(binaryPath, promises_namespaceObject.constants.S_IXUSR | promises_namespaceObject.constants.S_IXGRP); return binaryPath; } + /** + * A helper function for failing on error only if strict mode is enabled. + * This is intended only for CI environments testing Actions themselves. + */ + failOnError(msg) { + if (this.strictMode) { + core.setFailed(`strict mode failure: ${msg}`); + } + } async complete() { this.recordEvent(`complete_${this.executionPhase}`); await this.submitEvents(); @@ -94551,29 +94917,33 @@ var IdsToolbox = class { core.debug(`Nix not at ${candidateNix}`); } } - this.addFact("nix_location", nixLocation || ""); + this.addFact(FACT_NIX_LOCATION, nixLocation || ""); if (this.actionOptions.requireNix === "ignore") { return true; } - const currentNotFoundState = core.getState( - "idstoolbox_nix_not_found" - ); - if (currentNotFoundState === "not-found") { + const currentNotFoundState = core.getState(STATE_KEY_NIX_NOT_FOUND); + if (currentNotFoundState === STATE_NOT_FOUND) { return false; } if (nixLocation !== void 0) { return true; } - core.saveState("idstoolbox_nix_not_found", "not-found"); + core.saveState(STATE_KEY_NIX_NOT_FOUND, STATE_NOT_FOUND); switch (this.actionOptions.requireNix) { case "fail": core.setFailed( - "This action can only be used when Nix is installed. Add `- uses: DeterminateSystems/nix-installer-action@main` earlier in your workflow." + [ + "This action can only be used when Nix is installed.", + "Add `- uses: DeterminateSystems/nix-installer-action@main` earlier in your workflow." + ].join(" ") ); break; case "warn": core.warning( - "This action is in no-op mode because Nix is not installed. Add `- uses: DeterminateSystems/nix-installer-action@main` earlier in your workflow." + [ + "This action is in no-op mode because Nix is not installed.", + "Add `- uses: DeterminateSystems/nix-installer-action@main` earlier in your workflow." + ].join(" ") ); break; } @@ -94616,11 +94986,11 @@ var IdsToolbox = class { } this.addFact(FACT_NIX_STORE_VERSION, JSON.stringify(parsed.version)); } catch (e) { - this.addFact(FACT_NIX_STORE_CHECK_ERROR, this.stringifyError(e)); + this.addFact(FACT_NIX_STORE_CHECK_ERROR, stringifyError(e)); } } async submitEvents() { - if (!this.actionOptions.diagnosticsUrl) { + if (this.actionOptions.diagnosticsUrl === void 0) { core.debug( "Diagnostics are disabled. Not sending the following events:" ); @@ -94636,8 +95006,10 @@ var IdsToolbox = class { await this.client.post(this.actionOptions.diagnosticsUrl, { json: batch }); - } catch (error2) { - core.debug(`Error submitting diagnostics event: ${error2}`); + } catch (e) { + core.debug( + `Error submitting diagnostics event: ${stringifyError(e)}` + ); } this.events = []; } @@ -94646,6 +95018,9 @@ var IdsToolbox = class { return external_node_path_namespaceObject.join(_tmpdir, `${this.actionOptions.name}-${(0,external_node_crypto_namespaceObject.randomUUID)()}`); } }; +function stringifyError(error2) { + return error2 instanceof Error || typeof error2 == "string" ? error2.toString() : JSON.stringify(error2); +} function makeOptionsConfident(actionOptions) { const idsProjectName = actionOptions.idsProjectName ?? actionOptions.name; const finalOpts = { @@ -94681,7 +95056,7 @@ function determineDiagnosticsUrl(idsProjectName, urlOption) { return mungeDiagnosticEndpoint(new URL(providedDiagnosticEndpoint)); } catch (e) { core.info( - `User-provided diagnostic endpoint ignored: not a valid URL: ${e}` + `User-provided diagnostic endpoint ignored: not a valid URL: ${stringifyError(e)}` ); } } @@ -94693,7 +95068,7 @@ function determineDiagnosticsUrl(idsProjectName, urlOption) { return diagnosticUrl; } catch (e) { core.info( - `Generated diagnostic endpoint ignored: not a valid URL: ${e}` + `Generated diagnostic endpoint ignored: not a valid URL: ${stringifyError(e)}` ); } return void 0; @@ -94714,7 +95089,9 @@ function mungeDiagnosticEndpoint(inputUrl) { inputUrl.password = currentIdsHost.password; return inputUrl; } catch (e) { - core.info(`Default or overridden IDS host isn't a valid URL: ${e}`); + core.info( + `Default or overridden IDS host isn't a valid URL: ${stringifyError(e)}` + ); } return inputUrl; } @@ -94732,8 +95109,6 @@ function mungeDiagnosticEndpoint(inputUrl) { //# sourceMappingURL=index.js.map // EXTERNAL MODULE: external "http" var external_http_ = __nccwpck_require__(3685); -;// CONCATENATED MODULE: external "node:child_process" -const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:child_process"); ;// CONCATENATED MODULE: ./dist/index.js // src/helpers.ts @@ -94802,17 +95177,16 @@ var STARTED_HINT = "true"; var TEXT_NOOP = "Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?"; var TEXT_TRUST_UNTRUSTED = "The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled."; var TEXT_TRUST_UNKNOWN = "The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly."; -var MagicNixCacheAction = class { +var MagicNixCacheAction = class extends DetSysAction { constructor() { - this.idslib = new IdsToolbox({ + super({ name: "magic-nix-cache", fetchStyle: "gh-env-style", idsProjectName: "magic-nix-cache-closure", requireNix: "warn" }); - this.strictMode = inputs_exports.getBool("_internal-strict-mode"); this.hostAndPort = inputs_exports.getString("listen"); - this.client = got_dist_source.extend({ + this.httpClient = got_dist_source.extend({ retry: { limit: 1, methods: ["POST", "GET", "PUT", "HEAD", "DELETE", "OPTIONS", "TRACE"] @@ -94831,7 +95205,7 @@ var MagicNixCacheAction = class { if (core.getState(STATE_DAEMONDIR) !== "") { this.daemonDir = core.getState(STATE_DAEMONDIR); } else { - this.daemonDir = this.idslib.getTemporaryName(); + this.daemonDir = this.getTemporaryName(); (0,external_node_fs_namespaceObject.mkdirSync)(this.daemonDir); core.saveState(STATE_DAEMONDIR, this.daemonDir); } @@ -94841,11 +95215,35 @@ var MagicNixCacheAction = class { } else { this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir; } - this.idslib.addFact("noop_mode", this.noopMode); - this.idslib.stapleFile( - "daemon.log", - external_node_path_namespaceObject.join(this.daemonDir, "daemon.log") - ); + this.addFact("noop_mode", this.noopMode); + this.stapleFile("daemon.log", external_node_path_namespaceObject.join(this.daemonDir, "daemon.log")); + } + async main() { + if (this.noopMode) { + core.warning(TEXT_NOOP); + return; + } + if (this.nixStoreTrust === "untrusted") { + core.warning(TEXT_TRUST_UNTRUSTED); + return; + } else if (this.nixStoreTrust === "unknown") { + core.info(TEXT_TRUST_UNKNOWN); + } + await this.setUpAutoCache(); + await this.notifyAutoCache(); + } + async post() { + if (this.noopMode) { + core.debug(TEXT_NOOP); + return; + } + if (this.nixStoreTrust === "untrusted") { + core.debug(TEXT_TRUST_UNTRUSTED); + return; + } else if (this.nixStoreTrust === "unknown") { + core.debug(TEXT_TRUST_UNKNOWN); + } + await this.tearDownAutoCache(); } async setUpAutoCache() { const requiredEnv = [ @@ -94862,7 +95260,7 @@ var MagicNixCacheAction = class { ); } } - this.idslib.addFact("authenticated_env", !anyMissing); + this.addFact("authenticated_env", !anyMissing); if (anyMissing) { return; } @@ -94959,7 +95357,6 @@ var MagicNixCacheAction = class { }).catch((err) => { const msg = `error in notifyPromise: ${err}`; reject(new Error(msg)); - this.failInStrictMode(msg); }); daemon.on("exit", async (code, signal) => { let msg; @@ -94971,7 +95368,6 @@ var MagicNixCacheAction = class { msg = "Daemon unexpectedly exited"; } reject(new Error(msg)); - this.failInStrictMode(msg); }); }); daemon.unref(); @@ -94979,8 +95375,8 @@ var MagicNixCacheAction = class { log.unwatch(); } async fetchAutoCacher() { - const closurePath = await this.idslib.fetch(); - this.idslib.recordEvent("load_closure"); + const closurePath = await this.fetchExecutable(); + this.recordEvent("load_closure"); const { stdout } = await (0,external_node_util_.promisify)(external_node_child_process_namespaceObject.exec)( `cat "${closurePath}" | xz -d | nix-store --import` ); @@ -94995,14 +95391,14 @@ var MagicNixCacheAction = class { } try { core.debug(`Indicating workflow start`); - const res = await this.client.post( + const res = await this.httpClient.post( `http://${this.hostAndPort}/api/workflow-start` ); core.debug( `Response from POST to /api/workflow-start: (status: ${res.statusCode}, body: ${res.body})` ); if (res.statusCode !== 200) { - this.failInStrictMode( + throw new Error( `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})` ); } @@ -95011,7 +95407,7 @@ var MagicNixCacheAction = class { core.info(`Error marking the workflow as started:`); core.info((0,external_node_util_.inspect)(e)); core.info(`Magic Nix Cache may not be running for this workflow.`); - this.failInStrictMode(`Magic Nix Cache failed to start: ${(0,external_node_util_.inspect)(e)}`); + this.failOnError(`Magic Nix Cache failed to start: ${(0,external_node_util_.inspect)(e)}`); } } async tearDownAutoCache() { @@ -95023,21 +95419,19 @@ var MagicNixCacheAction = class { const pid = parseInt(await promises_namespaceObject.readFile(pidFile, { encoding: "ascii" })); core.debug(`found daemon pid: ${pid}`); if (!pid) { - const msg = "magic-nix-cache did not start successfully"; - this.failInStrictMode(msg); - throw new Error(msg); + throw new Error("magic-nix-cache did not start successfully"); } const log = tailLog(this.daemonDir); try { core.debug(`about to post to localhost`); - const res = await this.client.post( + const res = await this.httpClient.post( `http://${this.hostAndPort}/api/workflow-finish` ); core.debug( `Response from POST to /api/workflow-finish: (status: ${res.statusCode}, body: ${res.body})` ); if (res.statusCode !== 200) { - this.failInStrictMode( + throw new Error( `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})` ); } @@ -95050,7 +95444,6 @@ var MagicNixCacheAction = class { process.kill(pid, "SIGTERM"); } catch (e) { if (typeof e === "object" && e && "code" in e && e.code !== "ESRCH") { - this.failInStrictMode(e.toString()); throw e; } } finally { @@ -95061,42 +95454,9 @@ var MagicNixCacheAction = class { } } } - failInStrictMode(msg) { - if (this.strictMode) { - core.setFailed(`strict mode error: ${msg}`); - } - } }; function main() { - const cacheAction = new MagicNixCacheAction(); - cacheAction.idslib.onMain(async () => { - if (cacheAction.noopMode) { - core.warning(TEXT_NOOP); - return; - } - if (cacheAction.idslib.nixStoreTrust === "untrusted") { - core.warning(TEXT_TRUST_UNTRUSTED); - return; - } else if (cacheAction.idslib.nixStoreTrust === "unknown") { - core.info(TEXT_TRUST_UNKNOWN); - } - await cacheAction.setUpAutoCache(); - await cacheAction.notifyAutoCache(); - }); - cacheAction.idslib.onPost(async () => { - if (cacheAction.noopMode) { - core.debug(TEXT_NOOP); - return; - } - if (cacheAction.idslib.nixStoreTrust === "untrusted") { - core.debug(TEXT_TRUST_UNTRUSTED); - return; - } else if (cacheAction.idslib.nixStoreTrust === "unknown") { - core.debug(TEXT_TRUST_UNKNOWN); - } - await cacheAction.tearDownAutoCache(); - }); - cacheAction.idslib.execute(); + new MagicNixCacheAction().execute(); } main(); //# sourceMappingURL=index.js.map diff --git a/dist/index.js.map b/dist/index.js.map index fe4fb2e..f724407 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { IdsToolbox, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction {\n idslib: IdsToolbox;\n private strictMode: boolean;\n private hostAndPort: string;\n private client: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n this.idslib = new IdsToolbox({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.strictMode = inputs.getBool(\"_internal-strict-mode\");\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.client = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.idslib.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.idslib.addFact(\"noop_mode\", this.noopMode);\n\n this.idslib.stapleFile(\n \"daemon.log\",\n path.join(this.daemonDir, \"daemon.log\"),\n );\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.idslib.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n this.failInStrictMode(msg);\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.idslib.fetch();\n this.idslib.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-start: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n\n this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n const msg = \"magic-nix-cache did not start successfully\";\n this.failInStrictMode(msg);\n throw new Error(msg);\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.client.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-finish: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n this.failInStrictMode(\n `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n this.failInStrictMode(e.toString());\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n\n private failInStrictMode(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(`strict mode error: ${msg}`);\n }\n }\n}\n\nfunction main(): void {\n const cacheAction = new MagicNixCacheAction();\n\n cacheAction.idslib.onMain(async () => {\n if (cacheAction.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.setUpAutoCache();\n await cacheAction.notifyAutoCache();\n });\n cacheAction.idslib.onPost(async () => {\n if (cacheAction.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (cacheAction.idslib.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (cacheAction.idslib.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await cacheAction.tearDownAutoCache();\n });\n\n cacheAction.idslib.execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { DetSysAction, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction extends DetSysAction {\n private hostAndPort: string;\n private httpClient: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n super({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.httpClient = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.addFact(\"noop_mode\", this.noopMode);\n\n this.stapleFile(\"daemon.log\", path.join(this.daemonDir, \"daemon.log\"));\n }\n\n async main(): Promise {\n if (this.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (this.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (this.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await this.setUpAutoCache();\n await this.notifyAutoCache();\n }\n\n async post(): Promise {\n if (this.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (this.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (this.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await this.tearDownAutoCache();\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.fetchExecutable();\n this.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.httpClient.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-start: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n throw new Error(\n `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n this.failOnError(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n throw new Error(\"magic-nix-cache did not start successfully\");\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.httpClient.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-finish: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n throw new Error(\n `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n}\n\nfunction main(): void {\n new MagicNixCacheAction().execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file diff --git a/package.json b/package.json index 205b74d..73607f8 100644 --- a/package.json +++ b/package.json @@ -28,15 +28,15 @@ "@actions/core": "^1.10.1", "@actions/exec": "^1.1.1", "detsys-ts": "github:DeterminateSystems/detsys-ts", - "got": "^14.2.1", + "got": "^14.3.0", "tail": "^2.2.6" }, "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^4.3.0", - "@types/node": "^20.12.11", + "@types/node": "^20.12.12", "@types/tail": "^2.2.3", "@types/uuid": "^9.0.8", - "@typescript-eslint/eslint-plugin": "^7.8.0", + "@typescript-eslint/eslint-plugin": "^7.10.0", "@vercel/ncc": "^0.38.1", "eslint": "^8.57.0", "eslint-import-resolver-typescript": "^3.6.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a6a9ac..5f097aa 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,10 +13,10 @@ dependencies: version: 1.1.1 detsys-ts: specifier: github:DeterminateSystems/detsys-ts - version: github.com/DeterminateSystems/detsys-ts/93a5166cd57eefcd448ea79923c11eb4b56d4563 + version: github.com/DeterminateSystems/detsys-ts/ed02129aed8e4d6402d920152652877189bece70 got: - specifier: ^14.2.1 - version: 14.2.1 + specifier: ^14.3.0 + version: 14.3.0 tail: specifier: ^2.2.6 version: 2.2.6 @@ -26,8 +26,8 @@ devDependencies: specifier: ^4.3.0 version: 4.3.0(prettier@3.2.5) '@types/node': - specifier: ^20.12.11 - version: 20.12.11 + specifier: ^20.12.12 + version: 20.12.12 '@types/tail': specifier: ^2.2.3 version: 2.2.3 @@ -35,8 +35,8 @@ devDependencies: specifier: ^9.0.8 version: 9.0.8 '@typescript-eslint/eslint-plugin': - specifier: ^7.8.0 - version: 7.8.0(@typescript-eslint/parser@7.8.0)(eslint@8.57.0)(typescript@5.4.5) + specifier: ^7.10.0 + version: 7.10.0(@typescript-eslint/parser@7.10.0)(eslint@8.57.0)(typescript@5.4.5) '@vercel/ncc': specifier: ^0.38.1 version: 0.38.1 @@ -45,13 +45,13 @@ devDependencies: version: 8.57.0 eslint-import-resolver-typescript: specifier: ^3.6.1 - version: 3.6.1(@typescript-eslint/parser@7.8.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + version: 3.6.1(@typescript-eslint/parser@7.10.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) eslint-plugin-github: specifier: ^4.10.2 version: 4.10.2(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0)(typescript@5.4.5) eslint-plugin-import: specifier: ^2.29.1 - version: 2.29.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + version: 2.29.1(@typescript-eslint/parser@7.10.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-prettier: specifier: ^5.1.3 version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5) @@ -77,7 +77,7 @@ packages: '@actions/io': 1.1.3 '@azure/abort-controller': 1.1.0 '@azure/ms-rest-js': 2.7.0 - '@azure/storage-blob': 12.17.0 + '@azure/storage-blob': 12.18.0 semver: 6.3.1 uuid: 3.4.0 transitivePeerDependencies: @@ -215,8 +215,8 @@ packages: - encoding dev: false - /@azure/storage-blob@12.17.0: - resolution: {integrity: sha512-sM4vpsCpcCApagRW5UIjQNlNylo02my2opgp0Emi8x888hZUvJ3dN69Oq20cEGXkMUWnoCrBaB0zyS3yeB87sQ==} + /@azure/storage-blob@12.18.0: + resolution: {integrity: sha512-BzBZJobMoDyjJsPRMLNHvqHycTGrT8R/dtcTx9qUFcqwSRfGVK9A/cZ7Nx38UQydT9usZGbaDCN75QRNjezSAA==} engines: {node: '>=14.0.0'} dependencies: '@azure/abort-controller': 1.1.0 @@ -236,7 +236,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/highlight': 7.24.5 - picocolors: 1.0.0 + picocolors: 1.0.1 dev: true /@babel/generator@7.17.7: @@ -302,7 +302,7 @@ packages: '@babel/helper-validator-identifier': 7.24.5 chalk: 2.4.2 js-tokens: 4.0.0 - picocolors: 1.0.0 + picocolors: 1.0.1 dev: true /@babel/parser@7.24.5: @@ -717,136 +717,140 @@ packages: engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} dev: true - /@rollup/rollup-android-arm-eabi@4.17.2: - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} + /@rollup/rollup-android-arm-eabi@4.18.0: + resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} cpu: [arm] os: [android] requiresBuild: true dev: true optional: true - /@rollup/rollup-android-arm64@4.17.2: - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} + /@rollup/rollup-android-arm64@4.18.0: + resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} cpu: [arm64] os: [android] requiresBuild: true dev: true optional: true - /@rollup/rollup-darwin-arm64@4.17.2: - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} + /@rollup/rollup-darwin-arm64@4.18.0: + resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} cpu: [arm64] os: [darwin] requiresBuild: true dev: true optional: true - /@rollup/rollup-darwin-x64@4.17.2: - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} + /@rollup/rollup-darwin-x64@4.18.0: + resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} cpu: [x64] os: [darwin] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm-gnueabihf@4.17.2: - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} + /@rollup/rollup-linux-arm-gnueabihf@4.18.0: + resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} cpu: [arm] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm-musleabihf@4.17.2: - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} + /@rollup/rollup-linux-arm-musleabihf@4.18.0: + resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} cpu: [arm] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm64-gnu@4.17.2: - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} + /@rollup/rollup-linux-arm64-gnu@4.18.0: + resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm64-musl@4.17.2: - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} + /@rollup/rollup-linux-arm64-musl@4.18.0: + resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-powerpc64le-gnu@4.17.2: - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} + /@rollup/rollup-linux-powerpc64le-gnu@4.18.0: + resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} cpu: [ppc64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-riscv64-gnu@4.17.2: - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} + /@rollup/rollup-linux-riscv64-gnu@4.18.0: + resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} cpu: [riscv64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-s390x-gnu@4.17.2: - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} + /@rollup/rollup-linux-s390x-gnu@4.18.0: + resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} cpu: [s390x] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-x64-gnu@4.17.2: - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} + /@rollup/rollup-linux-x64-gnu@4.18.0: + resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-x64-musl@4.17.2: - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} + /@rollup/rollup-linux-x64-musl@4.18.0: + resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-arm64-msvc@4.17.2: - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} + /@rollup/rollup-win32-arm64-msvc@4.18.0: + resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} cpu: [arm64] os: [win32] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-ia32-msvc@4.17.2: - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} + /@rollup/rollup-win32-ia32-msvc@4.18.0: + resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} cpu: [ia32] os: [win32] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-x64-msvc@4.17.2: - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} + /@rollup/rollup-win32-x64-msvc@4.18.0: + resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} cpu: [x64] os: [win32] requiresBuild: true dev: true optional: true - /@sindresorhus/is@6.3.0: - resolution: {integrity: sha512-bOSPck7aIJjASXIg1qvXSIjXhVBpIEKdl2Wxg4pVqoTRPL8wWExKBrnGIh6CEnhkFQHfc36k7APhO3uXV4g5xg==} + /@sec-ant/readable-stream@0.4.1: + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + dev: false + + /@sindresorhus/is@6.3.1: + resolution: {integrity: sha512-FX4MfcifwJyFOI2lPoX7PQxCqx8BG1HCho7WdiXwpEQx1Ycij0JxkfYtGK7yqNScrZGSlt6RE6sw8QYoH7eKnQ==} engines: {node: '>=16'} dev: false @@ -885,10 +889,6 @@ packages: resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} dev: false - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: true - /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true @@ -896,19 +896,15 @@ packages: /@types/node-fetch@2.6.11: resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==} dependencies: - '@types/node': 20.12.11 + '@types/node': 20.12.12 form-data: 4.0.0 dev: false - /@types/node@20.12.11: - resolution: {integrity: sha512-vDg9PZ/zi+Nqp6boSOT7plNuthRugEKixDv5sFTIpkE89MmNtEArAShI4mxuX2+UrLEe9pxC1vm2cjm9YlWbJw==} + /@types/node@20.12.12: + resolution: {integrity: sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==} dependencies: undici-types: 5.26.5 - /@types/semver@7.5.8: - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - dev: true - /@types/tail@2.2.3: resolution: {integrity: sha512-Hnf352egOlDR4nVTaGX0t/kmTNXHMdovF2C7PVDFtHTHJPFmIspOI1b86vEOxU7SfCq/dADS7ptbqgG/WGGxnA==} dev: true @@ -916,15 +912,15 @@ packages: /@types/tunnel@0.0.3: resolution: {integrity: sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA==} dependencies: - '@types/node': 20.12.11 + '@types/node': 20.12.12 dev: false /@types/uuid@9.0.8: resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} dev: true - /@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0)(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==} + /@typescript-eslint/eslint-plugin@7.10.0(@typescript-eslint/parser@7.10.0)(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -935,25 +931,23 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/type-utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.8.0 - debug: 4.3.4 + '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.10.0 + '@typescript-eslint/type-utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.10.0 eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - semver: 7.6.2 ts-api-utils: 1.3.0(typescript@5.4.5) typescript: 5.4.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==} + /@typescript-eslint/parser@7.10.0(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -962,10 +956,10 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/scope-manager': 7.10.0 + '@typescript-eslint/types': 7.10.0 + '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.10.0 debug: 4.3.4 eslint: 8.57.0 typescript: 5.4.5 @@ -973,16 +967,16 @@ packages: - supports-color dev: true - /@typescript-eslint/scope-manager@7.8.0: - resolution: {integrity: sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==} + /@typescript-eslint/scope-manager@7.10.0: + resolution: {integrity: sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==} engines: {node: ^18.18.0 || >=20.0.0} dependencies: - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/types': 7.10.0 + '@typescript-eslint/visitor-keys': 7.10.0 dev: true - /@typescript-eslint/type-utils@7.8.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==} + /@typescript-eslint/type-utils@7.10.0(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -991,8 +985,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) + '@typescript-eslint/utils': 7.10.0(eslint@8.57.0)(typescript@5.4.5) debug: 4.3.4 eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.4.5) @@ -1001,13 +995,13 @@ packages: - supports-color dev: true - /@typescript-eslint/types@7.8.0: - resolution: {integrity: sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==} + /@typescript-eslint/types@7.10.0: + resolution: {integrity: sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==} engines: {node: ^18.18.0 || >=20.0.0} dev: true - /@typescript-eslint/typescript-estree@7.8.0(typescript@5.4.5): - resolution: {integrity: sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==} + /@typescript-eslint/typescript-estree@7.10.0(typescript@5.4.5): + resolution: {integrity: sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' @@ -1015,8 +1009,8 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/visitor-keys': 7.8.0 + '@typescript-eslint/types': 7.10.0 + '@typescript-eslint/visitor-keys': 7.10.0 debug: 4.3.4 globby: 11.1.0 is-glob: 4.0.3 @@ -1028,30 +1022,27 @@ packages: - supports-color dev: true - /@typescript-eslint/utils@7.8.0(eslint@8.57.0)(typescript@5.4.5): - resolution: {integrity: sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==} + /@typescript-eslint/utils@7.10.0(eslint@8.57.0)(typescript@5.4.5): + resolution: {integrity: sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 7.8.0 - '@typescript-eslint/types': 7.8.0 - '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.10.0 + '@typescript-eslint/types': 7.10.0 + '@typescript-eslint/typescript-estree': 7.10.0(typescript@5.4.5) eslint: 8.57.0 - semver: 7.6.2 transitivePeerDependencies: - supports-color - typescript dev: true - /@typescript-eslint/visitor-keys@7.8.0: - resolution: {integrity: sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==} + /@typescript-eslint/visitor-keys@7.10.0: + resolution: {integrity: sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==} engines: {node: ^18.18.0 || >=20.0.0} dependencies: - '@typescript-eslint/types': 7.8.0 + '@typescript-eslint/types': 7.10.0 eslint-visitor-keys: 3.4.3 dev: true @@ -1262,11 +1253,11 @@ packages: balanced-match: 1.0.2 dev: true - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + /braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} dependencies: - fill-range: 7.0.1 + fill-range: 7.1.1 dev: true /browserslist@4.23.0: @@ -1274,10 +1265,10 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001617 - electron-to-chromium: 1.4.763 + caniuse-lite: 1.0.30001621 + electron-to-chromium: 1.4.777 node-releases: 2.0.14 - update-browserslist-db: 1.0.15(browserslist@4.23.0) + update-browserslist-db: 1.0.16(browserslist@4.23.0) dev: true /bundle-require@4.1.0(esbuild@0.19.12): @@ -1300,12 +1291,12 @@ packages: engines: {node: '>=14.16'} dev: false - /cacheable-request@10.2.14: - resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} - engines: {node: '>=14.16'} + /cacheable-request@12.0.1: + resolution: {integrity: sha512-Yo9wGIQUaAfIbk+qY0X4cDQgCosecfBe3V9NSyeY4qPC2SAkbCS4Xj79VP8WOzitpJUZKc/wsRCYF5ariDIwkg==} + engines: {node: '>=18'} dependencies: '@types/http-cache-semantics': 4.0.4 - get-stream: 6.0.1 + get-stream: 9.0.1 http-cache-semantics: 4.1.1 keyv: 4.5.4 mimic-response: 4.0.0 @@ -1329,8 +1320,8 @@ packages: engines: {node: '>=6'} dev: true - /caniuse-lite@1.0.30001617: - resolution: {integrity: sha512-mLyjzNI9I+Pix8zwcrpxEbGlfqOkF9kM3ptzmKNw5tizSyYwMe+nGLTqMK9cO+0E+Bh6TsBxNAaHWEM8xwSsmA==} + /caniuse-lite@1.0.30001621: + resolution: {integrity: sha512-+NLXZiviFFKX0fk8Piwv3PfLPGtRqJeq2TiNoUff/qB5KJgwecJTvCXDpmlyP/eCI/GUEmp/h/y5j0yckiiZrA==} dev: true /chalk@2.4.2: @@ -1355,7 +1346,7 @@ packages: engines: {node: '>= 8.10.0'} dependencies: anymatch: 3.1.3 - braces: 3.0.2 + braces: 3.0.3 glob-parent: 5.1.2 is-binary-path: 2.1.0 is-glob: 4.0.3 @@ -1533,8 +1524,8 @@ packages: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} dev: true - /electron-to-chromium@1.4.763: - resolution: {integrity: sha512-k4J8NrtJ9QrvHLRo8Q18OncqBCB7tIUyqxRcJnlonQ0ioHKYB988GcDFF3ZePmnb8eHEopDs/wPHR/iGAFgoUQ==} + /electron-to-chromium@1.4.777: + resolution: {integrity: sha512-n02NCwLJ3wexLfK/yQeqfywCblZqLcXphzmid5e8yVPdtEcida7li0A5WQKghHNG0FeOMCzeFOzEbtAh5riXFw==} dev: true /emoji-regex@8.0.0: @@ -1733,7 +1724,7 @@ packages: - supports-color dev: true - /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.8.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0): + /eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@7.10.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0): resolution: {integrity: sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -1743,8 +1734,8 @@ packages: debug: 4.3.4 enhanced-resolve: 5.16.1 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.10.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.10.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.5 is-core-module: 2.13.1 @@ -1756,7 +1747,7 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + /eslint-module-utils@2.8.1(@typescript-eslint/parser@7.10.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): resolution: {integrity: sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==} engines: {node: '>=4'} peerDependencies: @@ -1777,11 +1768,11 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5) debug: 3.2.7 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.8.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@7.10.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) transitivePeerDependencies: - supports-color dev: true @@ -1825,8 +1816,8 @@ packages: eslint: ^8.0.1 dependencies: '@github/browserslist-config': 1.0.0 - '@typescript-eslint/eslint-plugin': 7.8.0(@typescript-eslint/parser@7.8.0)(eslint@8.57.0)(typescript@5.4.5) - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/eslint-plugin': 7.10.0(@typescript-eslint/parser@7.10.0)(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5) aria-query: 5.3.0 eslint: 8.57.0 eslint-config-prettier: 9.1.0(eslint@8.57.0) @@ -1834,7 +1825,7 @@ packages: eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) eslint-plugin-filenames: 1.3.2(eslint@8.57.0) eslint-plugin-i18n-text: 1.0.1(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.10.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) eslint-plugin-no-only-tests: 3.1.0 eslint-plugin-prettier: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.2.5) @@ -1858,7 +1849,7 @@ packages: eslint: 8.57.0 dev: true - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + /eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.10.0)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} engines: {node: '>=4'} peerDependencies: @@ -1868,7 +1859,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: - '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.10.0(eslint@8.57.0)(typescript@5.4.5) array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 array.prototype.flat: 1.3.2 @@ -1877,7 +1868,7 @@ packages: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.8.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.10.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -2083,7 +2074,7 @@ packages: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.7 dev: true /fast-json-stable-stringify@2.1.0: @@ -2107,8 +2098,8 @@ packages: flat-cache: 3.2.0 dev: true - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + /fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 @@ -2216,12 +2207,21 @@ packages: /get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} + dev: true /get-stream@8.0.1: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} dev: false + /get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + dev: false + /get-symbol-description@1.0.2: resolution: {integrity: sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==} engines: {node: '>= 0.4'} @@ -2251,16 +2251,16 @@ packages: is-glob: 4.0.3 dev: true - /glob@10.3.14: - resolution: {integrity: sha512-4fkAqu93xe9Mk7le9v0y3VrPDqLKHarNi2s4Pv7f2yOvfhWfhc7hRPHC/JyqMqb8B/Dt/eGS4n7ykwf3fOsl8g==} - engines: {node: '>=16 || 14 >=14.17'} + /glob@10.3.16: + resolution: {integrity: sha512-JDKXl1DiuuHJ6fVS2FXjownaavciiHNUU4mOvV/B793RLh05vZL1rcPnCSaOgv1hDT6RDlY7AB7ZUvFYAtPgAw==} + engines: {node: '>=16 || 14 >=14.18'} hasBin: true dependencies: foreground-child: 3.1.1 - jackspeak: 2.3.6 + jackspeak: 3.1.2 minimatch: 9.0.4 minipass: 7.1.1 - path-scurry: 1.11.0 + path-scurry: 1.11.1 dev: true /glob@7.2.3: @@ -2312,14 +2312,14 @@ packages: get-intrinsic: 1.2.4 dev: true - /got@14.2.1: - resolution: {integrity: sha512-KOaPMremmsvx6l9BLC04LYE6ZFW4x7e4HkTe3LwBmtuYYQwpeS4XKqzhubTIkaQ1Nr+eXxeori0zuwupXMovBQ==} + /got@14.3.0: + resolution: {integrity: sha512-vZkrXdq5BtPWTXqvjXSpl6zky3zpHaOVfSug/RfFHu3YrtSsvYzopVMDqrh2do77WnGoCSSRCHW25zXOSAQ9zw==} engines: {node: '>=20'} dependencies: - '@sindresorhus/is': 6.3.0 + '@sindresorhus/is': 6.3.1 '@szmarczak/http-timer': 5.0.1 cacheable-lookup: 7.0.0 - cacheable-request: 10.2.14 + cacheable-request: 12.0.1 decompress-response: 6.0.0 form-data-encoder: 4.0.2 get-stream: 8.0.1 @@ -2579,6 +2579,11 @@ packages: engines: {node: '>=8'} dev: true + /is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + dev: false + /is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} @@ -2637,8 +2642,8 @@ packages: set-function-name: 2.0.2 dev: true - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + /jackspeak@3.1.2: + resolution: {integrity: sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==} engines: {node: '>=14'} dependencies: '@isaacs/cliui': 8.0.2 @@ -2705,15 +2710,15 @@ packages: dependencies: json-buffer: 3.0.1 - /language-subtag-registry@0.3.22: - resolution: {integrity: sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==} + /language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} dev: true /language-tags@1.0.9: resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} engines: {node: '>=0.10'} dependencies: - language-subtag-registry: 0.3.22 + language-subtag-registry: 0.3.23 dev: true /levn@0.4.1: @@ -2792,11 +2797,11 @@ packages: engines: {node: '>= 8'} dev: true - /micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + /micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 dev: true @@ -3032,9 +3037,9 @@ packages: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true - /path-scurry@1.11.0: - resolution: {integrity: sha512-LNHTaVkzaYaLGlO+0u3rQTz7QrHTFOuKyba9JMTQutkmtNew8dw8wOD7mTU/5fCPZzCWpfW0XnQKzY61P0aTaw==} - engines: {node: '>=16 || 14 >=14.17'} + /path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} dependencies: lru-cache: 10.2.2 minipass: 7.1.1 @@ -3045,8 +3050,8 @@ packages: engines: {node: '>=8'} dev: true - /picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + /picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} dev: true /picomatch@2.3.1: @@ -3197,29 +3202,29 @@ packages: glob: 7.2.3 dev: true - /rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} + /rollup@4.18.0: + resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 + '@rollup/rollup-android-arm-eabi': 4.18.0 + '@rollup/rollup-android-arm64': 4.18.0 + '@rollup/rollup-darwin-arm64': 4.18.0 + '@rollup/rollup-darwin-x64': 4.18.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 + '@rollup/rollup-linux-arm-musleabihf': 4.18.0 + '@rollup/rollup-linux-arm64-gnu': 4.18.0 + '@rollup/rollup-linux-arm64-musl': 4.18.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 + '@rollup/rollup-linux-riscv64-gnu': 4.18.0 + '@rollup/rollup-linux-s390x-gnu': 4.18.0 + '@rollup/rollup-linux-x64-gnu': 4.18.0 + '@rollup/rollup-linux-x64-musl': 4.18.0 + '@rollup/rollup-win32-arm64-msvc': 4.18.0 + '@rollup/rollup-win32-ia32-msvc': 4.18.0 + '@rollup/rollup-win32-x64-msvc': 4.18.0 fsevents: 2.3.3 dev: true @@ -3413,7 +3418,7 @@ packages: dependencies: '@jridgewell/gen-mapping': 0.3.5 commander: 4.1.1 - glob: 10.3.14 + glob: 10.3.16 lines-and-columns: 1.2.4 mz: 2.7.0 pirates: 4.0.6 @@ -3563,7 +3568,7 @@ packages: joycon: 3.1.1 postcss-load-config: 4.0.2 resolve-from: 5.0.0 - rollup: 4.17.2 + rollup: 4.18.0 source-map: 0.8.0-beta.0 sucrase: 3.35.0 tree-kill: 1.2.2 @@ -3659,15 +3664,15 @@ packages: '@fastify/busboy': 2.1.1 dev: false - /update-browserslist-db@1.0.15(browserslist@4.23.0): - resolution: {integrity: sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==} + /update-browserslist-db@1.0.16(browserslist@4.23.0): + resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' dependencies: browserslist: 4.23.0 escalade: 3.1.2 - picocolors: 1.0.0 + picocolors: 1.0.1 dev: true /uri-js@4.4.1: @@ -3818,15 +3823,15 @@ packages: engines: {node: '>=10'} dev: true - github.com/DeterminateSystems/detsys-ts/93a5166cd57eefcd448ea79923c11eb4b56d4563: - resolution: {tarball: https://codeload.github.com/DeterminateSystems/detsys-ts/tar.gz/93a5166cd57eefcd448ea79923c11eb4b56d4563} + github.com/DeterminateSystems/detsys-ts/ed02129aed8e4d6402d920152652877189bece70: + resolution: {tarball: https://codeload.github.com/DeterminateSystems/detsys-ts/tar.gz/ed02129aed8e4d6402d920152652877189bece70} name: detsys-ts version: 1.0.0 dependencies: '@actions/cache': 3.2.4 '@actions/core': 1.10.1 '@actions/exec': 1.1.1 - got: 14.2.1 + got: 14.3.0 transitivePeerDependencies: - encoding dev: false diff --git a/src/index.ts b/src/index.ts index 7bcf751..76736e8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ import { netrcPath, tailLog } from "./helpers.js"; import * as actionsCore from "@actions/core"; -import { IdsToolbox, inputs } from "detsys-ts"; +import { DetSysAction, inputs } from "detsys-ts"; import got, { Got, Response } from "got"; import * as http from "http"; import { SpawnOptions, exec, spawn } from "node:child_process"; @@ -26,28 +26,25 @@ const TEXT_TRUST_UNTRUSTED = const TEXT_TRUST_UNKNOWN = "The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly."; -class MagicNixCacheAction { - idslib: IdsToolbox; - private strictMode: boolean; +class MagicNixCacheAction extends DetSysAction { private hostAndPort: string; - private client: Got; + private httpClient: Got; noopMode: boolean; private daemonDir: string; private daemonStarted: boolean; constructor() { - this.idslib = new IdsToolbox({ + super({ name: "magic-nix-cache", fetchStyle: "gh-env-style", idsProjectName: "magic-nix-cache-closure", requireNix: "warn", }); - this.strictMode = inputs.getBool("_internal-strict-mode"); this.hostAndPort = inputs.getString("listen"); - this.client = got.extend({ + this.httpClient = got.extend({ retry: { limit: 1, methods: ["POST", "GET", "PUT", "HEAD", "DELETE", "OPTIONS", "TRACE"], @@ -68,7 +65,7 @@ class MagicNixCacheAction { if (actionsCore.getState(STATE_DAEMONDIR) !== "") { this.daemonDir = actionsCore.getState(STATE_DAEMONDIR); } else { - this.daemonDir = this.idslib.getTemporaryName(); + this.daemonDir = this.getTemporaryName(); mkdirSync(this.daemonDir); actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir); } @@ -79,12 +76,42 @@ class MagicNixCacheAction { } else { this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir; } - this.idslib.addFact("noop_mode", this.noopMode); + this.addFact("noop_mode", this.noopMode); - this.idslib.stapleFile( - "daemon.log", - path.join(this.daemonDir, "daemon.log"), - ); + this.stapleFile("daemon.log", path.join(this.daemonDir, "daemon.log")); + } + + async main(): Promise { + if (this.noopMode) { + actionsCore.warning(TEXT_NOOP); + return; + } + + if (this.nixStoreTrust === "untrusted") { + actionsCore.warning(TEXT_TRUST_UNTRUSTED); + return; + } else if (this.nixStoreTrust === "unknown") { + actionsCore.info(TEXT_TRUST_UNKNOWN); + } + + await this.setUpAutoCache(); + await this.notifyAutoCache(); + } + + async post(): Promise { + if (this.noopMode) { + actionsCore.debug(TEXT_NOOP); + return; + } + + if (this.nixStoreTrust === "untrusted") { + actionsCore.debug(TEXT_TRUST_UNTRUSTED); + return; + } else if (this.nixStoreTrust === "unknown") { + actionsCore.debug(TEXT_TRUST_UNKNOWN); + } + + await this.tearDownAutoCache(); } async setUpAutoCache(): Promise { @@ -104,7 +131,7 @@ class MagicNixCacheAction { } } - this.idslib.addFact("authenticated_env", !anyMissing); + this.addFact("authenticated_env", !anyMissing); if (anyMissing) { return; } @@ -229,7 +256,6 @@ class MagicNixCacheAction { .catch((err) => { const msg = `error in notifyPromise: ${err}`; reject(new Error(msg)); - this.failInStrictMode(msg); }); daemon.on("exit", async (code, signal) => { let msg: string; @@ -241,7 +267,6 @@ class MagicNixCacheAction { msg = "Daemon unexpectedly exited"; } reject(new Error(msg)); - this.failInStrictMode(msg); }); }); @@ -253,8 +278,8 @@ class MagicNixCacheAction { } private async fetchAutoCacher(): Promise { - const closurePath = await this.idslib.fetch(); - this.idslib.recordEvent("load_closure"); + const closurePath = await this.fetchExecutable(); + this.recordEvent("load_closure"); const { stdout } = await promisify(exec)( `cat "${closurePath}" | xz -d | nix-store --import`, ); @@ -273,7 +298,7 @@ class MagicNixCacheAction { try { actionsCore.debug(`Indicating workflow start`); - const res: Response = await this.client.post( + const res: Response = await this.httpClient.post( `http://${this.hostAndPort}/api/workflow-start`, ); @@ -282,7 +307,7 @@ class MagicNixCacheAction { ); if (res.statusCode !== 200) { - this.failInStrictMode( + throw new Error( `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`, ); } @@ -292,8 +317,7 @@ class MagicNixCacheAction { actionsCore.info(`Error marking the workflow as started:`); actionsCore.info(inspect(e)); actionsCore.info(`Magic Nix Cache may not be running for this workflow.`); - - this.failInStrictMode(`Magic Nix Cache failed to start: ${inspect(e)}`); + this.failOnError(`Magic Nix Cache failed to start: ${inspect(e)}`); } } @@ -307,16 +331,14 @@ class MagicNixCacheAction { const pid = parseInt(await fs.readFile(pidFile, { encoding: "ascii" })); actionsCore.debug(`found daemon pid: ${pid}`); if (!pid) { - const msg = "magic-nix-cache did not start successfully"; - this.failInStrictMode(msg); - throw new Error(msg); + throw new Error("magic-nix-cache did not start successfully"); } const log = tailLog(this.daemonDir); try { actionsCore.debug(`about to post to localhost`); - const res: Response = await this.client.post( + const res: Response = await this.httpClient.post( `http://${this.hostAndPort}/api/workflow-finish`, ); @@ -325,7 +347,7 @@ class MagicNixCacheAction { ); if (res.statusCode !== 200) { - this.failInStrictMode( + throw new Error( `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`, ); } @@ -339,7 +361,6 @@ class MagicNixCacheAction { process.kill(pid, "SIGTERM"); } catch (e) { if (typeof e === "object" && e && "code" in e && e.code !== "ESRCH") { - this.failInStrictMode(e.toString()); throw e; } } finally { @@ -350,50 +371,10 @@ class MagicNixCacheAction { } } } - - private failInStrictMode(msg: string): void { - if (this.strictMode) { - actionsCore.setFailed(`strict mode error: ${msg}`); - } - } } function main(): void { - const cacheAction = new MagicNixCacheAction(); - - cacheAction.idslib.onMain(async () => { - if (cacheAction.noopMode) { - actionsCore.warning(TEXT_NOOP); - return; - } - - if (cacheAction.idslib.nixStoreTrust === "untrusted") { - actionsCore.warning(TEXT_TRUST_UNTRUSTED); - return; - } else if (cacheAction.idslib.nixStoreTrust === "unknown") { - actionsCore.info(TEXT_TRUST_UNKNOWN); - } - - await cacheAction.setUpAutoCache(); - await cacheAction.notifyAutoCache(); - }); - cacheAction.idslib.onPost(async () => { - if (cacheAction.noopMode) { - actionsCore.debug(TEXT_NOOP); - return; - } - - if (cacheAction.idslib.nixStoreTrust === "untrusted") { - actionsCore.debug(TEXT_TRUST_UNTRUSTED); - return; - } else if (cacheAction.idslib.nixStoreTrust === "unknown") { - actionsCore.debug(TEXT_TRUST_UNKNOWN); - } - - await cacheAction.tearDownAutoCache(); - }); - - cacheAction.idslib.execute(); + new MagicNixCacheAction().execute(); } main(); From 6e56af9a6e8883adb882e6bc50a8e96360d3a445 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Wed, 22 May 2024 16:06:52 -0300 Subject: [PATCH 24/27] Use built-in closure unpacking --- dist/index.js | 13 +------------ dist/index.js.map | 2 +- src/index.ts | 22 +++++----------------- 3 files changed, 7 insertions(+), 30 deletions(-) diff --git a/dist/index.js b/dist/index.js index 7a70a69..9f7fbc9 100644 --- a/dist/index.js +++ b/dist/index.js @@ -95169,7 +95169,6 @@ async function flakeHubLogin(netrc) { - var ENV_DAEMON_DIR = "MAGIC_NIX_CACHE_DAEMONDIR"; var STATE_DAEMONDIR = "MAGIC_NIX_CACHE_DAEMONDIR"; var STATE_STARTED = "MAGIC_NIX_CACHE_STARTED"; @@ -95272,7 +95271,7 @@ var MagicNixCacheAction = class extends DetSysAction { `GitHub Action Cache URL: ${process.env["ACTIONS_CACHE_URL"]}` ); const sourceBinary = inputs_exports.getStringOrNull("source-binary"); - const daemonBin = sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher(); + const daemonBin = sourceBinary !== null ? sourceBinary : await this.unpackClosure("magic-nix-cache"); let runEnv; if (core.isDebug()) { runEnv = { @@ -95374,16 +95373,6 @@ var MagicNixCacheAction = class extends DetSysAction { core.info("Launched Magic Nix Cache"); log.unwatch(); } - async fetchAutoCacher() { - const closurePath = await this.fetchExecutable(); - this.recordEvent("load_closure"); - const { stdout } = await (0,external_node_util_.promisify)(external_node_child_process_namespaceObject.exec)( - `cat "${closurePath}" | xz -d | nix-store --import` - ); - const paths = stdout.split(external_node_os_.EOL); - const lastPath = paths.at(-2); - return `${lastPath}/bin/magic-nix-cache`; - } async notifyAutoCache() { if (!this.daemonStarted) { core.debug("magic-nix-cache not started - Skipping"); diff --git a/dist/index.js.map b/dist/index.js.map index f724407..2f8cbc6 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { DetSysAction, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, exec, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport * as path from \"node:path\";\nimport { inspect, promisify } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction extends DetSysAction {\n private hostAndPort: string;\n private httpClient: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n super({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.httpClient = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.addFact(\"noop_mode\", this.noopMode);\n\n this.stapleFile(\"daemon.log\", path.join(this.daemonDir, \"daemon.log\"));\n }\n\n async main(): Promise {\n if (this.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (this.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (this.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await this.setUpAutoCache();\n await this.notifyAutoCache();\n }\n\n async post(): Promise {\n if (this.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (this.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (this.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await this.tearDownAutoCache();\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher();\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async fetchAutoCacher(): Promise {\n const closurePath = await this.fetchExecutable();\n this.recordEvent(\"load_closure\");\n const { stdout } = await promisify(exec)(\n `cat \"${closurePath}\" | xz -d | nix-store --import`,\n );\n\n const paths = stdout.split(os.EOL);\n // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last).\n const lastPath = paths.at(-2);\n return `${lastPath}/bin/magic-nix-cache`;\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.httpClient.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-start: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n throw new Error(\n `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n this.failOnError(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n throw new Error(\"magic-nix-cache did not start successfully\");\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.httpClient.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-finish: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n throw new Error(\n `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n}\n\nfunction main(): void {\n new MagicNixCacheAction().execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","os","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { DetSysAction, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { inspect } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction extends DetSysAction {\n private hostAndPort: string;\n private httpClient: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n super({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.httpClient = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.addFact(\"noop_mode\", this.noopMode);\n\n this.stapleFile(\"daemon.log\", path.join(this.daemonDir, \"daemon.log\"));\n }\n\n async main(): Promise {\n if (this.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (this.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (this.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await this.setUpAutoCache();\n await this.notifyAutoCache();\n }\n\n async post(): Promise {\n if (this.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (this.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (this.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await this.tearDownAutoCache();\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null\n ? sourceBinary\n : await this.unpackClosure(\"magic-nix-cache\");\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.httpClient.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-start: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n throw new Error(\n `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n this.failOnError(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n throw new Error(\"magic-nix-cache did not start successfully\");\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.httpClient.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-finish: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n throw new Error(\n `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n}\n\nfunction main(): void {\n new MagicNixCacheAction().execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","path"]} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 76736e8..4e3ae12 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,12 +3,11 @@ import * as actionsCore from "@actions/core"; import { DetSysAction, inputs } from "detsys-ts"; import got, { Got, Response } from "got"; import * as http from "http"; -import { SpawnOptions, exec, spawn } from "node:child_process"; +import { SpawnOptions, spawn } from "node:child_process"; import { mkdirSync, openSync, readFileSync } from "node:fs"; import * as fs from "node:fs/promises"; -import * as os from "node:os"; import * as path from "node:path"; -import { inspect, promisify } from "node:util"; +import { inspect } from "node:util"; // The ENV_DAEMON_DIR is intended to determine if we "own" the daemon or not, // in the case that a user has put the magic nix cache into their workflow @@ -147,7 +146,9 @@ class MagicNixCacheAction extends DetSysAction { const sourceBinary = inputs.getStringOrNull("source-binary"); const daemonBin = - sourceBinary !== null ? sourceBinary : await this.fetchAutoCacher(); + sourceBinary !== null + ? sourceBinary + : await this.unpackClosure("magic-nix-cache"); let runEnv; if (actionsCore.isDebug()) { @@ -277,19 +278,6 @@ class MagicNixCacheAction extends DetSysAction { log.unwatch(); } - private async fetchAutoCacher(): Promise { - const closurePath = await this.fetchExecutable(); - this.recordEvent("load_closure"); - const { stdout } = await promisify(exec)( - `cat "${closurePath}" | xz -d | nix-store --import`, - ); - - const paths = stdout.split(os.EOL); - // Since the export is in reverse topologically sorted order, magic-nix-cache is always the penultimate entry in the list (the empty string left by split being the last). - const lastPath = paths.at(-2); - return `${lastPath}/bin/magic-nix-cache`; - } - async notifyAutoCache(): Promise { if (!this.daemonStarted) { actionsCore.debug("magic-nix-cache not started - Skipping"); From f7ad2ac79e2bb5f79968619463c62ad55d220685 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Wed, 22 May 2024 16:38:26 -0300 Subject: [PATCH 25/27] Use fixed closure unpacking function --- dist/index.js | 136 ++++++++++++++++++++++------------------------ dist/index.js.map | 2 +- package.json | 2 +- pnpm-lock.yaml | 8 +-- src/index.ts | 8 +-- 5 files changed, 74 insertions(+), 82 deletions(-) diff --git a/dist/index.js b/dist/index.js index 9f7fbc9..0c7b3e5 100644 --- a/dist/index.js +++ b/dist/index.js @@ -39513,7 +39513,7 @@ module.exports = { parallel : __nccwpck_require__(644), serial : __nccwpck_require__(4501), - serialOrdered : __nccwpck_require__(3958) + serialOrdered : __nccwpck_require__(2362) }; @@ -39844,7 +39844,7 @@ function parallel(list, iterator, callback) /***/ 4501: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { -var serialOrdered = __nccwpck_require__(3958); +var serialOrdered = __nccwpck_require__(2362); // Public API module.exports = serial; @@ -39865,7 +39865,7 @@ function serial(list, iterator, callback) /***/ }), -/***/ 3958: +/***/ 2362: /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { var iterate = __nccwpck_require__(5748) @@ -94066,7 +94066,7 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq const external_node_stream_promises_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:stream/promises"); ;// CONCATENATED MODULE: external "node:zlib" const external_node_zlib_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:zlib"); -;// CONCATENATED MODULE: ./node_modules/.pnpm/github.com+DeterminateSystems+detsys-ts@ed02129aed8e4d6402d920152652877189bece70_3whmnlhrx56zhgtsjnkrhnutfu/node_modules/detsys-ts/dist/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/github.com+DeterminateSystems+detsys-ts@f1554c0d3a5f1114cff78879e50bc118451a03c0_t7eoi6mjzqgr2plrflke2xdf7i/node_modules/detsys-ts/dist/index.js var __defProp = Object.defineProperty; var __export = (target, all) => { for (var name in all) @@ -94640,16 +94640,6 @@ var DetSysAction = class { stapleFile(name, location) { this.exceptionAttachments.set(name, location); } - setExecutionPhase() { - const phase = core.getState(STATE_KEY_EXECUTION_PHASE); - if (phase === "") { - core.saveState(STATE_KEY_EXECUTION_PHASE, "post"); - this.executionPhase = "main"; - } else { - this.executionPhase = "post"; - } - this.facts.execution_phase = this.executionPhase; - } /** * Execute the Action as defined. */ @@ -94659,7 +94649,56 @@ var DetSysAction = class { process.exitCode = 1; }); } - // Whether the + getTemporaryName() { + const tmpDir = process.env["RUNNER_TEMP"] || (0,external_node_os_.tmpdir)(); + return external_node_path_namespaceObject.join(tmpDir, `${this.actionOptions.name}-${(0,external_node_crypto_namespaceObject.randomUUID)()}`); + } + addFact(key, value) { + this.facts[key] = value; + } + getDiagnosticsUrl() { + return this.actionOptions.diagnosticsUrl; + } + getUniqueId() { + return this.identity.run_differentiator || process.env.RUNNER_TRACKING_ID || (0,external_node_crypto_namespaceObject.randomUUID)(); + } + getCorrelationHashes() { + return this.identity; + } + recordEvent(eventName, context = {}) { + this.events.push({ + event_name: `${this.actionOptions.eventPrefix}${eventName}`, + context, + correlation: this.identity, + facts: this.facts, + timestamp: /* @__PURE__ */ new Date(), + uuid: (0,external_node_crypto_namespaceObject.randomUUID)() + }); + } + /** + * Fetches a file in `.xz` format from the URL determined by the `source-*` + * parameters (or `source-binary` if set). It then imports that file's + * contents into the Nix store and returns the path of the executable at + * `/nix/store/STORE_PATH/bin/${bin}`. + */ + async unpackClosure(bin) { + const artifact = await this.fetchArtifact(); + const { stdout } = await (0,external_node_util_.promisify)(external_node_child_process_namespaceObject.exec)( + `cat "${artifact}" | xz -d | nix-store --import` + ); + const paths = stdout.split(external_node_os_.EOL); + const lastPath = paths.at(-2); + return `${lastPath}/bin/${bin}`; + } + /** + * Fetches the executable at the URL determined by the `source-*` inputs and + * other facts, `chmod`s it, and returns the path to the executable on disk. + */ + async fetchExecutable() { + const binaryPath = await this.fetchArtifact(); + await (0,promises_namespaceObject.chmod)(binaryPath, promises_namespaceObject.constants.S_IXUSR | promises_namespaceObject.constants.S_IXGRP); + return binaryPath; + } get isMain() { return this.executionPhase === "main"; } @@ -94715,52 +94754,23 @@ var DetSysAction = class { await this.complete(); } } - addFact(key, value) { - this.facts[key] = value; - } - getDiagnosticsUrl() { - return this.actionOptions.diagnosticsUrl; - } - getUniqueId() { - return this.identity.run_differentiator || process.env.RUNNER_TRACKING_ID || (0,external_node_crypto_namespaceObject.randomUUID)(); - } - getCorrelationHashes() { - return this.identity; - } - recordEvent(eventName, context = {}) { - this.events.push({ - event_name: `${this.actionOptions.eventPrefix}${eventName}`, - context, - correlation: this.identity, - facts: this.facts, - timestamp: /* @__PURE__ */ new Date(), - uuid: (0,external_node_crypto_namespaceObject.randomUUID)() - }); - } - /** - * Fetches a file in `.xz` format, imports its contents into the Nix store, - * and returns the path of the executable at `/nix/store/STORE_PATH/bin/${bin}`. - */ - async unpackClosure(bin) { - const artifact = this.fetchArtifact(); - const { stdout } = await (0,external_node_util_.promisify)(external_node_child_process_namespaceObject.exec)( - `cat "${artifact}" | xz -d | nix-store --import` - ); - const paths = stdout.split(external_node_os_.EOL); - const lastPath = paths.at(-2); - return `${lastPath}/bin/${bin}`; - } /** * Fetch an artifact, such as a tarball, from the URL determined by the `source-*` - * inputs and other factors. + * inputs or use a provided binary specified by the `source-binary` + * input. */ async fetchArtifact() { + const sourceBinary = getStringOrNull("source-binary"); + if (sourceBinary !== null) { + core.debug(`Using the provided source binary at ${sourceBinary}`); + return sourceBinary; + } core.startGroup( `Downloading ${this.actionOptions.name} for ${this.architectureFetchSuffix}` ); try { - core.info(`Fetching from ${this.getUrl()}`); - const correlatedUrl = this.getUrl(); + core.info(`Fetching from ${this.getSourceUrl()}`); + const correlatedUrl = this.getSourceUrl(); correlatedUrl.searchParams.set("ci", "github"); correlatedUrl.searchParams.set( "correlation", @@ -94771,7 +94781,7 @@ var DetSysAction = class { const v = versionCheckup.headers.etag; this.addFact(FACT_SOURCE_URL_ETAG, v); core.debug( - `Checking the tool cache for ${this.getUrl()} at ${v}` + `Checking the tool cache for ${this.getSourceUrl()} at ${v}` ); const cached = await this.getCachedVersion(v); if (cached) { @@ -94806,15 +94816,6 @@ var DetSysAction = class { core.endGroup(); } } - /** - * Fetches the executable at the URL determined by the `source-*` inputs and - * other facts, `chmod`s it, and returns the path to the executable on disk. - */ - async fetchExecutable() { - const binaryPath = await this.fetchArtifact(); - await (0,promises_namespaceObject.chmod)(binaryPath, promises_namespaceObject.constants.S_IXUSR | promises_namespaceObject.constants.S_IXGRP); - return binaryPath; - } /** * A helper function for failing on error only if strict mode is enabled. * This is intended only for CI environments testing Actions themselves. @@ -94828,7 +94829,7 @@ var DetSysAction = class { this.recordEvent(`complete_${this.executionPhase}`); await this.submitEvents(); } - getUrl() { + getSourceUrl() { const p = this.sourceParameters; if (p.url) { this.addFact(FACT_SOURCE_URL, p.url); @@ -95013,10 +95014,6 @@ var DetSysAction = class { } this.events = []; } - getTemporaryName() { - const _tmpdir = process.env["RUNNER_TEMP"] || (0,external_node_os_.tmpdir)(); - return external_node_path_namespaceObject.join(_tmpdir, `${this.actionOptions.name}-${(0,external_node_crypto_namespaceObject.randomUUID)()}`); - } }; function stringifyError(error2) { return error2 instanceof Error || typeof error2 == "string" ? error2.toString() : JSON.stringify(error2); @@ -95270,8 +95267,7 @@ var MagicNixCacheAction = class extends DetSysAction { core.debug( `GitHub Action Cache URL: ${process.env["ACTIONS_CACHE_URL"]}` ); - const sourceBinary = inputs_exports.getStringOrNull("source-binary"); - const daemonBin = sourceBinary !== null ? sourceBinary : await this.unpackClosure("magic-nix-cache"); + const daemonBin = await this.unpackClosure("magic-nix-cache"); let runEnv; if (core.isDebug()) { runEnv = { diff --git a/dist/index.js.map b/dist/index.js.map index 2f8cbc6..ef45f12 100644 --- a/dist/index.js.map +++ b/dist/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { DetSysAction, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { inspect } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction extends DetSysAction {\n private hostAndPort: string;\n private httpClient: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n super({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.httpClient = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.addFact(\"noop_mode\", this.noopMode);\n\n this.stapleFile(\"daemon.log\", path.join(this.daemonDir, \"daemon.log\"));\n }\n\n async main(): Promise {\n if (this.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (this.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (this.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await this.setUpAutoCache();\n await this.notifyAutoCache();\n }\n\n async post(): Promise {\n if (this.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (this.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (this.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await this.tearDownAutoCache();\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const sourceBinary = inputs.getStringOrNull(\"source-binary\");\n const daemonBin =\n sourceBinary !== null\n ? sourceBinary\n : await this.unpackClosure(\"magic-nix-cache\");\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.httpClient.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-start: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n throw new Error(\n `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n this.failOnError(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n throw new Error(\"magic-nix-cache did not start successfully\");\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.httpClient.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-finish: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n throw new Error(\n `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n}\n\nfunction main(): void {\n new MagicNixCacheAction().execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","path"]} \ No newline at end of file +{"version":3,"sources":["../src/helpers.ts","../src/index.ts"],"sourcesContent":["import * as actionsCore from \"@actions/core\";\nimport * as fs from \"node:fs/promises\";\nimport * as os from \"node:os\";\nimport path from \"node:path\";\nimport { Tail } from \"tail\";\n\nexport function tailLog(daemonDir: string): Tail {\n const log = new Tail(path.join(daemonDir, \"daemon.log\"));\n actionsCore.debug(`tailing daemon.log...`);\n log.on(\"line\", (line) => {\n actionsCore.info(line);\n });\n return log;\n}\n\nexport async function netrcPath(): Promise {\n const expectedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"determinate-nix-installer-netrc\",\n );\n try {\n await fs.access(expectedNetrcPath);\n return expectedNetrcPath;\n } catch {\n // `nix-installer` was not used, the user may be registered with FlakeHub though.\n const destinedNetrcPath = path.join(\n process.env[\"RUNNER_TEMP\"] || os.tmpdir(),\n \"magic-nix-cache-netrc\",\n );\n try {\n await flakeHubLogin(destinedNetrcPath);\n } catch (e) {\n actionsCore.info(\"FlakeHub cache disabled.\");\n actionsCore.debug(`Error while logging into FlakeHub: ${e}`);\n }\n return destinedNetrcPath;\n }\n}\n\nasync function flakeHubLogin(netrc: string): Promise {\n const jwt = await actionsCore.getIDToken(\"api.flakehub.com\");\n\n await fs.writeFile(\n netrc,\n [\n `machine api.flakehub.com login flakehub password ${jwt}`,\n `machine flakehub.com login flakehub password ${jwt}`,\n `machine cache.flakehub.com login flakehub password ${jwt}`,\n ].join(\"\\n\"),\n );\n\n actionsCore.info(\"Logged in to FlakeHub.\");\n}\n","import { netrcPath, tailLog } from \"./helpers.js\";\nimport * as actionsCore from \"@actions/core\";\nimport { DetSysAction, inputs } from \"detsys-ts\";\nimport got, { Got, Response } from \"got\";\nimport * as http from \"http\";\nimport { SpawnOptions, spawn } from \"node:child_process\";\nimport { mkdirSync, openSync, readFileSync } from \"node:fs\";\nimport * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { inspect } from \"node:util\";\n\n// The ENV_DAEMON_DIR is intended to determine if we \"own\" the daemon or not,\n// in the case that a user has put the magic nix cache into their workflow\n// twice.\nconst ENV_DAEMON_DIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_NOOP =\n \"Magic Nix Cache is already running, this workflow job is in noop mode. Is the Magic Nix Cache in the workflow twice?\";\nconst TEXT_TRUST_UNTRUSTED =\n \"The Nix daemon does not consider the user running this workflow to be trusted. Magic Nix Cache is disabled.\";\nconst TEXT_TRUST_UNKNOWN =\n \"The Nix daemon may not consider the user running this workflow to be trusted. Magic Nix Cache may not start correctly.\";\n\nclass MagicNixCacheAction extends DetSysAction {\n private hostAndPort: string;\n private httpClient: Got;\n\n noopMode: boolean;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n constructor() {\n super({\n name: \"magic-nix-cache\",\n fetchStyle: \"gh-env-style\",\n idsProjectName: \"magic-nix-cache-closure\",\n requireNix: \"warn\",\n });\n\n this.hostAndPort = inputs.getString(\"listen\");\n\n this.httpClient = got.extend({\n retry: {\n limit: 1,\n methods: [\"POST\", \"GET\", \"PUT\", \"HEAD\", \"DELETE\", \"OPTIONS\", \"TRACE\"],\n },\n hooks: {\n beforeRetry: [\n (error, retryCount) => {\n actionsCore.info(\n `Retrying after error ${error.code}, retry #: ${retryCount}`,\n );\n },\n ],\n },\n });\n\n this.daemonStarted = actionsCore.getState(STATE_STARTED) === STARTED_HINT;\n\n if (actionsCore.getState(STATE_DAEMONDIR) !== \"\") {\n this.daemonDir = actionsCore.getState(STATE_DAEMONDIR);\n } else {\n this.daemonDir = this.getTemporaryName();\n mkdirSync(this.daemonDir);\n actionsCore.saveState(STATE_DAEMONDIR, this.daemonDir);\n }\n\n if (process.env[ENV_DAEMON_DIR] === undefined) {\n this.noopMode = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.noopMode = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.addFact(\"noop_mode\", this.noopMode);\n\n this.stapleFile(\"daemon.log\", path.join(this.daemonDir, \"daemon.log\"));\n }\n\n async main(): Promise {\n if (this.noopMode) {\n actionsCore.warning(TEXT_NOOP);\n return;\n }\n\n if (this.nixStoreTrust === \"untrusted\") {\n actionsCore.warning(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (this.nixStoreTrust === \"unknown\") {\n actionsCore.info(TEXT_TRUST_UNKNOWN);\n }\n\n await this.setUpAutoCache();\n await this.notifyAutoCache();\n }\n\n async post(): Promise {\n if (this.noopMode) {\n actionsCore.debug(TEXT_NOOP);\n return;\n }\n\n if (this.nixStoreTrust === \"untrusted\") {\n actionsCore.debug(TEXT_TRUST_UNTRUSTED);\n return;\n } else if (this.nixStoreTrust === \"unknown\") {\n actionsCore.debug(TEXT_TRUST_UNKNOWN);\n }\n\n await this.tearDownAutoCache();\n }\n\n async setUpAutoCache(): Promise {\n const requiredEnv = [\n \"ACTIONS_CACHE_URL\",\n \"ACTIONS_RUNTIME_URL\",\n \"ACTIONS_RUNTIME_TOKEN\",\n ];\n\n let anyMissing = false;\n for (const n of requiredEnv) {\n if (!process.env.hasOwnProperty(n)) {\n anyMissing = true;\n actionsCore.warning(\n `Disabling automatic caching since required environment ${n} isn't available`,\n );\n }\n }\n\n this.addFact(\"authenticated_env\", !anyMissing);\n if (anyMissing) {\n return;\n }\n\n if (this.daemonStarted) {\n actionsCore.debug(\"Already started.\");\n return;\n }\n\n actionsCore.debug(\n `GitHub Action Cache URL: ${process.env[\"ACTIONS_CACHE_URL\"]}`,\n );\n\n const daemonBin = await this.unpackClosure(\"magic-nix-cache\");\n\n let runEnv;\n if (actionsCore.isDebug()) {\n runEnv = {\n RUST_LOG: \"trace,magic_nix_cache=debug,gha_cache=debug\",\n RUST_BACKTRACE: \"full\",\n ...process.env,\n };\n } else {\n runEnv = process.env;\n }\n\n const notifyPort = inputs.getString(\"startup-notification-port\");\n\n const notifyPromise = new Promise>((resolveListening) => {\n const promise = new Promise(async (resolveQuit) => {\n const notifyServer = http.createServer((req, res) => {\n if (req.method === \"POST\" && req.url === \"/\") {\n actionsCore.debug(`Notify server shutting down.`);\n res.writeHead(200, { \"Content-Type\": \"application/json\" });\n res.end(\"{}\");\n notifyServer.close(() => {\n resolveQuit();\n });\n }\n });\n\n notifyServer.listen(notifyPort, () => {\n actionsCore.debug(`Notify server running.`);\n resolveListening(promise);\n });\n });\n });\n\n // Start tailing the daemon log.\n const outputPath = `${this.daemonDir}/daemon.log`;\n const output = openSync(outputPath, \"a\");\n const log = tailLog(this.daemonDir);\n const netrc = await netrcPath();\n const nixConfPath = `${process.env[\"HOME\"]}/.config/nix/nix.conf`;\n const upstreamCache = inputs.getString(\"upstream-cache\");\n const diagnosticEndpoint = inputs.getString(\"diagnostic-endpoint\");\n const useFlakeHub = inputs.getBool(\"use-flakehub\");\n const flakeHubCacheServer = inputs.getString(\"flakehub-cache-server\");\n const flakeHubApiServer = inputs.getString(\"flakehub-api-server\");\n const flakeHubFlakeName = inputs.getString(\"flakehub-flake-name\");\n const useGhaCache = inputs.getBool(\"use-gha-cache\");\n\n const daemonCliFlags: string[] = [\n \"--startup-notification-url\",\n `http://127.0.0.1:${notifyPort}`,\n \"--listen\",\n this.hostAndPort,\n \"--upstream\",\n upstreamCache,\n \"--diagnostic-endpoint\",\n diagnosticEndpoint,\n \"--nix-conf\",\n nixConfPath,\n ]\n .concat(\n useFlakeHub\n ? [\n \"--use-flakehub\",\n \"--flakehub-cache-server\",\n flakeHubCacheServer,\n \"--flakehub-api-server\",\n flakeHubApiServer,\n \"--flakehub-api-server-netrc\",\n netrc,\n \"--flakehub-flake-name\",\n flakeHubFlakeName,\n ]\n : [],\n )\n .concat(useGhaCache ? [\"--use-gha-cache\"] : []);\n\n const opts: SpawnOptions = {\n stdio: [\"ignore\", output, output],\n env: runEnv,\n detached: true,\n };\n\n // Display the final command for debugging purposes\n actionsCore.debug(\"Full daemon start command:\");\n actionsCore.debug(`${daemonBin} ${daemonCliFlags.join(\" \")}`);\n\n // Start the server. Once it is ready, it will notify us via the notification server.\n const daemon = spawn(daemonBin, daemonCliFlags, opts);\n\n this.daemonStarted = true;\n actionsCore.saveState(STATE_STARTED, STARTED_HINT);\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n await fs.writeFile(pidFile, `${daemon.pid}`);\n\n actionsCore.info(\"Waiting for magic-nix-cache to start...\");\n\n await new Promise((resolve, reject) => {\n notifyPromise\n // eslint-disable-next-line github/no-then\n .then((_value) => {\n resolve();\n })\n // eslint-disable-next-line github/no-then\n .catch((err) => {\n const msg = `error in notifyPromise: ${err}`;\n reject(new Error(msg));\n });\n daemon.on(\"exit\", async (code, signal) => {\n let msg: string;\n if (signal) {\n msg = `Daemon was killed by signal ${signal}`;\n } else if (code) {\n msg = `Daemon exited with code ${code}`;\n } else {\n msg = \"Daemon unexpectedly exited\";\n }\n reject(new Error(msg));\n });\n });\n\n daemon.unref();\n\n actionsCore.info(\"Launched Magic Nix Cache\");\n\n log.unwatch();\n }\n\n private async notifyAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n try {\n actionsCore.debug(`Indicating workflow start`);\n const res: Response = await this.httpClient.post(\n `http://${this.hostAndPort}/api/workflow-start`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-start: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n throw new Error(\n `Failed to trigger workflow start hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n\n actionsCore.debug(`back from post: ${res.body}`);\n } catch (e) {\n actionsCore.info(`Error marking the workflow as started:`);\n actionsCore.info(inspect(e));\n actionsCore.info(`Magic Nix Cache may not be running for this workflow.`);\n this.failOnError(`Magic Nix Cache failed to start: ${inspect(e)}`);\n }\n }\n\n async tearDownAutoCache(): Promise {\n if (!this.daemonStarted) {\n actionsCore.debug(\"magic-nix-cache not started - Skipping\");\n return;\n }\n\n const pidFile = path.join(this.daemonDir, \"daemon.pid\");\n const pid = parseInt(await fs.readFile(pidFile, { encoding: \"ascii\" }));\n actionsCore.debug(`found daemon pid: ${pid}`);\n if (!pid) {\n throw new Error(\"magic-nix-cache did not start successfully\");\n }\n\n const log = tailLog(this.daemonDir);\n\n try {\n actionsCore.debug(`about to post to localhost`);\n const res: Response = await this.httpClient.post(\n `http://${this.hostAndPort}/api/workflow-finish`,\n );\n\n actionsCore.debug(\n `Response from POST to /api/workflow-finish: (status: ${res.statusCode}, body: ${res.body})`,\n );\n\n if (res.statusCode !== 200) {\n throw new Error(\n `Failed to trigger workflow finish hook; expected status 200 but got (status: ${res.statusCode}, body: ${res.body})`,\n );\n }\n } finally {\n actionsCore.debug(`unwatching the daemon log`);\n log.unwatch();\n }\n\n actionsCore.debug(`killing`);\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n throw e;\n }\n } finally {\n if (actionsCore.isDebug()) {\n actionsCore.info(\"Entire log:\");\n const entireLog = readFileSync(path.join(this.daemonDir, \"daemon.log\"));\n actionsCore.info(entireLog.toString());\n }\n }\n }\n}\n\nfunction main(): void {\n new MagicNixCacheAction().execute();\n}\n\nmain();\n"],"mappings":"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","names":["actionsCore","fs","path"]} \ No newline at end of file diff --git a/package.json b/package.json index 73607f8..f3278cb 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "dependencies": { "@actions/core": "^1.10.1", "@actions/exec": "^1.1.1", - "detsys-ts": "github:DeterminateSystems/detsys-ts", + "detsys-ts": "github:DeterminateSystems/detsys-ts#source-binary", "got": "^14.3.0", "tail": "^2.2.6" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f097aa..3c75a4f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ dependencies: specifier: ^1.1.1 version: 1.1.1 detsys-ts: - specifier: github:DeterminateSystems/detsys-ts - version: github.com/DeterminateSystems/detsys-ts/ed02129aed8e4d6402d920152652877189bece70 + specifier: github:DeterminateSystems/detsys-ts#source-binary + version: github.com/DeterminateSystems/detsys-ts/f1554c0d3a5f1114cff78879e50bc118451a03c0 got: specifier: ^14.3.0 version: 14.3.0 @@ -3823,8 +3823,8 @@ packages: engines: {node: '>=10'} dev: true - github.com/DeterminateSystems/detsys-ts/ed02129aed8e4d6402d920152652877189bece70: - resolution: {tarball: https://codeload.github.com/DeterminateSystems/detsys-ts/tar.gz/ed02129aed8e4d6402d920152652877189bece70} + github.com/DeterminateSystems/detsys-ts/f1554c0d3a5f1114cff78879e50bc118451a03c0: + resolution: {tarball: https://codeload.github.com/DeterminateSystems/detsys-ts/tar.gz/f1554c0d3a5f1114cff78879e50bc118451a03c0} name: detsys-ts version: 1.0.0 dependencies: diff --git a/src/index.ts b/src/index.ts index 4e3ae12..dbdd76d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -144,11 +144,7 @@ class MagicNixCacheAction extends DetSysAction { `GitHub Action Cache URL: ${process.env["ACTIONS_CACHE_URL"]}`, ); - const sourceBinary = inputs.getStringOrNull("source-binary"); - const daemonBin = - sourceBinary !== null - ? sourceBinary - : await this.unpackClosure("magic-nix-cache"); + const daemonBin = await this.unpackClosure("magic-nix-cache"); let runEnv; if (actionsCore.isDebug()) { @@ -278,7 +274,7 @@ class MagicNixCacheAction extends DetSysAction { log.unwatch(); } - async notifyAutoCache(): Promise { + private async notifyAutoCache(): Promise { if (!this.daemonStarted) { actionsCore.debug("magic-nix-cache not started - Skipping"); return; From 9eec5fd5a2cc59bbc7a77f275cdf026cc4c93237 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Wed, 22 May 2024 17:27:53 -0300 Subject: [PATCH 26/27] Switch back to main branch of detsys-ts --- dist/index.js | 14 ++++++-------- package.json | 2 +- pnpm-lock.yaml | 8 ++++---- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/dist/index.js b/dist/index.js index 0c7b3e5..7d4656e 100644 --- a/dist/index.js +++ b/dist/index.js @@ -94066,7 +94066,7 @@ const external_node_child_process_namespaceObject = __WEBPACK_EXTERNAL_createReq const external_node_stream_promises_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:stream/promises"); ;// CONCATENATED MODULE: external "node:zlib" const external_node_zlib_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:zlib"); -;// CONCATENATED MODULE: ./node_modules/.pnpm/github.com+DeterminateSystems+detsys-ts@f1554c0d3a5f1114cff78879e50bc118451a03c0_t7eoi6mjzqgr2plrflke2xdf7i/node_modules/detsys-ts/dist/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/github.com+DeterminateSystems+detsys-ts@a089656286a58dc6767247181b5280826f20473a_q6benjgi5pgerrbnqocqupyoxq/node_modules/detsys-ts/dist/index.js var __defProp = Object.defineProperty; var __export = (target, all) => { for (var name in all) @@ -94676,9 +94676,8 @@ var DetSysAction = class { }); } /** - * Fetches a file in `.xz` format from the URL determined by the `source-*` - * parameters (or `source-binary` if set). It then imports that file's - * contents into the Nix store and returns the path of the executable at + * Unpacks the closure returned by `fetchArtifact()`, imports the + * contents into the Nix store, and returns the path of the executable at * `/nix/store/STORE_PATH/bin/${bin}`. */ async unpackClosure(bin) { @@ -94755,13 +94754,12 @@ var DetSysAction = class { } } /** - * Fetch an artifact, such as a tarball, from the URL determined by the `source-*` - * inputs or use a provided binary specified by the `source-binary` - * input. + * Fetch an artifact, such as a tarball, from the URL determined by the + * `source-*` inputs. */ async fetchArtifact() { const sourceBinary = getStringOrNull("source-binary"); - if (sourceBinary !== null) { + if (sourceBinary !== null && sourceBinary !== "") { core.debug(`Using the provided source binary at ${sourceBinary}`); return sourceBinary; } diff --git a/package.json b/package.json index f3278cb..73607f8 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "dependencies": { "@actions/core": "^1.10.1", "@actions/exec": "^1.1.1", - "detsys-ts": "github:DeterminateSystems/detsys-ts#source-binary", + "detsys-ts": "github:DeterminateSystems/detsys-ts", "got": "^14.3.0", "tail": "^2.2.6" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3c75a4f..bd29d48 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,8 +12,8 @@ dependencies: specifier: ^1.1.1 version: 1.1.1 detsys-ts: - specifier: github:DeterminateSystems/detsys-ts#source-binary - version: github.com/DeterminateSystems/detsys-ts/f1554c0d3a5f1114cff78879e50bc118451a03c0 + specifier: github:DeterminateSystems/detsys-ts + version: github.com/DeterminateSystems/detsys-ts/a089656286a58dc6767247181b5280826f20473a got: specifier: ^14.3.0 version: 14.3.0 @@ -3823,8 +3823,8 @@ packages: engines: {node: '>=10'} dev: true - github.com/DeterminateSystems/detsys-ts/f1554c0d3a5f1114cff78879e50bc118451a03c0: - resolution: {tarball: https://codeload.github.com/DeterminateSystems/detsys-ts/tar.gz/f1554c0d3a5f1114cff78879e50bc118451a03c0} + github.com/DeterminateSystems/detsys-ts/a089656286a58dc6767247181b5280826f20473a: + resolution: {tarball: https://codeload.github.com/DeterminateSystems/detsys-ts/tar.gz/a089656286a58dc6767247181b5280826f20473a} name: detsys-ts version: 1.0.0 dependencies: From 669ed126ac9b8a7e3fd7eedc5d9e4ff826d3a9b3 Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Wed, 22 May 2024 17:33:00 -0300 Subject: [PATCH 27/27] Add aarch64-linux test --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5a98ed3..916de9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,7 +49,7 @@ jobs: run-x86_64-linux-untrusted: needs: build - name: Run x86_64 Linux, Untrusted + name: Run x86_64-linux, Untrusted runs-on: ubuntu-22.04 permissions: id-token: "write" @@ -89,6 +89,8 @@ jobs: runner: "macos-latest-xlarge" - nix-system: "x86_64-darwin" runner: "macos-12" + - nix-system: "aarch64-linux" + runner: "namespace-profile-default-arm64" - nix-system: "x86_64-linux" runner: "ubuntu-22.04" steps: