@h-rig/cli 0.0.6-alpha.13 → 0.0.6-alpha.14
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/bin/rig.js +710 -226
- package/dist/src/commands/_doctor-checks.js +7 -20
- package/dist/src/commands/_operator-surface.js +157 -0
- package/dist/src/commands/_operator-view.js +160 -51
- package/dist/src/commands/_preflight.js +30 -26
- package/dist/src/commands/_server-client.js +46 -22
- package/dist/src/commands/_snapshot-upload.js +7 -20
- package/dist/src/commands/_task-picker.js +21 -13
- package/dist/src/commands/agent.js +1 -0
- package/dist/src/commands/doctor.js +7 -20
- package/dist/src/commands/github.js +9 -22
- package/dist/src/commands/init.js +183 -44
- package/dist/src/commands/queue.js +1 -0
- package/dist/src/commands/run.js +172 -76
- package/dist/src/commands/server.js +7 -20
- package/dist/src/commands/setup.js +7 -20
- package/dist/src/commands/task-run-driver.js +446 -53
- package/dist/src/commands/task.js +231 -98
- package/dist/src/commands.js +702 -218
- package/dist/src/index.js +710 -226
- package/package.json +5 -5
|
@@ -3,7 +3,7 @@ var __require = import.meta.require;
|
|
|
3
3
|
|
|
4
4
|
// packages/cli/src/commands/init.ts
|
|
5
5
|
import { appendFileSync, existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
6
|
-
import { spawnSync
|
|
6
|
+
import { spawnSync } from "child_process";
|
|
7
7
|
import { resolve as resolve6 } from "path";
|
|
8
8
|
|
|
9
9
|
// packages/cli/src/runner.ts
|
|
@@ -49,6 +49,7 @@ function takeOption(args, option) {
|
|
|
49
49
|
|
|
50
50
|
// packages/cli/src/commands/init.ts
|
|
51
51
|
import { buildRigInitConfigSource } from "@rig/core";
|
|
52
|
+
import { listGitHubProjects as listGitHubProjectsDirect, resolveProjectStatusField as resolveProjectStatusFieldDirect } from "@rig/server";
|
|
52
53
|
|
|
53
54
|
// packages/cli/src/commands/_connection-state.ts
|
|
54
55
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
@@ -153,17 +154,17 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
153
154
|
}
|
|
154
155
|
|
|
155
156
|
// packages/cli/src/commands/_server-client.ts
|
|
156
|
-
import { spawnSync } from "child_process";
|
|
157
157
|
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
|
|
158
158
|
import { resolve as resolve2 } from "path";
|
|
159
159
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
160
|
-
var
|
|
160
|
+
var scopedGitHubBearerTokens = new Map;
|
|
161
161
|
function cleanToken(value) {
|
|
162
162
|
const trimmed = value?.trim();
|
|
163
163
|
return trimmed ? trimmed : null;
|
|
164
164
|
}
|
|
165
|
-
function setGitHubBearerTokenForCurrentProcess(token) {
|
|
166
|
-
|
|
165
|
+
function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
|
|
166
|
+
const scopedKey = resolve2(projectRoot ?? process.cwd());
|
|
167
|
+
scopedGitHubBearerTokens.set(scopedKey, cleanToken(token ?? undefined));
|
|
167
168
|
}
|
|
168
169
|
function readPrivateRemoteSessionToken(projectRoot) {
|
|
169
170
|
const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
|
|
@@ -177,25 +178,13 @@ function readPrivateRemoteSessionToken(projectRoot) {
|
|
|
177
178
|
}
|
|
178
179
|
}
|
|
179
180
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
180
|
-
|
|
181
|
-
|
|
181
|
+
const scopedKey = resolve2(projectRoot);
|
|
182
|
+
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
183
|
+
return scopedGitHubBearerTokens.get(scopedKey) ?? null;
|
|
182
184
|
const privateSession = readPrivateRemoteSessionToken(projectRoot);
|
|
183
|
-
if (privateSession)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
const envToken = cleanToken(process.env.RIG_GITHUB_TOKEN) ?? cleanToken(process.env.GITHUB_TOKEN) ?? cleanToken(process.env.GH_TOKEN);
|
|
188
|
-
if (envToken) {
|
|
189
|
-
cachedGitHubBearerToken = envToken;
|
|
190
|
-
return cachedGitHubBearerToken;
|
|
191
|
-
}
|
|
192
|
-
const result = spawnSync("gh", ["auth", "token"], {
|
|
193
|
-
encoding: "utf8",
|
|
194
|
-
timeout: 5000,
|
|
195
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
196
|
-
});
|
|
197
|
-
cachedGitHubBearerToken = result.status === 0 ? cleanToken(result.stdout) : null;
|
|
198
|
-
return cachedGitHubBearerToken;
|
|
185
|
+
if (privateSession)
|
|
186
|
+
return privateSession;
|
|
187
|
+
return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
|
|
199
188
|
}
|
|
200
189
|
async function ensureServerForCli(projectRoot) {
|
|
201
190
|
try {
|
|
@@ -337,6 +326,20 @@ async function switchServerProjectRootViaServer(context, projectRoot, options =
|
|
|
337
326
|
}
|
|
338
327
|
throw new CliError2(`Rig server did not switch to ${projectRoot} before timeout (${lastError instanceof Error ? lastError.message : String(lastError ?? "no status")}).`, 1);
|
|
339
328
|
}
|
|
329
|
+
async function ensureTaskLabelsViaServer(context) {
|
|
330
|
+
const payload = await requestServerJson(context, "/api/workspace/task-labels", { method: "POST" });
|
|
331
|
+
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
332
|
+
}
|
|
333
|
+
async function listGitHubProjectsViaServer(context, owner) {
|
|
334
|
+
const url = new URL("http://rig.local/api/github/projects");
|
|
335
|
+
url.searchParams.set("owner", owner);
|
|
336
|
+
const payload = await requestServerJson(context, `${url.pathname}${url.search}`);
|
|
337
|
+
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : { projects: [] };
|
|
338
|
+
}
|
|
339
|
+
async function getGitHubProjectStatusFieldViaServer(context, projectId) {
|
|
340
|
+
const payload = await requestServerJson(context, `/api/github/projects/${encodeURIComponent(projectId)}/status-field`);
|
|
341
|
+
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
342
|
+
}
|
|
340
343
|
|
|
341
344
|
// packages/cli/src/commands/_pi-install.ts
|
|
342
345
|
import { existsSync as existsSync3, readFileSync as readFileSync3, rmSync } from "fs";
|
|
@@ -839,7 +842,7 @@ function parseRepoSlugFromRemote(remoteUrl) {
|
|
|
839
842
|
return gitHubMatch ? `${gitHubMatch[1]}/${gitHubMatch[2]}` : null;
|
|
840
843
|
}
|
|
841
844
|
function detectOriginRepoSlug(projectRoot) {
|
|
842
|
-
const result =
|
|
845
|
+
const result = spawnSync("git", ["-C", projectRoot, "remote", "get-url", "origin"], { encoding: "utf8" });
|
|
843
846
|
if (result.status !== 0)
|
|
844
847
|
return null;
|
|
845
848
|
return parseRepoSlugFromRemote(result.stdout.trim());
|
|
@@ -895,11 +898,14 @@ function applyGitHubProjectConfig(source, options) {
|
|
|
895
898
|
return source;
|
|
896
899
|
const projectId = JSON.stringify(options.githubProject);
|
|
897
900
|
const statusFieldId = JSON.stringify(options.githubProjectStatusField ?? "Status");
|
|
901
|
+
const statuses = options.githubProjectStatuses && Object.keys(options.githubProjectStatuses).length > 0 ? `
|
|
902
|
+
statuses: ${JSON.stringify(options.githubProjectStatuses, null, 8).replace(/\n/g, `
|
|
903
|
+
`)},` : "";
|
|
898
904
|
return source.replace(` projects: { enabled: false },`, [
|
|
899
905
|
` projects: {`,
|
|
900
906
|
` enabled: true,`,
|
|
901
907
|
` projectId: ${projectId},`,
|
|
902
|
-
` statusFieldId: ${statusFieldId}
|
|
908
|
+
` statusFieldId: ${statusFieldId},${statuses}`,
|
|
903
909
|
` },`
|
|
904
910
|
].join(`
|
|
905
911
|
`));
|
|
@@ -920,11 +926,11 @@ function checkoutForInit(projectRoot, serverKind, strategy) {
|
|
|
920
926
|
}
|
|
921
927
|
}
|
|
922
928
|
function detectGhLogin() {
|
|
923
|
-
const result =
|
|
929
|
+
const result = spawnSync("gh", ["api", "user", "--jq", ".login"], { encoding: "utf8", timeout: 5000, stdio: ["ignore", "pipe", "ignore"] });
|
|
924
930
|
return result.status === 0 && result.stdout.trim() ? result.stdout.trim() : null;
|
|
925
931
|
}
|
|
926
932
|
function readGhAuthToken() {
|
|
927
|
-
const result =
|
|
933
|
+
const result = spawnSync("gh", ["auth", "token"], { encoding: "utf8" });
|
|
928
934
|
if (result.status !== 0 || !result.stdout.trim()) {
|
|
929
935
|
throw new CliError2(result.stderr.trim() || "Could not read GitHub token from `gh auth token`.", result.status || 1);
|
|
930
936
|
}
|
|
@@ -933,8 +939,15 @@ function readGhAuthToken() {
|
|
|
933
939
|
async function loadClackPrompts() {
|
|
934
940
|
return await import("@clack/prompts");
|
|
935
941
|
}
|
|
942
|
+
function clackTextOptions(options) {
|
|
943
|
+
return {
|
|
944
|
+
message: options.message,
|
|
945
|
+
...options.placeholder ? { placeholder: options.placeholder } : {},
|
|
946
|
+
...(options.initialValue ?? options.defaultValue)?.trim() ? { initialValue: (options.initialValue ?? options.defaultValue).trim() } : {}
|
|
947
|
+
};
|
|
948
|
+
}
|
|
936
949
|
async function promptRequiredText(prompts, options) {
|
|
937
|
-
const value = await prompts.text(options);
|
|
950
|
+
const value = await prompts.text(clackTextOptions(options));
|
|
938
951
|
if (prompts.isCancel(value))
|
|
939
952
|
throw new CliError2("Init cancelled.", 1);
|
|
940
953
|
const text = String(value ?? "").trim();
|
|
@@ -943,7 +956,7 @@ async function promptRequiredText(prompts, options) {
|
|
|
943
956
|
return text;
|
|
944
957
|
}
|
|
945
958
|
async function promptOptionalText(prompts, options) {
|
|
946
|
-
const value = await prompts.text(options);
|
|
959
|
+
const value = await prompts.text(clackTextOptions(options));
|
|
947
960
|
if (prompts.isCancel(value))
|
|
948
961
|
throw new CliError2("Init cancelled.", 1);
|
|
949
962
|
return String(value ?? "").trim();
|
|
@@ -954,6 +967,132 @@ async function promptSelect(prompts, options) {
|
|
|
954
967
|
throw new CliError2("Init cancelled.", 1);
|
|
955
968
|
return String(value);
|
|
956
969
|
}
|
|
970
|
+
function repoOwnerFromSlug(repoSlug) {
|
|
971
|
+
return repoSlug.trim().match(/^([^/]+)\/[^/]+$/)?.[1] ?? null;
|
|
972
|
+
}
|
|
973
|
+
function recordArray(value, key) {
|
|
974
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
975
|
+
return [];
|
|
976
|
+
const raw = value[key];
|
|
977
|
+
return Array.isArray(raw) ? raw.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))) : [];
|
|
978
|
+
}
|
|
979
|
+
async function listGitHubProjectsForInit(context, owner, token) {
|
|
980
|
+
if (token?.trim()) {
|
|
981
|
+
try {
|
|
982
|
+
return { ok: true, projects: await listGitHubProjectsDirect({ owner, token: token.trim() }) };
|
|
983
|
+
} catch (directError) {
|
|
984
|
+
const serverPayload = await listGitHubProjectsViaServer(context, owner).catch(() => null);
|
|
985
|
+
if (recordArray(serverPayload, "projects").length > 0)
|
|
986
|
+
return serverPayload;
|
|
987
|
+
return { ok: false, error: directError instanceof Error ? directError.message : String(directError), projects: [] };
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
return listGitHubProjectsViaServer(context, owner);
|
|
991
|
+
}
|
|
992
|
+
async function getGitHubProjectStatusFieldForInit(context, projectId, token) {
|
|
993
|
+
if (token?.trim()) {
|
|
994
|
+
try {
|
|
995
|
+
return { ok: true, field: await resolveProjectStatusFieldDirect({ projectId, token: token.trim() }) };
|
|
996
|
+
} catch (directError) {
|
|
997
|
+
const serverPayload = await getGitHubProjectStatusFieldViaServer(context, projectId).catch(() => null);
|
|
998
|
+
if (serverPayload && typeof serverPayload === "object" && !Array.isArray(serverPayload) && "field" in serverPayload) {
|
|
999
|
+
return serverPayload;
|
|
1000
|
+
}
|
|
1001
|
+
return { ok: false, error: directError instanceof Error ? directError.message : String(directError) };
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
return getGitHubProjectStatusFieldViaServer(context, projectId);
|
|
1005
|
+
}
|
|
1006
|
+
var PROJECT_STATUS_PROMPTS = {
|
|
1007
|
+
running: "Running/In progress",
|
|
1008
|
+
prOpen: "PR open/review",
|
|
1009
|
+
ciFixing: "CI/review fixing",
|
|
1010
|
+
merging: "Merging",
|
|
1011
|
+
done: "Done",
|
|
1012
|
+
needsAttention: "Needs attention"
|
|
1013
|
+
};
|
|
1014
|
+
var DEFAULT_PROJECT_STATUS_OPTIONS = {
|
|
1015
|
+
running: "In Progress",
|
|
1016
|
+
prOpen: "In Review",
|
|
1017
|
+
ciFixing: "In Review",
|
|
1018
|
+
merging: "Merging",
|
|
1019
|
+
done: "Done",
|
|
1020
|
+
needsAttention: "Needs Attention"
|
|
1021
|
+
};
|
|
1022
|
+
async function promptManualProjectStatusMapping(prompts) {
|
|
1023
|
+
const statuses = {};
|
|
1024
|
+
for (const [key, label] of Object.entries(PROJECT_STATUS_PROMPTS)) {
|
|
1025
|
+
const defaultLabel = DEFAULT_PROJECT_STATUS_OPTIONS[key] ?? label;
|
|
1026
|
+
const value = await promptOptionalText(prompts, {
|
|
1027
|
+
message: `Project status option id/name for ${label} (blank for ${defaultLabel})`,
|
|
1028
|
+
placeholder: defaultLabel
|
|
1029
|
+
});
|
|
1030
|
+
statuses[key] = value || defaultLabel;
|
|
1031
|
+
}
|
|
1032
|
+
return statuses;
|
|
1033
|
+
}
|
|
1034
|
+
async function promptGitHubProjectConfig(context, prompts, repoSlug, githubToken) {
|
|
1035
|
+
const projectChoice = await promptSelect(prompts, {
|
|
1036
|
+
message: "GitHub Projects status sync",
|
|
1037
|
+
options: [
|
|
1038
|
+
{ value: "off", label: "Off" },
|
|
1039
|
+
{ value: "select", label: "Select accessible ProjectV2" },
|
|
1040
|
+
{ value: "manual", label: "Enter ProjectV2 ids manually" }
|
|
1041
|
+
]
|
|
1042
|
+
});
|
|
1043
|
+
if (projectChoice === "off")
|
|
1044
|
+
return { githubProject: "off" };
|
|
1045
|
+
if (projectChoice === "manual") {
|
|
1046
|
+
return {
|
|
1047
|
+
githubProject: await promptRequiredText(prompts, { message: "GitHub ProjectV2 id", placeholder: "PVT_..." }),
|
|
1048
|
+
githubProjectStatusField: await promptRequiredText(prompts, { message: "Project Status field id", placeholder: "field_status" }),
|
|
1049
|
+
githubProjectStatuses: await promptManualProjectStatusMapping(prompts)
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1052
|
+
const owner = repoOwnerFromSlug(repoSlug);
|
|
1053
|
+
if (!owner)
|
|
1054
|
+
throw new CliError2(`Cannot derive GitHub owner from repo slug ${repoSlug}.`, 1);
|
|
1055
|
+
const projectsPayload = await listGitHubProjectsForInit(context, owner, githubToken).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error), projects: [] }));
|
|
1056
|
+
const projects = recordArray(projectsPayload, "projects");
|
|
1057
|
+
if (projects.length === 0) {
|
|
1058
|
+
const error = typeof projectsPayload.error === "string" ? ` (${projectsPayload.error})` : "";
|
|
1059
|
+
prompts.outro?.(`No accessible GitHub Projects were returned${error}; falling back to manual ProjectV2 ids.`);
|
|
1060
|
+
return {
|
|
1061
|
+
githubProject: await promptRequiredText(prompts, { message: "GitHub ProjectV2 id", placeholder: "PVT_..." }),
|
|
1062
|
+
githubProjectStatusField: await promptRequiredText(prompts, { message: "Project Status field id", placeholder: "field_status" }),
|
|
1063
|
+
githubProjectStatuses: await promptManualProjectStatusMapping(prompts)
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
const selectedProjectId = await promptSelect(prompts, {
|
|
1067
|
+
message: "GitHub ProjectV2 project",
|
|
1068
|
+
options: [
|
|
1069
|
+
...projects.map((project) => ({
|
|
1070
|
+
value: String(project.id),
|
|
1071
|
+
label: `${String(project.title ?? "Untitled project")} (#${String(project.number ?? "?")})`,
|
|
1072
|
+
hint: typeof project.url === "string" ? project.url : undefined
|
|
1073
|
+
})),
|
|
1074
|
+
{ value: "manual", label: "Enter ProjectV2 id manually" }
|
|
1075
|
+
]
|
|
1076
|
+
});
|
|
1077
|
+
const projectId = selectedProjectId === "manual" ? await promptRequiredText(prompts, { message: "GitHub ProjectV2 id", placeholder: "PVT_..." }) : selectedProjectId;
|
|
1078
|
+
const fieldPayload = await getGitHubProjectStatusFieldForInit(context, projectId, githubToken).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error) }));
|
|
1079
|
+
const fieldPayloadRecord = fieldPayload && typeof fieldPayload === "object" && !Array.isArray(fieldPayload) ? fieldPayload : {};
|
|
1080
|
+
const rawField = fieldPayloadRecord.field;
|
|
1081
|
+
const field = rawField && typeof rawField === "object" && !Array.isArray(rawField) ? rawField : null;
|
|
1082
|
+
const fieldId = typeof field?.id === "string" && field.id.trim() ? field.id : await promptRequiredText(prompts, { message: "Project Status field id", placeholder: "field_status" });
|
|
1083
|
+
const options = Array.isArray(field?.options) ? field.options.filter((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry))) : [];
|
|
1084
|
+
if (options.length === 0) {
|
|
1085
|
+
return { githubProject: projectId, githubProjectStatusField: fieldId, githubProjectStatuses: await promptManualProjectStatusMapping(prompts) };
|
|
1086
|
+
}
|
|
1087
|
+
const statuses = {};
|
|
1088
|
+
for (const [key, label] of Object.entries(PROJECT_STATUS_PROMPTS)) {
|
|
1089
|
+
statuses[key] = await promptSelect(prompts, {
|
|
1090
|
+
message: `Project status option for ${label}`,
|
|
1091
|
+
options: options.map((option) => ({ value: String(option.id ?? option.name), label: String(option.name ?? option.id) }))
|
|
1092
|
+
});
|
|
1093
|
+
}
|
|
1094
|
+
return { githubProject: projectId, githubProjectStatusField: fieldId, githubProjectStatuses: Object.keys(statuses).length > 0 ? statuses : undefined };
|
|
1095
|
+
}
|
|
957
1096
|
function sleep2(ms) {
|
|
958
1097
|
return new Promise((resolve7) => setTimeout(resolve7, ms));
|
|
959
1098
|
}
|
|
@@ -1082,7 +1221,7 @@ async function runControlPlaneInit(context, options) {
|
|
|
1082
1221
|
if (token) {
|
|
1083
1222
|
githubAuth = await postGitHubTokenViaServer(context, token, { selectedRepo: repo.slug });
|
|
1084
1223
|
const apiSessionToken = apiSessionTokenFrom(githubAuth);
|
|
1085
|
-
setGitHubBearerTokenForCurrentProcess(apiSessionToken ?? token);
|
|
1224
|
+
setGitHubBearerTokenForCurrentProcess(apiSessionToken ?? token, projectRoot);
|
|
1086
1225
|
if (serverKind === "remote") {
|
|
1087
1226
|
writeRemoteGitHubAuthState(projectRoot, {
|
|
1088
1227
|
source: authMethod === "gh" ? "gh" : "init-token",
|
|
@@ -1107,7 +1246,7 @@ async function runControlPlaneInit(context, options) {
|
|
|
1107
1246
|
if (completed) {
|
|
1108
1247
|
const apiSessionToken = apiSessionTokenFrom(completed);
|
|
1109
1248
|
if (apiSessionToken) {
|
|
1110
|
-
setGitHubBearerTokenForCurrentProcess(apiSessionToken);
|
|
1249
|
+
setGitHubBearerTokenForCurrentProcess(apiSessionToken, projectRoot);
|
|
1111
1250
|
if (serverKind === "remote") {
|
|
1112
1251
|
writeRemoteGitHubAuthState(projectRoot, { source: "device", selectedRepo: repo.slug, apiSessionToken, authPayload: completed });
|
|
1113
1252
|
}
|
|
@@ -1131,7 +1270,7 @@ async function runControlPlaneInit(context, options) {
|
|
|
1131
1270
|
if (serverKind === "remote" && checkoutPath && token) {
|
|
1132
1271
|
githubAuth = await postGitHubTokenViaServer(context, token, { selectedRepo: repo.slug, projectRoot: checkoutPath });
|
|
1133
1272
|
const apiSessionToken = apiSessionTokenFrom(githubAuth);
|
|
1134
|
-
setGitHubBearerTokenForCurrentProcess(apiSessionToken ?? token);
|
|
1273
|
+
setGitHubBearerTokenForCurrentProcess(apiSessionToken ?? token, projectRoot);
|
|
1135
1274
|
writeRemoteGitHubAuthState(projectRoot, { source: authMethod === "gh" ? "gh" : "init-token", selectedRepo: repo.slug, apiSessionToken, authPayload: githubAuth });
|
|
1136
1275
|
}
|
|
1137
1276
|
const registered = await registerProjectViaServer(context, {
|
|
@@ -1140,6 +1279,12 @@ async function runControlPlaneInit(context, options) {
|
|
|
1140
1279
|
});
|
|
1141
1280
|
const serverRootSwitch = serverKind === "remote" && checkoutPath ? await switchServerProjectRootViaServer(context, checkoutPath) : null;
|
|
1142
1281
|
const activeProjectRegistration = serverRootSwitch ? await registerProjectViaServer(context, { repoSlug: repo.slug, checkout }) : null;
|
|
1282
|
+
const labelSetup = await ensureTaskLabelsViaServer(context).catch((error) => ({
|
|
1283
|
+
ok: false,
|
|
1284
|
+
ready: false,
|
|
1285
|
+
labelsReady: false,
|
|
1286
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1287
|
+
}));
|
|
1143
1288
|
const pi = serverKind === "remote" ? await ensureRemotePiRigInstalled({ requestJson: (pathname, init) => requestServerJson(context, pathname, init) }).catch((error) => ({
|
|
1144
1289
|
remote: true,
|
|
1145
1290
|
pi: { ok: false, label: "pi", hint: error instanceof Error ? error.message : String(error) },
|
|
@@ -1170,6 +1315,7 @@ async function runControlPlaneInit(context, options) {
|
|
|
1170
1315
|
githubAuth,
|
|
1171
1316
|
deviceAuth,
|
|
1172
1317
|
githubAuthWarning: remoteGhTokenWarning,
|
|
1318
|
+
labelSetup,
|
|
1173
1319
|
pi,
|
|
1174
1320
|
doctor
|
|
1175
1321
|
};
|
|
@@ -1324,24 +1470,17 @@ async function runInteractiveControlPlaneInit(context, prompts) {
|
|
|
1324
1470
|
throw new CliError2("Remote gh-token import cancelled.", 1);
|
|
1325
1471
|
}
|
|
1326
1472
|
}
|
|
1327
|
-
const githubToken = authMethod === "token" ? await promptRequiredText(prompts, { message: "GitHub token", placeholder: "ghp_..." }) : undefined;
|
|
1328
|
-
const
|
|
1329
|
-
message: "GitHub Projects status sync",
|
|
1330
|
-
options: [
|
|
1331
|
-
{ value: "off", label: "Off" },
|
|
1332
|
-
{ value: "configure", label: "Configure ProjectV2 status field" }
|
|
1333
|
-
]
|
|
1334
|
-
});
|
|
1335
|
-
const githubProject = projectChoice === "configure" ? await promptRequiredText(prompts, { message: "GitHub ProjectV2 id", placeholder: "PVT_..." }) : "off";
|
|
1336
|
-
const githubProjectStatusField = projectChoice === "configure" ? await promptRequiredText(prompts, { message: "Project Status field id", placeholder: "field_status" }) : undefined;
|
|
1473
|
+
const githubToken = authMethod === "token" ? await promptRequiredText(prompts, { message: "GitHub token", placeholder: "ghp_..." }) : authMethod === "gh" ? readGhAuthToken() : undefined;
|
|
1474
|
+
const projectConfig = await promptGitHubProjectConfig(context, prompts, repoSlug, githubToken);
|
|
1337
1475
|
const result = await runControlPlaneInit(context, {
|
|
1338
1476
|
server: serverChoice,
|
|
1339
1477
|
remoteUrl,
|
|
1340
1478
|
repoSlug,
|
|
1341
1479
|
githubToken,
|
|
1342
1480
|
githubAuthMethod: authMethod,
|
|
1343
|
-
githubProject,
|
|
1344
|
-
githubProjectStatusField,
|
|
1481
|
+
githubProject: projectConfig.githubProject,
|
|
1482
|
+
githubProjectStatusField: projectConfig.githubProjectStatusField,
|
|
1483
|
+
githubProjectStatuses: projectConfig.githubProjectStatuses,
|
|
1345
1484
|
remoteCheckout,
|
|
1346
1485
|
repair,
|
|
1347
1486
|
privateStateOnly
|
|
@@ -90,6 +90,7 @@ import { ensureProjectMainFreshBeforeRun } from "@rig/runtime/control-plane/proj
|
|
|
90
90
|
|
|
91
91
|
// packages/cli/src/commands/_server-client.ts
|
|
92
92
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
93
|
+
var scopedGitHubBearerTokens = new Map;
|
|
93
94
|
|
|
94
95
|
// packages/cli/src/commands/_preflight.ts
|
|
95
96
|
async function runProjectMainSyncPreflight(context, options) {
|