@devdogsuga/devtools 0.1.0
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 +44 -0
- package/bin/devtools-ci-bare.mjs +48 -0
- package/bin/devtools-ci.mjs +17 -0
- package/bin/devtools.mjs +27 -0
- package/dist/args.d.ts +26 -0
- package/dist/args.js +78 -0
- package/dist/bws/bw.d.ts +9 -0
- package/dist/bws/bw.js +49 -0
- package/dist/bws/client.d.ts +43 -0
- package/dist/bws/client.js +363 -0
- package/dist/bws/environments.d.ts +96 -0
- package/dist/bws/environments.js +111 -0
- package/dist/bws/pace.d.ts +27 -0
- package/dist/bws/pace.js +43 -0
- package/dist/bws/retry.d.ts +12 -0
- package/dist/bws/retry.js +39 -0
- package/dist/bws/store.d.ts +1 -0
- package/dist/bws/store.js +32 -0
- package/dist/bws/token.d.ts +31 -0
- package/dist/bws/token.js +88 -0
- package/dist/bws/vault.d.ts +29 -0
- package/dist/bws/vault.js +200 -0
- package/dist/catalog.d.ts +55 -0
- package/dist/catalog.js +81 -0
- package/dist/cf/commands.d.ts +1 -0
- package/dist/cf/commands.js +182 -0
- package/dist/cf/local-env.d.ts +44 -0
- package/dist/cf/local-env.js +148 -0
- package/dist/ci.d.ts +1 -0
- package/dist/ci.js +319 -0
- package/dist/cli.d.ts +11 -0
- package/dist/cli.js +1077 -0
- package/dist/commands.d.ts +255 -0
- package/dist/commands.js +1279 -0
- package/dist/completions.d.ts +4 -0
- package/dist/completions.js +110 -0
- package/dist/cron/commands.d.ts +47 -0
- package/dist/cron/commands.js +372 -0
- package/dist/cron/discovery.d.ts +55 -0
- package/dist/cron/discovery.js +85 -0
- package/dist/cron/schema.d.ts +45 -0
- package/dist/cron/schema.js +35 -0
- package/dist/db/config-push.d.ts +8 -0
- package/dist/db/config-push.js +11 -0
- package/dist/db/connection.d.ts +79 -0
- package/dist/db/connection.js +114 -0
- package/dist/db/exec.d.ts +1 -0
- package/dist/db/exec.js +11 -0
- package/dist/db/generate-migration.d.ts +1 -0
- package/dist/db/generate-migration.js +67 -0
- package/dist/db/generate-types.d.ts +1 -0
- package/dist/db/generate-types.js +4 -0
- package/dist/db/introspect.d.ts +1 -0
- package/dist/db/introspect.js +113 -0
- package/dist/db/local-env.d.ts +65 -0
- package/dist/db/local-env.js +23 -0
- package/dist/db/new-migration.d.ts +1 -0
- package/dist/db/new-migration.js +8 -0
- package/dist/db/run.d.ts +70 -0
- package/dist/db/run.js +158 -0
- package/dist/db/seed-buckets.d.ts +2 -0
- package/dist/db/seed-buckets.js +4 -0
- package/dist/db/seed-production.d.ts +8 -0
- package/dist/db/seed-production.js +73 -0
- package/dist/db/seed-roles.d.ts +7 -0
- package/dist/db/seed-roles.js +31 -0
- package/dist/db/session-refresh.d.ts +43 -0
- package/dist/db/session-refresh.js +40 -0
- package/dist/deploy/migrations.d.ts +20 -0
- package/dist/deploy/migrations.js +68 -0
- package/dist/deploy/orphans.d.ts +20 -0
- package/dist/deploy/orphans.js +177 -0
- package/dist/deploy/preflight.d.ts +53 -0
- package/dist/deploy/preflight.js +189 -0
- package/dist/deploy/report.d.ts +26 -0
- package/dist/deploy/report.js +70 -0
- package/dist/deploy/require-planner.d.ts +2 -0
- package/dist/deploy/require-planner.js +60 -0
- package/dist/deploy/require-token.d.ts +15 -0
- package/dist/deploy/require-token.js +78 -0
- package/dist/deploy/secrets-file.d.ts +17 -0
- package/dist/deploy/secrets-file.js +167 -0
- package/dist/deploy/write-env.d.ts +40 -0
- package/dist/deploy/write-env.js +393 -0
- package/dist/docs/index-pages.d.ts +36 -0
- package/dist/docs/index-pages.js +184 -0
- package/dist/doctor.d.ts +62 -0
- package/dist/doctor.js +225 -0
- package/dist/emails/commands.d.ts +15 -0
- package/dist/emails/commands.js +130 -0
- package/dist/emails/email-types.d.ts +13 -0
- package/dist/emails/email-types.js +1 -0
- package/dist/emails/fixtures.d.ts +20 -0
- package/dist/emails/fixtures.js +20 -0
- package/dist/env/audit.d.ts +206 -0
- package/dist/env/audit.js +436 -0
- package/dist/env/cloudflare.d.ts +21 -0
- package/dist/env/cloudflare.js +61 -0
- package/dist/env/commands.d.ts +99 -0
- package/dist/env/commands.js +612 -0
- package/dist/env/discovery.d.ts +15 -0
- package/dist/env/discovery.js +226 -0
- package/dist/env/document.d.ts +119 -0
- package/dist/env/document.js +323 -0
- package/dist/env/example.d.ts +68 -0
- package/dist/env/example.js +603 -0
- package/dist/env/selection.d.ts +105 -0
- package/dist/env/selection.js +226 -0
- package/dist/environment.d.ts +92 -0
- package/dist/environment.js +206 -0
- package/dist/fingerprint.d.ts +10 -0
- package/dist/fingerprint.js +18 -0
- package/dist/gen/campus-map.d.ts +1 -0
- package/dist/gen/campus-map.js +473 -0
- package/dist/gen/commands.d.ts +1 -0
- package/dist/gen/commands.js +25 -0
- package/dist/gen/hypno.d.ts +1 -0
- package/dist/gen/hypno.js +134 -0
- package/dist/gh/client.d.ts +80 -0
- package/dist/gh/client.js +258 -0
- package/dist/gh/environments.d.ts +83 -0
- package/dist/gh/environments.js +178 -0
- package/dist/gh/rulesets/actors.d.ts +14 -0
- package/dist/gh/rulesets/actors.js +68 -0
- package/dist/gh/rulesets/api.d.ts +15 -0
- package/dist/gh/rulesets/api.js +99 -0
- package/dist/gh/rulesets/commands.d.ts +3 -0
- package/dist/gh/rulesets/commands.js +203 -0
- package/dist/gh/rulesets/desired.d.ts +112 -0
- package/dist/gh/rulesets/desired.js +247 -0
- package/dist/gh/rulesets/diff.d.ts +65 -0
- package/dist/gh/rulesets/diff.js +134 -0
- package/dist/gh/rulesets/types.d.ts +76 -0
- package/dist/gh/rulesets/types.js +13 -0
- package/dist/gh/settings/api.d.ts +40 -0
- package/dist/gh/settings/api.js +172 -0
- package/dist/gh/settings/commands.d.ts +1 -0
- package/dist/gh/settings/commands.js +245 -0
- package/dist/gh/settings/desired.d.ts +53 -0
- package/dist/gh/settings/desired.js +39 -0
- package/dist/gh/settings/diff.d.ts +57 -0
- package/dist/gh/settings/diff.js +156 -0
- package/dist/gh/settings/types.d.ts +92 -0
- package/dist/gh/settings/types.js +11 -0
- package/dist/gh/settings/workflows.d.ts +41 -0
- package/dist/gh/settings/workflows.js +124 -0
- package/dist/grantRoot.d.ts +42 -0
- package/dist/grantRoot.js +89 -0
- package/dist/help.d.ts +18 -0
- package/dist/help.js +169 -0
- package/dist/images/commands.d.ts +35 -0
- package/dist/images/commands.js +233 -0
- package/dist/images/events.d.ts +36 -0
- package/dist/images/events.js +152 -0
- package/dist/images/graphics.d.ts +70 -0
- package/dist/images/graphics.js +233 -0
- package/dist/images/open-graph-types.d.ts +75 -0
- package/dist/images/open-graph-types.js +1 -0
- package/dist/images/prompts.d.ts +34 -0
- package/dist/images/prompts.js +100 -0
- package/dist/images/render.d.ts +21 -0
- package/dist/images/render.js +57 -0
- package/dist/images/select.d.ts +64 -0
- package/dist/images/select.js +96 -0
- package/dist/instance.d.ts +67 -0
- package/dist/instance.js +129 -0
- package/dist/invocation.d.ts +49 -0
- package/dist/invocation.js +78 -0
- package/dist/launch-ci.d.ts +1 -0
- package/dist/launch-ci.js +86 -0
- package/dist/launch.d.ts +29 -0
- package/dist/launch.js +371 -0
- package/dist/menu.d.ts +31 -0
- package/dist/menu.js +277 -0
- package/dist/newsletter/commands.d.ts +16 -0
- package/dist/newsletter/commands.js +311 -0
- package/dist/newsletter/imap.d.ts +17 -0
- package/dist/newsletter/imap.js +127 -0
- package/dist/newsletter/loopback.d.ts +24 -0
- package/dist/newsletter/loopback.js +100 -0
- package/dist/newsletter/oauth.d.ts +26 -0
- package/dist/newsletter/oauth.js +130 -0
- package/dist/newsletter/smtp.d.ts +23 -0
- package/dist/newsletter/smtp.js +133 -0
- package/dist/oauth/browser.d.ts +1 -0
- package/dist/oauth/browser.js +13 -0
- package/dist/oauth/config.d.ts +24 -0
- package/dist/oauth/config.js +24 -0
- package/dist/oauth/connect-url.d.ts +17 -0
- package/dist/oauth/connect-url.js +23 -0
- package/dist/oauth/db.d.ts +37 -0
- package/dist/oauth/db.js +108 -0
- package/dist/oauth/device.d.ts +93 -0
- package/dist/oauth/device.js +190 -0
- package/dist/oauth/discovery.d.ts +28 -0
- package/dist/oauth/discovery.js +54 -0
- package/dist/oauth/env-file.d.ts +6 -0
- package/dist/oauth/env-file.js +35 -0
- package/dist/oauth/exchange.d.ts +43 -0
- package/dist/oauth/exchange.js +87 -0
- package/dist/oauth/label.d.ts +1 -0
- package/dist/oauth/label.js +25 -0
- package/dist/oauth/loopback.d.ts +52 -0
- package/dist/oauth/loopback.js +162 -0
- package/dist/oauth/pkce.d.ts +6 -0
- package/dist/oauth/pkce.js +34 -0
- package/dist/oauth/target.d.ts +54 -0
- package/dist/oauth/target.js +102 -0
- package/dist/oauth/transport.d.ts +41 -0
- package/dist/oauth/transport.js +32 -0
- package/dist/oauth/wizard.d.ts +33 -0
- package/dist/oauth/wizard.js +571 -0
- package/dist/pick.d.ts +6 -0
- package/dist/pick.js +64 -0
- package/dist/planner/checks.d.ts +26 -0
- package/dist/planner/checks.js +104 -0
- package/dist/planner/commands.d.ts +10 -0
- package/dist/planner/commands.js +367 -0
- package/dist/planner/db.d.ts +15 -0
- package/dist/planner/db.js +33 -0
- package/dist/planner/role.d.ts +33 -0
- package/dist/planner/role.js +68 -0
- package/dist/repo/peers.d.ts +24 -0
- package/dist/repo/peers.js +114 -0
- package/dist/repo/preflight.d.ts +109 -0
- package/dist/repo/preflight.js +266 -0
- package/dist/repo/resolve.d.ts +41 -0
- package/dist/repo/resolve.js +152 -0
- package/dist/repo/root.d.ts +23 -0
- package/dist/repo/root.js +91 -0
- package/dist/repo/source.d.ts +14 -0
- package/dist/repo/source.js +54 -0
- package/dist/repo/tsx-loader.d.ts +6 -0
- package/dist/repo/tsx-loader.js +41 -0
- package/dist/run/pick.d.ts +60 -0
- package/dist/run/pick.js +559 -0
- package/dist/setup.d.ts +1 -0
- package/dist/setup.js +152 -0
- package/dist/stack.d.ts +48 -0
- package/dist/stack.js +290 -0
- package/dist/telemetry.d.ts +34 -0
- package/dist/telemetry.js +93 -0
- package/dist/tier.d.ts +40 -0
- package/dist/tier.js +93 -0
- package/dist/tsconfig.typecheck.tsbuildinfo +1 -0
- package/dist/ui.d.ts +25 -0
- package/dist/ui.js +51 -0
- package/dist/workers.d.ts +5 -0
- package/dist/workers.js +35 -0
- package/dist/workflows/commands.d.ts +44 -0
- package/dist/workflows/commands.js +668 -0
- package/env.ts +158 -0
- package/package.json +80 -0
package/dist/ci.js
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `devtools-ci deploy <app|step> [flags]`
|
|
3
|
+
*
|
|
4
|
+
* The CI entry point. No wizard and no `@clack/prompts`. Commands that create
|
|
5
|
+
* the deploy env file run through the bare `ci` package script; commands that
|
|
6
|
+
* consume that file run through `ci:env`, which wraps this same entry point in
|
|
7
|
+
* `with-env`. Every command runs in GitHub Actions and reports failures by
|
|
8
|
+
* exiting non-zero.
|
|
9
|
+
*
|
|
10
|
+
* ## Why a separate bin
|
|
11
|
+
*
|
|
12
|
+
* The contributor CLI (`devtools`) prompts interactively and wraps output in
|
|
13
|
+
* clack's box-drawing. None of that belongs in a deploy job. This entry point
|
|
14
|
+
* never imports clack, so a caller that pipes its stdout is never surprised by
|
|
15
|
+
* a banner landing on that stream. `with-env` reports its selected file on
|
|
16
|
+
* stderr, leaving the command's stdout protocol intact.
|
|
17
|
+
*
|
|
18
|
+
* ## The deploy orchestrator
|
|
19
|
+
*
|
|
20
|
+
* `devtools-ci deploy <app> --tier <staging|production>` replaces the three
|
|
21
|
+
* near-identical `cf:deploy:*` shell strings in the app package.json files.
|
|
22
|
+
* It runs `require-token`, then the app-specific deploy commands: docs index
|
|
23
|
+
* for platform only, then a plain `wrangler deploy` for all three apps.
|
|
24
|
+
* Both Next.js apps are on vinext now -- deploy-app.yaml's separate "Build"
|
|
25
|
+
* step already ran `vinext build` (`cf:build:$DEPLOY_ENV`), which leaves a
|
|
26
|
+
* Wrangler "config redirect" at `.wrangler/deploy/config.json` pointing at
|
|
27
|
+
* the generated `dist/server/wrangler.json`; a bare `wrangler deploy` from
|
|
28
|
+
* the app dir resolves through that redirect with no `--config` needed.
|
|
29
|
+
* Sandbox (plain Worker, wrangler bundles it at deploy time) always used
|
|
30
|
+
* this shape, so all three apps now share one deploy step.
|
|
31
|
+
*
|
|
32
|
+
* Step commands (`write-env`, `secrets-file`, etc.) are still individually
|
|
33
|
+
* addressable for jobs that run only one step.
|
|
34
|
+
*/
|
|
35
|
+
import { spawn } from "node:child_process";
|
|
36
|
+
import { loadEnvLoad } from "./repo/peers.js";
|
|
37
|
+
import { DeployError, say } from "./deploy/report.js";
|
|
38
|
+
import { renderWriteEnvReport, runDeployWriteEnv } from "./deploy/write-env.js";
|
|
39
|
+
import { runDeploySecretsFile } from "./deploy/secrets-file.js";
|
|
40
|
+
import { runDeployOrphans } from "./deploy/orphans.js";
|
|
41
|
+
import { runPreflight } from "./deploy/preflight.js";
|
|
42
|
+
import { runDeployMigrate, runDeployPlan } from "./deploy/migrations.js";
|
|
43
|
+
import { runRequirePlanner } from "./deploy/require-planner.js";
|
|
44
|
+
import { runRequireToken } from "./deploy/require-token.js";
|
|
45
|
+
import { runDocsIndex } from "./docs/index-pages.js";
|
|
46
|
+
import { loadRegistry } from "./env/discovery.js";
|
|
47
|
+
import { positionals } from "./args.js";
|
|
48
|
+
import { findCiCommand, subcommandCiNames } from "./commands.js";
|
|
49
|
+
import { isWorkerApp, workerApps } from "./workers.js";
|
|
50
|
+
import { captureDevtoolsError, initDevtoolsTelemetry } from "./telemetry.js";
|
|
51
|
+
function flagValue(rest, flag) {
|
|
52
|
+
const index = rest.indexOf(flag);
|
|
53
|
+
if (index === -1)
|
|
54
|
+
return undefined;
|
|
55
|
+
const value = rest[index + 1];
|
|
56
|
+
return value && !value.startsWith("--") ? value : undefined;
|
|
57
|
+
}
|
|
58
|
+
function isApp(value) {
|
|
59
|
+
return isWorkerApp(value);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Wrangler's local Hyperdrive emulator wants its binding-specific alias, not
|
|
63
|
+
* `DB_URL`. Mirror both of `process.env`'s relevant keys into a scratch
|
|
64
|
+
* object so the shared `applyWranglerLocalDatabaseAlias` guard — never
|
|
65
|
+
* clobber an alias someone already set — runs against the same values it
|
|
66
|
+
* would in-process, then hand back only the alias override for `pnpm()`'s
|
|
67
|
+
* env merge (`DB_URL` itself reaches the child already, via the base
|
|
68
|
+
* `process.env` spread).
|
|
69
|
+
*/
|
|
70
|
+
async function hyperdriveLocalAliasEnv() {
|
|
71
|
+
const { applyWranglerLocalDatabaseAlias, HYPERDRIVE_LOCAL_CONNECTION_ENV } = await loadEnvLoad();
|
|
72
|
+
const scratch = {};
|
|
73
|
+
const existingAlias = process.env[HYPERDRIVE_LOCAL_CONNECTION_ENV];
|
|
74
|
+
if (existingAlias !== undefined) {
|
|
75
|
+
scratch[HYPERDRIVE_LOCAL_CONNECTION_ENV] = existingAlias;
|
|
76
|
+
}
|
|
77
|
+
if (process.env.DB_URL !== undefined)
|
|
78
|
+
scratch.DB_URL = process.env.DB_URL;
|
|
79
|
+
applyWranglerLocalDatabaseAlias(scratch);
|
|
80
|
+
delete scratch.DB_URL;
|
|
81
|
+
return scratch;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Runs a command via pnpm, inheriting stdio, returning the exit code.
|
|
85
|
+
*
|
|
86
|
+
* All orchestrator steps are external processes rather than imported
|
|
87
|
+
* functions: `wrangler` (and, for platform, the docs build) own their own
|
|
88
|
+
* stdout and must not be wrapped.
|
|
89
|
+
*/
|
|
90
|
+
function pnpm(args, env) {
|
|
91
|
+
return new Promise((resolve) => {
|
|
92
|
+
const child = spawn("pnpm", args, {
|
|
93
|
+
stdio: "inherit",
|
|
94
|
+
env: { ...process.env, ...env },
|
|
95
|
+
});
|
|
96
|
+
child.on("exit", (code) => resolve(code ?? 1));
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* `devtools-ci deploy <app> --tier <staging|production>`
|
|
101
|
+
*
|
|
102
|
+
* Orchestrates the full deploy for one app:
|
|
103
|
+
* 1. `require-token` guard
|
|
104
|
+
* 2. Docs index (platform only)
|
|
105
|
+
* 3. App deploy via `wrangler deploy`
|
|
106
|
+
*
|
|
107
|
+
* The `--dry-run` flag prints what would run and exits 0.
|
|
108
|
+
*/
|
|
109
|
+
async function runAppDeploy(app, rest) {
|
|
110
|
+
const tier = flagValue(rest, "--tier") ?? process.env.DEPLOY_ENV;
|
|
111
|
+
if (!tier) {
|
|
112
|
+
throw new DeployError("--tier <staging|production> is required.", [
|
|
113
|
+
"Or set DEPLOY_ENV in the environment.",
|
|
114
|
+
]);
|
|
115
|
+
}
|
|
116
|
+
if (tier !== "staging" && tier !== "production") {
|
|
117
|
+
throw new DeployError(`Unknown tier "${tier}".`, [
|
|
118
|
+
"Use --tier staging or --tier production.",
|
|
119
|
+
]);
|
|
120
|
+
}
|
|
121
|
+
const dryRun = rest.includes("--dry-run");
|
|
122
|
+
const secretsFile = process.env.DEPLOY_SECRETS_FILE;
|
|
123
|
+
const steps = [];
|
|
124
|
+
// Platform is the only app with a prestep: it owns the docs site, so its
|
|
125
|
+
// deploy re-indexes the (already-built-elsewhere) docs into the remote
|
|
126
|
+
// search store before the Worker goes out.
|
|
127
|
+
if (app === "platform") {
|
|
128
|
+
steps.push({
|
|
129
|
+
label: "Index docs",
|
|
130
|
+
fn: async () => {
|
|
131
|
+
const buildCode = await pnpm(["--filter", "@devdogsuga/docs", "build"]);
|
|
132
|
+
if (buildCode !== 0)
|
|
133
|
+
return buildCode;
|
|
134
|
+
const before = process.exitCode;
|
|
135
|
+
process.exitCode = 0;
|
|
136
|
+
await runDocsIndex({ target: "remote" });
|
|
137
|
+
const code = process.exitCode === 0 ? 0 : 1;
|
|
138
|
+
process.exitCode = before;
|
|
139
|
+
return code;
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
// All three apps now share one deploy shape: a bare `wrangler deploy -e
|
|
144
|
+
// <tier>` from the app directory. Both Next.js apps' target environment is
|
|
145
|
+
// baked in at BUILD time (deploy-app.yaml's separate "Build" step already
|
|
146
|
+
// ran `cf:build:$DEPLOY_ENV`, i.e. `vinext build` with
|
|
147
|
+
// `CLOUDFLARE_ENV=$tier`), which leaves a Wrangler "config redirect" at
|
|
148
|
+
// `.wrangler/deploy/config.json` pointing at `dist/server/wrangler.json`;
|
|
149
|
+
// sandbox is a plain Worker with no such redirect and no build step at all.
|
|
150
|
+
// `-e` is passed regardless: for the vinext apps, Wrangler cross-checks it
|
|
151
|
+
// against the environment the build was tagged with and errors loudly on a
|
|
152
|
+
// mismatch, rather than silently deploying the wrong tier.
|
|
153
|
+
const deployArgs = [
|
|
154
|
+
"--filter",
|
|
155
|
+
app,
|
|
156
|
+
"exec",
|
|
157
|
+
"wrangler",
|
|
158
|
+
"deploy",
|
|
159
|
+
"-e",
|
|
160
|
+
tier,
|
|
161
|
+
];
|
|
162
|
+
if (secretsFile)
|
|
163
|
+
deployArgs.push("--secrets-file", secretsFile);
|
|
164
|
+
// See apps/*/cloudflare/worker.ts's `WorkerEnv` doc: `SENTRY_RELEASE` is
|
|
165
|
+
// the deploy's git SHA, minted fresh by CI every run rather than a value
|
|
166
|
+
// Bitwarden holds, so it reaches the Worker as a `--var` here rather than
|
|
167
|
+
// through `~/env`'s schema or the secrets file above. Absent outside a
|
|
168
|
+
// CI-driven deploy.
|
|
169
|
+
if (process.env.SENTRY_RELEASE) {
|
|
170
|
+
deployArgs.push("--var", `SENTRY_RELEASE:${process.env.SENTRY_RELEASE}`);
|
|
171
|
+
}
|
|
172
|
+
steps.push({
|
|
173
|
+
label: `Deploy ${app} (${tier})`,
|
|
174
|
+
// sandbox has no Hyperdrive binding, so the local-database alias is a
|
|
175
|
+
// no-op for it; passing it unconditionally keeps this one step shape for
|
|
176
|
+
// all three apps rather than branching again just to omit it.
|
|
177
|
+
fn: async () => pnpm(deployArgs, await hyperdriveLocalAliasEnv()),
|
|
178
|
+
});
|
|
179
|
+
if (dryRun) {
|
|
180
|
+
say([
|
|
181
|
+
`devtools-ci deploy ${app} --tier ${tier} --dry-run`,
|
|
182
|
+
...steps.map((s) => ` ${s.label}`),
|
|
183
|
+
]);
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
// require-token guard: checked inline so the step list above prints on
|
|
187
|
+
// --dry-run without requiring the token.
|
|
188
|
+
runRequireToken();
|
|
189
|
+
for (const step of steps) {
|
|
190
|
+
const code = await step.fn();
|
|
191
|
+
if (code !== 0) {
|
|
192
|
+
process.exitCode = code;
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// ── Deploy dispatch ───────────────────────────────────────────────────────────
|
|
198
|
+
async function runDeployCommand(rest) {
|
|
199
|
+
const [sub] = positionals(rest);
|
|
200
|
+
if (!sub) {
|
|
201
|
+
const steps = subcommandCiNames(["deploy"]);
|
|
202
|
+
const width = Math.max(...steps.map((name) => name.length)) + 2;
|
|
203
|
+
say([
|
|
204
|
+
"devtools-ci deploy: which step or app?",
|
|
205
|
+
...steps.map((name) => ` ${name.padEnd(width)}${findCiCommand(["deploy", name]).summary}`),
|
|
206
|
+
]);
|
|
207
|
+
process.exitCode = 1;
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
// App orchestrators
|
|
211
|
+
if (isApp(sub)) {
|
|
212
|
+
await runAppDeploy(sub, rest.slice(1));
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
if (sub === "require-token") {
|
|
217
|
+
runRequireToken();
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (sub === "require-planner") {
|
|
221
|
+
await runRequirePlanner();
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (sub === "plan") {
|
|
225
|
+
await runDeployPlan(flagValue(rest, "--label"));
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (sub === "migrate") {
|
|
229
|
+
await runDeployMigrate();
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (sub === "preflight") {
|
|
233
|
+
await runPreflight();
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
await loadRegistry();
|
|
237
|
+
if (sub === "write-env") {
|
|
238
|
+
const index = rest.indexOf("--source");
|
|
239
|
+
const source = index === -1 ? null : rest[index + 1];
|
|
240
|
+
if (index !== -1 && (!source || source.startsWith("--"))) {
|
|
241
|
+
throw new DeployError("--source needs a manifest name, e.g. --source supabase.");
|
|
242
|
+
}
|
|
243
|
+
const result = await runDeployWriteEnv({ source });
|
|
244
|
+
say(renderWriteEnvReport(result));
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
if (sub === "secrets-file") {
|
|
248
|
+
const app = flagValue(rest, "--app");
|
|
249
|
+
if (!app) {
|
|
250
|
+
throw new DeployError("--app <name> is required.", [
|
|
251
|
+
"It names the workspace app whose manifest declares the Worker's",
|
|
252
|
+
`secrets — ${workerApps().join(", ")}.`,
|
|
253
|
+
]);
|
|
254
|
+
}
|
|
255
|
+
await runDeploySecretsFile({ app });
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (sub === "orphans") {
|
|
259
|
+
await runDeployOrphans({ prune: rest.includes("--prune") });
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
say([`devtools-ci deploy: unknown subcommand "${sub}".`]);
|
|
263
|
+
process.exitCode = 1;
|
|
264
|
+
}
|
|
265
|
+
catch (err) {
|
|
266
|
+
say(err instanceof DeployError
|
|
267
|
+
? [
|
|
268
|
+
`devtools-ci deploy ${sub}: ${err.message}`,
|
|
269
|
+
...err.detail.map((line) => ` ${line}`),
|
|
270
|
+
]
|
|
271
|
+
: [
|
|
272
|
+
`devtools-ci deploy ${sub}: ${err instanceof Error ? err.message : String(err)}`,
|
|
273
|
+
]);
|
|
274
|
+
process.exitCode = 1;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// ── Entry ─────────────────────────────────────────────────────────────────────
|
|
278
|
+
export async function main(argv) {
|
|
279
|
+
const [first, ...rest] = argv;
|
|
280
|
+
// Same bootstrap point as `cli.ts`'s `main()`: after `argv` is split, before
|
|
281
|
+
// any dispatch below. `[first, rest[0]]` names the step (`deploy
|
|
282
|
+
// secrets-file`, `deploy platform`, …) as the `command` tag rather than just
|
|
283
|
+
// "deploy", which every invocation here would otherwise share.
|
|
284
|
+
initDevtoolsTelemetry([first, rest[0]].filter(Boolean).join(" ") || "help");
|
|
285
|
+
if (!first || first === "--help" || first === "-h") {
|
|
286
|
+
const steps = subcommandCiNames(["deploy"]);
|
|
287
|
+
const width = Math.max(...steps.map((name) => name.length)) + 2;
|
|
288
|
+
process.stdout.write([
|
|
289
|
+
"devtools-ci <command>",
|
|
290
|
+
"",
|
|
291
|
+
"Commands:",
|
|
292
|
+
` ${"deploy".padEnd(width)}Deploy an app or run a deploy step.`,
|
|
293
|
+
"",
|
|
294
|
+
"Run `devtools-ci deploy` for the full step list.",
|
|
295
|
+
"",
|
|
296
|
+
].join("\n"));
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
if (first === "deploy") {
|
|
300
|
+
await runDeployCommand(rest);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
process.stderr.write(`devtools-ci: unknown command "${first}".\n`);
|
|
304
|
+
process.exitCode = 1;
|
|
305
|
+
}
|
|
306
|
+
// Run only from `src/launch-ci.ts` (via the `devtools-ci` bin) or from a
|
|
307
|
+
// bare `run ci` package script for the steps that must not go through
|
|
308
|
+
// `with-env`'s replacement at all — see that file's header. Never
|
|
309
|
+
// self-invoking here: importing this module must not run anything, so
|
|
310
|
+
// `launch-ci.ts` can resolve the deploy tier and enter its environment
|
|
311
|
+
// first.
|
|
312
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
313
|
+
main(process.argv.slice(2)).catch(async (err) => {
|
|
314
|
+
process.stderr.write(`devtools-ci: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
315
|
+
// Report BEFORE exiting — see `captureDevtoolsError`'s header.
|
|
316
|
+
await captureDevtoolsError(err);
|
|
317
|
+
process.exitCode = 1;
|
|
318
|
+
});
|
|
319
|
+
}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs the CLI against an already-resolved argv.
|
|
3
|
+
*
|
|
4
|
+
* Exported rather than run at import, so `src/launch.ts` can resolve the
|
|
5
|
+
* deploy tier and enter its environment BEFORE this module's imports (and the
|
|
6
|
+
* commands they pull in) ever see `process.env` — see that file's header. The
|
|
7
|
+
* shebang above stays harmless: importing this module runs nothing, only
|
|
8
|
+
* `main()` does, and nothing calls it but `launch.ts` and the `import.meta.url`
|
|
9
|
+
* guard at the bottom of this file, for a direct `tsx src/cli.ts` run.
|
|
10
|
+
*/
|
|
11
|
+
export declare function main(argv: string[]): Promise<void>;
|