diff --git a/dist/index.js b/dist/index.js index c4f5f72..1d059c2 100644 --- a/dist/index.js +++ b/dist/index.js @@ -89319,6 +89319,8 @@ var external_path_ = __nccwpck_require__(1017); var external_node_util_ = __nccwpck_require__(7261); // EXTERNAL MODULE: external "os" var external_os_ = __nccwpck_require__(2037); +;// CONCATENATED MODULE: external "node:zlib" +const external_node_zlib_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:zlib"); ;// CONCATENATED MODULE: external "node:crypto" const external_node_crypto_namespaceObject = __WEBPACK_EXTERNAL_createRequire(import.meta.url)("node:crypto"); ;// CONCATENATED MODULE: ./node_modules/.pnpm/@sindresorhus+is@7.0.0/node_modules/@sindresorhus/is/distribution/index.js @@ -96403,9 +96405,7 @@ var cache = __nccwpck_require__(6878); 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@17bd89132b0366c45ca87ab5d0361b890fa73f4f_cjpznqjwacyuxsurysbimtbktq/node_modules/detsys-ts/dist/index.js +;// CONCATENATED MODULE: ./node_modules/.pnpm/github.com+DeterminateSystems+detsys-ts@cf1897a891edc164a8240f469cd56d14364e6be1_fq5hfjh622jf54cg4vepqdc2u4/node_modules/detsys-ts/dist/index.js var __defProp = Object.defineProperty; var __export = (target, all) => { for (var name in all) @@ -96618,6 +96618,160 @@ async function getDetails() { }; } +// src/errors.ts +function stringifyError(e) { + if (e instanceof Error) { + return e.message; + } else if (typeof e === "string") { + return e; + } else { + return JSON.stringify(e); + } +} + +// src/backtrace.ts + + + + + +async function collectBacktraces(prefixes) { + if (isMacOS) { + return await collectBacktracesMacOS(prefixes); + } + if (isLinux) { + return await collectBacktracesSystemd(prefixes); + } + return /* @__PURE__ */ new Map(); +} +async function collectBacktracesMacOS(prefixes) { + const backtraces = /* @__PURE__ */ new Map(); + try { + const { stdout: logJson } = await exec.getExecOutput( + "log", + [ + "show", + "--style", + "json", + "--last", + // Note we collect the last 1m only, because it should only take a few seconds to write the crash log. + // Therefore, any crashes before this 1m should be long done by now. + "1m", + "--no-info", + "--predicate", + "sender = 'ReportCrash'" + ], + { + silent: true + } + ); + const sussyArray = JSON.parse(logJson); + if (!Array.isArray(sussyArray)) { + throw new Error(`Log json isn't an array: ${logJson}`); + } + if (sussyArray.length > 0) { + core.info(`Collecting crash data...`); + const delay = async (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + await delay(5e3); + } + } catch (e) { + core.debug( + "Failed to check logs for in-progress crash dumps; now proceeding with the assumption that all crash dumps completed." + ); + } + const dirs = [ + ["system", "/Library/Logs/DiagnosticReports/"], + ["user", `${process.env["HOME"]}/Library/Logs/DiagnosticReports/`] + ]; + for (const [source, dir] of dirs) { + const fileNames = (await (0,promises_namespaceObject.readdir)(dir)).filter((fileName) => { + return prefixes.some((prefix) => fileName.startsWith(prefix)); + }); + const doGzip = (0,external_node_util_.promisify)(external_node_zlib_namespaceObject.gzip); + for (const fileName of fileNames) { + try { + const logText = await (0,promises_namespaceObject.readFile)(`${dir}/${fileName}`); + const buf = await doGzip(logText); + backtraces.set( + `backtrace_value_${source}_${fileName}`, + buf.toString("base64") + ); + } catch (innerError) { + backtraces.set( + `backtrace_failure_${source}_${fileName}`, + stringifyError(innerError) + ); + } + } + } + return backtraces; +} +async function collectBacktracesSystemd(prefixes) { + const backtraces = /* @__PURE__ */ new Map(); + const coredumps = []; + try { + const { stdout: coredumpjson } = await exec.getExecOutput( + "coredumpctl", + ["--json=pretty", "list", "--since", "1 hour ago"], + { + silent: true + } + ); + const sussyArray = JSON.parse(coredumpjson); + if (!Array.isArray(sussyArray)) { + throw new Error(`Coredump isn't an array: ${coredumpjson}`); + } + for (const sussyObject of sussyArray) { + const keys = Object.keys(sussyObject); + if (keys.includes("exe") && keys.includes("pid")) { + if (typeof sussyObject.exe == "string" && typeof sussyObject.pid == "number") { + const execParts = sussyObject.exe.split("/"); + const binaryName = execParts[execParts.length - 1]; + if (prefixes.some((prefix) => binaryName.startsWith(prefix))) { + coredumps.push({ + exe: sussyObject.exe, + pid: sussyObject.pid + }); + } + } else { + core.debug( + `Mysterious coredump entry missing exe string and/or pid number: ${JSON.stringify(sussyObject)}` + ); + } + } else { + core.debug( + `Mysterious coredump entry missing exe value and/or pid value: ${JSON.stringify(sussyObject)}` + ); + } + } + } catch (innerError) { + core.debug( + `Cannot collect backtraces: ${stringifyError(innerError)}` + ); + return backtraces; + } + const doGzip = (0,external_node_util_.promisify)(external_node_zlib_namespaceObject.gzip); + for (const coredump of coredumps) { + try { + const { stdout: logText } = await exec.getExecOutput( + "coredumpctl", + ["info", `${coredump.pid}`], + { + silent: true + } + ); + const buf = await doGzip(logText); + backtraces.set(`backtrace_value_${coredump.pid}`, buf.toString("base64")); + } catch (innerError) { + backtraces.set( + `backtrace_failure_${coredump.pid}`, + stringifyError(innerError) + ); + } + } + return backtraces; +} + // src/correlation.ts @@ -96709,17 +96863,6 @@ function hashEnvironmentVariables(prefix, variables) { return `${prefix}-${hash.digest("hex")}`; } -// src/errors.ts -function stringifyError(e) { - if (e instanceof Error) { - return e.message; - } else if (typeof e === "string") { - return e; - } else { - return JSON.stringify(e); - } -} - // src/ids-host.ts @@ -97119,6 +97262,7 @@ function noisilyGetInput(suffix, legacyPrefix) { +var EVENT_BACKTRACES = "backtrace"; var EVENT_EXCEPTION = "exception"; var EVENT_ARTIFACT_CACHE_HIT = "artifact_cache_hit"; var EVENT_ARTIFACT_CACHE_MISS = "artifact_cache_miss"; @@ -97346,6 +97490,9 @@ var DetSysAction = class { } this.recordEvent(EVENT_EXCEPTION, Object.fromEntries(exceptionContext)); } finally { + if (this.isPost) { + await this.collectBacktraces(); + } await this.complete(); } } @@ -97605,6 +97752,21 @@ var DetSysAction = class { process.chdir(startCwd); } } + async collectBacktraces() { + try { + const backtraces = await collectBacktraces( + this.actionOptions.binaryNamePrefixes + ); + core.debug(`Backtraces identified: ${backtraces.size}`); + if (backtraces.size > 0) { + this.recordEvent(EVENT_BACKTRACES, Object.fromEntries(backtraces)); + } + } catch (innerError) { + core.debug( + `Error collecting backtraces: ${stringifyError2(innerError)}` + ); + } + } async preflightRequireNix() { let nixLocation; const pathParts = (process.env["PATH"] || "").split(":"); @@ -97731,7 +97893,8 @@ function makeOptionsConfident(actionOptions) { eventPrefix: actionOptions.eventPrefix || "action:", fetchStyle: actionOptions.fetchStyle, legacySourcePrefix: actionOptions.legacySourcePrefix, - requireNix: actionOptions.requireNix + requireNix: actionOptions.requireNix, + binaryNamePrefixes: actionOptions.binaryNamePrefixes || ["nix"] }; core.debug("idslib options:"); core.debug(JSON.stringify(finalOpts, void 0, 2)); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0f17248..3c02474 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,7 +16,7 @@ dependencies: version: 5.1.1 detsys-ts: specifier: github:DeterminateSystems/detsys-ts - version: github.com/DeterminateSystems/detsys-ts/17bd89132b0366c45ca87ab5d0361b890fa73f4f + version: github.com/DeterminateSystems/detsys-ts/cf1897a891edc164a8240f469cd56d14364e6be1 got: specifier: ^14.3.0 version: 14.3.0 @@ -5685,10 +5685,10 @@ packages: engines: { node: ">=10" } dev: true - github.com/DeterminateSystems/detsys-ts/17bd89132b0366c45ca87ab5d0361b890fa73f4f: + github.com/DeterminateSystems/detsys-ts/cf1897a891edc164a8240f469cd56d14364e6be1: resolution: { - tarball: https://codeload.github.com/DeterminateSystems/detsys-ts/tar.gz/17bd89132b0366c45ca87ab5d0361b890fa73f4f, + tarball: https://codeload.github.com/DeterminateSystems/detsys-ts/tar.gz/cf1897a891edc164a8240f469cd56d14364e6be1, } name: detsys-ts version: 1.0.0