carrick 0.3.61 → 0.3.63
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 +32 -12
- package/bin/carrick.mjs +7 -6
- package/dist/auth/read.d.ts +6 -6
- package/dist/contract.d.ts +102 -0
- package/dist/contract.js +22 -0
- package/dist/contract.js.map +1 -1
- package/dist/init/connect.d.ts +31 -2
- package/dist/init/connect.js +153 -29
- package/dist/init/connect.js.map +1 -1
- package/dist/init/projects.d.ts +110 -0
- package/dist/init/projects.js +162 -3
- package/dist/init/projects.js.map +1 -1
- package/dist/init/repos.d.ts +61 -7
- package/dist/init/repos.js +125 -31
- package/dist/init/repos.js.map +1 -1
- package/dist/init/run.d.ts +33 -2
- package/dist/init/run.js +227 -135
- package/dist/init/run.js.map +1 -1
- package/dist/render.d.ts +20 -8
- package/dist/render.js +65 -16
- package/dist/render.js.map +1 -1
- package/package.json +6 -6
package/dist/init/connect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/init/connect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAsB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../src/init/connect.ts"],"names":[],"mappings":"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"}
|
package/dist/init/projects.d.ts
CHANGED
|
@@ -17,6 +17,31 @@ declare const project: z.ZodObject<{
|
|
|
17
17
|
}>;
|
|
18
18
|
/** One project in the signed-in workspace. */
|
|
19
19
|
export type Project = z.infer<typeof project>;
|
|
20
|
+
/** What one repo's assignment did, as the server reports it (carrick#999). */
|
|
21
|
+
declare const placement: z.ZodObject<{
|
|
22
|
+
full_name: z.ZodString;
|
|
23
|
+
/** This repo is in the project now, including one that already was. */
|
|
24
|
+
assigned: z.ZodBoolean;
|
|
25
|
+
/** Whether a write happened. False for a repo that was already there. */
|
|
26
|
+
moved: z.ZodBoolean;
|
|
27
|
+
project_slug: z.ZodNullable<z.ZodString>;
|
|
28
|
+
/** Why this repo was not placed, as a sentence completing its name. */
|
|
29
|
+
reason: z.ZodNullable<z.ZodString>;
|
|
30
|
+
}, "strip", z.ZodTypeAny, {
|
|
31
|
+
full_name: string;
|
|
32
|
+
project_slug: string | null;
|
|
33
|
+
assigned: boolean;
|
|
34
|
+
moved: boolean;
|
|
35
|
+
reason: string | null;
|
|
36
|
+
}, {
|
|
37
|
+
full_name: string;
|
|
38
|
+
project_slug: string | null;
|
|
39
|
+
assigned: boolean;
|
|
40
|
+
moved: boolean;
|
|
41
|
+
reason: string | null;
|
|
42
|
+
}>;
|
|
43
|
+
/** One repo's outcome inside a successful `assign-repos` answer. */
|
|
44
|
+
export type Placement = z.infer<typeof placement>;
|
|
20
45
|
/** What a create attempt did. `absent` is "this server has no such action". */
|
|
21
46
|
export type CreateOutcome = {
|
|
22
47
|
kind: "created";
|
|
@@ -27,6 +52,23 @@ export type CreateOutcome = {
|
|
|
27
52
|
} | {
|
|
28
53
|
kind: "absent";
|
|
29
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* What an assignment attempt did.
|
|
57
|
+
*
|
|
58
|
+
* `placed` is a 200: the action ran, and every repo in it carries its own
|
|
59
|
+
* outcome. A repo the workspace does not hold, or one whose write failed, is
|
|
60
|
+
* reported there rather than as a refusal, so a partial result is read rather
|
|
61
|
+
* than discarded.
|
|
62
|
+
*/
|
|
63
|
+
export type AssignOutcome = {
|
|
64
|
+
kind: "placed";
|
|
65
|
+
repos: Placement[];
|
|
66
|
+
} | {
|
|
67
|
+
kind: "refused";
|
|
68
|
+
message: string;
|
|
69
|
+
} | {
|
|
70
|
+
kind: "absent";
|
|
71
|
+
};
|
|
30
72
|
/**
|
|
31
73
|
* Every project in the signed-in workspace, or null when this API has no such
|
|
32
74
|
* action. Throws only on 401.
|
|
@@ -41,6 +83,74 @@ export declare function listProjects(token: string, request?: typeof fetch, sign
|
|
|
41
83
|
* one it has to normalise silently into something the user did not ask for.
|
|
42
84
|
*/
|
|
43
85
|
export declare function createProject(token: string, slug: string, name?: string, request?: typeof fetch, signal?: AbortSignal): Promise<CreateOutcome>;
|
|
86
|
+
/**
|
|
87
|
+
* Put the named repos in the named project, where this API can do it.
|
|
88
|
+
*
|
|
89
|
+
* The second browser step this command used to end on: the GitHub App grant
|
|
90
|
+
* puts a newly connected repo in the workspace's default project, so a run
|
|
91
|
+
* started with `--project` sat waiting for someone to move it on the Repos
|
|
92
|
+
* page (carrick#999). The action is idempotent, which is what makes it safe
|
|
93
|
+
* to call from inside the polling loop as repos arrive from the grant.
|
|
94
|
+
*
|
|
95
|
+
* `absent` is the same wide condition the other two actions use: this client
|
|
96
|
+
* is published ahead of the deploy that serves the action, and until it lands
|
|
97
|
+
* the credential-kind gate answers first. The caller then prints the browser
|
|
98
|
+
* instruction it printed before.
|
|
99
|
+
*/
|
|
100
|
+
export declare function assignRepos(token: string, project: string, repos: string[], request?: typeof fetch, signal?: AbortSignal): Promise<AssignOutcome>;
|
|
101
|
+
/** The slug shape the dashboard enforces, applied before anything is sent. */
|
|
102
|
+
export declare const SLUG: RegExp;
|
|
103
|
+
/** What a project is, said once, above the picker that asks for one. */
|
|
104
|
+
export declare const PROJECT_RULE = "One project per interconnected system: repos that call each other belong together.";
|
|
105
|
+
/** What init asks the terminal during the project step. */
|
|
106
|
+
export type ProjectPrompts = {
|
|
107
|
+
say: (line: string) => void;
|
|
108
|
+
/** A free-text answer, already trimmed. Empty means "skip this". */
|
|
109
|
+
ask: (question: string) => Promise<string>;
|
|
110
|
+
confirm: (question: string) => Promise<boolean>;
|
|
111
|
+
interactive: boolean;
|
|
112
|
+
assumeYes: boolean;
|
|
113
|
+
list?: (token: string) => Promise<Project[] | null>;
|
|
114
|
+
create?: (token: string, slug: string) => Promise<CreateOutcome>;
|
|
115
|
+
};
|
|
116
|
+
/**
|
|
117
|
+
* The project these repos should be in, and whether this run can state that it
|
|
118
|
+
* exists.
|
|
119
|
+
*
|
|
120
|
+
* `slug: null` is the honest answer whenever the terminal could not settle it:
|
|
121
|
+
* an API without the project actions, a workspace whose repos are spread
|
|
122
|
+
* across projects with nobody at the keyboard, a declined offer. The caller
|
|
123
|
+
* then does what it did before this step existed — connect the repos and leave
|
|
124
|
+
* the project to the browser.
|
|
125
|
+
*/
|
|
126
|
+
export type ProjectChoice = {
|
|
127
|
+
slug: string | null;
|
|
128
|
+
exists: boolean;
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* Make sure a named project exists, from the terminal where that is possible.
|
|
132
|
+
*
|
|
133
|
+
* Returns whether this run can state that it exists. `false` covers every case
|
|
134
|
+
* it could not settle — an API without the actions, a declined offer, a
|
|
135
|
+
* refused create — and the caller then prints the browser instructions, which
|
|
136
|
+
* include creating it.
|
|
137
|
+
*/
|
|
138
|
+
export declare function ensureProject(token: string, slug: string, prompts: ProjectPrompts): Promise<boolean>;
|
|
139
|
+
/**
|
|
140
|
+
* The project step for a plain `carrick init`, with no `--project` to verify
|
|
141
|
+
* (carrick#987, decision record carrick-cloud#772 step 3).
|
|
142
|
+
*
|
|
143
|
+
* Without the flag this used to do nothing at all, so a first run never saw
|
|
144
|
+
* the workspace's projects and the repo silently stayed wherever the browser
|
|
145
|
+
* had put it. The order is: the assignment the repos already have, then the
|
|
146
|
+
* list, then a name the user types, which may be one that does not exist yet.
|
|
147
|
+
* Assignment itself is still the browser's, so everything settled here only
|
|
148
|
+
* removes a step from the wait.
|
|
149
|
+
*
|
|
150
|
+
* `current` is one entry per requested repo: the project it is in, or null
|
|
151
|
+
* when it is not connected to this workspace at all.
|
|
152
|
+
*/
|
|
153
|
+
export declare function projectStep(token: string, current: Array<string | null>, prompts: ProjectPrompts): Promise<ProjectChoice>;
|
|
44
154
|
/** The list as init prints it: one line per project, active ones first. */
|
|
45
155
|
export declare function projectLines(projects: Project[]): string[];
|
|
46
156
|
export {};
|
package/dist/init/projects.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
// Listing and
|
|
1
|
+
// Listing, creating and filling Carrick projects from the terminal
|
|
2
|
+
// (carrick#955, carrick#999).
|
|
2
3
|
//
|
|
3
4
|
// `carrick init --project <slug>` could only ever point at a browser: the
|
|
4
5
|
// workspace read (`resolve-repos`) returns the projects the named repos are
|
|
5
|
-
// already in, never the workspace's project list, and creation
|
|
6
|
-
// the dashboard. These
|
|
6
|
+
// already in, never the workspace's project list, and creation and assignment
|
|
7
|
+
// lived only in the dashboard. These three actions are the terminal half, and
|
|
8
|
+
// they leave the GitHub App grant as the only browser step.
|
|
7
9
|
//
|
|
8
10
|
// **The server may not have them.** They are a separate cloud change, so
|
|
9
11
|
// every call here is a probe: a workspace whose API does not answer them gets
|
|
@@ -36,6 +38,22 @@ const createResponse = z.object({
|
|
|
36
38
|
schema: z.literal("carrick.create-project/0"),
|
|
37
39
|
project,
|
|
38
40
|
});
|
|
41
|
+
/** What one repo's assignment did, as the server reports it (carrick#999). */
|
|
42
|
+
const placement = z.object({
|
|
43
|
+
full_name: z.string(),
|
|
44
|
+
/** This repo is in the project now, including one that already was. */
|
|
45
|
+
assigned: z.boolean(),
|
|
46
|
+
/** Whether a write happened. False for a repo that was already there. */
|
|
47
|
+
moved: z.boolean(),
|
|
48
|
+
project_slug: z.string().nullable(),
|
|
49
|
+
/** Why this repo was not placed, as a sentence completing its name. */
|
|
50
|
+
reason: z.string().nullable(),
|
|
51
|
+
});
|
|
52
|
+
const assignResponse = z.object({
|
|
53
|
+
schema: z.literal("carrick.assign-repos/0"),
|
|
54
|
+
project_slug: z.string(),
|
|
55
|
+
repos: z.array(placement),
|
|
56
|
+
});
|
|
39
57
|
const REJECTED = "Carrick rejected this credential. Run carrick login (unset CARRICK_TOKEN first if it overrides your login).";
|
|
40
58
|
async function post(token, body, request, signal) {
|
|
41
59
|
try {
|
|
@@ -120,6 +138,147 @@ export async function createProject(token, slug, name = slug, request = fetch, s
|
|
|
120
138
|
const parsed = createResponse.safeParse(payload);
|
|
121
139
|
return parsed.success ? { kind: "created", project: parsed.data.project } : { kind: "absent" };
|
|
122
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Put the named repos in the named project, where this API can do it.
|
|
143
|
+
*
|
|
144
|
+
* The second browser step this command used to end on: the GitHub App grant
|
|
145
|
+
* puts a newly connected repo in the workspace's default project, so a run
|
|
146
|
+
* started with `--project` sat waiting for someone to move it on the Repos
|
|
147
|
+
* page (carrick#999). The action is idempotent, which is what makes it safe
|
|
148
|
+
* to call from inside the polling loop as repos arrive from the grant.
|
|
149
|
+
*
|
|
150
|
+
* `absent` is the same wide condition the other two actions use: this client
|
|
151
|
+
* is published ahead of the deploy that serves the action, and until it lands
|
|
152
|
+
* the credential-kind gate answers first. The caller then prints the browser
|
|
153
|
+
* instruction it printed before.
|
|
154
|
+
*/
|
|
155
|
+
export async function assignRepos(token, project, repos, request = fetch, signal) {
|
|
156
|
+
const result = await post(token, { action: "assign-repos", project, repos }, request, signal);
|
|
157
|
+
if (!result)
|
|
158
|
+
return { kind: "absent" };
|
|
159
|
+
if (result.status === 401)
|
|
160
|
+
throw new Error(REJECTED);
|
|
161
|
+
if (!result.ok) {
|
|
162
|
+
const message = await refusal(result);
|
|
163
|
+
return message ? { kind: "refused", message } : { kind: "absent" };
|
|
164
|
+
}
|
|
165
|
+
let payload;
|
|
166
|
+
try {
|
|
167
|
+
payload = await result.json();
|
|
168
|
+
}
|
|
169
|
+
catch {
|
|
170
|
+
return { kind: "absent" };
|
|
171
|
+
}
|
|
172
|
+
const parsed = assignResponse.safeParse(payload);
|
|
173
|
+
// The schema tag is the handshake, as it is for the list: an answer this
|
|
174
|
+
// client cannot read is the same situation as an API without the action.
|
|
175
|
+
return parsed.success && parsed.data.project_slug === project
|
|
176
|
+
? { kind: "placed", repos: parsed.data.repos }
|
|
177
|
+
: { kind: "absent" };
|
|
178
|
+
}
|
|
179
|
+
/** The slug shape the dashboard enforces, applied before anything is sent. */
|
|
180
|
+
export const SLUG = /^[a-z0-9](?:[a-z0-9]|-(?=[a-z0-9])){2,31}$/;
|
|
181
|
+
/** What a project is, said once, above the picker that asks for one. */
|
|
182
|
+
export const PROJECT_RULE = "One project per interconnected system: repos that call each other belong together.";
|
|
183
|
+
/**
|
|
184
|
+
* Make sure a named project exists, from the terminal where that is possible.
|
|
185
|
+
*
|
|
186
|
+
* Returns whether this run can state that it exists. `false` covers every case
|
|
187
|
+
* it could not settle — an API without the actions, a declined offer, a
|
|
188
|
+
* refused create — and the caller then prints the browser instructions, which
|
|
189
|
+
* include creating it.
|
|
190
|
+
*/
|
|
191
|
+
export async function ensureProject(token, slug, prompts) {
|
|
192
|
+
const { say } = prompts;
|
|
193
|
+
const projects = await (prompts.list ?? ((token) => listProjects(token)))(token);
|
|
194
|
+
if (projects === null)
|
|
195
|
+
return false;
|
|
196
|
+
if (projects.some((project) => project.slug === slug && !project.archived)) {
|
|
197
|
+
say(`Project "${slug}" is in this workspace.`);
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
say(projects.length === 0 ? "This workspace has no projects yet." : "Projects in this workspace:");
|
|
201
|
+
for (const line of projectLines(projects))
|
|
202
|
+
say(line);
|
|
203
|
+
const create = prompts.assumeYes || (prompts.interactive && (await prompts.confirm(`Create project "${slug}"?`)));
|
|
204
|
+
if (!create)
|
|
205
|
+
return false;
|
|
206
|
+
const outcome = await (prompts.create ?? ((token, slug) => createProject(token, slug)))(token, slug);
|
|
207
|
+
if (outcome.kind === "created") {
|
|
208
|
+
say(`Created project "${slug}".`);
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
if (outcome.kind === "refused")
|
|
212
|
+
say(`Carrick did not create "${slug}": ${outcome.message}`);
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* The project step for a plain `carrick init`, with no `--project` to verify
|
|
217
|
+
* (carrick#987, decision record carrick-cloud#772 step 3).
|
|
218
|
+
*
|
|
219
|
+
* Without the flag this used to do nothing at all, so a first run never saw
|
|
220
|
+
* the workspace's projects and the repo silently stayed wherever the browser
|
|
221
|
+
* had put it. The order is: the assignment the repos already have, then the
|
|
222
|
+
* list, then a name the user types, which may be one that does not exist yet.
|
|
223
|
+
* Assignment itself is still the browser's, so everything settled here only
|
|
224
|
+
* removes a step from the wait.
|
|
225
|
+
*
|
|
226
|
+
* `current` is one entry per requested repo: the project it is in, or null
|
|
227
|
+
* when it is not connected to this workspace at all.
|
|
228
|
+
*/
|
|
229
|
+
export async function projectStep(token, current, prompts) {
|
|
230
|
+
const list = prompts.list ?? ((token) => listProjects(token));
|
|
231
|
+
if (current.length === 0)
|
|
232
|
+
return { slug: null, exists: false };
|
|
233
|
+
const assigned = [...new Set(current)];
|
|
234
|
+
const sole = assigned.length === 1 ? assigned[0] : null;
|
|
235
|
+
if (sole != null) {
|
|
236
|
+
// Every repo is connected and in one project. That is the answer unless
|
|
237
|
+
// someone at the keyboard says otherwise, and the caller states the
|
|
238
|
+
// assignment it verifies, so this says nothing of its own.
|
|
239
|
+
if (!prompts.interactive || prompts.assumeYes)
|
|
240
|
+
return { slug: sole, exists: true };
|
|
241
|
+
if (await prompts.confirm(`These repos are in project "${sole}". Keep them there?`)) {
|
|
242
|
+
return { slug: sole, exists: true };
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// Nothing to ask without a terminal, and nothing this run may assume: a
|
|
246
|
+
// repo's project is not a thing to guess at.
|
|
247
|
+
if (!prompts.interactive)
|
|
248
|
+
return { slug: null, exists: false };
|
|
249
|
+
const projects = await list(token);
|
|
250
|
+
if (projects === null)
|
|
251
|
+
return { slug: null, exists: false };
|
|
252
|
+
// The one thing someone picking a project has to know, said where the
|
|
253
|
+
// question is asked: a project is the boundary every cross-service answer
|
|
254
|
+
// is computed inside, so repos split across two of them see nothing of each
|
|
255
|
+
// other (carrick#993).
|
|
256
|
+
prompts.say(PROJECT_RULE);
|
|
257
|
+
prompts.say(projects.length === 0 ? "This workspace has no projects yet." : "Projects in this workspace:");
|
|
258
|
+
for (const line of projectLines(projects))
|
|
259
|
+
prompts.say(line);
|
|
260
|
+
const answer = await prompts.ask("Which project should these repos be in? Enter a slug, or press Enter to leave it to the browser.");
|
|
261
|
+
if (answer === "")
|
|
262
|
+
return { slug: null, exists: false };
|
|
263
|
+
if (!SLUG.test(answer)) {
|
|
264
|
+
prompts.say(`"${answer}" is not a project slug: use 3-32 lowercase letters, digits, and single hyphens. Leaving the project step to the browser.`);
|
|
265
|
+
return { slug: null, exists: false };
|
|
266
|
+
}
|
|
267
|
+
if (projects.some((project) => project.slug === answer && !project.archived)) {
|
|
268
|
+
return { slug: answer, exists: true };
|
|
269
|
+
}
|
|
270
|
+
const create = await prompts.confirm(`Create project "${answer}"?`);
|
|
271
|
+
if (!create)
|
|
272
|
+
return { slug: answer, exists: false };
|
|
273
|
+
const outcome = await (prompts.create ?? ((token, slug) => createProject(token, slug)))(token, answer);
|
|
274
|
+
if (outcome.kind === "created") {
|
|
275
|
+
prompts.say(`Created project "${answer}".`);
|
|
276
|
+
return { slug: answer, exists: true };
|
|
277
|
+
}
|
|
278
|
+
if (outcome.kind === "refused")
|
|
279
|
+
prompts.say(`Carrick did not create "${answer}": ${outcome.message}`);
|
|
280
|
+
return { slug: answer, exists: false };
|
|
281
|
+
}
|
|
123
282
|
/** The list as init prints it: one line per project, active ones first. */
|
|
124
283
|
export function projectLines(projects) {
|
|
125
284
|
const ordered = [...projects].sort((left, right) => left.archived === right.archived
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/init/projects.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/init/projects.ts"],"names":[],"mappings":"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"}
|
package/dist/init/repos.d.ts
CHANGED
|
@@ -101,13 +101,67 @@ declare const proposal: z.ZodObject<{
|
|
|
101
101
|
} | null;
|
|
102
102
|
}>;
|
|
103
103
|
export type WorkspaceProposal = z.infer<typeof proposal>;
|
|
104
|
+
/**
|
|
105
|
+
* One `carrick derive` run: the document as the scanner printed it, and the
|
|
106
|
+
* same document parsed.
|
|
107
|
+
*
|
|
108
|
+
* Both halves are kept because they are read by different consumers. `plan` is
|
|
109
|
+
* what this CLI prints and decides on; `document` is what lands in
|
|
110
|
+
* `.carrick/proposal.json` for the scaffold tool's agent, and it has to be the
|
|
111
|
+
* scanner's own bytes — the schema above is not a passthrough at the top level,
|
|
112
|
+
* so parsing and re-serialising would silently drop any field a later
|
|
113
|
+
* `carrick.derive/0` adds.
|
|
114
|
+
*/
|
|
115
|
+
export type DerivedWorkspace = {
|
|
116
|
+
plan: WorkspaceProposal;
|
|
117
|
+
document: string;
|
|
118
|
+
};
|
|
104
119
|
/** Rust owns service selection, tsconfig precedence and configuration validation. */
|
|
105
|
-
export declare function deriveWorkspace(workspace: string):
|
|
106
|
-
/**
|
|
107
|
-
export declare
|
|
120
|
+
export declare function deriveWorkspace(workspace: string): DerivedWorkspace;
|
|
121
|
+
/** The seam document, relative to the workspace root (carrick-cloud#799). */
|
|
122
|
+
export declare const PROPOSAL_FILE: string;
|
|
123
|
+
/**
|
|
124
|
+
* Write the derived proposal where the scaffold tool's agent reads it.
|
|
125
|
+
*
|
|
126
|
+
* This is the whole of what init leaves in the workspace besides the hook
|
|
127
|
+
* settings: the agent seeds `carrick.json` from this document, and nothing
|
|
128
|
+
* this command derived without a model is committed to the repository
|
|
129
|
+
* (carrick-cloud#799). Rewritten on every run rather than created once — it is
|
|
130
|
+
* a derived file in an ignored directory, and a stale one would seed the
|
|
131
|
+
* config from a workspace that has since changed.
|
|
132
|
+
*/
|
|
133
|
+
export declare function writeProposal(workspace: string, derived: DerivedWorkspace): string;
|
|
134
|
+
/**
|
|
135
|
+
* What one repository on disk says it is on GitHub, and why it said nothing.
|
|
136
|
+
*
|
|
137
|
+
* `problem` is a clause, so a caller can put it after the path it read: it is
|
|
138
|
+
* printed for every repo that contributes no identity, because a repo silently
|
|
139
|
+
* left out of the project and connection steps looked like a complete run
|
|
140
|
+
* (carrick#991).
|
|
141
|
+
*/
|
|
142
|
+
export type RepoIdentity = {
|
|
108
143
|
path: string;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
|
|
144
|
+
/** `owner/repo`, or null when this repo names no GitHub repository. */
|
|
145
|
+
name: string | null;
|
|
146
|
+
/** The origin remote as written, for the line that says what was read. */
|
|
147
|
+
remote: string | null;
|
|
148
|
+
problem: string | null;
|
|
149
|
+
};
|
|
150
|
+
/** The two machine reads, injected so tests never spawn anything. */
|
|
151
|
+
export type IdentityProbe = {
|
|
152
|
+
/** `git remote get-url origin`, or null when there is no origin. */
|
|
153
|
+
remote: (repo: string) => string | null;
|
|
154
|
+
/** The `hostname` ssh resolves a host to, or null when ssh cannot say. */
|
|
155
|
+
sshHostname: (host: string) => string | null;
|
|
156
|
+
};
|
|
157
|
+
/**
|
|
158
|
+
* Only GitHub origin identities are sent to the workspace metadata read.
|
|
159
|
+
*
|
|
160
|
+
* A host that is already github.com is taken without spawning anything; an ssh
|
|
161
|
+
* host that is not is resolved through the user's ssh configuration, because a
|
|
162
|
+
* machine with two GitHub accounts writes its remotes through a per-account
|
|
163
|
+
* alias and that repository is an ordinary GitHub repository (carrick#991,
|
|
164
|
+
* carrick#978).
|
|
165
|
+
*/
|
|
166
|
+
export declare function repoIdentity(repo: string, probe?: IdentityProbe): RepoIdentity;
|
|
113
167
|
export {};
|
package/dist/init/repos.js
CHANGED
|
@@ -29,43 +29,137 @@ export function deriveWorkspace(workspace) {
|
|
|
29
29
|
const parsed = proposal.safeParse(JSON.parse(result.stdout));
|
|
30
30
|
if (!parsed.success)
|
|
31
31
|
throw new Error("The scanner returned an unsupported workspace proposal. Install matching Carrick CLI and scanner versions.");
|
|
32
|
-
return parsed.data;
|
|
32
|
+
return { plan: parsed.data, document: result.stdout };
|
|
33
33
|
}
|
|
34
|
-
/**
|
|
35
|
-
export
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
34
|
+
/** The seam document, relative to the workspace root (carrick-cloud#799). */
|
|
35
|
+
export const PROPOSAL_FILE = path.join(".carrick", "proposal.json");
|
|
36
|
+
/**
|
|
37
|
+
* Byte-identical to `write_self_ignore` in `src/local_mode/workspace.rs`.
|
|
38
|
+
*
|
|
39
|
+
* Two writers, because either command can be the first to create the
|
|
40
|
+
* directory: `carrick index` writes it on every build, and `carrick init` now
|
|
41
|
+
* writes the proposal before any index exists. Same bytes so neither rewrites
|
|
42
|
+
* the other's file. Keep the two in step.
|
|
43
|
+
*/
|
|
44
|
+
const SELF_IGNORE = "# Written by Carrick. Everything here is derived from your source and is\n" +
|
|
45
|
+
"# rebuilt by re-running `carrick index`.\n*\n";
|
|
46
|
+
/**
|
|
47
|
+
* Write the derived proposal where the scaffold tool's agent reads it.
|
|
48
|
+
*
|
|
49
|
+
* This is the whole of what init leaves in the workspace besides the hook
|
|
50
|
+
* settings: the agent seeds `carrick.json` from this document, and nothing
|
|
51
|
+
* this command derived without a model is committed to the repository
|
|
52
|
+
* (carrick-cloud#799). Rewritten on every run rather than created once — it is
|
|
53
|
+
* a derived file in an ignored directory, and a stale one would seed the
|
|
54
|
+
* config from a workspace that has since changed.
|
|
55
|
+
*/
|
|
56
|
+
export function writeProposal(workspace, derived) {
|
|
57
|
+
const directory = path.join(workspace, ".carrick");
|
|
58
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
59
|
+
fs.writeFileSync(path.join(directory, ".gitignore"), SELF_IGNORE);
|
|
60
|
+
const document = derived.document.endsWith("\n") ? derived.document : `${derived.document}\n`;
|
|
61
|
+
fs.writeFileSync(path.join(workspace, PROPOSAL_FILE), document);
|
|
62
|
+
return PROPOSAL_FILE;
|
|
50
63
|
}
|
|
51
|
-
|
|
52
|
-
export function githubRemote(repo) {
|
|
64
|
+
function gitOrigin(repo) {
|
|
53
65
|
const result = spawnSync("git", ["-C", repo, "remote", "get-url", "origin"], { encoding: "utf8", timeout: 5000 });
|
|
54
|
-
|
|
66
|
+
return result.status === 0 ? result.stdout.trim() : null;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The host ssh itself would dial, which for a per-account alias
|
|
70
|
+
* (`Host github.com-work` / `HostName github.com`) is not the host in the
|
|
71
|
+
* remote. `ssh -G` prints the whole resolved configuration and connects to
|
|
72
|
+
* nothing, so this reads the user's own `~/.ssh/config` without a list of
|
|
73
|
+
* alias spellings. An alias no config entry matches is not an error: ssh
|
|
74
|
+
* exits 0 and echoes the name back, which is why an unresolvable alias is
|
|
75
|
+
* detected by the hostname it returns rather than by a status.
|
|
76
|
+
*/
|
|
77
|
+
function sshHostname(host) {
|
|
78
|
+
// Never spawn on a string that could be read as an option, and never on one
|
|
79
|
+
// ssh would reject anyway.
|
|
80
|
+
if (!/^[A-Za-z0-9._-]+$/.test(host) || host.startsWith("-"))
|
|
81
|
+
return null;
|
|
82
|
+
const result = spawnSync("ssh", ["-G", host], {
|
|
83
|
+
encoding: "utf8",
|
|
84
|
+
timeout: 5000,
|
|
85
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
86
|
+
});
|
|
87
|
+
if (result.error || result.status !== 0 || typeof result.stdout !== "string")
|
|
55
88
|
return null;
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
89
|
+
const line = /^hostname (\S+)$/im.exec(result.stdout);
|
|
90
|
+
return line ? line[1] : null;
|
|
91
|
+
}
|
|
92
|
+
const DEFAULT_PROBE = { remote: gitOrigin, sshHostname };
|
|
93
|
+
/** The host and `owner/repo` a remote names, in either spelling git accepts. */
|
|
94
|
+
function splitRemote(remote) {
|
|
95
|
+
let host;
|
|
96
|
+
let repoPath;
|
|
97
|
+
let ssh;
|
|
98
|
+
// The two spellings are told apart by the `//`, not by whether `new URL`
|
|
99
|
+
// throws: a host alias with no user (`host-work:owner/repo`) parses as a URL
|
|
100
|
+
// whose scheme is the host, and would otherwise be read as neither form.
|
|
101
|
+
if (/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(remote)) {
|
|
102
|
+
let url;
|
|
103
|
+
try {
|
|
104
|
+
url = new URL(remote);
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
if (!["https:", "http:", "ssh:"].includes(url.protocol))
|
|
63
110
|
return null;
|
|
64
|
-
|
|
65
|
-
|
|
111
|
+
host = url.hostname;
|
|
112
|
+
repoPath = url.pathname;
|
|
113
|
+
ssh = url.protocol === "ssh:";
|
|
66
114
|
}
|
|
67
|
-
|
|
68
|
-
|
|
115
|
+
else {
|
|
116
|
+
// The scp spelling `[user@]host:owner/repo`, which is not a URL.
|
|
117
|
+
const scp = /^(?:[^@\s/]+@)?([^:/\s]+):(\S+)$/.exec(remote);
|
|
118
|
+
if (!scp)
|
|
119
|
+
return null;
|
|
120
|
+
host = scp[1];
|
|
121
|
+
repoPath = scp[2];
|
|
122
|
+
ssh = true;
|
|
123
|
+
}
|
|
124
|
+
const name = repoPath.replace(/^\/+/, "").replace(/\.git$/, "");
|
|
125
|
+
return { host, name: /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/.test(name) ? name : null, ssh };
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Only GitHub origin identities are sent to the workspace metadata read.
|
|
129
|
+
*
|
|
130
|
+
* A host that is already github.com is taken without spawning anything; an ssh
|
|
131
|
+
* host that is not is resolved through the user's ssh configuration, because a
|
|
132
|
+
* machine with two GitHub accounts writes its remotes through a per-account
|
|
133
|
+
* alias and that repository is an ordinary GitHub repository (carrick#991,
|
|
134
|
+
* carrick#978).
|
|
135
|
+
*/
|
|
136
|
+
export function repoIdentity(repo, probe = DEFAULT_PROBE) {
|
|
137
|
+
const remote = probe.remote(repo);
|
|
138
|
+
if (remote === null)
|
|
139
|
+
return { path: repo, name: null, remote: null, problem: "it has no origin remote" };
|
|
140
|
+
const parts = splitRemote(remote);
|
|
141
|
+
if (!parts)
|
|
142
|
+
return { path: repo, name: null, remote, problem: `its origin ${remote} is not a GitHub URL` };
|
|
143
|
+
const { host, name, ssh } = parts;
|
|
144
|
+
if (name === null) {
|
|
145
|
+
return { path: repo, name: null, remote, problem: `its origin ${remote} names no owner/repo path` };
|
|
146
|
+
}
|
|
147
|
+
if (host.toLowerCase() === "github.com")
|
|
148
|
+
return { path: repo, name, remote, problem: null };
|
|
149
|
+
if (!ssh) {
|
|
150
|
+
return { path: repo, name: null, remote, problem: `its origin ${remote} is on ${host}, not github.com` };
|
|
151
|
+
}
|
|
152
|
+
const resolved = probe.sshHostname(host);
|
|
153
|
+
if (resolved === null) {
|
|
154
|
+
return { path: repo, name: null, remote, problem: `its origin ${remote} names the host "${host}", which ssh could not resolve` };
|
|
69
155
|
}
|
|
156
|
+
if (resolved.toLowerCase() === "github.com")
|
|
157
|
+
return { path: repo, name, remote, problem: null };
|
|
158
|
+
return {
|
|
159
|
+
path: repo,
|
|
160
|
+
name: null,
|
|
161
|
+
remote,
|
|
162
|
+
problem: `its origin ${remote} names the host "${host}", which ssh resolves to "${resolved}", not github.com`,
|
|
163
|
+
};
|
|
70
164
|
}
|
|
71
165
|
//# sourceMappingURL=repos.js.map
|