@clipboard-health/groundcrew 1.12.3 → 1.12.4
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/commands/remoteSetup.d.ts +3 -0
- package/dist/commands/remoteSetup.d.ts.map +1 -1
- package/dist/commands/remoteSetup.js +33 -25
- package/dist/lib/spriteRemoteRunnerProvider.d.ts +3 -0
- package/dist/lib/spriteRemoteRunnerProvider.d.ts.map +1 -1
- package/dist/lib/spriteRemoteRunnerProvider.js +6 -6
- package/package.json +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type RemoteRunnerConfig } from "../lib/config.ts";
|
|
1
2
|
export interface McpServer {
|
|
2
3
|
name: string;
|
|
3
4
|
url: string;
|
|
@@ -23,6 +24,8 @@ export interface RemoteBootstrapOptions {
|
|
|
23
24
|
owner: string;
|
|
24
25
|
baseBranch: string;
|
|
25
26
|
gitRemote?: string;
|
|
27
|
+
repoRoot?: string;
|
|
28
|
+
remoteConfig?: RemoteRunnerConfig;
|
|
26
29
|
secretNames: string[];
|
|
27
30
|
shouldRequireSelectedSecrets: boolean;
|
|
28
31
|
shouldUseSecrets: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remoteSetup.d.ts","sourceRoot":"","sources":["../../src/commands/remoteSetup.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"remoteSetup.d.ts","sourceRoot":"","sources":["../../src/commands/remoteSetup.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,kBAAkB,CAAC;AAkB1B,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,wBAAwB,EAAE,OAAO,CAAC;IAClC,uBAAuB,EAAE,OAAO,CAAC;IACjC,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,wBAAwB,EAAE,OAAO,CAAC;IAClC,qBAAqB,EAAE,OAAO,CAAC;IAC/B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,4BAA4B,EAAE,OAAO,CAAC;IACtC,gBAAgB,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAiBD,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AA02BD,wBAAsB,yBAAyB,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsC9F;AAUD,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAItF;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrF;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAItF;AAED,wBAAsB,2BAA2B,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG;AAYD,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgClF;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2B7D"}
|
|
@@ -2,9 +2,9 @@ import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
|
2
2
|
import { homedir, tmpdir } from "node:os";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
5
|
-
import {
|
|
5
|
+
import { DEFAULT_REMOTE_SETUP_COMMAND, loadConfig, } from "../lib/config.js";
|
|
6
6
|
import { shellSingleQuote } from "../lib/shell.js";
|
|
7
|
-
import { getRemoteRunnerProvider, remoteConfigWithRunnerName, } from "../lib/spriteRemoteRunnerProvider.js";
|
|
7
|
+
import { getRemoteRunnerProvider, remotePathJoin, remoteConfigWithRunnerName, remoteRepositoryDirectoryName, remoteRepositorySlug, } from "../lib/spriteRemoteRunnerProvider.js";
|
|
8
8
|
import { log, readEnvironmentVariable, writeOutput } from "../lib/util.js";
|
|
9
9
|
const KNOWN_MCP_SERVER_URLS = {
|
|
10
10
|
linear: "https://mcp.linear.app/mcp",
|
|
@@ -13,8 +13,8 @@ const KNOWN_MCP_SERVER_URLS = {
|
|
|
13
13
|
};
|
|
14
14
|
const DEFAULT_CHECKPOINT_COMMENT = "groundcrew remote runner baseline: selected agent auth, git identity, and MCP config";
|
|
15
15
|
const CLAUDE_SUBSCRIPTION_LOGIN_FLAG = ["--claude", "ai"].join("");
|
|
16
|
-
const DEFAULT_REPOSITORY_OWNER = "ClipboardHealth";
|
|
17
16
|
const DEFAULT_GIT_REMOTE = "origin";
|
|
17
|
+
const BOOTSTRAP_SECRET_FLAGS_CONFLICT_MESSAGE = "--secret and --no-secrets are mutually exclusive. Use --secret to forward selected build secrets or --no-secrets to disable secret forwarding.";
|
|
18
18
|
const DATADOG_PUP_VERSION = "0.63.0";
|
|
19
19
|
const DATADOG_OAUTH_CALLBACK_PORT = 8000;
|
|
20
20
|
const DATADOG_AUTH_STATUS_RETRY_ATTEMPTS = 5;
|
|
@@ -53,9 +53,9 @@ function usage() {
|
|
|
53
53
|
"Bootstrap options:",
|
|
54
54
|
" --branch <branch> Checkout/create a ticket branch before installing deps",
|
|
55
55
|
" --base <branch> Base branch used when creating a missing branch (default: git.defaultBranch)",
|
|
56
|
-
" --owner <owner> GitHub owner for bare repo names (default:
|
|
56
|
+
" --owner <owner> GitHub owner for bare repo names (default: remote.owner)",
|
|
57
57
|
" --secret <env-name> Forward one required build secret; repeat for multiple",
|
|
58
|
-
" --no-secrets Do not forward
|
|
58
|
+
" --no-secrets Do not forward configured build secrets even if present",
|
|
59
59
|
"",
|
|
60
60
|
"Bootstrap example:",
|
|
61
61
|
" crew remote bootstrap crew-claude-1 core-utils --branch rocky-team-123",
|
|
@@ -232,7 +232,7 @@ function parseBootstrapArguments(argv) {
|
|
|
232
232
|
throw new Error(usage());
|
|
233
233
|
}
|
|
234
234
|
validateRepository(repository);
|
|
235
|
-
let owner
|
|
235
|
+
let owner;
|
|
236
236
|
let baseBranch;
|
|
237
237
|
let branchName;
|
|
238
238
|
let shouldUseSecrets = true;
|
|
@@ -259,6 +259,9 @@ function parseBootstrapArguments(argv) {
|
|
|
259
259
|
continue;
|
|
260
260
|
}
|
|
261
261
|
if (argument === "--secret") {
|
|
262
|
+
if (!shouldUseSecrets) {
|
|
263
|
+
throw new Error(BOOTSTRAP_SECRET_FLAGS_CONFLICT_MESSAGE);
|
|
264
|
+
}
|
|
262
265
|
const secretName = requireValue(argv, index, "--secret");
|
|
263
266
|
validateSecretName(secretName);
|
|
264
267
|
selectedSecretNames.push(secretName);
|
|
@@ -267,6 +270,9 @@ function parseBootstrapArguments(argv) {
|
|
|
267
270
|
continue;
|
|
268
271
|
}
|
|
269
272
|
if (argument === "--no-secrets") {
|
|
273
|
+
if (selectedSecretNames.length > 0 || shouldRequireSelectedSecrets) {
|
|
274
|
+
throw new Error(BOOTSTRAP_SECRET_FLAGS_CONFLICT_MESSAGE);
|
|
275
|
+
}
|
|
270
276
|
shouldUseSecrets = false;
|
|
271
277
|
continue;
|
|
272
278
|
}
|
|
@@ -275,10 +281,10 @@ function parseBootstrapArguments(argv) {
|
|
|
275
281
|
return {
|
|
276
282
|
runnerName,
|
|
277
283
|
repository,
|
|
278
|
-
owner,
|
|
279
|
-
secretNames: selectedSecretNames.length > 0 ? selectedSecretNames : [...BUILD_SECRET_NAMES],
|
|
280
284
|
shouldRequireSelectedSecrets,
|
|
281
285
|
shouldUseSecrets,
|
|
286
|
+
...(owner === undefined ? {} : { owner }),
|
|
287
|
+
...(selectedSecretNames.length > 0 ? { secretNames: selectedSecretNames } : {}),
|
|
282
288
|
...(baseBranch === undefined ? {} : { baseBranch }),
|
|
283
289
|
...(branchName === undefined ? {} : { branchName }),
|
|
284
290
|
};
|
|
@@ -620,17 +626,6 @@ async function checkpoint(arguments_) {
|
|
|
620
626
|
}
|
|
621
627
|
await provider.checkpoint(config, options.checkpointComment);
|
|
622
628
|
}
|
|
623
|
-
function repositorySlug(options) {
|
|
624
|
-
return options.repository.includes("/")
|
|
625
|
-
? options.repository
|
|
626
|
-
: `${options.owner}/${options.repository}`;
|
|
627
|
-
}
|
|
628
|
-
function repositoryDirectoryName(repository) {
|
|
629
|
-
const name = repository.includes("/")
|
|
630
|
-
? repository.slice(repository.lastIndexOf("/") + 1)
|
|
631
|
-
: repository;
|
|
632
|
-
return name.endsWith(".git") ? name.slice(0, -4) : name;
|
|
633
|
-
}
|
|
634
629
|
function validateRemoteBootstrapOptions(options) {
|
|
635
630
|
validateRepository(options.repository);
|
|
636
631
|
validateRepositoryOwner(options.owner);
|
|
@@ -644,8 +639,9 @@ function validateRemoteBootstrapOptions(options) {
|
|
|
644
639
|
}
|
|
645
640
|
}
|
|
646
641
|
function remoteBootstrapCommand(options) {
|
|
647
|
-
const slug =
|
|
648
|
-
const directoryName =
|
|
642
|
+
const slug = remoteRepositorySlug(options.owner, options.repository);
|
|
643
|
+
const directoryName = remoteRepositoryDirectoryName(options.owner, options.repository);
|
|
644
|
+
const repoDir = remotePathJoin(options.repoRoot, directoryName);
|
|
649
645
|
const baseRef = `${options.gitRemote}/${options.baseBranch}`;
|
|
650
646
|
const unsetSecretsLine = options.secretNames.length === 0 ? ":" : `unset ${options.secretNames.join(" ")}`;
|
|
651
647
|
const checkoutLines = options.branchName === undefined
|
|
@@ -661,9 +657,10 @@ function remoteBootstrapCommand(options) {
|
|
|
661
657
|
"set -euo pipefail",
|
|
662
658
|
`cleanup() { rm -f ${shellSingleQuote(REMOTE_SECRETS_FILE)}; ${unsetSecretsLine}; }`,
|
|
663
659
|
"trap cleanup EXIT",
|
|
660
|
+
`repo_root=${shellSingleQuote(options.repoRoot)}`,
|
|
661
|
+
`repo_dir=${shellSingleQuote(repoDir)}`,
|
|
664
662
|
`git_remote=${shellSingleQuote(options.gitRemote)}`,
|
|
665
|
-
'mkdir -p "$
|
|
666
|
-
`repo_dir="$HOME/dev"/${shellSingleQuote(directoryName)}`,
|
|
663
|
+
'mkdir -p "$repo_root"',
|
|
667
664
|
'if [ ! -d "$repo_dir/.git" ]; then',
|
|
668
665
|
` gh repo clone ${shellSingleQuote(slug)} "$repo_dir"`,
|
|
669
666
|
"fi",
|
|
@@ -680,10 +677,19 @@ function remoteBootstrapCommand(options) {
|
|
|
680
677
|
}
|
|
681
678
|
async function resolveBootstrapOptions(options) {
|
|
682
679
|
const config = await loadConfig();
|
|
680
|
+
const remoteConfig = {
|
|
681
|
+
...config.remote,
|
|
682
|
+
runnerName: options.runnerName,
|
|
683
|
+
secretNames: [...config.remote.secretNames],
|
|
684
|
+
};
|
|
683
685
|
return {
|
|
684
686
|
...options,
|
|
687
|
+
owner: options.owner ?? remoteConfig.owner,
|
|
685
688
|
baseBranch: options.baseBranch ?? config.git.defaultBranch,
|
|
686
689
|
gitRemote: config.git.remote,
|
|
690
|
+
repoRoot: remoteConfig.repoRoot,
|
|
691
|
+
remoteConfig,
|
|
692
|
+
secretNames: options.secretNames ?? [...remoteConfig.secretNames],
|
|
687
693
|
};
|
|
688
694
|
}
|
|
689
695
|
function noSecretCleanup() {
|
|
@@ -721,12 +727,14 @@ function stageBuildSecrets(options) {
|
|
|
721
727
|
};
|
|
722
728
|
}
|
|
723
729
|
export async function bootstrapRemoteRepository(options) {
|
|
730
|
+
const config = options.remoteConfig ?? remoteConfigWithRunnerName(options.runnerName);
|
|
724
731
|
const bootstrapOptions = {
|
|
725
732
|
...options,
|
|
726
733
|
gitRemote: options.gitRemote ?? DEFAULT_GIT_REMOTE,
|
|
734
|
+
repoRoot: options.repoRoot ?? config.repoRoot,
|
|
735
|
+
remoteConfig: config,
|
|
727
736
|
};
|
|
728
737
|
validateRemoteBootstrapOptions(bootstrapOptions);
|
|
729
|
-
const config = remoteConfigWithRunnerName(options.runnerName);
|
|
730
738
|
const provider = providerFor(config);
|
|
731
739
|
if (!(await provider.runnerExists(config))) {
|
|
732
740
|
throw new Error(`Remote runner ${options.runnerName} does not exist. Run crew remote setup first.`);
|
|
@@ -739,7 +747,7 @@ export async function bootstrapRemoteRepository(options) {
|
|
|
739
747
|
const files = stagedSecrets.filePath === undefined
|
|
740
748
|
? []
|
|
741
749
|
: [{ localPath: stagedSecrets.filePath, remotePath: REMOTE_SECRETS_FILE }];
|
|
742
|
-
log(`Bootstrapping ${
|
|
750
|
+
log(`Bootstrapping ${remoteRepositorySlug(bootstrapOptions.owner, bootstrapOptions.repository)} in ${options.runnerName}`);
|
|
743
751
|
await provider.runCommand({
|
|
744
752
|
config,
|
|
745
753
|
files,
|
|
@@ -66,6 +66,9 @@ export interface RemoteRunnerProvider {
|
|
|
66
66
|
createWorktree(arguments_: RemoteWorktreeCreateArguments): Promise<RemoteWorktreeLocation>;
|
|
67
67
|
removeWorktree(arguments_: RemoteWorktreeRemoveArguments): Promise<void>;
|
|
68
68
|
}
|
|
69
|
+
export declare function remotePathJoin(root: string, leaf: string): string;
|
|
70
|
+
export declare function remoteRepositorySlug(owner: string, repository: string): string;
|
|
71
|
+
export declare function remoteRepositoryDirectoryName(owner: string, repository: string): string;
|
|
69
72
|
export declare const spriteRemoteRunnerProvider: RemoteRunnerProvider;
|
|
70
73
|
export declare function remoteConfigWithRunnerName(runnerName: string): RemoteRunnerConfig;
|
|
71
74
|
export declare function getRemoteRunnerProvider(provider: RemoteRunnerProviderName): RemoteRunnerProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"spriteRemoteRunnerProvider.d.ts","sourceRoot":"","sources":["../../src/lib/spriteRemoteRunnerProvider.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"spriteRemoteRunnerProvider.d.ts","sourceRoot":"","sources":["../../src/lib/spriteRemoteRunnerProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -82,18 +82,18 @@ function buildSpriteTtyCommand(arguments_) {
|
|
|
82
82
|
...arguments_.remoteArguments.map(shellSingleQuote),
|
|
83
83
|
].join(" ");
|
|
84
84
|
}
|
|
85
|
-
function remotePathJoin(root, leaf) {
|
|
85
|
+
export function remotePathJoin(root, leaf) {
|
|
86
86
|
let end = root.length;
|
|
87
87
|
while (end > 0 && root[end - 1] === "/") {
|
|
88
88
|
end -= 1;
|
|
89
89
|
}
|
|
90
90
|
return `${root.slice(0, end)}/${leaf}`;
|
|
91
91
|
}
|
|
92
|
-
function
|
|
92
|
+
export function remoteRepositorySlug(owner, repository) {
|
|
93
93
|
return repository.includes("/") ? repository : `${owner}/${repository}`;
|
|
94
94
|
}
|
|
95
|
-
function
|
|
96
|
-
const slug =
|
|
95
|
+
export function remoteRepositoryDirectoryName(owner, repository) {
|
|
96
|
+
const slug = remoteRepositorySlug(owner, repository);
|
|
97
97
|
const normalizedSlug = slug.endsWith(".git") ? slug.slice(0, -4) : slug;
|
|
98
98
|
return normalizedSlug.replaceAll("/", "--");
|
|
99
99
|
}
|
|
@@ -104,7 +104,7 @@ function worktreeTicketComponent(ticket) {
|
|
|
104
104
|
return ticket;
|
|
105
105
|
}
|
|
106
106
|
function spriteCreateWorktreeCommand(arguments_) {
|
|
107
|
-
const slug =
|
|
107
|
+
const slug = remoteRepositorySlug(arguments_.owner, arguments_.repository);
|
|
108
108
|
const branchRemoteRef = `refs/remotes/${arguments_.gitRemote}/${arguments_.branchName}`;
|
|
109
109
|
const branchRef = `${arguments_.gitRemote}/${arguments_.branchName}`;
|
|
110
110
|
const baseRef = `${arguments_.gitRemote}/${arguments_.baseBranch}`;
|
|
@@ -317,7 +317,7 @@ export const spriteRemoteRunnerProvider = {
|
|
|
317
317
|
},
|
|
318
318
|
async createWorktree(arguments_) {
|
|
319
319
|
const { config, repository, ticket, branchName, baseBranch, gitRemote, signal } = arguments_;
|
|
320
|
-
const remoteRepositoryName =
|
|
320
|
+
const remoteRepositoryName = remoteRepositoryDirectoryName(config.owner, repository);
|
|
321
321
|
const remoteRepoDir = remotePathJoin(config.repoRoot, remoteRepositoryName);
|
|
322
322
|
const remoteWorktreeDir = remotePathJoin(config.worktreeRoot, `${remoteRepositoryName}-${worktreeTicketComponent(ticket)}`);
|
|
323
323
|
await runCommandAsync("sprite", [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clipboard-health/groundcrew",
|
|
3
|
-
"version": "1.12.
|
|
3
|
+
"version": "1.12.4",
|
|
4
4
|
"description": "Linear-driven orchestrator that launches AI coding agents in git worktrees, with workspace lifecycle, remote runners, and usage tracking.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|