From 45d13621c5a0ff9b49811bf00fbbe571f21af0ba Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 15 Jul 2024 17:38:01 -0700 Subject: [PATCH] Provide info output for potential missing permissions block --- dist/index.js | 7 ++++++- dist/index.js.map | 2 +- src/helpers.ts | 7 ++++++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/dist/index.js b/dist/index.js index ffd3643..1ab9bd7 100644 --- a/dist/index.js +++ b/dist/index.js @@ -88421,7 +88421,12 @@ async function netrcPath() { try { await flakeHubLogin(destinedNetrcPath); } catch (e) { - core.info("FlakeHub cache disabled."); + core.info( + "FlakeHub Cache is disabled due to missing or invalid token" + ); + core.info( + `If you're signed up for FlakeHub Cache, make sure that your Actions config has a \`permissions\` block with \`id-token\` set to "write" and \`contents\` set to "read"` + ); core.debug(`Error while logging into FlakeHub: ${e}`); } return destinedNetrcPath; diff --git a/dist/index.js.map b/dist/index.js.map index fc91772..bfb587f 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, stringifyError } 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\";\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 FACT_ENV_VARS_PRESENT = \"required_env_vars_present\";\nconst FACT_DIFF_STORE_ENABLED = \"diff_store\";\nconst FACT_ALREADY_RUNNING = \"noop_mode\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_ERROR_IN_MAIN = \"ERROR_IN_MAIN\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_ALREADY_RUNNING =\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 diffStore: boolean;\n private httpClient: Got;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n // This is set to `true` if the MNC is already running, in which case the\n // workflow will use the existing process rather than starting a new one.\n private alreadyRunning: 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 diagnosticsSuffix: \"perf\",\n });\n\n this.hostAndPort = inputs.getString(\"listen\");\n this.diffStore = inputs.getBool(\"diff-store\");\n\n this.addFact(FACT_DIFF_STORE_ENABLED, this.diffStore);\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.alreadyRunning = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.alreadyRunning = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.addFact(FACT_ALREADY_RUNNING, this.alreadyRunning);\n\n this.stapleFile(\"daemon.log\", path.join(this.daemonDir, \"daemon.log\"));\n }\n\n async main(): Promise {\n if (this.alreadyRunning) {\n actionsCore.warning(TEXT_ALREADY_RUNNING);\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 strict mode is off and there was an error in main, such as the daemon not starting,\n // then the post phase is skipped with a warning.\n if (!this.strictMode && this.errorInMain) {\n actionsCore.warning(\n `skipping post phase due to error in main phase: ${this.errorInMain}`,\n );\n return;\n }\n\n if (this.alreadyRunning) {\n actionsCore.debug(TEXT_ALREADY_RUNNING);\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(FACT_ENV_VARS_PRESENT, !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: \"debug,magic_nix_cache=trace,gha_cache=trace\",\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(this.diffStore ? [\"--diff-store\"] : [])\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) => {\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((e: unknown) => {\n this.exitMain(`Error in notifyPromise: ${stringifyError(e)}`);\n });\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\n this.exitMain(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: unknown) {\n this.exitMain(`Error starting the Magic Nix Cache: ${stringifyError(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 daemon process ${pid}`);\n\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e: unknown) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n // Throw an error only in strict mode, otherwise ignore because\n // we're in the post phase and shutting down after this anyway\n if (this.strictMode) {\n throw e;\n }\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 // Exit the workflow during the main phase. If strict mode is set, fail; if not, save the error\n // message to the workflow's state and exit successfully.\n private exitMain(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(msg);\n } else {\n actionsCore.saveState(STATE_ERROR_IN_MAIN, msg);\n process.exit(0);\n }\n }\n\n // If the main phase threw an error (not in strict mode), this will be a non-empty\n // string available in the post phase.\n private get errorInMain(): string | undefined {\n const state = actionsCore.getState(STATE_ERROR_IN_MAIN);\n return state !== \"\" ? state : undefined;\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(\n \"FlakeHub Cache is disabled due to missing or invalid token\",\n );\n actionsCore.info(\n `If you're signed up for FlakeHub Cache, make sure that your Actions config has a \\`permissions\\` block with \\`id-token\\` set to \"write\" and \\`contents\\` set to \"read\"`,\n );\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, stringifyError } 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\";\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 FACT_ENV_VARS_PRESENT = \"required_env_vars_present\";\nconst FACT_DIFF_STORE_ENABLED = \"diff_store\";\nconst FACT_ALREADY_RUNNING = \"noop_mode\";\n\nconst STATE_DAEMONDIR = \"MAGIC_NIX_CACHE_DAEMONDIR\";\nconst STATE_ERROR_IN_MAIN = \"ERROR_IN_MAIN\";\nconst STATE_STARTED = \"MAGIC_NIX_CACHE_STARTED\";\nconst STARTED_HINT = \"true\";\n\nconst TEXT_ALREADY_RUNNING =\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 diffStore: boolean;\n private httpClient: Got;\n private daemonDir: string;\n private daemonStarted: boolean;\n\n // This is set to `true` if the MNC is already running, in which case the\n // workflow will use the existing process rather than starting a new one.\n private alreadyRunning: 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 diagnosticsSuffix: \"perf\",\n });\n\n this.hostAndPort = inputs.getString(\"listen\");\n this.diffStore = inputs.getBool(\"diff-store\");\n\n this.addFact(FACT_DIFF_STORE_ENABLED, this.diffStore);\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.alreadyRunning = false;\n actionsCore.exportVariable(ENV_DAEMON_DIR, this.daemonDir);\n } else {\n this.alreadyRunning = process.env[ENV_DAEMON_DIR] !== this.daemonDir;\n }\n this.addFact(FACT_ALREADY_RUNNING, this.alreadyRunning);\n\n this.stapleFile(\"daemon.log\", path.join(this.daemonDir, \"daemon.log\"));\n }\n\n async main(): Promise {\n if (this.alreadyRunning) {\n actionsCore.warning(TEXT_ALREADY_RUNNING);\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 strict mode is off and there was an error in main, such as the daemon not starting,\n // then the post phase is skipped with a warning.\n if (!this.strictMode && this.errorInMain) {\n actionsCore.warning(\n `skipping post phase due to error in main phase: ${this.errorInMain}`,\n );\n return;\n }\n\n if (this.alreadyRunning) {\n actionsCore.debug(TEXT_ALREADY_RUNNING);\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(FACT_ENV_VARS_PRESENT, !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: \"debug,magic_nix_cache=trace,gha_cache=trace\",\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(this.diffStore ? [\"--diff-store\"] : [])\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) => {\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((e: unknown) => {\n this.exitMain(`Error in notifyPromise: ${stringifyError(e)}`);\n });\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\n this.exitMain(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: unknown) {\n this.exitMain(`Error starting the Magic Nix Cache: ${stringifyError(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 daemon process ${pid}`);\n\n try {\n process.kill(pid, \"SIGTERM\");\n } catch (e: unknown) {\n if (typeof e === \"object\" && e && \"code\" in e && e.code !== \"ESRCH\") {\n // Throw an error only in strict mode, otherwise ignore because\n // we're in the post phase and shutting down after this anyway\n if (this.strictMode) {\n throw e;\n }\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 // Exit the workflow during the main phase. If strict mode is set, fail; if not, save the error\n // message to the workflow's state and exit successfully.\n private exitMain(msg: string): void {\n if (this.strictMode) {\n actionsCore.setFailed(msg);\n } else {\n actionsCore.saveState(STATE_ERROR_IN_MAIN, msg);\n process.exit(0);\n }\n }\n\n // If the main phase threw an error (not in strict mode), this will be a non-empty\n // string available in the post phase.\n private get errorInMain(): string | undefined {\n const state = actionsCore.getState(STATE_ERROR_IN_MAIN);\n return state !== \"\" ? state : undefined;\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/helpers.ts b/src/helpers.ts index 4fcc011..c2a7596 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -30,7 +30,12 @@ export async function netrcPath(): Promise { try { await flakeHubLogin(destinedNetrcPath); } catch (e) { - actionsCore.info("FlakeHub cache disabled."); + actionsCore.info( + "FlakeHub Cache is disabled due to missing or invalid token", + ); + actionsCore.info( + `If you're signed up for FlakeHub Cache, make sure that your Actions config has a \`permissions\` block with \`id-token\` set to "write" and \`contents\` set to "read"`, + ); actionsCore.debug(`Error while logging into FlakeHub: ${e}`); } return destinedNetrcPath;