deepline 0.3.123 → 0.3.125
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/dist/bundling-sources/sdk/src/client.ts +25 -2
- package/dist/bundling-sources/sdk/src/compat.ts +17 -2
- package/dist/bundling-sources/sdk/src/play.ts +3 -1
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/monitors/package.json +2 -0
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-batch-operation.ts +61 -10
- package/dist/bundling-sources/shared_libs/monitors/provider-monitor-control-plane-capability.ts +47 -0
- package/dist/bundling-sources/shared_libs/observability/redaction.ts +3 -0
- package/dist/bundling-sources/shared_libs/observability/runtime-console.ts +174 -0
- package/dist/bundling-sources/shared_libs/observability/telemetry.ts +26 -2
- package/dist/bundling-sources/shared_libs/play-runtime/play-admission-outcome.ts +3 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/contracts.ts +20 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/index.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/admission/postgres-adapter.ts +28 -11
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-telemetry.ts +121 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-deploy-task.ts +91 -2
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +87 -41
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/scheduler-capacity.ts +5 -0
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +1 -0
- package/dist/cli/index.js +538 -469
- package/dist/cli/index.mjs +538 -469
- package/dist/index.d.mts +14 -1
- package/dist/index.d.ts +14 -1
- package/dist/index.js +11 -4
- package/dist/index.mjs +11 -4
- package/dist/install-integrity.json +2 -0
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +1 -1
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -3063,7 +3063,7 @@ var SDK_RELEASE = {
|
|
|
3063
3063
|
// getters keep their established compatibility behavior.
|
|
3064
3064
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
3065
3065
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
3066
|
-
version: "0.3.
|
|
3066
|
+
version: "0.3.125",
|
|
3067
3067
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
3068
3068
|
packageCapabilities: {
|
|
3069
3069
|
updatePreferences: 1
|
|
@@ -6914,7 +6914,7 @@ function playRunStatusFromState(state) {
|
|
|
6914
6914
|
..."result" in state ? { result: state.result } : {}
|
|
6915
6915
|
};
|
|
6916
6916
|
}
|
|
6917
|
-
var DeeplineClient = class {
|
|
6917
|
+
var DeeplineClient = class _DeeplineClient {
|
|
6918
6918
|
http;
|
|
6919
6919
|
config;
|
|
6920
6920
|
/** Canonical run lifecycle namespace backed by `/api/v2/runs`. */
|
|
@@ -9839,9 +9839,16 @@ var DeeplineClient = class {
|
|
|
9839
9839
|
// ——————————————————————————————————————————————————————————
|
|
9840
9840
|
// Monitor Jobs, Batches, and Fleets
|
|
9841
9841
|
// ——————————————————————————————————————————————————————————
|
|
9842
|
+
static MONITOR_JOB_IDEMPOTENCY_KEY_MAX_LENGTH = 96;
|
|
9842
9843
|
monitorJobIdempotencyKey(operation) {
|
|
9843
|
-
const uuid = globalThis.crypto?.randomUUID?.()
|
|
9844
|
-
|
|
9844
|
+
const uuid = globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
9845
|
+
const prefix = "monitor-job-";
|
|
9846
|
+
const safeOperation = operation.replace(/[^A-Za-z0-9._-]/g, "-");
|
|
9847
|
+
const maxOperationLength = Math.max(
|
|
9848
|
+
0,
|
|
9849
|
+
_DeeplineClient.MONITOR_JOB_IDEMPOTENCY_KEY_MAX_LENGTH - prefix.length - uuid.length - 1
|
|
9850
|
+
);
|
|
9851
|
+
return `${prefix}${safeOperation.slice(0, maxOperationLength)}-${uuid}`;
|
|
9845
9852
|
}
|
|
9846
9853
|
monitorJobHeaders(operation, idempotencyKey) {
|
|
9847
9854
|
return {
|
|
@@ -10291,6 +10298,12 @@ async function checkSdkCompatibility(baseUrl, options = {}) {
|
|
|
10291
10298
|
clearTimeout(timeout);
|
|
10292
10299
|
}
|
|
10293
10300
|
}
|
|
10301
|
+
function isCiEnvironment() {
|
|
10302
|
+
return ["CI", "GITHUB_ACTIONS"].some((name) => {
|
|
10303
|
+
const value = process.env[name]?.trim().toLowerCase();
|
|
10304
|
+
return value === "1" || value === "true" || value === "yes";
|
|
10305
|
+
});
|
|
10306
|
+
}
|
|
10294
10307
|
function enforceSdkCompatibilityResponse(response) {
|
|
10295
10308
|
if (!response) {
|
|
10296
10309
|
return;
|
|
@@ -10298,7 +10311,7 @@ function enforceSdkCompatibilityResponse(response) {
|
|
|
10298
10311
|
if (response.update_required) {
|
|
10299
10312
|
throw new Error(response.message);
|
|
10300
10313
|
}
|
|
10301
|
-
if (response.status === "deprecated" || response.status === "update_available") {
|
|
10314
|
+
if ((response.status === "deprecated" || response.status === "update_available") && !isCiEnvironment()) {
|
|
10302
10315
|
process.stderr.write(`${response.message}
|
|
10303
10316
|
`);
|
|
10304
10317
|
}
|
|
@@ -21304,7 +21317,8 @@ function printResult(input2) {
|
|
|
21304
21317
|
lines: [
|
|
21305
21318
|
`${input2.directory}: ${input2.status}`,
|
|
21306
21319
|
...input2.outcomes.map(renderOutcome),
|
|
21307
|
-
...failed && input2.deployment.error ? [input2.deployment.error] : []
|
|
21320
|
+
...failed && input2.deployment.error ? [input2.deployment.error] : [],
|
|
21321
|
+
`Details: deepline plays deployments ${input2.deployment.id}`
|
|
21308
21322
|
]
|
|
21309
21323
|
}
|
|
21310
21324
|
]
|
|
@@ -21383,6 +21397,461 @@ async function handlePlaysDeploy(directory, options) {
|
|
|
21383
21397
|
}
|
|
21384
21398
|
}
|
|
21385
21399
|
|
|
21400
|
+
// src/cli/commands/git.ts
|
|
21401
|
+
var GIT_DEPLOY_FEATURE = "github-deploy";
|
|
21402
|
+
function shellQuote2(value) {
|
|
21403
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
21404
|
+
}
|
|
21405
|
+
function renderProject(project) {
|
|
21406
|
+
const root = project.rootDirectory ? ` (${project.rootDirectory})` : "";
|
|
21407
|
+
const flags = [
|
|
21408
|
+
project.disabled ? "unlinked" : "linked",
|
|
21409
|
+
`deploys ${project.productionBranch}`,
|
|
21410
|
+
project.checkOnPullRequest ? "PR checks on" : "PR checks off"
|
|
21411
|
+
].join(", ");
|
|
21412
|
+
return `${project.id} ${project.repoFullName}${root} - ${flags}`;
|
|
21413
|
+
}
|
|
21414
|
+
function renderDeployment(deployment) {
|
|
21415
|
+
const fromDirectory = deployment.playProjectId === null;
|
|
21416
|
+
const kind = fromDirectory ? "directory deploy" : deployment.isProduction ? "production" : deployment.trigger === "pull_request" ? `pr #${deployment.pullRequestNumber ?? "?"}` : deployment.trigger;
|
|
21417
|
+
const suffix = deployment.error ? ` - ${deployment.error.slice(0, 80)}` : "";
|
|
21418
|
+
const source = [
|
|
21419
|
+
deployment.commitSha?.slice(0, 10),
|
|
21420
|
+
deployment.ref?.replace("refs/heads/", ""),
|
|
21421
|
+
fromDirectory ? deployment.repoFullName : null
|
|
21422
|
+
].filter(Boolean).join(" ") || "no git metadata";
|
|
21423
|
+
return `${deployment.id} ${source} (${kind}) - ${deployment.status}${suffix}`;
|
|
21424
|
+
}
|
|
21425
|
+
async function handleList(options) {
|
|
21426
|
+
const { http } = getAuthedHttpClient();
|
|
21427
|
+
const payload = await http.get(
|
|
21428
|
+
`/api/v2/play-projects${options.all ? "?includeDisabled=1" : ""}`
|
|
21429
|
+
);
|
|
21430
|
+
printCommandEnvelope(
|
|
21431
|
+
{
|
|
21432
|
+
projects: payload.projects,
|
|
21433
|
+
count: payload.projects.length,
|
|
21434
|
+
render: {
|
|
21435
|
+
sections: [
|
|
21436
|
+
{
|
|
21437
|
+
title: "linked repositories",
|
|
21438
|
+
lines: payload.projects.length ? payload.projects.map(renderProject) : [
|
|
21439
|
+
"No repositories are linked. Run `deepline git repos` to see what the GitHub installation can reach, then `deepline git link`."
|
|
21440
|
+
]
|
|
21441
|
+
}
|
|
21442
|
+
]
|
|
21443
|
+
}
|
|
21444
|
+
},
|
|
21445
|
+
{ json: options.json }
|
|
21446
|
+
);
|
|
21447
|
+
}
|
|
21448
|
+
function describeInstallationStatus(installation) {
|
|
21449
|
+
switch (installation.status) {
|
|
21450
|
+
case "active":
|
|
21451
|
+
return [
|
|
21452
|
+
`Connected to ${installation.accountLogin} (installation ${installation.installationId}).`
|
|
21453
|
+
];
|
|
21454
|
+
case "uninstalled":
|
|
21455
|
+
return [
|
|
21456
|
+
`The Deepline GitHub App was uninstalled from ${installation.accountLogin}${installation.uninstalledAt ? ` at ${new Date(installation.uninstalledAt).toISOString()}` : ""}.`,
|
|
21457
|
+
"Deploys are paused for every linked repository. Run `deepline git connect`, then `deepline git link <owner/repo>` again for each repository; links from the old installation cannot be resumed."
|
|
21458
|
+
];
|
|
21459
|
+
case "suspended":
|
|
21460
|
+
return [
|
|
21461
|
+
`GitHub suspended the Deepline App on ${installation.accountLogin}${installation.suspendedAt ? ` at ${new Date(installation.suspendedAt).toISOString()}` : ""}.`,
|
|
21462
|
+
"Pushes are not delivered while it is suspended; unsuspend it in GitHub settings."
|
|
21463
|
+
];
|
|
21464
|
+
}
|
|
21465
|
+
}
|
|
21466
|
+
async function handleStatus2(options) {
|
|
21467
|
+
const { http } = getAuthedHttpClient();
|
|
21468
|
+
const payload = await http.get("/api/v2/github/installation");
|
|
21469
|
+
const installation = payload.installation;
|
|
21470
|
+
const others = (payload.installations ?? []).filter(
|
|
21471
|
+
(row) => row.installationId !== installation?.installationId
|
|
21472
|
+
);
|
|
21473
|
+
const lines = installation ? describeInstallationStatus(installation) : [
|
|
21474
|
+
"No GitHub installation is connected to this workspace. Run `deepline git connect`."
|
|
21475
|
+
];
|
|
21476
|
+
for (const other of others) {
|
|
21477
|
+
lines.push(
|
|
21478
|
+
`Also: ${other.accountLogin} (installation ${other.installationId}) is ${other.status}.`
|
|
21479
|
+
);
|
|
21480
|
+
}
|
|
21481
|
+
const byId = new Map(
|
|
21482
|
+
(payload.installations ?? []).map((row) => [row.installationId, row])
|
|
21483
|
+
);
|
|
21484
|
+
const { projects } = await http.get(
|
|
21485
|
+
"/api/v2/play-projects?includeDisabled=1"
|
|
21486
|
+
);
|
|
21487
|
+
const affected_links = projects.map((project) => {
|
|
21488
|
+
const own = byId.get(project.installationId);
|
|
21489
|
+
const verdict = !own ? "unknown" : own.status === "active" ? null : own.status;
|
|
21490
|
+
return verdict ? {
|
|
21491
|
+
id: project.id,
|
|
21492
|
+
repoId: project.repoId,
|
|
21493
|
+
repoFullName: project.repoFullName,
|
|
21494
|
+
rootDirectory: project.rootDirectory,
|
|
21495
|
+
productionBranch: project.productionBranch,
|
|
21496
|
+
manifestPath: project.manifestPath,
|
|
21497
|
+
checkOnPullRequest: project.checkOnPullRequest,
|
|
21498
|
+
disabled: project.disabled,
|
|
21499
|
+
installationId: project.installationId,
|
|
21500
|
+
installationStatus: verdict
|
|
21501
|
+
} : null;
|
|
21502
|
+
}).filter((row) => row !== null);
|
|
21503
|
+
const activeInstallations = (payload.installations ?? []).filter(
|
|
21504
|
+
(row) => row.status === "active"
|
|
21505
|
+
);
|
|
21506
|
+
const relinkCommand = (link2) => [
|
|
21507
|
+
// The numeric repo id, not the name: a repository renamed while the
|
|
21508
|
+
// App was gone keeps a stale name here, and `git link` accepts the id.
|
|
21509
|
+
`deepline git link ${link2.repoId}`,
|
|
21510
|
+
// Stored values are admin-controlled text and this line is
|
|
21511
|
+
// copy-pasted into a shell by whoever reads it, so every
|
|
21512
|
+
// interpolated value below is quoted.
|
|
21513
|
+
`--branch ${shellQuote2(link2.productionBranch)}`,
|
|
21514
|
+
link2.rootDirectory ? `--root-dir ${shellQuote2(link2.rootDirectory)}` : "",
|
|
21515
|
+
link2.manifestPath && link2.manifestPath !== "deepline.json" ? `--manifest ${shellQuote2(link2.manifestPath)}` : "",
|
|
21516
|
+
link2.checkOnPullRequest ? "" : "--no-pr-checks",
|
|
21517
|
+
// With several active installations no id is guessed: the reader picks.
|
|
21518
|
+
activeInstallations.length > 1 ? "--installation <id>" : ""
|
|
21519
|
+
].filter(Boolean).join(" ");
|
|
21520
|
+
for (const link2 of affected_links) {
|
|
21521
|
+
const label = `${link2.repoFullName}${link2.rootDirectory ? ` (${link2.rootDirectory})` : ""}`;
|
|
21522
|
+
lines.push(
|
|
21523
|
+
link2.installationStatus !== "suspended" ? `Link again: ${label} \u2014 its installation ${link2.installationId} is ${link2.installationStatus}; run \`${relinkCommand(link2)}\`${activeInstallations.length > 1 ? ` with <id> being the installation that reaches this repo: ${activeInstallations.map((row) => `${row.installationId} (${row.accountLogin})`).join(", ")}` : ""}.` : (
|
|
21524
|
+
// A link disabled during the suspension stays disabled; only an
|
|
21525
|
+
// enabled one picks up again on its own when GitHub unsuspends.
|
|
21526
|
+
link2.disabled ? `Paused and disabled: ${label} \u2014 its installation is suspended, and the link stays disabled after GitHub unsuspends it until you run \`deepline git set ${link2.id} --enabled\`.` : `Paused: ${label} \u2014 its installation is suspended; pushes resume when GitHub unsuspends it.`
|
|
21527
|
+
)
|
|
21528
|
+
);
|
|
21529
|
+
}
|
|
21530
|
+
printCommandEnvelope(
|
|
21531
|
+
{
|
|
21532
|
+
installation,
|
|
21533
|
+
installations: payload.installations ?? [],
|
|
21534
|
+
affected_links,
|
|
21535
|
+
render: { sections: [{ title: "github installation", lines }] }
|
|
21536
|
+
},
|
|
21537
|
+
{ json: options.json }
|
|
21538
|
+
);
|
|
21539
|
+
}
|
|
21540
|
+
async function handleRepos(options) {
|
|
21541
|
+
const { http } = getAuthedHttpClient();
|
|
21542
|
+
const query = options.installation ? `?installationId=${encodeURIComponent(options.installation)}` : "";
|
|
21543
|
+
const payload = await http.get(`/api/v2/github/repos${query}`);
|
|
21544
|
+
printCommandEnvelope(
|
|
21545
|
+
{
|
|
21546
|
+
installation: payload.installation,
|
|
21547
|
+
repositories: payload.repositories,
|
|
21548
|
+
count: payload.repositories.length,
|
|
21549
|
+
render: {
|
|
21550
|
+
sections: [
|
|
21551
|
+
{
|
|
21552
|
+
title: `repos on installation @${payload.installation.accountLogin} (${payload.installation.repositorySelection})`,
|
|
21553
|
+
lines: payload.repositories.map(
|
|
21554
|
+
(repo) => `${repo.repoId} ${repo.fullName} (default: ${repo.defaultBranch}${repo.private ? ", private" : ""}${repo.fork ? ", fork" : ""})`
|
|
21555
|
+
)
|
|
21556
|
+
}
|
|
21557
|
+
]
|
|
21558
|
+
}
|
|
21559
|
+
},
|
|
21560
|
+
{ json: options.json }
|
|
21561
|
+
);
|
|
21562
|
+
}
|
|
21563
|
+
async function resolveRepoId(repo, installation) {
|
|
21564
|
+
if (/^\d+$/.test(repo)) return Number(repo);
|
|
21565
|
+
const { http } = getAuthedHttpClient();
|
|
21566
|
+
const query = installation ? `?installationId=${encodeURIComponent(installation)}` : "";
|
|
21567
|
+
const payload = await http.get(
|
|
21568
|
+
`/api/v2/github/repos${query}`
|
|
21569
|
+
);
|
|
21570
|
+
const match = payload.repositories.find(
|
|
21571
|
+
(entry) => entry.fullName.toLowerCase() === repo.toLowerCase()
|
|
21572
|
+
);
|
|
21573
|
+
if (!match) {
|
|
21574
|
+
throw new Error(
|
|
21575
|
+
`Repo "${repo}" is not accessible to the workspace's GitHub installation. Run \`deepline git repos\` to list what is.`
|
|
21576
|
+
);
|
|
21577
|
+
}
|
|
21578
|
+
return match.repoId;
|
|
21579
|
+
}
|
|
21580
|
+
async function handleLink(repo, options) {
|
|
21581
|
+
const repoId = await resolveRepoId(repo, options.installation);
|
|
21582
|
+
const { http } = getAuthedHttpClient();
|
|
21583
|
+
const payload = await http.post("/api/v2/play-projects", {
|
|
21584
|
+
repoId,
|
|
21585
|
+
...options.installation !== void 0 ? { installationId: options.installation } : {},
|
|
21586
|
+
...options.rootDir !== void 0 ? { rootDirectory: options.rootDir } : {},
|
|
21587
|
+
...options.manifest !== void 0 ? { manifestPath: options.manifest } : {},
|
|
21588
|
+
...options.branch !== void 0 ? { productionBranch: options.branch } : {},
|
|
21589
|
+
...options.prChecks !== void 0 ? { checkOnPullRequest: options.prChecks } : {}
|
|
21590
|
+
});
|
|
21591
|
+
printCommandEnvelope(
|
|
21592
|
+
{
|
|
21593
|
+
project: payload.project,
|
|
21594
|
+
render: {
|
|
21595
|
+
sections: [
|
|
21596
|
+
{
|
|
21597
|
+
title: "linked",
|
|
21598
|
+
lines: [
|
|
21599
|
+
renderProject(payload.project),
|
|
21600
|
+
...(payload.warnings ?? []).map(
|
|
21601
|
+
(warning) => `WARNING: ${warning}`
|
|
21602
|
+
),
|
|
21603
|
+
"Pushes to the production branch now register and promote changed plays.",
|
|
21604
|
+
"Anyone who can push to this repo can change what runs in this workspace."
|
|
21605
|
+
]
|
|
21606
|
+
}
|
|
21607
|
+
]
|
|
21608
|
+
}
|
|
21609
|
+
},
|
|
21610
|
+
{ json: options.json }
|
|
21611
|
+
);
|
|
21612
|
+
}
|
|
21613
|
+
async function handleGet(id, options) {
|
|
21614
|
+
const { http } = getAuthedHttpClient();
|
|
21615
|
+
const payload = await http.get(
|
|
21616
|
+
`/api/v2/play-projects/${encodeURIComponent(id)}`
|
|
21617
|
+
);
|
|
21618
|
+
printCommandEnvelope(
|
|
21619
|
+
{
|
|
21620
|
+
project: payload.project,
|
|
21621
|
+
render: {
|
|
21622
|
+
sections: [
|
|
21623
|
+
{
|
|
21624
|
+
title: "linked repository",
|
|
21625
|
+
lines: [renderProject(payload.project)]
|
|
21626
|
+
}
|
|
21627
|
+
]
|
|
21628
|
+
}
|
|
21629
|
+
},
|
|
21630
|
+
{ json: options.json }
|
|
21631
|
+
);
|
|
21632
|
+
}
|
|
21633
|
+
async function handleSet(id, options) {
|
|
21634
|
+
const { http } = getAuthedHttpClient();
|
|
21635
|
+
const payload = await http.patch(
|
|
21636
|
+
`/api/v2/play-projects/${encodeURIComponent(id)}`,
|
|
21637
|
+
{
|
|
21638
|
+
...options.branch !== void 0 ? { productionBranch: options.branch } : {},
|
|
21639
|
+
...options.rootDir !== void 0 ? { rootDirectory: options.rootDir } : {},
|
|
21640
|
+
...options.manifest !== void 0 ? { manifestPath: options.manifest } : {},
|
|
21641
|
+
...options.prChecks !== void 0 ? { checkOnPullRequest: options.prChecks } : {},
|
|
21642
|
+
...options.disabled !== void 0 ? { disabled: options.disabled } : {}
|
|
21643
|
+
}
|
|
21644
|
+
);
|
|
21645
|
+
printCommandEnvelope(
|
|
21646
|
+
{
|
|
21647
|
+
project: payload.project,
|
|
21648
|
+
render: {
|
|
21649
|
+
sections: [
|
|
21650
|
+
{ title: "updated", lines: [renderProject(payload.project)] }
|
|
21651
|
+
]
|
|
21652
|
+
}
|
|
21653
|
+
},
|
|
21654
|
+
{ json: options.json }
|
|
21655
|
+
);
|
|
21656
|
+
}
|
|
21657
|
+
async function handleUnlink(id, options) {
|
|
21658
|
+
const { http } = getAuthedHttpClient();
|
|
21659
|
+
await http.delete(`/api/v2/play-projects/${encodeURIComponent(id)}`);
|
|
21660
|
+
printCommandEnvelope(
|
|
21661
|
+
{
|
|
21662
|
+
ok: true,
|
|
21663
|
+
id,
|
|
21664
|
+
render: {
|
|
21665
|
+
sections: [
|
|
21666
|
+
{
|
|
21667
|
+
title: "unlinked",
|
|
21668
|
+
lines: [
|
|
21669
|
+
`Repository link ${id} removed. Deployments stop immediately and in-flight deploy credentials die; live plays keep running.`
|
|
21670
|
+
]
|
|
21671
|
+
}
|
|
21672
|
+
]
|
|
21673
|
+
}
|
|
21674
|
+
},
|
|
21675
|
+
{ json: options.json }
|
|
21676
|
+
);
|
|
21677
|
+
}
|
|
21678
|
+
async function handleConnect(options) {
|
|
21679
|
+
const baseUrl = resolveBaseUrlOnly();
|
|
21680
|
+
const connectUrl = `${baseUrl.replace(/\/$/, "")}/api/v2/github/connect`;
|
|
21681
|
+
const opened = openInBrowser(connectUrl);
|
|
21682
|
+
printCommandEnvelope(
|
|
21683
|
+
{
|
|
21684
|
+
connectUrl,
|
|
21685
|
+
browser: opened,
|
|
21686
|
+
render: {
|
|
21687
|
+
sections: [
|
|
21688
|
+
{
|
|
21689
|
+
title: "connect GitHub",
|
|
21690
|
+
lines: [
|
|
21691
|
+
opened === "opened" ? `Opened ${connectUrl} in your browser.` : `Open ${connectUrl} in your browser.`,
|
|
21692
|
+
"Sign in as a workspace admin if prompted, approve the GitHub",
|
|
21693
|
+
"installation, then return here and run `deepline git repos`."
|
|
21694
|
+
]
|
|
21695
|
+
}
|
|
21696
|
+
]
|
|
21697
|
+
}
|
|
21698
|
+
},
|
|
21699
|
+
{ json: options.json }
|
|
21700
|
+
);
|
|
21701
|
+
}
|
|
21702
|
+
async function handleDeploymentsList(options) {
|
|
21703
|
+
const { http } = getAuthedHttpClient();
|
|
21704
|
+
const query = new URLSearchParams();
|
|
21705
|
+
if (options.repo) query.set("projectId", options.repo);
|
|
21706
|
+
if (options.limit) query.set("limit", options.limit);
|
|
21707
|
+
const suffix = query.size > 0 ? `?${query.toString()}` : "";
|
|
21708
|
+
const payload = await http.get(
|
|
21709
|
+
`/api/v2/deployments${suffix}`
|
|
21710
|
+
);
|
|
21711
|
+
printCommandEnvelope(
|
|
21712
|
+
{
|
|
21713
|
+
deployments: payload.deployments,
|
|
21714
|
+
count: payload.deployments.length,
|
|
21715
|
+
render: {
|
|
21716
|
+
sections: [
|
|
21717
|
+
{
|
|
21718
|
+
title: "deployments",
|
|
21719
|
+
lines: payload.deployments.length ? payload.deployments.map(renderDeployment) : [
|
|
21720
|
+
"No deployments yet. Push to a linked repository, or run `deepline plays deploy`."
|
|
21721
|
+
]
|
|
21722
|
+
}
|
|
21723
|
+
]
|
|
21724
|
+
}
|
|
21725
|
+
},
|
|
21726
|
+
{ json: options.json }
|
|
21727
|
+
);
|
|
21728
|
+
}
|
|
21729
|
+
function renderDeploymentPlayLines(results) {
|
|
21730
|
+
const plays = results?.plays;
|
|
21731
|
+
if (!Array.isArray(plays)) return [];
|
|
21732
|
+
return plays.flatMap((play) => {
|
|
21733
|
+
const version = play.version === void 0 ? "" : play.previousVersion === void 0 ? ` v${play.version}` : ` v${play.previousVersion} -> v${play.version}`;
|
|
21734
|
+
const file = play.file ? ` (${play.file})` : "";
|
|
21735
|
+
return [
|
|
21736
|
+
`${play.name ?? "?"}${file} - ${play.status ?? "?"}${version}`,
|
|
21737
|
+
...play.error ? [` error: ${play.error}`] : [],
|
|
21738
|
+
...play.warning ? [` warning: ${play.warning}`] : []
|
|
21739
|
+
];
|
|
21740
|
+
});
|
|
21741
|
+
}
|
|
21742
|
+
async function handleDeploymentGet(id, options) {
|
|
21743
|
+
const { http } = getAuthedHttpClient();
|
|
21744
|
+
const payload = await http.get(`/api/v2/deployments/${encodeURIComponent(id)}`);
|
|
21745
|
+
const playLines = renderDeploymentPlayLines(payload.deployment.results);
|
|
21746
|
+
const repository = payload.project?.repoFullName ?? payload.deployment.repoFullName;
|
|
21747
|
+
printCommandEnvelope(
|
|
21748
|
+
{
|
|
21749
|
+
deployment: payload.deployment,
|
|
21750
|
+
project: payload.project,
|
|
21751
|
+
render: {
|
|
21752
|
+
sections: [
|
|
21753
|
+
{
|
|
21754
|
+
title: `deployment ${payload.deployment.id}${repository ? ` (${repository})` : ""}`,
|
|
21755
|
+
lines: [renderDeployment(payload.deployment)]
|
|
21756
|
+
},
|
|
21757
|
+
...playLines.length ? [{ title: "plays", lines: playLines }] : []
|
|
21758
|
+
]
|
|
21759
|
+
}
|
|
21760
|
+
},
|
|
21761
|
+
{ json: options.json }
|
|
21762
|
+
);
|
|
21763
|
+
}
|
|
21764
|
+
async function handleDeploymentCancel(id, options) {
|
|
21765
|
+
const { http } = getAuthedHttpClient();
|
|
21766
|
+
const payload = await http.post(`/api/v2/deployments/${encodeURIComponent(id)}/cancel`, {});
|
|
21767
|
+
printCommandEnvelope(
|
|
21768
|
+
{
|
|
21769
|
+
cancelled: payload.cancelled,
|
|
21770
|
+
deployment: payload.deployment,
|
|
21771
|
+
render: {
|
|
21772
|
+
sections: [
|
|
21773
|
+
{
|
|
21774
|
+
title: payload.cancelled ? "cancelled" : "already cancelled",
|
|
21775
|
+
lines: [
|
|
21776
|
+
payload.deployment ? renderDeployment(payload.deployment) : `Deployment ${id} cancelled.`,
|
|
21777
|
+
"The build stops at its next step and nothing from it goes live."
|
|
21778
|
+
]
|
|
21779
|
+
}
|
|
21780
|
+
]
|
|
21781
|
+
}
|
|
21782
|
+
},
|
|
21783
|
+
{ json: options.json }
|
|
21784
|
+
);
|
|
21785
|
+
}
|
|
21786
|
+
function registerGitCommands(program) {
|
|
21787
|
+
const git = program.command("git", { hidden: !cliFeatureEnabled(GIT_DEPLOY_FEATURE) }).alias("projects").description(
|
|
21788
|
+
"Git deploys: link repositories to this workspace and deploy plays on push."
|
|
21789
|
+
).addHelpText(
|
|
21790
|
+
"after",
|
|
21791
|
+
`
|
|
21792
|
+
Examples:
|
|
21793
|
+
deepline git connect
|
|
21794
|
+
deepline git repos
|
|
21795
|
+
deepline git link acme/growth --branch main
|
|
21796
|
+
deepline git list
|
|
21797
|
+
deepline git set <id> --branch release
|
|
21798
|
+
deepline git unlink <id>
|
|
21799
|
+
deepline git deployments --repo <id>
|
|
21800
|
+
deepline git cancel <deployment-id>
|
|
21801
|
+
`
|
|
21802
|
+
);
|
|
21803
|
+
git.command("connect").description("Connect a GitHub installation (browser step).").option("--json", "Emit JSON output").action(async (options) => handleConnect(options));
|
|
21804
|
+
git.command("status").description(
|
|
21805
|
+
"Show the workspace's GitHub installation and whether it is still usable."
|
|
21806
|
+
).option("--json", "Emit JSON output").action(async (options) => handleStatus2(options));
|
|
21807
|
+
git.command("repos").description("List repos the workspace's GitHub installation can reach.").option(
|
|
21808
|
+
"--installation <id>",
|
|
21809
|
+
"GitHub installation id (required when several are connected)"
|
|
21810
|
+
).option("--json", "Emit JSON output").action(
|
|
21811
|
+
async (options) => handleRepos(options)
|
|
21812
|
+
);
|
|
21813
|
+
git.command("list").description("List linked repositories.").option("--all", "Include unlinked repositories").option("--json", "Emit JSON output").action(
|
|
21814
|
+
async (options) => handleList(options)
|
|
21815
|
+
);
|
|
21816
|
+
git.command("link").description("Link a repository to this workspace for deploy-on-push.").argument("<repo>", "Repo full name (owner/name) or numeric repo id").option("--root-dir <path>", "Base path inside the repo for this link").option("--branch <name>", "Production branch (default: repo default)").option(
|
|
21817
|
+
"--manifest <file>",
|
|
21818
|
+
"Manifest file name under the base path (default: deepline.json)"
|
|
21819
|
+
).option(
|
|
21820
|
+
"--installation <id>",
|
|
21821
|
+
"GitHub installation id (required when several are connected)"
|
|
21822
|
+
).option("--no-pr-checks", "Skip Check Runs on pull requests").option("--json", "Emit JSON output").action(
|
|
21823
|
+
async (repo, options) => handleLink(repo, options)
|
|
21824
|
+
);
|
|
21825
|
+
git.command("get").description("Show one linked repository.").argument("<id>", "Repository link id").option("--json", "Emit JSON output").action(async (id, options) => handleGet(id, options));
|
|
21826
|
+
git.command("set").description("Update a linked repository.").argument("<id>", "Repository link id").option("--branch <name>", "Production branch").option("--root-dir <path>", "Base path inside the repo for this link").option(
|
|
21827
|
+
"--manifest <file>",
|
|
21828
|
+
"Manifest file name under the base path (default: deepline.json)"
|
|
21829
|
+
).option("--pr-checks", "Enable Check Runs on pull requests").option("--no-pr-checks", "Disable Check Runs on pull requests").option("--disabled", "Pause deployments for this link").option("--enabled", "Resume deployments for this link").option("--json", "Emit JSON output").action(
|
|
21830
|
+
async (id, options) => handleSet(id, {
|
|
21831
|
+
...options,
|
|
21832
|
+
disabled: options.enabled === true ? false : options.disabled === true ? true : void 0
|
|
21833
|
+
})
|
|
21834
|
+
);
|
|
21835
|
+
git.command("unlink").description("Unlink a repository (live plays keep running).").argument("<id>", "Repository link id").option("--json", "Emit JSON output").action(
|
|
21836
|
+
async (id, options) => handleUnlink(id, options)
|
|
21837
|
+
);
|
|
21838
|
+
git.command("deployments").description("Deployment history; pass an id for one deployment.").argument("[id]", "Deployment id (omit to list)").option("--repo <id>", "Filter to one repository link").option("--limit <n>", "Max rows (default 50)").option("--json", "Emit JSON output").action(
|
|
21839
|
+
async (id, options) => id ? handleDeploymentGet(id, options) : handleDeploymentsList(options)
|
|
21840
|
+
);
|
|
21841
|
+
git.command("cancel").description(
|
|
21842
|
+
"Cancel a queued or running deployment before its plays go live (admin)."
|
|
21843
|
+
).argument("<id>", "Deployment id").option("--json", "Emit JSON output").action(
|
|
21844
|
+
async (id, options) => handleDeploymentCancel(id, options)
|
|
21845
|
+
);
|
|
21846
|
+
const deployments = program.command("deployments", { hidden: true });
|
|
21847
|
+
deployments.command("list").option("--project <id>", "Filter to one repository link").option("--limit <n>", "Max rows (default 50)").option("--json", "Emit JSON output").action(
|
|
21848
|
+
async (options) => handleDeploymentsList({ ...options, repo: options.project })
|
|
21849
|
+
);
|
|
21850
|
+
deployments.command("get").argument("<id>", "Deployment id").option("--json", "Emit JSON output").action(
|
|
21851
|
+
async (id, options) => handleDeploymentGet(id, options)
|
|
21852
|
+
);
|
|
21853
|
+
}
|
|
21854
|
+
|
|
21386
21855
|
// src/cli/commands/play.ts
|
|
21387
21856
|
var PLAY_BUNDLER_MODULE_PATHS = [
|
|
21388
21857
|
// Built CLI bundle: dist/cli/index.mjs -> dist/plays/bundle-play-file.mjs.
|
|
@@ -21729,7 +22198,7 @@ function rankPlayReferenceSuggestions(input2) {
|
|
|
21729
22198
|
function searchQueryForMissingPlayReference(target) {
|
|
21730
22199
|
return parseReferencedPlayTarget2(target).unqualifiedPlayName.replace(/[-_./]+/g, " ").replace(/\s+/g, " ").trim();
|
|
21731
22200
|
}
|
|
21732
|
-
function
|
|
22201
|
+
function shellQuote3(value) {
|
|
21733
22202
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
21734
22203
|
}
|
|
21735
22204
|
function buildPlayReferenceNotFoundMessage(input2) {
|
|
@@ -21762,7 +22231,7 @@ function buildPlayReferenceNotFoundMessage(input2) {
|
|
|
21762
22231
|
lines.push(
|
|
21763
22232
|
"",
|
|
21764
22233
|
"Search visible plays:",
|
|
21765
|
-
` deepline plays search ${
|
|
22234
|
+
` deepline plays search ${shellQuote3(searchQuery)} --all --json`
|
|
21766
22235
|
);
|
|
21767
22236
|
}
|
|
21768
22237
|
return lines.join("\n");
|
|
@@ -26522,7 +26991,7 @@ function printPlayCheckOutcome(outcome, target, prefix) {
|
|
|
26522
26991
|
printPlayCheckLimits(result.limits);
|
|
26523
26992
|
if (result.artifactHash && outcome.exportName === PLAY_DEFAULT_EXPORT) {
|
|
26524
26993
|
console.log(
|
|
26525
|
-
` publish: deepline plays publish ${
|
|
26994
|
+
` publish: deepline plays publish ${shellQuote3(target)} --expected-artifact ${result.artifactHash}`
|
|
26526
26995
|
);
|
|
26527
26996
|
}
|
|
26528
26997
|
printPlayTriggers(result.triggers);
|
|
@@ -27155,7 +27624,7 @@ async function handleRunsList(args) {
|
|
|
27155
27624
|
return lines2.join("\n");
|
|
27156
27625
|
});
|
|
27157
27626
|
const nextOffset = (page.offset ?? offset ?? 0) + runs.length;
|
|
27158
|
-
const nextPage = page.hasMore && playName ? `deepline runs list --play ${
|
|
27627
|
+
const nextPage = page.hasMore && playName ? `deepline runs list --play ${shellQuote3(playName)}${statusFilter ? ` --status ${shellQuote3(statusFilter)}` : ""} --limit ${page.limit ?? limit ?? 20} --offset ${nextOffset} --json` : null;
|
|
27159
27628
|
if (page.hasMore) {
|
|
27160
27629
|
lines.push("List truncated \u2014 more runs match this filter.");
|
|
27161
27630
|
lines.push(
|
|
@@ -27916,7 +28385,7 @@ async function handlePlayList(args) {
|
|
|
27916
28385
|
cursor
|
|
27917
28386
|
});
|
|
27918
28387
|
const plays = page.plays;
|
|
27919
|
-
const nextPage = page.hasMore && page.cursor ? `deepline plays list${categories ? ` --categories ${
|
|
28388
|
+
const nextPage = page.hasMore && page.cursor ? `deepline plays list${categories ? ` --categories ${shellQuote3(categories)}` : ""}${limit ? ` --limit ${limit}` : ""}${showCost ? " --show-cost" : ""} --cursor ${shellQuote3(page.cursor)} --json` : null;
|
|
27920
28389
|
if (page.hasMore && !nextPage) {
|
|
27921
28390
|
throw new Error(
|
|
27922
28391
|
"Play list reported more results without a continuation cursor"
|
|
@@ -28337,7 +28806,7 @@ async function handlePlaySave(args) {
|
|
|
28337
28806
|
message: "Refusing to save: the local file no longer produces the artifact checked earlier.",
|
|
28338
28807
|
expectedArtifactHash: options.expectedArtifactHash,
|
|
28339
28808
|
currentArtifactHash: artifactHash,
|
|
28340
|
-
next: `deepline plays check ${
|
|
28809
|
+
next: `deepline plays check ${shellQuote3(options.target)}`
|
|
28341
28810
|
};
|
|
28342
28811
|
if (options.jsonOutput) {
|
|
28343
28812
|
printCompactJson(result);
|
|
@@ -28402,7 +28871,7 @@ async function handlePlaySave(args) {
|
|
|
28402
28871
|
graphHash: graph.root.artifact.graphHash,
|
|
28403
28872
|
artifactStorageKey: saved.artifactStorageKey,
|
|
28404
28873
|
next: {
|
|
28405
|
-
publish: `deepline plays publish ${
|
|
28874
|
+
publish: `deepline plays publish ${shellQuote3(options.target)} --expected-artifact ${artifactHash}`,
|
|
28406
28875
|
get: `deepline plays get ${playName} --source --out ./${playName}/ --working`
|
|
28407
28876
|
}
|
|
28408
28877
|
};
|
|
@@ -28462,7 +28931,7 @@ async function handlePlayPublish(args) {
|
|
|
28462
28931
|
message: "Refusing to publish: the local file no longer produces the artifact checked earlier.",
|
|
28463
28932
|
expectedArtifactHash: options.expectedArtifactHash,
|
|
28464
28933
|
currentArtifactHash: artifactHash,
|
|
28465
|
-
next: `deepline plays check ${
|
|
28934
|
+
next: `deepline plays check ${shellQuote3(playName)}`
|
|
28466
28935
|
};
|
|
28467
28936
|
if (options.jsonOutput) {
|
|
28468
28937
|
printCompactJson(result3);
|
|
@@ -29230,6 +29699,22 @@ Examples:
|
|
|
29230
29699
|
).option("--repo <owner/name>", "Repository to record on the deployment").option("--ref <ref>", "Branch or ref to record on the deployment").option("--commit <sha>", "Commit to record on the deployment").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(
|
|
29231
29700
|
async (directory, options) => handlePlaysDeploy(directory, options)
|
|
29232
29701
|
);
|
|
29702
|
+
play.command("deployments [id]").description(
|
|
29703
|
+
"Deployment history for this workspace; pass an id for one deployment and its plays."
|
|
29704
|
+
).addHelpText(
|
|
29705
|
+
"after",
|
|
29706
|
+
`
|
|
29707
|
+
Notes:
|
|
29708
|
+
Lists every deployment, whether \`deepline plays deploy\` or a linked
|
|
29709
|
+
repository's push made it. The same views as \`deepline git deployments\`.
|
|
29710
|
+
|
|
29711
|
+
Examples:
|
|
29712
|
+
deepline plays deployments
|
|
29713
|
+
deepline plays deployments <deployment-id>
|
|
29714
|
+
`
|
|
29715
|
+
).option("--limit <n>", "Max rows (default 50)").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(
|
|
29716
|
+
async (id, options) => id ? handleDeploymentGet(id, options) : handleDeploymentsList(options)
|
|
29717
|
+
);
|
|
29233
29718
|
addPublishHelp(
|
|
29234
29719
|
play.command("publish <target>").description(
|
|
29235
29720
|
"Promote a saved play revision or publish a local play file."
|
|
@@ -37650,6 +38135,7 @@ function renderMonitorJob(payload) {
|
|
|
37650
38135
|
if (!job) return void 0;
|
|
37651
38136
|
const id = asString(job.id) ?? "<unknown>";
|
|
37652
38137
|
const state = asString(job.state) ?? "unknown";
|
|
38138
|
+
const outcome = asString(job.outcome);
|
|
37653
38139
|
const phase = asString(job.phase);
|
|
37654
38140
|
const counts = asRecord2(job.counts);
|
|
37655
38141
|
const reconciliation = asRecord2(job.reconciliation);
|
|
@@ -37657,6 +38143,9 @@ function renderMonitorJob(payload) {
|
|
|
37657
38143
|
`Monitor job: ${id}`,
|
|
37658
38144
|
`State: ${state}${phase ? ` (${phase})` : ""}`
|
|
37659
38145
|
];
|
|
38146
|
+
if (outcome) lines.push(`Outcome: ${outcome}`);
|
|
38147
|
+
const operationId = asString(job.operation_id);
|
|
38148
|
+
if (operationId) lines.push(`Operation: ${operationId}`);
|
|
37660
38149
|
if (counts) {
|
|
37661
38150
|
lines.push(
|
|
37662
38151
|
`Counts: requested ${asFiniteNumber(counts.requested) ?? 0}, created ${asFiniteNumber(counts.created) ?? 0}, updated ${asFiniteNumber(counts.updated) ?? 0}, removed ${asFiniteNumber(counts.removed) ?? 0}, unchanged ${asFiniteNumber(counts.unchanged) ?? 0}, verified ${asFiniteNumber(counts.verified) ?? 0}, failed ${asFiniteNumber(counts.failed) ?? 0}`
|
|
@@ -40852,448 +41341,6 @@ Examples:
|
|
|
40852
41341
|
);
|
|
40853
41342
|
}
|
|
40854
41343
|
|
|
40855
|
-
// src/cli/commands/git.ts
|
|
40856
|
-
var GIT_DEPLOY_FEATURE = "github-deploy";
|
|
40857
|
-
function shellQuote3(value) {
|
|
40858
|
-
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
40859
|
-
}
|
|
40860
|
-
function renderProject(project) {
|
|
40861
|
-
const root = project.rootDirectory ? ` (${project.rootDirectory})` : "";
|
|
40862
|
-
const flags = [
|
|
40863
|
-
project.disabled ? "unlinked" : "linked",
|
|
40864
|
-
`deploys ${project.productionBranch}`,
|
|
40865
|
-
project.checkOnPullRequest ? "PR checks on" : "PR checks off"
|
|
40866
|
-
].join(", ");
|
|
40867
|
-
return `${project.id} ${project.repoFullName}${root} - ${flags}`;
|
|
40868
|
-
}
|
|
40869
|
-
function renderDeployment(deployment) {
|
|
40870
|
-
const kind = deployment.isProduction ? "production" : deployment.trigger === "pull_request" ? `pr #${deployment.pullRequestNumber ?? "?"}` : deployment.trigger;
|
|
40871
|
-
const suffix = deployment.error ? ` - ${deployment.error.slice(0, 80)}` : "";
|
|
40872
|
-
const source = [
|
|
40873
|
-
deployment.commitSha?.slice(0, 10),
|
|
40874
|
-
deployment.ref?.replace("refs/heads/", "") ?? deployment.repoFullName
|
|
40875
|
-
].filter(Boolean).join(" ") || "directory";
|
|
40876
|
-
return `${deployment.id} ${source} (${kind}) - ${deployment.status}${suffix}`;
|
|
40877
|
-
}
|
|
40878
|
-
async function handleList(options) {
|
|
40879
|
-
const { http } = getAuthedHttpClient();
|
|
40880
|
-
const payload = await http.get(
|
|
40881
|
-
`/api/v2/play-projects${options.all ? "?includeDisabled=1" : ""}`
|
|
40882
|
-
);
|
|
40883
|
-
printCommandEnvelope(
|
|
40884
|
-
{
|
|
40885
|
-
projects: payload.projects,
|
|
40886
|
-
count: payload.projects.length,
|
|
40887
|
-
render: {
|
|
40888
|
-
sections: [
|
|
40889
|
-
{
|
|
40890
|
-
title: "linked repositories",
|
|
40891
|
-
lines: payload.projects.length ? payload.projects.map(renderProject) : [
|
|
40892
|
-
"No repositories are linked. Run `deepline git repos` to see what the GitHub installation can reach, then `deepline git link`."
|
|
40893
|
-
]
|
|
40894
|
-
}
|
|
40895
|
-
]
|
|
40896
|
-
}
|
|
40897
|
-
},
|
|
40898
|
-
{ json: options.json }
|
|
40899
|
-
);
|
|
40900
|
-
}
|
|
40901
|
-
function describeInstallationStatus(installation) {
|
|
40902
|
-
switch (installation.status) {
|
|
40903
|
-
case "active":
|
|
40904
|
-
return [
|
|
40905
|
-
`Connected to ${installation.accountLogin} (installation ${installation.installationId}).`
|
|
40906
|
-
];
|
|
40907
|
-
case "uninstalled":
|
|
40908
|
-
return [
|
|
40909
|
-
`The Deepline GitHub App was uninstalled from ${installation.accountLogin}${installation.uninstalledAt ? ` at ${new Date(installation.uninstalledAt).toISOString()}` : ""}.`,
|
|
40910
|
-
"Deploys are paused for every linked repository. Run `deepline git connect`, then `deepline git link <owner/repo>` again for each repository; links from the old installation cannot be resumed."
|
|
40911
|
-
];
|
|
40912
|
-
case "suspended":
|
|
40913
|
-
return [
|
|
40914
|
-
`GitHub suspended the Deepline App on ${installation.accountLogin}${installation.suspendedAt ? ` at ${new Date(installation.suspendedAt).toISOString()}` : ""}.`,
|
|
40915
|
-
"Pushes are not delivered while it is suspended; unsuspend it in GitHub settings."
|
|
40916
|
-
];
|
|
40917
|
-
}
|
|
40918
|
-
}
|
|
40919
|
-
async function handleStatus2(options) {
|
|
40920
|
-
const { http } = getAuthedHttpClient();
|
|
40921
|
-
const payload = await http.get("/api/v2/github/installation");
|
|
40922
|
-
const installation = payload.installation;
|
|
40923
|
-
const others = (payload.installations ?? []).filter(
|
|
40924
|
-
(row) => row.installationId !== installation?.installationId
|
|
40925
|
-
);
|
|
40926
|
-
const lines = installation ? describeInstallationStatus(installation) : [
|
|
40927
|
-
"No GitHub installation is connected to this workspace. Run `deepline git connect`."
|
|
40928
|
-
];
|
|
40929
|
-
for (const other of others) {
|
|
40930
|
-
lines.push(
|
|
40931
|
-
`Also: ${other.accountLogin} (installation ${other.installationId}) is ${other.status}.`
|
|
40932
|
-
);
|
|
40933
|
-
}
|
|
40934
|
-
const byId = new Map(
|
|
40935
|
-
(payload.installations ?? []).map((row) => [row.installationId, row])
|
|
40936
|
-
);
|
|
40937
|
-
const { projects } = await http.get(
|
|
40938
|
-
"/api/v2/play-projects?includeDisabled=1"
|
|
40939
|
-
);
|
|
40940
|
-
const affected_links = projects.map((project) => {
|
|
40941
|
-
const own = byId.get(project.installationId);
|
|
40942
|
-
const verdict = !own ? "unknown" : own.status === "active" ? null : own.status;
|
|
40943
|
-
return verdict ? {
|
|
40944
|
-
id: project.id,
|
|
40945
|
-
repoId: project.repoId,
|
|
40946
|
-
repoFullName: project.repoFullName,
|
|
40947
|
-
rootDirectory: project.rootDirectory,
|
|
40948
|
-
productionBranch: project.productionBranch,
|
|
40949
|
-
manifestPath: project.manifestPath,
|
|
40950
|
-
checkOnPullRequest: project.checkOnPullRequest,
|
|
40951
|
-
disabled: project.disabled,
|
|
40952
|
-
installationId: project.installationId,
|
|
40953
|
-
installationStatus: verdict
|
|
40954
|
-
} : null;
|
|
40955
|
-
}).filter((row) => row !== null);
|
|
40956
|
-
const activeInstallations = (payload.installations ?? []).filter(
|
|
40957
|
-
(row) => row.status === "active"
|
|
40958
|
-
);
|
|
40959
|
-
const relinkCommand = (link2) => [
|
|
40960
|
-
// The numeric repo id, not the name: a repository renamed while the
|
|
40961
|
-
// App was gone keeps a stale name here, and `git link` accepts the id.
|
|
40962
|
-
`deepline git link ${link2.repoId}`,
|
|
40963
|
-
// Stored values are admin-controlled text and this line is
|
|
40964
|
-
// copy-pasted into a shell by whoever reads it, so every
|
|
40965
|
-
// interpolated value below is quoted.
|
|
40966
|
-
`--branch ${shellQuote3(link2.productionBranch)}`,
|
|
40967
|
-
link2.rootDirectory ? `--root-dir ${shellQuote3(link2.rootDirectory)}` : "",
|
|
40968
|
-
link2.manifestPath && link2.manifestPath !== "deepline.json" ? `--manifest ${shellQuote3(link2.manifestPath)}` : "",
|
|
40969
|
-
link2.checkOnPullRequest ? "" : "--no-pr-checks",
|
|
40970
|
-
// With several active installations no id is guessed: the reader picks.
|
|
40971
|
-
activeInstallations.length > 1 ? "--installation <id>" : ""
|
|
40972
|
-
].filter(Boolean).join(" ");
|
|
40973
|
-
for (const link2 of affected_links) {
|
|
40974
|
-
const label = `${link2.repoFullName}${link2.rootDirectory ? ` (${link2.rootDirectory})` : ""}`;
|
|
40975
|
-
lines.push(
|
|
40976
|
-
link2.installationStatus !== "suspended" ? `Link again: ${label} \u2014 its installation ${link2.installationId} is ${link2.installationStatus}; run \`${relinkCommand(link2)}\`${activeInstallations.length > 1 ? ` with <id> being the installation that reaches this repo: ${activeInstallations.map((row) => `${row.installationId} (${row.accountLogin})`).join(", ")}` : ""}.` : (
|
|
40977
|
-
// A link disabled during the suspension stays disabled; only an
|
|
40978
|
-
// enabled one picks up again on its own when GitHub unsuspends.
|
|
40979
|
-
link2.disabled ? `Paused and disabled: ${label} \u2014 its installation is suspended, and the link stays disabled after GitHub unsuspends it until you run \`deepline git set ${link2.id} --enabled\`.` : `Paused: ${label} \u2014 its installation is suspended; pushes resume when GitHub unsuspends it.`
|
|
40980
|
-
)
|
|
40981
|
-
);
|
|
40982
|
-
}
|
|
40983
|
-
printCommandEnvelope(
|
|
40984
|
-
{
|
|
40985
|
-
installation,
|
|
40986
|
-
installations: payload.installations ?? [],
|
|
40987
|
-
affected_links,
|
|
40988
|
-
render: { sections: [{ title: "github installation", lines }] }
|
|
40989
|
-
},
|
|
40990
|
-
{ json: options.json }
|
|
40991
|
-
);
|
|
40992
|
-
}
|
|
40993
|
-
async function handleRepos(options) {
|
|
40994
|
-
const { http } = getAuthedHttpClient();
|
|
40995
|
-
const query = options.installation ? `?installationId=${encodeURIComponent(options.installation)}` : "";
|
|
40996
|
-
const payload = await http.get(`/api/v2/github/repos${query}`);
|
|
40997
|
-
printCommandEnvelope(
|
|
40998
|
-
{
|
|
40999
|
-
installation: payload.installation,
|
|
41000
|
-
repositories: payload.repositories,
|
|
41001
|
-
count: payload.repositories.length,
|
|
41002
|
-
render: {
|
|
41003
|
-
sections: [
|
|
41004
|
-
{
|
|
41005
|
-
title: `repos on installation @${payload.installation.accountLogin} (${payload.installation.repositorySelection})`,
|
|
41006
|
-
lines: payload.repositories.map(
|
|
41007
|
-
(repo) => `${repo.repoId} ${repo.fullName} (default: ${repo.defaultBranch}${repo.private ? ", private" : ""}${repo.fork ? ", fork" : ""})`
|
|
41008
|
-
)
|
|
41009
|
-
}
|
|
41010
|
-
]
|
|
41011
|
-
}
|
|
41012
|
-
},
|
|
41013
|
-
{ json: options.json }
|
|
41014
|
-
);
|
|
41015
|
-
}
|
|
41016
|
-
async function resolveRepoId(repo, installation) {
|
|
41017
|
-
if (/^\d+$/.test(repo)) return Number(repo);
|
|
41018
|
-
const { http } = getAuthedHttpClient();
|
|
41019
|
-
const query = installation ? `?installationId=${encodeURIComponent(installation)}` : "";
|
|
41020
|
-
const payload = await http.get(
|
|
41021
|
-
`/api/v2/github/repos${query}`
|
|
41022
|
-
);
|
|
41023
|
-
const match = payload.repositories.find(
|
|
41024
|
-
(entry) => entry.fullName.toLowerCase() === repo.toLowerCase()
|
|
41025
|
-
);
|
|
41026
|
-
if (!match) {
|
|
41027
|
-
throw new Error(
|
|
41028
|
-
`Repo "${repo}" is not accessible to the workspace's GitHub installation. Run \`deepline git repos\` to list what is.`
|
|
41029
|
-
);
|
|
41030
|
-
}
|
|
41031
|
-
return match.repoId;
|
|
41032
|
-
}
|
|
41033
|
-
async function handleLink(repo, options) {
|
|
41034
|
-
const repoId = await resolveRepoId(repo, options.installation);
|
|
41035
|
-
const { http } = getAuthedHttpClient();
|
|
41036
|
-
const payload = await http.post("/api/v2/play-projects", {
|
|
41037
|
-
repoId,
|
|
41038
|
-
...options.installation !== void 0 ? { installationId: options.installation } : {},
|
|
41039
|
-
...options.rootDir !== void 0 ? { rootDirectory: options.rootDir } : {},
|
|
41040
|
-
...options.manifest !== void 0 ? { manifestPath: options.manifest } : {},
|
|
41041
|
-
...options.branch !== void 0 ? { productionBranch: options.branch } : {},
|
|
41042
|
-
...options.prChecks !== void 0 ? { checkOnPullRequest: options.prChecks } : {}
|
|
41043
|
-
});
|
|
41044
|
-
printCommandEnvelope(
|
|
41045
|
-
{
|
|
41046
|
-
project: payload.project,
|
|
41047
|
-
render: {
|
|
41048
|
-
sections: [
|
|
41049
|
-
{
|
|
41050
|
-
title: "linked",
|
|
41051
|
-
lines: [
|
|
41052
|
-
renderProject(payload.project),
|
|
41053
|
-
...(payload.warnings ?? []).map(
|
|
41054
|
-
(warning) => `WARNING: ${warning}`
|
|
41055
|
-
),
|
|
41056
|
-
"Pushes to the production branch now register and promote changed plays.",
|
|
41057
|
-
"Anyone who can push to this repo can change what runs in this workspace."
|
|
41058
|
-
]
|
|
41059
|
-
}
|
|
41060
|
-
]
|
|
41061
|
-
}
|
|
41062
|
-
},
|
|
41063
|
-
{ json: options.json }
|
|
41064
|
-
);
|
|
41065
|
-
}
|
|
41066
|
-
async function handleGet(id, options) {
|
|
41067
|
-
const { http } = getAuthedHttpClient();
|
|
41068
|
-
const payload = await http.get(
|
|
41069
|
-
`/api/v2/play-projects/${encodeURIComponent(id)}`
|
|
41070
|
-
);
|
|
41071
|
-
printCommandEnvelope(
|
|
41072
|
-
{
|
|
41073
|
-
project: payload.project,
|
|
41074
|
-
render: {
|
|
41075
|
-
sections: [
|
|
41076
|
-
{
|
|
41077
|
-
title: "linked repository",
|
|
41078
|
-
lines: [renderProject(payload.project)]
|
|
41079
|
-
}
|
|
41080
|
-
]
|
|
41081
|
-
}
|
|
41082
|
-
},
|
|
41083
|
-
{ json: options.json }
|
|
41084
|
-
);
|
|
41085
|
-
}
|
|
41086
|
-
async function handleSet(id, options) {
|
|
41087
|
-
const { http } = getAuthedHttpClient();
|
|
41088
|
-
const payload = await http.patch(
|
|
41089
|
-
`/api/v2/play-projects/${encodeURIComponent(id)}`,
|
|
41090
|
-
{
|
|
41091
|
-
...options.branch !== void 0 ? { productionBranch: options.branch } : {},
|
|
41092
|
-
...options.rootDir !== void 0 ? { rootDirectory: options.rootDir } : {},
|
|
41093
|
-
...options.manifest !== void 0 ? { manifestPath: options.manifest } : {},
|
|
41094
|
-
...options.prChecks !== void 0 ? { checkOnPullRequest: options.prChecks } : {},
|
|
41095
|
-
...options.disabled !== void 0 ? { disabled: options.disabled } : {}
|
|
41096
|
-
}
|
|
41097
|
-
);
|
|
41098
|
-
printCommandEnvelope(
|
|
41099
|
-
{
|
|
41100
|
-
project: payload.project,
|
|
41101
|
-
render: {
|
|
41102
|
-
sections: [
|
|
41103
|
-
{ title: "updated", lines: [renderProject(payload.project)] }
|
|
41104
|
-
]
|
|
41105
|
-
}
|
|
41106
|
-
},
|
|
41107
|
-
{ json: options.json }
|
|
41108
|
-
);
|
|
41109
|
-
}
|
|
41110
|
-
async function handleUnlink(id, options) {
|
|
41111
|
-
const { http } = getAuthedHttpClient();
|
|
41112
|
-
await http.delete(`/api/v2/play-projects/${encodeURIComponent(id)}`);
|
|
41113
|
-
printCommandEnvelope(
|
|
41114
|
-
{
|
|
41115
|
-
ok: true,
|
|
41116
|
-
id,
|
|
41117
|
-
render: {
|
|
41118
|
-
sections: [
|
|
41119
|
-
{
|
|
41120
|
-
title: "unlinked",
|
|
41121
|
-
lines: [
|
|
41122
|
-
`Repository link ${id} removed. Deployments stop immediately and in-flight deploy credentials die; live plays keep running.`
|
|
41123
|
-
]
|
|
41124
|
-
}
|
|
41125
|
-
]
|
|
41126
|
-
}
|
|
41127
|
-
},
|
|
41128
|
-
{ json: options.json }
|
|
41129
|
-
);
|
|
41130
|
-
}
|
|
41131
|
-
async function handleConnect(options) {
|
|
41132
|
-
const baseUrl = resolveBaseUrlOnly();
|
|
41133
|
-
const connectUrl = `${baseUrl.replace(/\/$/, "")}/api/v2/github/connect`;
|
|
41134
|
-
const opened = openInBrowser(connectUrl);
|
|
41135
|
-
printCommandEnvelope(
|
|
41136
|
-
{
|
|
41137
|
-
connectUrl,
|
|
41138
|
-
browser: opened,
|
|
41139
|
-
render: {
|
|
41140
|
-
sections: [
|
|
41141
|
-
{
|
|
41142
|
-
title: "connect GitHub",
|
|
41143
|
-
lines: [
|
|
41144
|
-
opened === "opened" ? `Opened ${connectUrl} in your browser.` : `Open ${connectUrl} in your browser.`,
|
|
41145
|
-
"Sign in as a workspace admin if prompted, approve the GitHub",
|
|
41146
|
-
"installation, then return here and run `deepline git repos`."
|
|
41147
|
-
]
|
|
41148
|
-
}
|
|
41149
|
-
]
|
|
41150
|
-
}
|
|
41151
|
-
},
|
|
41152
|
-
{ json: options.json }
|
|
41153
|
-
);
|
|
41154
|
-
}
|
|
41155
|
-
async function handleDeploymentsList(options) {
|
|
41156
|
-
const { http } = getAuthedHttpClient();
|
|
41157
|
-
const query = new URLSearchParams();
|
|
41158
|
-
if (options.repo) query.set("projectId", options.repo);
|
|
41159
|
-
if (options.limit) query.set("limit", options.limit);
|
|
41160
|
-
const suffix = query.size > 0 ? `?${query.toString()}` : "";
|
|
41161
|
-
const payload = await http.get(
|
|
41162
|
-
`/api/v2/deployments${suffix}`
|
|
41163
|
-
);
|
|
41164
|
-
printCommandEnvelope(
|
|
41165
|
-
{
|
|
41166
|
-
deployments: payload.deployments,
|
|
41167
|
-
count: payload.deployments.length,
|
|
41168
|
-
render: {
|
|
41169
|
-
sections: [
|
|
41170
|
-
{
|
|
41171
|
-
title: "deployments",
|
|
41172
|
-
lines: payload.deployments.length ? payload.deployments.map(renderDeployment) : [
|
|
41173
|
-
"No deployments yet. Push to a linked repository to create one."
|
|
41174
|
-
]
|
|
41175
|
-
}
|
|
41176
|
-
]
|
|
41177
|
-
}
|
|
41178
|
-
},
|
|
41179
|
-
{ json: options.json }
|
|
41180
|
-
);
|
|
41181
|
-
}
|
|
41182
|
-
async function handleDeploymentGet(id, options) {
|
|
41183
|
-
const { http } = getAuthedHttpClient();
|
|
41184
|
-
const payload = await http.get(`/api/v2/deployments/${encodeURIComponent(id)}`);
|
|
41185
|
-
const results = payload.deployment.results;
|
|
41186
|
-
const playLines = Array.isArray(results?.plays) ? results.plays.map(
|
|
41187
|
-
(play) => `${play.name ?? "?"} - ${play.status ?? "?"}${play.error ? `: ${play.error}` : ""}`
|
|
41188
|
-
) : [];
|
|
41189
|
-
printCommandEnvelope(
|
|
41190
|
-
{
|
|
41191
|
-
deployment: payload.deployment,
|
|
41192
|
-
project: payload.project,
|
|
41193
|
-
render: {
|
|
41194
|
-
sections: [
|
|
41195
|
-
{
|
|
41196
|
-
title: `deployment ${payload.deployment.id}${payload.project ? ` (${payload.project.repoFullName})` : ""}`,
|
|
41197
|
-
lines: [renderDeployment(payload.deployment)]
|
|
41198
|
-
},
|
|
41199
|
-
...playLines.length ? [{ title: "plays", lines: playLines }] : []
|
|
41200
|
-
]
|
|
41201
|
-
}
|
|
41202
|
-
},
|
|
41203
|
-
{ json: options.json }
|
|
41204
|
-
);
|
|
41205
|
-
}
|
|
41206
|
-
async function handleDeploymentCancel(id, options) {
|
|
41207
|
-
const { http } = getAuthedHttpClient();
|
|
41208
|
-
const payload = await http.post(`/api/v2/deployments/${encodeURIComponent(id)}/cancel`, {});
|
|
41209
|
-
printCommandEnvelope(
|
|
41210
|
-
{
|
|
41211
|
-
cancelled: payload.cancelled,
|
|
41212
|
-
deployment: payload.deployment,
|
|
41213
|
-
render: {
|
|
41214
|
-
sections: [
|
|
41215
|
-
{
|
|
41216
|
-
title: payload.cancelled ? "cancelled" : "already cancelled",
|
|
41217
|
-
lines: [
|
|
41218
|
-
payload.deployment ? renderDeployment(payload.deployment) : `Deployment ${id} cancelled.`,
|
|
41219
|
-
"The build stops at its next step and nothing from it goes live."
|
|
41220
|
-
]
|
|
41221
|
-
}
|
|
41222
|
-
]
|
|
41223
|
-
}
|
|
41224
|
-
},
|
|
41225
|
-
{ json: options.json }
|
|
41226
|
-
);
|
|
41227
|
-
}
|
|
41228
|
-
function registerGitCommands(program) {
|
|
41229
|
-
const git = program.command("git", { hidden: !cliFeatureEnabled(GIT_DEPLOY_FEATURE) }).alias("projects").description(
|
|
41230
|
-
"Git deploys: link repositories to this workspace and deploy plays on push."
|
|
41231
|
-
).addHelpText(
|
|
41232
|
-
"after",
|
|
41233
|
-
`
|
|
41234
|
-
Examples:
|
|
41235
|
-
deepline git connect
|
|
41236
|
-
deepline git repos
|
|
41237
|
-
deepline git link acme/growth --branch main
|
|
41238
|
-
deepline git list
|
|
41239
|
-
deepline git set <id> --branch release
|
|
41240
|
-
deepline git unlink <id>
|
|
41241
|
-
deepline git deployments --repo <id>
|
|
41242
|
-
deepline git cancel <deployment-id>
|
|
41243
|
-
`
|
|
41244
|
-
);
|
|
41245
|
-
git.command("connect").description("Connect a GitHub installation (browser step).").option("--json", "Emit JSON output").action(async (options) => handleConnect(options));
|
|
41246
|
-
git.command("status").description(
|
|
41247
|
-
"Show the workspace's GitHub installation and whether it is still usable."
|
|
41248
|
-
).option("--json", "Emit JSON output").action(async (options) => handleStatus2(options));
|
|
41249
|
-
git.command("repos").description("List repos the workspace's GitHub installation can reach.").option(
|
|
41250
|
-
"--installation <id>",
|
|
41251
|
-
"GitHub installation id (required when several are connected)"
|
|
41252
|
-
).option("--json", "Emit JSON output").action(
|
|
41253
|
-
async (options) => handleRepos(options)
|
|
41254
|
-
);
|
|
41255
|
-
git.command("list").description("List linked repositories.").option("--all", "Include unlinked repositories").option("--json", "Emit JSON output").action(
|
|
41256
|
-
async (options) => handleList(options)
|
|
41257
|
-
);
|
|
41258
|
-
git.command("link").description("Link a repository to this workspace for deploy-on-push.").argument("<repo>", "Repo full name (owner/name) or numeric repo id").option("--root-dir <path>", "Base path inside the repo for this link").option("--branch <name>", "Production branch (default: repo default)").option(
|
|
41259
|
-
"--manifest <file>",
|
|
41260
|
-
"Manifest file name under the base path (default: deepline.json)"
|
|
41261
|
-
).option(
|
|
41262
|
-
"--installation <id>",
|
|
41263
|
-
"GitHub installation id (required when several are connected)"
|
|
41264
|
-
).option("--no-pr-checks", "Skip Check Runs on pull requests").option("--json", "Emit JSON output").action(
|
|
41265
|
-
async (repo, options) => handleLink(repo, options)
|
|
41266
|
-
);
|
|
41267
|
-
git.command("get").description("Show one linked repository.").argument("<id>", "Repository link id").option("--json", "Emit JSON output").action(async (id, options) => handleGet(id, options));
|
|
41268
|
-
git.command("set").description("Update a linked repository.").argument("<id>", "Repository link id").option("--branch <name>", "Production branch").option("--root-dir <path>", "Base path inside the repo for this link").option(
|
|
41269
|
-
"--manifest <file>",
|
|
41270
|
-
"Manifest file name under the base path (default: deepline.json)"
|
|
41271
|
-
).option("--pr-checks", "Enable Check Runs on pull requests").option("--no-pr-checks", "Disable Check Runs on pull requests").option("--disabled", "Pause deployments for this link").option("--enabled", "Resume deployments for this link").option("--json", "Emit JSON output").action(
|
|
41272
|
-
async (id, options) => handleSet(id, {
|
|
41273
|
-
...options,
|
|
41274
|
-
disabled: options.enabled === true ? false : options.disabled === true ? true : void 0
|
|
41275
|
-
})
|
|
41276
|
-
);
|
|
41277
|
-
git.command("unlink").description("Unlink a repository (live plays keep running).").argument("<id>", "Repository link id").option("--json", "Emit JSON output").action(
|
|
41278
|
-
async (id, options) => handleUnlink(id, options)
|
|
41279
|
-
);
|
|
41280
|
-
git.command("deployments").description("Deployment history; pass an id for one deployment.").argument("[id]", "Deployment id (omit to list)").option("--repo <id>", "Filter to one repository link").option("--limit <n>", "Max rows (default 50)").option("--json", "Emit JSON output").action(
|
|
41281
|
-
async (id, options) => id ? handleDeploymentGet(id, options) : handleDeploymentsList(options)
|
|
41282
|
-
);
|
|
41283
|
-
git.command("cancel").description(
|
|
41284
|
-
"Cancel a queued or running deployment before its plays go live (admin)."
|
|
41285
|
-
).argument("<id>", "Deployment id").option("--json", "Emit JSON output").action(
|
|
41286
|
-
async (id, options) => handleDeploymentCancel(id, options)
|
|
41287
|
-
);
|
|
41288
|
-
const deployments = program.command("deployments", { hidden: true });
|
|
41289
|
-
deployments.command("list").option("--project <id>", "Filter to one repository link").option("--limit <n>", "Max rows (default 50)").option("--json", "Emit JSON output").action(
|
|
41290
|
-
async (options) => handleDeploymentsList({ ...options, repo: options.project })
|
|
41291
|
-
);
|
|
41292
|
-
deployments.command("get").argument("<id>", "Deployment id").option("--json", "Emit JSON output").action(
|
|
41293
|
-
async (id, options) => handleDeploymentGet(id, options)
|
|
41294
|
-
);
|
|
41295
|
-
}
|
|
41296
|
-
|
|
41297
41344
|
// src/cli/getting-started.ts
|
|
41298
41345
|
var DEEPLINE_GTM_SKILL = "/deepline-gtm";
|
|
41299
41346
|
var DEEPLINE_GTM_STARTER_PROMPTS = [
|
|
@@ -41388,6 +41435,33 @@ function normalizeSecretName(value) {
|
|
|
41388
41435
|
}
|
|
41389
41436
|
return normalized;
|
|
41390
41437
|
}
|
|
41438
|
+
function normalizePlaySelector(value) {
|
|
41439
|
+
const normalized = value?.trim();
|
|
41440
|
+
if (value !== void 0 && !normalized) {
|
|
41441
|
+
throw new Error("--play requires a bare Play name.");
|
|
41442
|
+
}
|
|
41443
|
+
if (!normalized) return void 0;
|
|
41444
|
+
if (normalized.includes("/")) {
|
|
41445
|
+
throw new Error(
|
|
41446
|
+
"--play expects the bare Play name, not an org-qualified name."
|
|
41447
|
+
);
|
|
41448
|
+
}
|
|
41449
|
+
return normalized;
|
|
41450
|
+
}
|
|
41451
|
+
function resolveSecretWriteScope(options) {
|
|
41452
|
+
const playName = normalizePlaySelector(options.play);
|
|
41453
|
+
if (options.scope && options.scope !== "org" && options.scope !== "play") {
|
|
41454
|
+
throw new Error("--scope must be either org or play.");
|
|
41455
|
+
}
|
|
41456
|
+
const scope = options.scope === void 0 ? playName ? "play" : "org" : options.scope;
|
|
41457
|
+
if (scope === "play" && !playName) {
|
|
41458
|
+
throw new Error("--play <name> is required when --scope play is used.");
|
|
41459
|
+
}
|
|
41460
|
+
if (scope === "org" && playName) {
|
|
41461
|
+
throw new Error("--play can only be used with --scope play.");
|
|
41462
|
+
}
|
|
41463
|
+
return scope === "play" ? { scope, playName } : { scope };
|
|
41464
|
+
}
|
|
41391
41465
|
function renderSecret(secret) {
|
|
41392
41466
|
const scope = secret.scope === "play" && secret.playName ? `play:${secret.playName}` : secret.scope;
|
|
41393
41467
|
const added = new Date(secret.createdAt).toISOString();
|
|
@@ -41557,7 +41631,8 @@ async function handleList2(options) {
|
|
|
41557
41631
|
async function handleCheck(nameInput, options) {
|
|
41558
41632
|
const name = normalizeSecretName(nameInput);
|
|
41559
41633
|
const client2 = new DeeplineClient();
|
|
41560
|
-
const
|
|
41634
|
+
const playName = options.play === void 0 ? void 0 : normalizePlaySelector(options.play);
|
|
41635
|
+
const check = playName !== void 0 ? await client2.inspectSecret(name, { playName }) : null;
|
|
41561
41636
|
const secret = check ? check.secret : await client2.checkSecret(name);
|
|
41562
41637
|
const ok = check ? check.ok : Boolean(secret);
|
|
41563
41638
|
const quotedPlay = `'${(options.play ?? "PLAY").replace(/'/g, `'"'"'`)}'`;
|
|
@@ -41588,11 +41663,7 @@ async function handleCheck(nameInput, options) {
|
|
|
41588
41663
|
async function handleSet2(nameInput, forbidden, options) {
|
|
41589
41664
|
preventShellHistoryLeak(forbidden);
|
|
41590
41665
|
const name = normalizeSecretName(nameInput);
|
|
41591
|
-
const
|
|
41592
|
-
const playName = options.play?.trim();
|
|
41593
|
-
if (scope === "play" && !playName) {
|
|
41594
|
-
throw new Error("--play <name> is required when --scope play is used.");
|
|
41595
|
-
}
|
|
41666
|
+
const { scope, playName } = resolveSecretWriteScope(options);
|
|
41596
41667
|
const value = await readSecretValueFromOptions(options);
|
|
41597
41668
|
const { http } = getAuthedHttpClient();
|
|
41598
41669
|
const response = await http.post(
|
|
@@ -41684,7 +41755,8 @@ Notes:
|
|
|
41684
41755
|
Secret values are never accepted as command arguments. Use the hidden prompt,
|
|
41685
41756
|
or one explicit non-argv source: --value-stdin, --from-env NAME, or
|
|
41686
41757
|
--from-file PATH. Values are never printed. secrets list shows only metadata,
|
|
41687
|
-
including any note you intentionally added.
|
|
41758
|
+
including any note you intentionally added. Supplying --play implies
|
|
41759
|
+
--scope play; --play expects the bare Play name in the current workspace.
|
|
41688
41760
|
|
|
41689
41761
|
Examples:
|
|
41690
41762
|
deepline secrets list
|
|
@@ -41710,7 +41782,7 @@ Examples:
|
|
|
41710
41782
|
).option("--json", "Emit JSON output").action(async (name, options) => {
|
|
41711
41783
|
await handleCheck(name, options);
|
|
41712
41784
|
});
|
|
41713
|
-
secrets.command("set").description("Set or rotate a secret without exposing its value in argv.").argument("<name>", "Secret name").argument("[forbidden...]", "Do not pass secret values here").option("--json", "Emit JSON output").option("--scope <scope>", "Secret scope: org or play
|
|
41785
|
+
secrets.command("set").description("Set or rotate a secret without exposing its value in argv.").argument("<name>", "Secret name").argument("[forbidden...]", "Do not pass secret values here").option("--json", "Emit JSON output").option("--scope <scope>", "Secret scope: org or play; --play implies play").option("--play <name>", "Play name for play-scoped secrets").option(
|
|
41714
41786
|
"--note <note>",
|
|
41715
41787
|
"Optional non-sensitive memo (maximum 500 characters)"
|
|
41716
41788
|
).option("--value-stdin", "Read the value from piped stdin").option("--from-env <name>", "Read the value from an environment variable").option("--from-file <path>", "Read the value from a file").action(
|
|
@@ -42347,7 +42419,7 @@ async function maybeReportSdkCliFailure(input2) {
|
|
|
42347
42419
|
// src/cli/skills-sync.ts
|
|
42348
42420
|
var CHECK_TIMEOUT_MS2 = 3e3;
|
|
42349
42421
|
function shouldSkipSkillsSync() {
|
|
42350
|
-
if (detectAgentRuntime() === "claude_cowork") {
|
|
42422
|
+
if (detectAgentRuntime() === "claude_cowork" || isCiEnvironment()) {
|
|
42351
42423
|
return true;
|
|
42352
42424
|
}
|
|
42353
42425
|
const value = process.env.DEEPLINE_SKIP_SKILLS_SYNC?.trim().toLowerCase();
|
|
@@ -49809,11 +49881,8 @@ function envTruthy(name) {
|
|
|
49809
49881
|
const value = process.env[name]?.trim().toLowerCase();
|
|
49810
49882
|
return value === "1" || value === "true" || value === "yes";
|
|
49811
49883
|
}
|
|
49812
|
-
function isCi() {
|
|
49813
|
-
return envTruthy("CI") || envTruthy("GITHUB_ACTIONS");
|
|
49814
|
-
}
|
|
49815
49884
|
function shouldSkipSelfUpdate() {
|
|
49816
|
-
return envTruthy("DEEPLINE_SKIP_SELF_UPDATE") || envTruthy("DEEPLINE_NO_AUTO_UPDATE") || envTruthy("DEEPLINE_SKIP_SDK_AUTO_UPDATE") || envTruthy("DEEPLINE_DISABLE_AUTO_UPDATE") || !shouldRunCliAutoUpdate() ||
|
|
49885
|
+
return envTruthy("DEEPLINE_SKIP_SELF_UPDATE") || envTruthy("DEEPLINE_NO_AUTO_UPDATE") || envTruthy("DEEPLINE_SKIP_SDK_AUTO_UPDATE") || envTruthy("DEEPLINE_DISABLE_AUTO_UPDATE") || !shouldRunCliAutoUpdate() || isCiEnvironment();
|
|
49817
49886
|
}
|
|
49818
49887
|
function parseSemver(version) {
|
|
49819
49888
|
const trimmed = version?.trim();
|