bulletin-deploy 0.7.3 → 0.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -0
- package/bin/bulletin-deploy +94 -1
- package/dist/bug-report.js +4 -3
- package/dist/{chunk-MDYSENTW.js → chunk-CQ753LDA.js} +1 -1
- package/dist/{chunk-BYIVK52G.js → chunk-DHQ3JGF4.js} +67 -75
- package/dist/{chunk-EPNPPAMS.js → chunk-SVKCVNXD.js} +68 -41
- package/dist/chunk-UJP2PZGU.js +155 -0
- package/dist/chunk-YREZFNCC.js +869 -0
- package/dist/{chunk-4EQERQRG.js → chunk-YYULF2JX.js} +2 -2
- package/dist/deploy.d.ts +4 -2
- package/dist/deploy.js +8 -5
- package/dist/dotns.d.ts +12 -40
- package/dist/dotns.js +9 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +24 -6
- package/dist/memory-report.js +2 -1
- package/dist/run-state.d.ts +22 -0
- package/dist/run-state.js +21 -0
- package/dist/telemetry.d.ts +5 -1
- package/dist/telemetry.js +8 -1
- package/dist/version-check.js +3 -2
- package/package.json +4 -3
- package/dist/chunk-M3H3F4FY.js +0 -1048
package/README.md
CHANGED
|
@@ -274,6 +274,32 @@ What's tracked:
|
|
|
274
274
|
- Source metadata (repo, branch, PR number, CI vs local)
|
|
275
275
|
- Tool version (`deploy.tool_version`)
|
|
276
276
|
|
|
277
|
+
### Using bulletin-deploy as a library under your own Sentry
|
|
278
|
+
|
|
279
|
+
If your tool embeds bulletin-deploy as a library and already runs its own Sentry SDK (for example, Parity's `playground-cli`), you can route bulletin-deploy's deploy spans, tags, and diagnostics through your existing Sentry client rather than clobbering it with ours. Set two env vars **before** importing or invoking bulletin-deploy:
|
|
280
|
+
|
|
281
|
+
```sh
|
|
282
|
+
BULLETIN_DEPLOY_USE_AMBIENT_SENTRY=1
|
|
283
|
+
BULLETIN_DEPLOY_HOST_APP=<your-app-name>
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
What happens:
|
|
287
|
+
|
|
288
|
+
- `BULLETIN_DEPLOY_USE_AMBIENT_SENTRY=1` makes `initTelemetry()` skip its own `Sentry.init()` call. bulletin-deploy reuses the global Sentry client your app already configured. All deploy spans, breadcrumbs, `captureWarning`/`captureMessage` calls route to your DSN.
|
|
289
|
+
- `BULLETIN_DEPLOY_HOST_APP=<name>` attaches `deploy.host_app: <name>` to every deploy span **and** as a Sentry scope tag, so downstream events in the same process carry it too. Use it to facet dashboards by host.
|
|
290
|
+
|
|
291
|
+
**Requirements:**
|
|
292
|
+
|
|
293
|
+
- Your app must call its own `Sentry.init()` **before** importing or spawning bulletin-deploy; otherwise there is no ambient client to reuse and telemetry is effectively off.
|
|
294
|
+
- Your Sentry project should live in the same Sentry organisation as `bulletin-deploy` (`o4511059872841728.ingest.de.sentry.io`) if you want our cross-project dashboards to aggregate your traffic. Different org = different world; no cross-aggregation is possible.
|
|
295
|
+
- If your consumer app is maintained by Parity, we can add its name to the `PARITY_HOST_APPS` allowlist in `src/telemetry.ts` so end-user installs of the compiled binary qualify for the same diagnostics as our internal CI. Today: `playground-cli`.
|
|
296
|
+
|
|
297
|
+
**Gotchas:**
|
|
298
|
+
|
|
299
|
+
- Quotas are per-project. A traffic spike in your project will eat your quota and can drop bulletin-deploy spans routing through it without any signal in our dashboards.
|
|
300
|
+
- Issue-feed fingerprints don't dedupe across projects: the same error in your project and ours surfaces as two separate Sentry issues.
|
|
301
|
+
- `@sentry/node` major version must be compatible with ours (currently v8.x). Skew risks runtime errors on the first span call.
|
|
302
|
+
|
|
277
303
|
### Tagging test and benchmark runs
|
|
278
304
|
|
|
279
305
|
Real-user deploys and automated test/benchmark deploys share the same telemetry pipeline. Use `--tag` (or the `DEPLOY_TAG` env var) to label non-production runs so Sentry dashboards can filter them out:
|
package/bin/bulletin-deploy
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
import { deploy, DEFAULT_BULLETIN_RPC, DEFAULT_POOL_SIZE, NonRetryableError, EXIT_CODE_NO_RETRY } from "../dist/deploy.js";
|
|
4
4
|
import { bootstrapPool } from "../dist/pool.js";
|
|
5
|
-
import { VERSION } from "../dist/telemetry.js";
|
|
5
|
+
import { VERSION, setDeployAttribute, captureWarning, closeTelemetry, setRunStateActive, markRelaunchOomHintShown } from "../dist/telemetry.js";
|
|
6
6
|
import { handleFailedDeploy, preReleaseWarning } from "../dist/version-check.js";
|
|
7
7
|
import { setDeployContext, installLogCapture, buildCliFlagsSummary } from "../dist/bug-report.js";
|
|
8
|
+
import { loadRunState, writeRunState, shouldSkipStaleWarning, shouldShowOomHint, probablyOomRssMb } from "../dist/run-state.js";
|
|
8
9
|
import * as fs from "fs";
|
|
9
10
|
|
|
10
11
|
// Install early so anything printed during flag parsing / preflight is
|
|
@@ -60,6 +61,92 @@ Options:
|
|
|
60
61
|
const rcWarning = preReleaseWarning(VERSION);
|
|
61
62
|
if (rcWarning) console.error(rcWarning);
|
|
62
63
|
|
|
64
|
+
// ── Crash capture (issue #154) ───────────────────────────────────
|
|
65
|
+
// Only wire crash capture for actual deploy / bootstrap runs — skip for
|
|
66
|
+
// --help / --version (which exit above) and --bootstrap (one-off ops op,
|
|
67
|
+
// no background work worth hinting OOM for).
|
|
68
|
+
if (!flags.help && !flags.version && !flags.bootstrap) {
|
|
69
|
+
// Sanitised argv — positional args + presence-only flag summary. Never
|
|
70
|
+
// puts a mnemonic/password/RPC/derivation-path on disk, even if the user
|
|
71
|
+
// passes one on the command line.
|
|
72
|
+
const sanitizedArgv = [
|
|
73
|
+
...positional,
|
|
74
|
+
...buildCliFlagsSummary(flags).split(" ").filter(Boolean),
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
// Check if the previous run left a stale "running" or "crashed" marker
|
|
78
|
+
// (i.e. this process is a relaunch after a SIGKILL/OOM). Print a hint
|
|
79
|
+
// BEFORE resetting state so the user sees what happened.
|
|
80
|
+
const prev = loadRunState();
|
|
81
|
+
if (prev && (prev.status === "running" || prev.status === "crashed") && !shouldSkipStaleWarning(prev)) {
|
|
82
|
+
if (shouldShowOomHint(prev)) {
|
|
83
|
+
const peak = prev.lastPeakRssMb ?? "unknown";
|
|
84
|
+
const stage = prev.lastStage ?? "unknown";
|
|
85
|
+
const threshold = probablyOomRssMb();
|
|
86
|
+
console.error("");
|
|
87
|
+
console.error(` Warning: previous deploy did not exit cleanly (peak RSS ${peak} MB at stage "${stage}", threshold ${threshold} MB).`);
|
|
88
|
+
console.error(` This looks like an out-of-memory kill. Retry with a larger heap:`);
|
|
89
|
+
console.error(` NODE_OPTIONS='--max-old-space-size=8192' bulletin-deploy ...`);
|
|
90
|
+
console.error("");
|
|
91
|
+
markRelaunchOomHintShown();
|
|
92
|
+
} else if (prev.status === "crashed" && prev.reason) {
|
|
93
|
+
console.error(` Previous deploy exited via ${prev.reason}. Continuing.`);
|
|
94
|
+
} else if (prev.status === "running") {
|
|
95
|
+
console.error(` Previous deploy did not exit cleanly. Continuing.`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Reset the state file to reflect THIS run. Any previous status (crashed,
|
|
100
|
+
// succeeded, etc.) is overwritten — we already surfaced the warning above.
|
|
101
|
+
writeRunState({
|
|
102
|
+
status: "running",
|
|
103
|
+
pid: process.pid,
|
|
104
|
+
startedAt: Date.now(),
|
|
105
|
+
endedAt: undefined,
|
|
106
|
+
toolVersion: VERSION,
|
|
107
|
+
argv: sanitizedArgv,
|
|
108
|
+
lastPeakRssMb: null,
|
|
109
|
+
lastStage: null,
|
|
110
|
+
reason: undefined,
|
|
111
|
+
});
|
|
112
|
+
setRunStateActive(true);
|
|
113
|
+
|
|
114
|
+
// ── Signal / uncaught handlers ──────────────────────────────
|
|
115
|
+
// Guard against re-entry: if a handler itself throws (e.g. Sentry close
|
|
116
|
+
// rejects), unhandledRejection must not recursively call finalize.
|
|
117
|
+
let finalizing = false;
|
|
118
|
+
const finalize = async (reason, exitCode) => {
|
|
119
|
+
if (finalizing) return;
|
|
120
|
+
finalizing = true;
|
|
121
|
+
try {
|
|
122
|
+
setDeployAttribute("deploy.killed", reason);
|
|
123
|
+
setDeployAttribute("deploy.sad", "true");
|
|
124
|
+
captureWarning(`deploy process terminated: ${reason}`);
|
|
125
|
+
} catch { /* telemetry best-effort */ }
|
|
126
|
+
try { await closeTelemetry(1000); } catch { /* ignore */ }
|
|
127
|
+
try {
|
|
128
|
+
writeRunState({ status: "crashed", endedAt: Date.now(), reason });
|
|
129
|
+
} catch { /* fs best-effort */ }
|
|
130
|
+
process.exit(exitCode);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
process.on("uncaughtException", (e) => {
|
|
134
|
+
try { setDeployAttribute("deploy.error", (e?.message ?? String(e)).slice(0, 200)); } catch {}
|
|
135
|
+
finalize("uncaught", 2);
|
|
136
|
+
});
|
|
137
|
+
process.on("unhandledRejection", (e) => {
|
|
138
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
139
|
+
try { setDeployAttribute("deploy.error", msg.slice(0, 200)); } catch {}
|
|
140
|
+
finalize("unhandled", 2);
|
|
141
|
+
});
|
|
142
|
+
// POSIX exit codes: 128 + signal number. Matches shell conventions so
|
|
143
|
+
// callers (e.g. consumer CI with EXIT_CODE_NO_RETRY=75) treat them as
|
|
144
|
+
// retryable.
|
|
145
|
+
process.on("SIGINT", () => finalize("SIGINT", 130));
|
|
146
|
+
process.on("SIGTERM", () => finalize("SIGTERM", 143));
|
|
147
|
+
process.on("SIGHUP", () => finalize("SIGHUP", 129));
|
|
148
|
+
}
|
|
149
|
+
|
|
63
150
|
try {
|
|
64
151
|
if (flags.bootstrap) {
|
|
65
152
|
const rpc = flags.rpc ?? process.env.BULLETIN_RPC ?? DEFAULT_BULLETIN_RPC;
|
|
@@ -112,10 +199,16 @@ try {
|
|
|
112
199
|
console.log(`CID: ${result.cid}`);
|
|
113
200
|
console.log(`Domain: ${result.domainName}`);
|
|
114
201
|
}
|
|
202
|
+
if (!flags.help && !flags.version && !flags.bootstrap) {
|
|
203
|
+
try { writeRunState({ status: "succeeded", endedAt: Date.now() }); } catch {}
|
|
204
|
+
}
|
|
115
205
|
process.exit(0);
|
|
116
206
|
} catch (error) {
|
|
117
207
|
const noRetry = error instanceof NonRetryableError;
|
|
118
208
|
console.error(`Deployment failed${noRetry ? " (not retryable)" : ""}:`, error.message);
|
|
119
209
|
await handleFailedDeploy(error);
|
|
210
|
+
if (!flags.help && !flags.version && !flags.bootstrap) {
|
|
211
|
+
try { writeRunState({ status: "failed", endedAt: Date.now(), reason: (error?.message ?? String(error)).slice(0, 200) }); } catch {}
|
|
212
|
+
}
|
|
120
213
|
process.exit(noRetry ? EXIT_CODE_NO_RETRY : 1);
|
|
121
214
|
}
|
package/dist/bug-report.js
CHANGED
|
@@ -9,9 +9,10 @@ import {
|
|
|
9
9
|
offerBugReport,
|
|
10
10
|
scrubSecrets,
|
|
11
11
|
setDeployContext
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-YYULF2JX.js";
|
|
13
|
+
import "./chunk-CQ753LDA.js";
|
|
14
|
+
import "./chunk-DHQ3JGF4.js";
|
|
15
|
+
import "./chunk-UJP2PZGU.js";
|
|
15
16
|
import "./chunk-QGM4M3NI.js";
|
|
16
17
|
export {
|
|
17
18
|
buildCliFlagsSummary,
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
package_default,
|
|
3
|
+
writeRunState
|
|
4
|
+
} from "./chunk-UJP2PZGU.js";
|
|
5
|
+
|
|
1
6
|
// src/memory-report.ts
|
|
2
7
|
import * as fs2 from "fs";
|
|
3
8
|
import * as os from "os";
|
|
@@ -9,77 +14,10 @@ import { execSync } from "child_process";
|
|
|
9
14
|
import { createHash } from "crypto";
|
|
10
15
|
import * as fs from "fs";
|
|
11
16
|
import * as path from "path";
|
|
12
|
-
|
|
13
|
-
// package.json
|
|
14
|
-
var package_default = {
|
|
15
|
-
name: "bulletin-deploy",
|
|
16
|
-
version: "0.7.3",
|
|
17
|
-
private: false,
|
|
18
|
-
repository: {
|
|
19
|
-
type: "git",
|
|
20
|
-
url: "https://github.com/paritytech/bulletin-deploy.git"
|
|
21
|
-
},
|
|
22
|
-
publishConfig: {
|
|
23
|
-
registry: "https://registry.npmjs.org",
|
|
24
|
-
access: "public"
|
|
25
|
-
},
|
|
26
|
-
type: "module",
|
|
27
|
-
main: "./dist/index.js",
|
|
28
|
-
types: "./dist/index.d.ts",
|
|
29
|
-
bin: {
|
|
30
|
-
"bulletin-deploy": "./bin/bulletin-deploy"
|
|
31
|
-
},
|
|
32
|
-
exports: {
|
|
33
|
-
".": {
|
|
34
|
-
types: "./dist/index.d.ts",
|
|
35
|
-
import: "./dist/index.js"
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
files: [
|
|
39
|
-
"dist",
|
|
40
|
-
"bin"
|
|
41
|
-
],
|
|
42
|
-
scripts: {
|
|
43
|
-
build: "tsup src/index.ts src/deploy.ts src/dotns.ts src/pool.ts src/telemetry.ts src/memory-report.ts src/merkle.ts src/gh-pages-mirror.ts src/version-check.ts src/bug-report.ts --format esm --dts --clean --target node22",
|
|
44
|
-
prepare: "npm run build",
|
|
45
|
-
test: "npm run build && node --test test/test.js test/pool.test.js test/helpers/e2e-helpers.test.js",
|
|
46
|
-
"test:e2e": "npm run build && node --test test/e2e.test.js",
|
|
47
|
-
"test:e2e:smoke": "bash scripts/e2e-pass.sh smoke",
|
|
48
|
-
"test:e2e:pr": "bash scripts/e2e-pass.sh pr",
|
|
49
|
-
"test:e2e:nightly": "bash scripts/e2e-pass.sh nightly",
|
|
50
|
-
benchmark: "npm run build && node benchmark.js"
|
|
51
|
-
},
|
|
52
|
-
dependencies: {
|
|
53
|
-
"@ipld/car": "^5.4.3",
|
|
54
|
-
"@ipld/dag-pb": "^4.1.3",
|
|
55
|
-
"@noble/hashes": "^1.7.2",
|
|
56
|
-
"@polkadot-api/substrate-bindings": "^0.16.5",
|
|
57
|
-
"@polkadot-labs/hdkd": "^0.0.25",
|
|
58
|
-
"@polkadot-labs/hdkd-helpers": "^0.0.26",
|
|
59
|
-
"@polkadot/keyring": "^13.0.0",
|
|
60
|
-
"@polkadot/util-crypto": "^13.0.0",
|
|
61
|
-
"@sentry/node": "^9.14.0",
|
|
62
|
-
"ipfs-unixfs": "^11.2.0",
|
|
63
|
-
"ipfs-unixfs-importer": "^16.1.4",
|
|
64
|
-
multiformats: "^13.4.1",
|
|
65
|
-
"polkadot-api": "^1.23.1",
|
|
66
|
-
viem: "^2.30.5"
|
|
67
|
-
},
|
|
68
|
-
devDependencies: {
|
|
69
|
-
"@types/node": "^22.0.0",
|
|
70
|
-
tsup: "^8.5.0",
|
|
71
|
-
typescript: "^5.9.3"
|
|
72
|
-
},
|
|
73
|
-
minimumVersion: "0.5.6",
|
|
74
|
-
engines: {
|
|
75
|
-
node: ">=22"
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
// src/telemetry.ts
|
|
80
17
|
var VERSION = package_default.version;
|
|
81
18
|
var DEFAULT_DSN = "https://e021c025d79c4c3ade2862a11f13c40b@o4511059872841728.ingest.de.sentry.io/4511093597405264";
|
|
82
19
|
var INTERNAL_ORG_RE = /^(paritytech|w3f|polkadot-fellows)\//i;
|
|
20
|
+
var PARITY_HOST_APPS = /* @__PURE__ */ new Set(["playground-cli"]);
|
|
83
21
|
function extractRepoSlug(url) {
|
|
84
22
|
return url.replace(/.*github\.com[:/]/, "").replace(/\.git$/, "");
|
|
85
23
|
}
|
|
@@ -94,13 +32,15 @@ function isInternalContextFromSignals(signals) {
|
|
|
94
32
|
if (INTERNAL_ORG_RE.test(signals.githubRepository ?? "")) return true;
|
|
95
33
|
if (signals.runnerName?.startsWith("parity-")) return true;
|
|
96
34
|
if (signals.gitRemote && INTERNAL_ORG_RE.test(signals.gitRemote)) return true;
|
|
35
|
+
if (signals.hostApp && PARITY_HOST_APPS.has(signals.hostApp)) return true;
|
|
97
36
|
return false;
|
|
98
37
|
}
|
|
99
38
|
function isInternalContext() {
|
|
100
39
|
return isInternalContextFromSignals({
|
|
101
40
|
githubRepository: process.env.GITHUB_REPOSITORY,
|
|
102
41
|
runnerName: process.env.RUNNER_NAME,
|
|
103
|
-
gitRemote: tryGitRemote()
|
|
42
|
+
gitRemote: tryGitRemote(),
|
|
43
|
+
hostApp: process.env.BULLETIN_DEPLOY_HOST_APP
|
|
104
44
|
});
|
|
105
45
|
}
|
|
106
46
|
var OPT_OUT = process.env.BULLETIN_DEPLOY_TELEMETRY === "0";
|
|
@@ -155,8 +95,26 @@ if (!DISABLED) {
|
|
|
155
95
|
} catch {
|
|
156
96
|
}
|
|
157
97
|
}
|
|
98
|
+
var runStateActive = false;
|
|
99
|
+
var relaunchOomHintShown = false;
|
|
100
|
+
function setRunStateActive(v) {
|
|
101
|
+
runStateActive = v;
|
|
102
|
+
}
|
|
103
|
+
function markRelaunchOomHintShown() {
|
|
104
|
+
relaunchOomHintShown = true;
|
|
105
|
+
}
|
|
106
|
+
async function closeTelemetry(timeoutMs) {
|
|
107
|
+
if (!Sentry) return;
|
|
108
|
+
try {
|
|
109
|
+
await Sentry.close(timeoutMs);
|
|
110
|
+
} catch {
|
|
111
|
+
}
|
|
112
|
+
}
|
|
158
113
|
function initTelemetry() {
|
|
159
114
|
if (!Sentry) return;
|
|
115
|
+
if (process.env.BULLETIN_DEPLOY_USE_AMBIENT_SENTRY === "1") {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
160
118
|
Sentry.init({
|
|
161
119
|
dsn: process.env.SENTRY_DSN || DEFAULT_DSN,
|
|
162
120
|
release: `${package_default.name}@${VERSION}`,
|
|
@@ -189,6 +147,12 @@ function initTelemetry() {
|
|
|
189
147
|
return event;
|
|
190
148
|
}
|
|
191
149
|
});
|
|
150
|
+
Sentry.setTag("bulletin-deploy.version", VERSION);
|
|
151
|
+
Sentry.setContext("bulletin-deploy", {
|
|
152
|
+
version: VERSION,
|
|
153
|
+
release: `${package_default.name}@${VERSION}`,
|
|
154
|
+
node: process.version
|
|
155
|
+
});
|
|
192
156
|
}
|
|
193
157
|
function tryPackageJsonRepo() {
|
|
194
158
|
try {
|
|
@@ -220,7 +184,8 @@ function resolveRunnerType() {
|
|
|
220
184
|
return "github-hosted";
|
|
221
185
|
}
|
|
222
186
|
function getDeployAttributes(domain) {
|
|
223
|
-
|
|
187
|
+
const hostApp = process.env.BULLETIN_DEPLOY_HOST_APP;
|
|
188
|
+
const attrs = {
|
|
224
189
|
"deploy.repo": sanitizeRepo(resolveRepo(domain)),
|
|
225
190
|
"deploy.branch": sanitizeBranch(process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || tryGitBranch()),
|
|
226
191
|
"deploy.source": process.env.CI ? "ci" : "local",
|
|
@@ -230,8 +195,18 @@ function getDeployAttributes(domain) {
|
|
|
230
195
|
"deploy.runner_type": resolveRunnerType(),
|
|
231
196
|
// Seed "false" so successful spans form the %SAD denominator; the catch block and
|
|
232
197
|
// captureWarning flip it to "true" on friction.
|
|
233
|
-
"deploy.sad": "false"
|
|
198
|
+
"deploy.sad": "false",
|
|
199
|
+
// Same ratio-denominator reasoning as deploy.sad above, but for the
|
|
200
|
+
// %EXPECTED-refusal metric: catch block flips to "true" when the error
|
|
201
|
+
// matches isExpectedError (user-facing product rule, not tool friction).
|
|
202
|
+
"deploy.expected": "false",
|
|
203
|
+
// Seed "false" so every span carries the attribute (boolean-both-values rule).
|
|
204
|
+
// Flipped to "true" by getWsProvider's onStatusChanged when papi connects to a
|
|
205
|
+
// non-primary endpoint, and flushed again in deploy()'s finally block.
|
|
206
|
+
"deploy.rpc.failed_over": "false"
|
|
234
207
|
};
|
|
208
|
+
if (hostApp) attrs["deploy.host_app"] = hostApp;
|
|
209
|
+
return attrs;
|
|
235
210
|
}
|
|
236
211
|
function isExpectedError(msg) {
|
|
237
212
|
return /personhood|owned by|owner mismatch|reserved for original|invalid domain label|not authorized for bulletin|insufficient balance|quota exhausted|insufficient .* authorization/i.test(msg);
|
|
@@ -281,6 +256,12 @@ function sampleMemory(stage) {
|
|
|
281
256
|
deployRootSpan.setAttribute("deploy.mem.peak_array_buffers_mb", String(toMb(memoryPeak.arrayBuffers)));
|
|
282
257
|
}
|
|
283
258
|
}
|
|
259
|
+
if (runStateActive && memoryPeak) {
|
|
260
|
+
try {
|
|
261
|
+
writeRunState({ lastPeakRssMb: toMb(memoryPeak.rss), lastStage: stage });
|
|
262
|
+
} catch {
|
|
263
|
+
}
|
|
264
|
+
}
|
|
284
265
|
}
|
|
285
266
|
async function withDeploySpan(domain, fn) {
|
|
286
267
|
if (!Sentry) return fn();
|
|
@@ -293,22 +274,30 @@ async function withDeploySpan(domain, fn) {
|
|
|
293
274
|
try {
|
|
294
275
|
return await Sentry.startSpan({ op: "deploy", name: `deploy ${domain}`, attributes: attrs }, async (span) => {
|
|
295
276
|
deployRootSpan = span;
|
|
296
|
-
|
|
277
|
+
span.setAttribute("deploy.tool_version", VERSION);
|
|
278
|
+
if (relaunchOomHintShown) {
|
|
279
|
+
span.setAttribute("deploy.relaunch.oom_hint_shown", "true");
|
|
280
|
+
}
|
|
281
|
+
const tagsToSet = {
|
|
297
282
|
"deploy.repo": attrs["deploy.repo"],
|
|
298
283
|
"deploy.branch": attrs["deploy.branch"],
|
|
299
284
|
"deploy.domain": domain,
|
|
300
285
|
"deploy.source": attrs["deploy.source"],
|
|
301
286
|
"deploy.tool_version": VERSION,
|
|
302
|
-
"deploy.runner_type": resolveRunnerType()
|
|
303
|
-
|
|
287
|
+
"deploy.runner_type": resolveRunnerType(),
|
|
288
|
+
"deploy.host_app": attrs["deploy.host_app"] ?? ""
|
|
289
|
+
};
|
|
290
|
+
if (!tagsToSet["deploy.host_app"]) delete tagsToSet["deploy.host_app"];
|
|
291
|
+
Sentry.setTags(tagsToSet);
|
|
304
292
|
try {
|
|
305
293
|
return await fn();
|
|
306
294
|
} catch (error) {
|
|
307
295
|
const msg = error.message;
|
|
308
296
|
span.setAttribute("deploy.status", "error");
|
|
309
297
|
span.setAttribute("deploy.error", msg.slice(0, 200));
|
|
310
|
-
span.setAttribute("deploy.sad", "true");
|
|
311
298
|
const isExpected = isExpectedError(msg);
|
|
299
|
+
span.setAttribute("deploy.expected", isExpected ? "true" : "false");
|
|
300
|
+
span.setAttribute("deploy.sad", isExpected ? "false" : "true");
|
|
312
301
|
if (!isExpected) {
|
|
313
302
|
span.setStatus({ code: 2, message: "internal_error" });
|
|
314
303
|
}
|
|
@@ -524,6 +513,9 @@ export {
|
|
|
524
513
|
truncateAddress,
|
|
525
514
|
sanitizeBranch,
|
|
526
515
|
sanitizeRepo,
|
|
516
|
+
setRunStateActive,
|
|
517
|
+
markRelaunchOomHintShown,
|
|
518
|
+
closeTelemetry,
|
|
527
519
|
initTelemetry,
|
|
528
520
|
resolveRepo,
|
|
529
521
|
resolveRunner,
|