bulletin-deploy 0.6.7 → 0.6.8

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 CHANGED
@@ -135,6 +135,7 @@ If you see **"Requires Full Personhood verification"**, the deploy will fail ear
135
135
  |---|---|---|
136
136
  | `BULLETIN_RPC` | `wss://paseo-bulletin-rpc.polkadot.io` | Bulletin chain WebSocket RPC |
137
137
  | `BULLETIN_DEPLOY_TELEMETRY` | `1` (enabled) | Set to `0` to disable Sentry telemetry |
138
+ | `BULLETIN_DEPLOY_UPDATE_CHECK` | `1` (enabled) | Set to `0` to disable version check on errors |
138
139
  | `DOTNS_STATUS` | `full` (testnet) / `none` (mainnet) | PoP level to self-grant before registration: `none`, `lite`, or `full` |
139
140
  | `IPFS_CID` | _(none)_ | Skip storage, use pre-existing CID |
140
141
 
@@ -202,6 +203,22 @@ Instead of using a single account for all storage transactions, bulletin-deploy
202
203
 
203
204
  When a pool account's authorization drops below thresholds (50 transactions or 50MB), bulletin-deploy automatically tops it up by submitting an `authorize_account` transaction from Alice.
204
205
 
206
+ ## Version Checking
207
+
208
+ When a deploy fails, bulletin-deploy checks whether a newer version is available. This helps catch cases where the error was already fixed in a later release.
209
+
210
+ Two sources are checked in parallel:
211
+ - **npm registry** — reads the `minimumVersion` field from the latest published version
212
+ - **GitHub kill switch** (`min-version.json` in the repo) — allows emergency deprecation without a release
213
+
214
+ If either source indicates your version is below the minimum, the CLI tells you the version is unsupported and why. If you're simply outdated (but above the minimum), you get a suggestion to update.
215
+
216
+ For **paritytech** contributors in an interactive terminal, the CLI offers to update and retry automatically. For everyone else (external users, CI), it prints the update command and exits.
217
+
218
+ If you're already on the latest version and hit an error, the CLI offers to open a GitHub issue with collected debug info (paritytech contributors only).
219
+
220
+ Set `BULLETIN_DEPLOY_UPDATE_CHECK=0` to disable version checking.
221
+
205
222
  ## Telemetry
206
223
 
207
224
  Sentry telemetry is enabled by default for deploy observability. Set `BULLETIN_DEPLOY_TELEMETRY=0` to disable.
@@ -212,10 +229,11 @@ What's tracked:
212
229
  - DotNS phase timing (registration, contenthash update)
213
230
  - Pool account selection
214
231
  - Source metadata (repo, branch, PR number, CI vs local)
232
+ - Tool version (`deploy.tool_version`)
215
233
 
216
234
  Dashboard:
217
- - Bulletin Deploy Health: https://paritytech.sentry.io/dashboard/1669817/
218
- - Deploy Failures Detail: https://paritytech.sentry.io/dashboard/1669818/
235
+ - Bulletin Deploy Health: https://paritytech.sentry.io/dashboard/1669817/?project=4511093597405264
236
+ - Deploy Failures Detail: https://paritytech.sentry.io/dashboard/1669818/?project=4511093597405264
219
237
 
220
238
  ## Troubleshooting
221
239
 
@@ -3,6 +3,8 @@
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
5
  import { VERSION } from "../dist/telemetry.js";
6
+ import { handleFailedDeploy } from "../dist/version-check.js";
7
+ import { setDeployContext } from "../dist/bug-report.js";
6
8
  import * as fs from "fs";
7
9
 
8
10
  const args = process.argv.slice(2);
@@ -57,6 +59,14 @@ try {
57
59
  if (!domain) { console.error("Error: domain required (e.g. my-app.dot)"); process.exit(1); }
58
60
  if (!fs.existsSync(buildDir)) { console.error(`Error: ${buildDir} does not exist`); process.exit(1); }
59
61
 
62
+ setDeployContext({
63
+ domain,
64
+ rpc: flags.rpc,
65
+ repo: process.env.GITHUB_REPOSITORY,
66
+ branch: process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME,
67
+ signerMode: flags.mnemonic ? "direct" : "pool",
68
+ });
69
+
60
70
  const result = await deploy(buildDir, domain, {
61
71
  playground: flags.playground,
62
72
  mnemonic: flags.mnemonic,
@@ -79,5 +89,6 @@ try {
79
89
  } catch (error) {
80
90
  const noRetry = error instanceof NonRetryableError;
81
91
  console.error(`Deployment failed${noRetry ? " (not retryable)" : ""}:`, error.message);
92
+ await handleFailedDeploy(error);
82
93
  process.exit(noRetry ? EXIT_CODE_NO_RETRY : 1);
83
94
  }
@@ -0,0 +1,14 @@
1
+ interface DeployContext {
2
+ domain?: string;
3
+ repo?: string;
4
+ branch?: string;
5
+ signerMode?: string;
6
+ chunkCount?: number;
7
+ totalSize?: string;
8
+ rpc?: string;
9
+ sentryTraceId?: string;
10
+ }
11
+ declare function setDeployContext(ctx: Partial<DeployContext>): void;
12
+ declare function offerBugReport(error: Error): Promise<void>;
13
+
14
+ export { offerBugReport, setDeployContext };
@@ -0,0 +1,108 @@
1
+ import {
2
+ classifyErrorArea,
3
+ isInteractive,
4
+ promptYesNo
5
+ } from "./chunk-SYJ2L6RU.js";
6
+ import {
7
+ VERSION
8
+ } from "./chunk-SLARK556.js";
9
+ import "./chunk-QGM4M3NI.js";
10
+
11
+ // src/bug-report.ts
12
+ import { execSync, execFileSync } from "child_process";
13
+ import * as os from "os";
14
+ var _deployContext = {};
15
+ function setDeployContext(ctx) {
16
+ _deployContext = { ..._deployContext, ...ctx };
17
+ }
18
+ function hasGhCli() {
19
+ try {
20
+ execSync("gh --version", { stdio: "pipe" });
21
+ return true;
22
+ } catch {
23
+ return false;
24
+ }
25
+ }
26
+ function buildReportBody(error) {
27
+ const lines = [
28
+ "## Environment",
29
+ "",
30
+ `- **bulletin-deploy**: ${VERSION}`,
31
+ `- **Node.js**: ${process.version}`,
32
+ `- **OS**: ${os.platform()} ${os.arch()} ${os.release()}`,
33
+ "",
34
+ "## Error",
35
+ "",
36
+ "```",
37
+ error.stack || error.message,
38
+ "```",
39
+ ""
40
+ ];
41
+ const ctx = _deployContext;
42
+ if (ctx.domain || ctx.repo || ctx.rpc) {
43
+ lines.push("## Deploy Context", "");
44
+ if (ctx.domain) lines.push(`- **Domain**: ${ctx.domain}`);
45
+ if (ctx.repo) lines.push(`- **Repo**: ${ctx.repo}`);
46
+ if (ctx.branch) lines.push(`- **Branch**: ${ctx.branch}`);
47
+ if (ctx.signerMode) lines.push(`- **Signer mode**: ${ctx.signerMode}`);
48
+ if (ctx.chunkCount != null) lines.push(`- **Chunks**: ${ctx.chunkCount}`);
49
+ if (ctx.totalSize) lines.push(`- **Total size**: ${ctx.totalSize}`);
50
+ if (ctx.rpc) lines.push(`- **RPC**: ${ctx.rpc}`);
51
+ if (ctx.sentryTraceId) lines.push(`- **Sentry trace**: ${ctx.sentryTraceId}`);
52
+ lines.push("");
53
+ }
54
+ return lines.join("\n");
55
+ }
56
+ function buildTitle(error) {
57
+ const msg = error.message.slice(0, 60);
58
+ return `[deploy-bug] ${msg}`;
59
+ }
60
+ function buildLabels(error) {
61
+ const labels = ["bug", "auto-report"];
62
+ const area = classifyErrorArea(error.message);
63
+ if (area) labels.push(area);
64
+ return labels;
65
+ }
66
+ async function offerBugReport(error) {
67
+ if (!isInteractive()) return;
68
+ const yes = await promptYesNo("\n This looks like a bug. Open an issue with debug info? [Y/n] ");
69
+ if (!yes) return;
70
+ const title = buildTitle(error);
71
+ const body = buildReportBody(error);
72
+ const labels = buildLabels(error);
73
+ if (hasGhCli()) {
74
+ try {
75
+ const args = [
76
+ "issue",
77
+ "create",
78
+ "--repo",
79
+ "paritytech/bulletin-deploy",
80
+ "--title",
81
+ title,
82
+ ...labels.flatMap((l) => ["--label", l]),
83
+ "--body-file",
84
+ "-"
85
+ ];
86
+ execFileSync("gh", args, { input: body, stdio: ["pipe", "inherit", "inherit"] });
87
+ console.error(" Issue created.");
88
+ } catch {
89
+ console.error(" Failed to create issue. Debug info below:\n");
90
+ printFallback(title, body, labels);
91
+ }
92
+ } else {
93
+ console.error("\n gh CLI not found. Debug info below \u2014 paste into a new issue:\n");
94
+ console.error(` https://github.com/paritytech/bulletin-deploy/issues/new
95
+ `);
96
+ printFallback(title, body, labels);
97
+ }
98
+ }
99
+ function printFallback(title, body, labels) {
100
+ console.error(` Title: ${title}`);
101
+ console.error(` Labels: ${labels.join(", ")}
102
+ `);
103
+ console.error(body);
104
+ }
105
+ export {
106
+ offerBugReport,
107
+ setDeployContext
108
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  captureWarning,
3
3
  withSpan
4
- } from "./chunk-ZGP4DMFK.js";
4
+ } from "./chunk-SLARK556.js";
5
5
 
6
6
  // src/dotns.ts
7
7
  import crypto from "crypto";
@@ -4,7 +4,7 @@ import {
4
4
  TX_TIMEOUT_MS,
5
5
  fetchNonce,
6
6
  validateDomainLabel
7
- } from "./chunk-FBXG7YMT.js";
7
+ } from "./chunk-KHLH5WQY.js";
8
8
  import {
9
9
  merkleizeJS
10
10
  } from "./chunk-GZ5UUECB.js";
@@ -18,10 +18,12 @@ import {
18
18
  VERSION,
19
19
  captureWarning,
20
20
  initTelemetry,
21
+ resolveRunner,
22
+ resolveRunnerType,
21
23
  setDeployAttribute,
22
24
  withDeploySpan,
23
25
  withSpan
24
- } from "./chunk-ZGP4DMFK.js";
26
+ } from "./chunk-SLARK556.js";
25
27
 
26
28
  // src/deploy.ts
27
29
  import { Buffer } from "buffer";
@@ -824,6 +826,7 @@ async function deploy(content, domainName = null, options = {}) {
824
826
  console.log("=".repeat(60));
825
827
  console.log(` Domain: ${name}.dot`);
826
828
  if (typeof content === "string") console.log(` Build dir: ${path.resolve(content)}`);
829
+ if (process.env.CI) console.log(` Runner: ${resolveRunner()} (${resolveRunnerType()})`);
827
830
  if (options.password) console.log(` Encrypted: yes`);
828
831
  let provider;
829
832
  const reconnect = options.mnemonic ? () => getDirectProvider(options.mnemonic) : () => getProvider();
@@ -6,7 +6,7 @@ import * as path from "path";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "bulletin-deploy",
9
- version: "0.6.7",
9
+ version: "0.6.8",
10
10
  private: false,
11
11
  repository: {
12
12
  type: "git",
@@ -34,7 +34,7 @@ var package_default = {
34
34
  "cdm.json"
35
35
  ],
36
36
  scripts: {
37
- build: "tsup src/index.ts src/deploy.ts src/dotns.ts src/pool.ts src/telemetry.ts src/merkle.ts --format esm --dts --clean --target node22",
37
+ build: "tsup src/index.ts src/deploy.ts src/dotns.ts src/pool.ts src/telemetry.ts src/merkle.ts src/version-check.ts src/bug-report.ts --format esm --dts --clean --target node22",
38
38
  test: "npm run build && node --test test/test.js",
39
39
  benchmark: "npm run build && node benchmark.js"
40
40
  },
@@ -61,6 +61,7 @@ var package_default = {
61
61
  tsup: "^8.5.0",
62
62
  typescript: "^5.9.3"
63
63
  },
64
+ minimumVersion: "0.5.6",
64
65
  engines: {
65
66
  node: ">=22"
66
67
  }
@@ -81,6 +82,7 @@ function initTelemetry() {
81
82
  if (!Sentry) return;
82
83
  Sentry.init({
83
84
  dsn: process.env.SENTRY_DSN || DEFAULT_DSN,
85
+ release: `${package_default.name}@${VERSION}`,
84
86
  tracesSampleRate: 1,
85
87
  environment: process.env.CI ? "ci" : "local"
86
88
  });
@@ -114,12 +116,25 @@ function tryGitBranch() {
114
116
  return "unknown";
115
117
  }
116
118
  }
119
+ function resolveRunner() {
120
+ if (!process.env.CI) return "local";
121
+ if (process.env.RUNNER_NAME?.startsWith("parity-")) return process.env.RUNNER_NAME;
122
+ return process.env.RUNNER_NAME || "unknown";
123
+ }
124
+ function resolveRunnerType() {
125
+ if (!process.env.CI) return "local";
126
+ if (process.env.RUNNER_NAME?.startsWith("parity-")) return "self-hosted";
127
+ return "github-hosted";
128
+ }
117
129
  function getDeployAttributes(domain) {
118
130
  return {
119
131
  "deploy.repo": resolveRepo(domain),
120
132
  "deploy.branch": process.env.GITHUB_HEAD_REF || process.env.GITHUB_REF_NAME || tryGitBranch(),
121
133
  "deploy.source": process.env.CI ? "ci" : "local",
122
- "deploy.pr": process.env.GITHUB_PR_NUMBER || void 0
134
+ "deploy.pr": process.env.GITHUB_PR_NUMBER || void 0,
135
+ "deploy.tool_version": VERSION,
136
+ "deploy.runner": resolveRunner(),
137
+ "deploy.runner_type": resolveRunnerType()
123
138
  };
124
139
  }
125
140
  function isExpectedError(msg) {
@@ -146,7 +161,9 @@ async function withDeploySpan(domain, fn) {
146
161
  "deploy.repo": attrs["deploy.repo"],
147
162
  "deploy.branch": attrs["deploy.branch"],
148
163
  "deploy.domain": domain,
149
- "deploy.source": attrs["deploy.source"]
164
+ "deploy.source": attrs["deploy.source"],
165
+ "deploy.tool_version": VERSION,
166
+ "deploy.runner_type": resolveRunnerType()
150
167
  });
151
168
  try {
152
169
  return await fn();
@@ -154,6 +171,7 @@ async function withDeploySpan(domain, fn) {
154
171
  const msg = error.message;
155
172
  span.setAttribute("deploy.status", "error");
156
173
  span.setAttribute("deploy.error", msg.slice(0, 200));
174
+ span.setAttribute("deploy.sad", true);
157
175
  const isExpected = isExpectedError(msg);
158
176
  if (!isExpected) {
159
177
  span.setStatus({ code: 2, message: "internal_error" });
@@ -189,6 +207,8 @@ export {
189
207
  VERSION,
190
208
  initTelemetry,
191
209
  resolveRepo,
210
+ resolveRunner,
211
+ resolveRunnerType,
192
212
  isExpectedError,
193
213
  withSpan,
194
214
  withDeploySpan,
@@ -0,0 +1,146 @@
1
+ import {
2
+ VERSION
3
+ } from "./chunk-SLARK556.js";
4
+
5
+ // src/version-check.ts
6
+ import { execSync, execFileSync } from "child_process";
7
+ import { createInterface } from "readline";
8
+ var REGISTRY_URL = "https://registry.npmjs.org/bulletin-deploy/latest";
9
+ var KILL_SWITCH_URL = "https://raw.githubusercontent.com/paritytech/bulletin-deploy/main/min-version.json";
10
+ var FETCH_TIMEOUT = 3e3;
11
+ function compareSemver(a, b) {
12
+ const pa = a.split(".").map(Number);
13
+ const pb = b.split(".").map(Number);
14
+ for (let i = 0; i < 3; i++) {
15
+ if ((pa[i] || 0) < (pb[i] || 0)) return -1;
16
+ if ((pa[i] || 0) > (pb[i] || 0)) return 1;
17
+ }
18
+ return 0;
19
+ }
20
+ async function fetchJson(url) {
21
+ try {
22
+ const controller = new AbortController();
23
+ const timer = setTimeout(() => controller.abort(), FETCH_TIMEOUT);
24
+ const res = await fetch(url, { signal: controller.signal });
25
+ clearTimeout(timer);
26
+ if (!res.ok) return null;
27
+ return await res.json();
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+ async function fetchVersionInfo() {
33
+ const [registry, killSwitch] = await Promise.all([
34
+ fetchJson(REGISTRY_URL),
35
+ fetchJson(KILL_SWITCH_URL)
36
+ ]);
37
+ if (!registry && !killSwitch) return null;
38
+ return {
39
+ latest: registry?.version ?? VERSION,
40
+ minimumFromRegistry: registry?.minimumVersion ?? null,
41
+ minimumFromKillSwitch: killSwitch?.minimumVersion ?? null,
42
+ killSwitchMessage: killSwitch?.message ?? null
43
+ };
44
+ }
45
+ function isInternalUser() {
46
+ const repo = process.env.GITHUB_REPOSITORY;
47
+ if (repo?.startsWith("paritytech/")) return true;
48
+ try {
49
+ const remote = execSync("git remote get-url origin", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
50
+ return remote.includes("paritytech/");
51
+ } catch {
52
+ return false;
53
+ }
54
+ }
55
+ function isInteractive() {
56
+ return Boolean(process.stdin.isTTY && !process.env.CI);
57
+ }
58
+ async function promptYesNo(question) {
59
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
60
+ return new Promise((resolve) => {
61
+ rl.question(question, (answer) => {
62
+ rl.close();
63
+ resolve(!answer || answer.toLowerCase().startsWith("y"));
64
+ });
65
+ });
66
+ }
67
+ function updateAndRetry() {
68
+ console.error("\n Updating bulletin-deploy...");
69
+ try {
70
+ execSync("npm install -g bulletin-deploy@latest", { stdio: "inherit" });
71
+ console.error(" Updated. Retrying deploy...\n");
72
+ execFileSync(process.argv[0], process.argv.slice(1), { stdio: "inherit" });
73
+ process.exit(0);
74
+ } catch {
75
+ console.error(" Update failed. Please run: npm install -g bulletin-deploy@latest");
76
+ process.exit(1);
77
+ }
78
+ }
79
+ function classifyErrorArea(msg) {
80
+ if (/personhood|owned by|owner mismatch|reserved for original|domain|dotns|commit-reveal/i.test(msg)) return "area:dotns";
81
+ if (/chunk|storage|authorized|authorization|pool|alice/i.test(msg)) return "area:storage";
82
+ if (/ipfs|cid|pin|dag/i.test(msg)) return "area:ipfs";
83
+ if (/connect|timeout|websocket|rpc|ECONNREFUSED|ENOTFOUND/i.test(msg)) return "area:network";
84
+ return null;
85
+ }
86
+ function assessVersion(currentVersion, info, internal) {
87
+ const effectiveMinimum = [info.minimumFromRegistry, info.minimumFromKillSwitch].filter(Boolean).sort((a, b) => compareSemver(b, a))[0] ?? null;
88
+ if (effectiveMinimum && compareSemver(currentVersion, effectiveMinimum) < 0) {
89
+ return { action: "forced_update", currentVersion, minimumVersion: effectiveMinimum, message: info.killSwitchMessage };
90
+ }
91
+ if (compareSemver(currentVersion, info.latest) < 0) {
92
+ return { action: "suggest_update", currentVersion, latestVersion: info.latest, internal };
93
+ }
94
+ if (internal) {
95
+ return { action: "bug_report", internal: true };
96
+ }
97
+ return { action: "none" };
98
+ }
99
+ async function handleFailedDeploy(error) {
100
+ if (process.env.BULLETIN_DEPLOY_UPDATE_CHECK === "0") return;
101
+ const info = await fetchVersionInfo();
102
+ if (!info) return;
103
+ let verdict = assessVersion(VERSION, info, false);
104
+ if (verdict.action === "suggest_update" || verdict.action === "none") {
105
+ const internal = isInternalUser();
106
+ if (internal) verdict = assessVersion(VERSION, info, true);
107
+ }
108
+ switch (verdict.action) {
109
+ case "forced_update":
110
+ console.error(`
111
+ bulletin-deploy ${verdict.currentVersion} is no longer supported (minimum: ${verdict.minimumVersion}).`);
112
+ if (verdict.message) console.error(` Reason: ${verdict.message}`);
113
+ console.error(` Please update: npm install -g bulletin-deploy@latest
114
+ `);
115
+ break;
116
+ case "suggest_update":
117
+ if (verdict.internal && isInteractive()) {
118
+ const yes = await promptYesNo(`
119
+ bulletin-deploy ${verdict.currentVersion} \u2192 ${verdict.latestVersion} available. Update and retry? [Y/n] `);
120
+ if (yes) updateAndRetry();
121
+ else console.error(` Skipped. Run: npm install -g bulletin-deploy@latest
122
+ `);
123
+ } else {
124
+ console.error(`
125
+ A newer version of bulletin-deploy is available (${verdict.currentVersion} \u2192 ${verdict.latestVersion}).`);
126
+ console.error(` Run: npm install -g bulletin-deploy@latest
127
+ `);
128
+ }
129
+ break;
130
+ case "bug_report": {
131
+ const { offerBugReport } = await import("./bug-report.js");
132
+ await offerBugReport(error);
133
+ break;
134
+ }
135
+ }
136
+ }
137
+
138
+ export {
139
+ compareSemver,
140
+ isInternalUser,
141
+ isInteractive,
142
+ promptYesNo,
143
+ classifyErrorArea,
144
+ assessVersion,
145
+ handleFailedDeploy
146
+ };
package/dist/deploy.js CHANGED
@@ -21,11 +21,11 @@ import {
21
21
  storeChunkedContent,
22
22
  storeDirectory,
23
23
  storeFile
24
- } from "./chunk-TD73EZ5I.js";
25
- import "./chunk-FBXG7YMT.js";
24
+ } from "./chunk-LVCOE5CC.js";
25
+ import "./chunk-KHLH5WQY.js";
26
26
  import "./chunk-GZ5UUECB.js";
27
27
  import "./chunk-LGPTJYA3.js";
28
- import "./chunk-ZGP4DMFK.js";
28
+ import "./chunk-SLARK556.js";
29
29
  import "./chunk-QGM4M3NI.js";
30
30
  export {
31
31
  DEFAULT_BULLETIN_RPC,
package/dist/dotns.js CHANGED
@@ -19,8 +19,8 @@ import {
19
19
  sanitizeDomainLabel,
20
20
  stripTrailingDigits,
21
21
  validateDomainLabel
22
- } from "./chunk-FBXG7YMT.js";
23
- import "./chunk-ZGP4DMFK.js";
22
+ } from "./chunk-KHLH5WQY.js";
23
+ import "./chunk-SLARK556.js";
24
24
  import "./chunk-QGM4M3NI.js";
25
25
  export {
26
26
  CONNECTION_TIMEOUT_MS,
package/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  deploy
3
- } from "./chunk-TD73EZ5I.js";
3
+ } from "./chunk-LVCOE5CC.js";
4
4
  import {
5
5
  DotNS
6
- } from "./chunk-FBXG7YMT.js";
6
+ } from "./chunk-KHLH5WQY.js";
7
7
  import {
8
8
  merkleizeJS
9
9
  } from "./chunk-GZ5UUECB.js";
@@ -14,7 +14,7 @@ import {
14
14
  fetchPoolAuthorizations,
15
15
  selectAccount
16
16
  } from "./chunk-LGPTJYA3.js";
17
- import "./chunk-ZGP4DMFK.js";
17
+ import "./chunk-SLARK556.js";
18
18
  import "./chunk-QGM4M3NI.js";
19
19
  export {
20
20
  DotNS,
@@ -1,6 +1,8 @@
1
1
  declare const VERSION: string;
2
2
  declare function initTelemetry(): void;
3
3
  declare function resolveRepo(domain: string): string;
4
+ declare function resolveRunner(): string;
5
+ declare function resolveRunnerType(): string;
4
6
  declare function isExpectedError(msg: string): boolean;
5
7
  declare function withSpan<T>(op: string, description: string, attributes: Record<string, string | number | boolean | undefined>, fn: () => T | Promise<T>): Promise<T>;
6
8
  declare function withDeploySpan<T>(domain: string, fn: () => T | Promise<T>): Promise<T>;
@@ -8,4 +10,4 @@ declare function setDeployAttribute(key: string, value: string | number | boolea
8
10
  declare function captureWarning(message: string, context?: Record<string, unknown>): void;
9
11
  declare function flush(): Promise<void>;
10
12
 
11
- export { VERSION, captureWarning, flush, initTelemetry, isExpectedError, resolveRepo, setDeployAttribute, withDeploySpan, withSpan };
13
+ export { VERSION, captureWarning, flush, initTelemetry, isExpectedError, resolveRepo, resolveRunner, resolveRunnerType, setDeployAttribute, withDeploySpan, withSpan };
package/dist/telemetry.js CHANGED
@@ -5,10 +5,12 @@ import {
5
5
  initTelemetry,
6
6
  isExpectedError,
7
7
  resolveRepo,
8
+ resolveRunner,
9
+ resolveRunnerType,
8
10
  setDeployAttribute,
9
11
  withDeploySpan,
10
12
  withSpan
11
- } from "./chunk-ZGP4DMFK.js";
13
+ } from "./chunk-SLARK556.js";
12
14
  import "./chunk-QGM4M3NI.js";
13
15
  export {
14
16
  VERSION,
@@ -17,6 +19,8 @@ export {
17
19
  initTelemetry,
18
20
  isExpectedError,
19
21
  resolveRepo,
22
+ resolveRunner,
23
+ resolveRunnerType,
20
24
  setDeployAttribute,
21
25
  withDeploySpan,
22
26
  withSpan
@@ -0,0 +1,31 @@
1
+ interface VersionInfo {
2
+ latest: string;
3
+ minimumFromRegistry: string | null;
4
+ minimumFromKillSwitch: string | null;
5
+ killSwitchMessage: string | null;
6
+ }
7
+ declare function compareSemver(a: string, b: string): number;
8
+ declare function isInternalUser(): boolean;
9
+ declare function isInteractive(): boolean;
10
+ declare function promptYesNo(question: string): Promise<boolean>;
11
+ declare function classifyErrorArea(msg: string): string | null;
12
+ type VersionVerdict = {
13
+ action: "forced_update";
14
+ currentVersion: string;
15
+ minimumVersion: string;
16
+ message: string | null;
17
+ } | {
18
+ action: "suggest_update";
19
+ currentVersion: string;
20
+ latestVersion: string;
21
+ internal: boolean;
22
+ } | {
23
+ action: "bug_report";
24
+ internal: boolean;
25
+ } | {
26
+ action: "none";
27
+ };
28
+ declare function assessVersion(currentVersion: string, info: VersionInfo, internal: boolean): VersionVerdict;
29
+ declare function handleFailedDeploy(error: Error): Promise<void>;
30
+
31
+ export { type VersionVerdict, assessVersion, classifyErrorArea, compareSemver, handleFailedDeploy, isInteractive, isInternalUser, promptYesNo };
@@ -0,0 +1,20 @@
1
+ import {
2
+ assessVersion,
3
+ classifyErrorArea,
4
+ compareSemver,
5
+ handleFailedDeploy,
6
+ isInteractive,
7
+ isInternalUser,
8
+ promptYesNo
9
+ } from "./chunk-SYJ2L6RU.js";
10
+ import "./chunk-SLARK556.js";
11
+ import "./chunk-QGM4M3NI.js";
12
+ export {
13
+ assessVersion,
14
+ classifyErrorArea,
15
+ compareSemver,
16
+ handleFailedDeploy,
17
+ isInteractive,
18
+ isInternalUser,
19
+ promptYesNo
20
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulletin-deploy",
3
- "version": "0.6.7",
3
+ "version": "0.6.8",
4
4
  "private": false,
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,7 +28,7 @@
28
28
  "cdm.json"
29
29
  ],
30
30
  "scripts": {
31
- "build": "tsup src/index.ts src/deploy.ts src/dotns.ts src/pool.ts src/telemetry.ts src/merkle.ts --format esm --dts --clean --target node22",
31
+ "build": "tsup src/index.ts src/deploy.ts src/dotns.ts src/pool.ts src/telemetry.ts src/merkle.ts src/version-check.ts src/bug-report.ts --format esm --dts --clean --target node22",
32
32
  "test": "npm run build && node --test test/test.js",
33
33
  "benchmark": "npm run build && node benchmark.js"
34
34
  },
@@ -55,6 +55,7 @@
55
55
  "tsup": "^8.5.0",
56
56
  "typescript": "^5.9.3"
57
57
  },
58
+ "minimumVersion": "0.5.6",
58
59
  "engines": {
59
60
  "node": ">=22"
60
61
  }