@devdogsuga/devtools 0.1.4 → 0.1.5

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
@@ -26,11 +26,11 @@ default, in both `pnpm devtools` and `devtools-ci`:
26
26
  naming the subcommand that threw (e.g. `db reset`, `deploy platform`).
27
27
  Nothing about a successful run is ever sent.
28
28
  - **When**: every run, unless `DEVTOOLS_TELEMETRY=0` is set (per-machine or
29
- per-job opt-out) — or `DEVTOOLS_SENTRY_DSN` is unset, which is the state of
30
- local development until an operator configures one and the state of every
31
- environment until the devtools Sentry project exists at all (see the
32
- committed placeholder in `src/telemetry.ts`). Either condition means no
33
- `Sentry.init()` call happens: no network request, no console output.
29
+ per-job opt-out) — or the build has no DSN. The DSN is baked in when
30
+ Backstage's `publish.yaml` builds the package, from the repo's
31
+ `DEVTOOLS_SENTRY_DSN` Actions variable, so only published builds report;
32
+ local builds and `pnpm pack:local` tarballs don't. Either condition means
33
+ no `Sentry.init()` call happens: no network request, no console output.
34
34
  - **What's scrubbed**: this CLI touches local `.env` files, so every event
35
35
  passes through
36
36
  `@devdogsuga/telemetry`'s shared scrubbers before it leaves the process —
@@ -0,0 +1,3 @@
1
+ {
2
+ "sentryDsn": ""
3
+ }
@@ -1,3 +1,5 @@
1
+ /** The run-time `DEVTOOLS_SENTRY_DSN` if set, else the baked one. */
2
+ export declare function resolveDevtoolsDsn(env: NodeJS.ProcessEnv, baked: string): string;
1
3
  /**
2
4
  * `'ci'` in every GitHub Actions job (`CI` is set by the runner itself,
3
5
  * before any workflow-authored env), `'local'` on a contributor's machine.
package/dist/telemetry.js CHANGED
@@ -7,29 +7,44 @@
7
7
  *
8
8
  * ## Reporting is on by default
9
9
  *
10
- * Every other `*_SENTRY_DSN` in this workspace is optional-and-empty until
11
- * an org exists to receive it (see `@devdogsuga/telemetry`'s no-op-without-
12
- * DSN contract). `DEVTOOLS_SENTRY_DSN` follows the same contract — empty
13
- * means `buildSentryOptions` returns `undefined` and `Sentry.init` never
14
- * runs — but the DEFAULT here is reporting ON once a DSN exists, unlike a
15
- * feature a contributor opts into. `DEVTOOLS_TELEMETRY=0` is the one escape
16
- * hatch, checked before `Sentry.init` and before every capture call, so it
17
- * also works as a kill switch after init already ran (a long-lived `pnpm
18
- * devtools` menu session, for instance).
10
+ * Every other `*_SENTRY_DSN` in this org is optional-and-empty until
11
+ * configured (see `@devdogsuga/telemetry`'s no-op-without-DSN contract), and
12
+ * so is this one — empty means `buildSentryOptions` returns `undefined` and
13
+ * `Sentry.init` never runs — but the DEFAULT here is reporting ON once a DSN
14
+ * exists, unlike a feature a contributor opts into. `DEVTOOLS_TELEMETRY=0` is
15
+ * the one escape hatch, checked before `Sentry.init` and before every capture
16
+ * call, so it also works as a kill switch after init already ran (a
17
+ * long-lived `pnpm devtools` menu session, for instance).
19
18
  *
20
- * `PLACEHOLDER_DEVTOOLS_SENTRY_DSN` is committed empty on purpose: the
21
- * devtools Sentry project does not exist yet. Once it does, either replace
22
- * this constant with the real ingest DSN or — preferably — set
23
- * `DEVTOOLS_SENTRY_DSN` in the environment, which always wins over the
24
- * placeholder. Either way, an empty result here is indistinguishable from
25
- * "not configured": no init, no network call, no console spam, which is the
26
- * whole point of shipping this file before the org is onboarded.
19
+ * ## Where the DSN comes from
20
+ *
21
+ * Baked in at build time, not read from the consumer's environment: devtools
22
+ * runs on contributors' machines, where no `.env` could be relied on to carry
23
+ * it. `scripts/write-build-info.mjs` writes `dist/build-info.json` from the
24
+ * build's `DEVTOOLS_SENTRY_DSN`, which Backstage's `publish.yaml` sets from
25
+ * the repo's Actions variable of the same name. Every other build bakes ""
26
+ * and reports nothing. `DEVTOOLS_SENTRY_DSN` in the run-time environment still
27
+ * wins, for pointing a local build at a test project.
27
28
  */
29
+ import { readFileSync } from "node:fs";
28
30
  import * as Sentry from "@sentry/node";
29
31
  import { buildSentryOptions } from "@devdogsuga/telemetry";
30
- // ⚠️ PLACEHOLDER — see this file's header. Leave empty until the devtools
31
- // Sentry project exists.
32
- const PLACEHOLDER_DEVTOOLS_SENTRY_DSN = "";
32
+ import { ownVersion } from "./repo/preflight.js";
33
+ /** The DSN baked into this build, or "" if there is none (a source run under
34
+ * tsx, or a build made without `DEVTOOLS_SENTRY_DSN`). */
35
+ function bakedSentryDsn() {
36
+ try {
37
+ const info = JSON.parse(readFileSync(new URL("./build-info.json", import.meta.url), "utf8"));
38
+ return typeof info.sentryDsn === "string" ? info.sentryDsn : "";
39
+ }
40
+ catch {
41
+ return "";
42
+ }
43
+ }
44
+ /** The run-time `DEVTOOLS_SENTRY_DSN` if set, else the baked one. */
45
+ export function resolveDevtoolsDsn(env, baked) {
46
+ return env.DEVTOOLS_SENTRY_DSN || baked;
47
+ }
33
48
  let initialized = false;
34
49
  /**
35
50
  * `'ci'` in every GitHub Actions job (`CI` is set by the runner itself,
@@ -63,12 +78,13 @@ export function initDevtoolsTelemetry(command) {
63
78
  initialized = true;
64
79
  if (!devtoolsTelemetryEnabled())
65
80
  return;
66
- const dsn = process.env.DEVTOOLS_SENTRY_DSN || PLACEHOLDER_DEVTOOLS_SENTRY_DSN;
67
81
  const options = buildSentryOptions({
68
82
  service: "devtools",
69
83
  environment: devtoolsEnvironment(),
70
- dsn,
71
- release: process.env.SENTRY_RELEASE,
84
+ dsn: resolveDevtoolsDsn(process.env, bakedSentryDsn()),
85
+ // The published version, so an issue names the release it came from; a
86
+ // dlx run has no SENTRY_RELEASE of its own.
87
+ release: `devtools@${ownVersion()}`,
72
88
  });
73
89
  if (!options)
74
90
  return;
package/env.ts CHANGED
@@ -121,25 +121,10 @@ declare({
121
121
  secrecy: "public",
122
122
  commented: true,
123
123
  }),
124
- // Same contract as the four apps' *_SENTRY_DSN (see
125
- // `@devdogsuga/telemetry`'s no-op-without-DSN guarantee): optional,
126
- // empty means `src/telemetry.ts` never calls `Sentry.init`. Committed
127
- // as a `PLACEHOLDER_DEVTOOLS_SENTRY_DSN` constant in that file until the
128
- // devtools Sentry project exists; this variable, when set, always wins
129
- // over that placeholder. `scope: "environment"` because the CI job that
130
- // reports as `environment: "ci"` needs the same value a contributor's
131
- // machine (`environment: "local"`) does -- there is no per-deploy-tier
132
- // split the way `DEPLOY_ENV` has, only per-target routing.
133
- DEVTOOLS_SENTRY_DSN: define(z.string().url().optional(), {
134
- doc:
135
- "Sentry ingest DSN for the devtools project. Optional -- empty " +
136
- "skips Sentry.init entirely, which is the state before the org is " +
137
- "onboarded and the state of local development. See " +
138
- "src/telemetry.ts.",
139
- scope: "environment",
140
- secrecy: "public",
141
- }),
142
- // Reporting is ON by default once DEVTOOLS_SENTRY_DSN is set -- unlike
124
+ // No DEVTOOLS_SENTRY_DSN here: the DSN is baked in at publish time, not
125
+ // configured by the consumer (see src/telemetry.ts).
126
+ //
127
+ // Reporting is ON by default in a published build -- unlike
143
128
  // every other telemetry surface in this workspace, which a consumer
144
129
  // opts INTO by configuring a DSN, this one an operator opts OUT of.
145
130
  // `"0"` is the one recognized value; anything else, including unset,
@@ -149,8 +134,7 @@ declare({
149
134
  DEVTOOLS_TELEMETRY: define(z.string().optional(), {
150
135
  doc:
151
136
  'Set to "0" to opt out of devtools\' Sentry error reporting (on by ' +
152
- "default whenever DEVTOOLS_SENTRY_DSN is configured). See " +
153
- "src/telemetry.ts.",
137
+ "default in published builds). See src/telemetry.ts.",
154
138
  scope: "developer",
155
139
  secrecy: "public",
156
140
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devdogsuga/devtools",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Contributor CLI for a DevDogsUGA checkout: database, env, images, emails, cron, deploy. Ships built JS; run via `pnpm dlx @devdogsuga/devtools` (or the `devtools`/`devtools-ci` bins once installed) from inside a DevDogsUGA clone.",
@@ -62,13 +62,13 @@
62
62
  "@vitest/coverage-v8": "^4.1.11",
63
63
  "react": "^19.2.8",
64
64
  "vitest": "^4.1.11",
65
+ "@devdogsuga/brand": "0.1.1",
65
66
  "@devdogsuga/config": "0.1.1",
66
67
  "@devdogsuga/env": "0.1.1",
67
- "@devdogsuga/db": "0.1.1",
68
- "@devdogsuga/brand": "0.1.1"
68
+ "@devdogsuga/db": "0.1.1"
69
69
  },
70
70
  "scripts": {
71
- "build": "tsc",
71
+ "build": "tsc && node scripts/write-build-info.mjs",
72
72
  "cli": "node ./bin/devtools.mjs",
73
73
  "ci": "node ./dist/ci.js",
74
74
  "ci:env": "node ./bin/devtools-ci.mjs",