@prover-coder-ai/docker-git 1.0.42 → 1.0.43
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.
|
@@ -1211,6 +1211,38 @@ var ensureGhAuthImage = (fs, path, cwd, buildLabel) => ensureDockerImage(fs, pat
|
|
|
1211
1211
|
buildLabel
|
|
1212
1212
|
});
|
|
1213
1213
|
//#endregion
|
|
1214
|
+
//#region ../lib/src/usecases/github-api-helpers.ts
|
|
1215
|
+
/**
|
|
1216
|
+
* Run `gh api <args>` inside the auth Docker container and return trimmed stdout.
|
|
1217
|
+
*
|
|
1218
|
+
* @pure false
|
|
1219
|
+
* @effect CommandExecutor (Docker)
|
|
1220
|
+
* @invariant exits with CommandFailedError on non-zero exit code
|
|
1221
|
+
* @complexity O(1)
|
|
1222
|
+
*/
|
|
1223
|
+
var runGhApiCapture = (cwd, hostPath, token, args) => runDockerAuthCapture(buildDockerAuthSpec({
|
|
1224
|
+
cwd,
|
|
1225
|
+
image: ghImageName,
|
|
1226
|
+
hostPath,
|
|
1227
|
+
containerPath: ghAuthDir,
|
|
1228
|
+
env: `GH_TOKEN=${token}`,
|
|
1229
|
+
args: ["api", ...args],
|
|
1230
|
+
interactive: false
|
|
1231
|
+
}), [0], (exitCode) => new CommandFailedError({
|
|
1232
|
+
command: `gh api ${args.join(" ")}`,
|
|
1233
|
+
exitCode
|
|
1234
|
+
})).pipe(Effect.map((raw) => raw.trim()));
|
|
1235
|
+
/**
|
|
1236
|
+
* Like `runGhApiCapture` but returns `null` instead of failing on API errors
|
|
1237
|
+
* (e.g. HTTP 404 / non-zero exit code).
|
|
1238
|
+
*
|
|
1239
|
+
* @pure false
|
|
1240
|
+
* @effect CommandExecutor (Docker)
|
|
1241
|
+
* @invariant never fails — errors become null
|
|
1242
|
+
* @complexity O(1)
|
|
1243
|
+
*/
|
|
1244
|
+
var runGhApiNullable = (cwd, hostPath, token, args) => runGhApiCapture(cwd, hostPath, token, args).pipe(Effect.catchTag("CommandFailedError", () => Effect.succeed("")), Effect.map((raw) => raw.length === 0 ? null : raw));
|
|
1245
|
+
//#endregion
|
|
1214
1246
|
//#region ../lib/src/usecases/runtime.ts
|
|
1215
1247
|
var withFsPathContext = (run) => Effect.gen(function* (_) {
|
|
1216
1248
|
return yield* _(run({
|
|
@@ -1228,20 +1260,7 @@ var resolveGithubToken$1 = (envText) => {
|
|
|
1228
1260
|
const labeled = entries.find((entry) => entry.key.startsWith("GITHUB_TOKEN__"));
|
|
1229
1261
|
return labeled && labeled.value.trim().length > 0 ? labeled.value.trim() : null;
|
|
1230
1262
|
};
|
|
1231
|
-
var
|
|
1232
|
-
cwd,
|
|
1233
|
-
image: ghImageName,
|
|
1234
|
-
hostPath,
|
|
1235
|
-
containerPath: ghAuthDir,
|
|
1236
|
-
env: `GH_TOKEN=${token}`,
|
|
1237
|
-
args: ["api", ...args],
|
|
1238
|
-
interactive: false
|
|
1239
|
-
}), [0], (exitCode) => new CommandFailedError({
|
|
1240
|
-
command: `gh api ${args.join(" ")}`,
|
|
1241
|
-
exitCode
|
|
1242
|
-
})).pipe(Effect.map((raw) => raw.trim()));
|
|
1243
|
-
var runGhApiCloneUrl = (cwd, hostPath, token, args) => runGhApiCapture(cwd, hostPath, token, args).pipe(Effect.catchTag("CommandFailedError", () => Effect.succeed("")), Effect.map((raw) => raw.length === 0 ? null : raw));
|
|
1244
|
-
var resolveViewerLogin = (cwd, hostPath, token) => Effect.gen(function* (_) {
|
|
1263
|
+
var resolveViewerLogin$1 = (cwd, hostPath, token) => Effect.gen(function* (_) {
|
|
1245
1264
|
const command = "gh api /user --jq .login";
|
|
1246
1265
|
const raw = yield* _(runGhApiCapture(cwd, hostPath, token, [
|
|
1247
1266
|
"/user",
|
|
@@ -1254,12 +1273,12 @@ var resolveViewerLogin = (cwd, hostPath, token) => Effect.gen(function* (_) {
|
|
|
1254
1273
|
})));
|
|
1255
1274
|
return raw;
|
|
1256
1275
|
});
|
|
1257
|
-
var resolveRepoCloneUrl = (cwd, hostPath, token, fullName) =>
|
|
1276
|
+
var resolveRepoCloneUrl = (cwd, hostPath, token, fullName) => runGhApiNullable(cwd, hostPath, token, [
|
|
1258
1277
|
`/repos/${fullName}`,
|
|
1259
1278
|
"--jq",
|
|
1260
1279
|
".clone_url"
|
|
1261
1280
|
]);
|
|
1262
|
-
var createFork = (cwd, hostPath, token, owner, repo) =>
|
|
1281
|
+
var createFork = (cwd, hostPath, token, owner, repo) => runGhApiNullable(cwd, hostPath, token, [
|
|
1263
1282
|
"-X",
|
|
1264
1283
|
"POST",
|
|
1265
1284
|
`/repos/${owner}/${repo}/forks`,
|
|
@@ -1277,7 +1296,7 @@ var resolveGithubForkUrl = (repoUrl, envGlobalPath) => withFsPathContext(({ cwd,
|
|
|
1277
1296
|
const ghRoot = resolvePathFromCwd(path, cwd, ghAuthRoot);
|
|
1278
1297
|
yield* _(fs.makeDirectory(ghRoot, { recursive: true }));
|
|
1279
1298
|
yield* _(ensureGhAuthImage(fs, path, cwd, "gh api"));
|
|
1280
|
-
const viewer = yield* _(resolveViewerLogin(cwd, ghRoot, token));
|
|
1299
|
+
const viewer = yield* _(resolveViewerLogin$1(cwd, ghRoot, token));
|
|
1281
1300
|
if (viewer.toLowerCase() === repo.owner.toLowerCase()) return null;
|
|
1282
1301
|
const existingFork = yield* _(resolveRepoCloneUrl(cwd, ghRoot, token, `${viewer}/${repo.repo}`));
|
|
1283
1302
|
if (existingFork !== null) return existingFork;
|
|
@@ -1588,28 +1607,15 @@ var resolveComposeResourceLimits = (template, hostResources) => {
|
|
|
1588
1607
|
//#region ../lib/src/usecases/resource-limits.ts
|
|
1589
1608
|
var resolveTemplateResourceLimits = (template) => Effect.succeed(withDefaultResourceLimitIntent(template));
|
|
1590
1609
|
//#endregion
|
|
1591
|
-
//#region ../lib/src/usecases/state-repo/env.ts
|
|
1592
|
-
var isTruthyEnv = (value) => {
|
|
1593
|
-
const normalized = value.trim().toLowerCase();
|
|
1594
|
-
return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
|
|
1595
|
-
};
|
|
1596
|
-
var isFalsyEnv = (value) => {
|
|
1597
|
-
const normalized = value.trim().toLowerCase();
|
|
1598
|
-
return normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off";
|
|
1599
|
-
};
|
|
1600
|
-
var autoSyncStrictEnvKey = "DOCKER_GIT_STATE_AUTO_SYNC_STRICT";
|
|
1601
|
-
var defaultSyncMessage = "chore(state): sync";
|
|
1602
|
-
var isAutoSyncEnabled = (envValue, hasRemote) => {
|
|
1603
|
-
if (envValue === void 0) return hasRemote;
|
|
1604
|
-
if (envValue.trim().length === 0) return hasRemote;
|
|
1605
|
-
if (isFalsyEnv(envValue)) return false;
|
|
1606
|
-
if (isTruthyEnv(envValue)) return true;
|
|
1607
|
-
return true;
|
|
1608
|
-
};
|
|
1609
|
-
//#endregion
|
|
1610
1610
|
//#region ../lib/src/usecases/state-repo/git-commands.ts
|
|
1611
1611
|
var successExitCode = Number(ExitCode(0));
|
|
1612
|
-
var gitBaseEnv$1 = {
|
|
1612
|
+
var gitBaseEnv$1 = {
|
|
1613
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
1614
|
+
GIT_AUTHOR_NAME: "docker-git",
|
|
1615
|
+
GIT_AUTHOR_EMAIL: "docker-git@users.noreply.github.com",
|
|
1616
|
+
GIT_COMMITTER_NAME: "docker-git",
|
|
1617
|
+
GIT_COMMITTER_EMAIL: "docker-git@users.noreply.github.com"
|
|
1618
|
+
};
|
|
1613
1619
|
var git = (cwd, args, env = gitBaseEnv$1) => runCommandWithExitCodes({
|
|
1614
1620
|
cwd,
|
|
1615
1621
|
command: "git",
|
|
@@ -1641,6 +1647,68 @@ var hasOriginRemote = (root) => Effect.map(gitExitCode(root, [
|
|
|
1641
1647
|
"origin"
|
|
1642
1648
|
]), (exit) => exit === successExitCode);
|
|
1643
1649
|
//#endregion
|
|
1650
|
+
//#region ../lib/src/usecases/state-repo/adopt-remote.ts
|
|
1651
|
+
var adoptRemoteHistoryIfOrphan = (root, repoRef, env) => Effect.gen(function* (_) {
|
|
1652
|
+
const fetchExit = yield* _(gitExitCode(root, [
|
|
1653
|
+
"fetch",
|
|
1654
|
+
"origin",
|
|
1655
|
+
repoRef
|
|
1656
|
+
], env));
|
|
1657
|
+
if (fetchExit !== successExitCode) {
|
|
1658
|
+
yield* _(Effect.logWarning(`git fetch origin ${repoRef} failed (exit ${fetchExit}); starting fresh history`));
|
|
1659
|
+
return;
|
|
1660
|
+
}
|
|
1661
|
+
const remoteRef = `origin/${repoRef}`;
|
|
1662
|
+
if ((yield* _(gitExitCode(root, [
|
|
1663
|
+
"show-ref",
|
|
1664
|
+
"--verify",
|
|
1665
|
+
"--quiet",
|
|
1666
|
+
`refs/remotes/${remoteRef}`
|
|
1667
|
+
], env))) !== successExitCode) return;
|
|
1668
|
+
if ((yield* _(gitExitCode(root, ["rev-parse", "HEAD"], env))) !== successExitCode) {
|
|
1669
|
+
yield* _(git(root, ["reset", remoteRef], env));
|
|
1670
|
+
yield* _(gitExitCode(root, ["checkout-index", "--all"], env));
|
|
1671
|
+
yield* _(Effect.log(`Adopted remote history from ${remoteRef}`));
|
|
1672
|
+
return;
|
|
1673
|
+
}
|
|
1674
|
+
if ((yield* _(gitExitCode(root, [
|
|
1675
|
+
"merge-base",
|
|
1676
|
+
"HEAD",
|
|
1677
|
+
remoteRef
|
|
1678
|
+
], env))) === successExitCode) return;
|
|
1679
|
+
yield* _(Effect.logWarning(`Local history has no common ancestor with ${remoteRef}; merging unrelated histories`));
|
|
1680
|
+
if ((yield* _(gitExitCode(root, [
|
|
1681
|
+
"merge",
|
|
1682
|
+
"--allow-unrelated-histories",
|
|
1683
|
+
"--no-edit",
|
|
1684
|
+
remoteRef
|
|
1685
|
+
], env))) === successExitCode) {
|
|
1686
|
+
yield* _(Effect.log(`Merged unrelated histories from ${remoteRef}`));
|
|
1687
|
+
return;
|
|
1688
|
+
}
|
|
1689
|
+
yield* _(gitExitCode(root, ["merge", "--abort"], env));
|
|
1690
|
+
yield* _(Effect.logWarning(`Merge conflict with ${remoteRef}; sync will open a PR for manual resolution`));
|
|
1691
|
+
});
|
|
1692
|
+
//#endregion
|
|
1693
|
+
//#region ../lib/src/usecases/state-repo/env.ts
|
|
1694
|
+
var isTruthyEnv = (value) => {
|
|
1695
|
+
const normalized = value.trim().toLowerCase();
|
|
1696
|
+
return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
|
|
1697
|
+
};
|
|
1698
|
+
var isFalsyEnv = (value) => {
|
|
1699
|
+
const normalized = value.trim().toLowerCase();
|
|
1700
|
+
return normalized === "0" || normalized === "false" || normalized === "no" || normalized === "off";
|
|
1701
|
+
};
|
|
1702
|
+
var autoSyncStrictEnvKey = "DOCKER_GIT_STATE_AUTO_SYNC_STRICT";
|
|
1703
|
+
var defaultSyncMessage = "chore(state): sync";
|
|
1704
|
+
var isAutoSyncEnabled = (envValue, hasRemote) => {
|
|
1705
|
+
if (envValue === void 0) return hasRemote;
|
|
1706
|
+
if (envValue.trim().length === 0) return hasRemote;
|
|
1707
|
+
if (isFalsyEnv(envValue)) return false;
|
|
1708
|
+
if (isTruthyEnv(envValue)) return true;
|
|
1709
|
+
return true;
|
|
1710
|
+
};
|
|
1711
|
+
//#endregion
|
|
1644
1712
|
//#region ../lib/src/usecases/state-repo/github-auth.ts
|
|
1645
1713
|
var githubTokenKey = "GITHUB_TOKEN";
|
|
1646
1714
|
var githubHttpsRemoteRe = /^https:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/;
|
|
@@ -4378,7 +4446,7 @@ var commitAllIfNeeded = (root, message, env) => Effect.gen(function* (_) {
|
|
|
4378
4446
|
], env));
|
|
4379
4447
|
});
|
|
4380
4448
|
var sanitizeBranchComponent = (value) => value.trim().replaceAll(" ", "-").replaceAll(":", "-").replaceAll("..", "-").replaceAll("@{", "-").replaceAll("\\", "-").replaceAll("^", "-").replaceAll("~", "-");
|
|
4381
|
-
var
|
|
4449
|
+
var pullRemoteAndRestoreLocal = (root, baseBranch, env) => Effect.gen(function* (_) {
|
|
4382
4450
|
const fetchExit = yield* _(gitExitCode(root, [
|
|
4383
4451
|
"fetch",
|
|
4384
4452
|
"origin",
|
|
@@ -4393,10 +4461,26 @@ var rebaseOntoOriginIfPossible = (root, baseBranch, env) => Effect.gen(function*
|
|
|
4393
4461
|
"--verify",
|
|
4394
4462
|
"--quiet",
|
|
4395
4463
|
`refs/remotes/origin/${baseBranch}`
|
|
4396
|
-
], env))) !== successExitCode) return
|
|
4397
|
-
|
|
4398
|
-
yield* _(gitExitCode(root, ["
|
|
4399
|
-
|
|
4464
|
+
], env))) !== successExitCode) return;
|
|
4465
|
+
yield* _(git(root, ["add", "-A"], env));
|
|
4466
|
+
const stashExit = yield* _(gitExitCode(root, ["stash", "--include-untracked"], env));
|
|
4467
|
+
yield* _(git(root, [
|
|
4468
|
+
"reset",
|
|
4469
|
+
"--hard",
|
|
4470
|
+
`origin/${baseBranch}`
|
|
4471
|
+
], env));
|
|
4472
|
+
if (stashExit === successExitCode) {
|
|
4473
|
+
if ((yield* _(gitExitCode(root, ["stash", "pop"], env))) !== successExitCode) {
|
|
4474
|
+
yield* _(gitExitCode(root, [
|
|
4475
|
+
"checkout",
|
|
4476
|
+
"--theirs",
|
|
4477
|
+
"--",
|
|
4478
|
+
"."
|
|
4479
|
+
], env));
|
|
4480
|
+
yield* _(git(root, ["add", "-A"], env));
|
|
4481
|
+
yield* _(gitExitCode(root, ["stash", "drop"], env));
|
|
4482
|
+
}
|
|
4483
|
+
}
|
|
4400
4484
|
});
|
|
4401
4485
|
var pushToNewBranch = (root, baseBranch, originPushTarget, env) => Effect.gen(function* (_) {
|
|
4402
4486
|
const headShort = yield* _(gitCapture$1(root, [
|
|
@@ -4422,15 +4506,9 @@ var getCurrentBranch = (root, env) => gitCapture$1(root, [
|
|
|
4422
4506
|
var runStateSyncOps = (root, originUrl, message, env, options) => Effect.gen(function* (_) {
|
|
4423
4507
|
const originPushTarget = resolveOriginPushTarget(options?.originPushUrlOverride ?? null);
|
|
4424
4508
|
yield* _(normalizeLegacyStateProjects(root));
|
|
4425
|
-
yield* _(commitAllIfNeeded(root, resolveSyncMessage(message), env));
|
|
4426
4509
|
const baseBranch = resolveBaseBranch(yield* _(getCurrentBranch(root, env)));
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
const compareUrl = tryBuildGithubCompareUrl(originUrl, baseBranch, prBranch);
|
|
4430
|
-
yield* _(Effect.logWarning(`State sync needs manual merge: pushed changes to branch '${prBranch}'.`));
|
|
4431
|
-
yield* _(logOpenPr(originUrl, baseBranch, prBranch, compareUrl));
|
|
4432
|
-
return;
|
|
4433
|
-
}
|
|
4510
|
+
yield* _(pullRemoteAndRestoreLocal(root, baseBranch, env));
|
|
4511
|
+
yield* _(commitAllIfNeeded(root, resolveSyncMessage(message), env));
|
|
4434
4512
|
const pushExit = yield* _(gitExitCode(root, [
|
|
4435
4513
|
"push",
|
|
4436
4514
|
"--no-verify",
|
|
@@ -4517,7 +4595,7 @@ var autoSyncState = (message) => Effect.gen(function* (_) {
|
|
|
4517
4595
|
onFailure: (error) => Effect.logWarning(`State auto-sync failed: ${String(error)}`),
|
|
4518
4596
|
onSuccess: () => Effect.void
|
|
4519
4597
|
}), Effect.asVoid);
|
|
4520
|
-
var cloneStateRepo = (root, input) => Effect.gen(function* (_) {
|
|
4598
|
+
var cloneStateRepo = (root, input, env) => Effect.gen(function* (_) {
|
|
4521
4599
|
const cloneBranchExit = yield* _(runCommandExitCode({
|
|
4522
4600
|
cwd: root,
|
|
4523
4601
|
command: "git",
|
|
@@ -4528,7 +4606,7 @@ var cloneStateRepo = (root, input) => Effect.gen(function* (_) {
|
|
|
4528
4606
|
input.repoUrl,
|
|
4529
4607
|
root
|
|
4530
4608
|
],
|
|
4531
|
-
env
|
|
4609
|
+
env
|
|
4532
4610
|
}));
|
|
4533
4611
|
if (cloneBranchExit === successExitCode) return;
|
|
4534
4612
|
yield* _(Effect.logWarning(`git clone --branch ${input.repoRef} failed (exit ${cloneBranchExit}); retrying without --branch`));
|
|
@@ -4540,58 +4618,63 @@ var cloneStateRepo = (root, input) => Effect.gen(function* (_) {
|
|
|
4540
4618
|
input.repoUrl,
|
|
4541
4619
|
root
|
|
4542
4620
|
],
|
|
4543
|
-
env
|
|
4621
|
+
env
|
|
4544
4622
|
}));
|
|
4545
4623
|
if (cloneDefaultExit !== successExitCode) return yield* _(Effect.fail(new CommandFailedError({
|
|
4546
4624
|
command: "git clone",
|
|
4547
4625
|
exitCode: cloneDefaultExit
|
|
4548
4626
|
})));
|
|
4549
4627
|
}).pipe(Effect.asVoid);
|
|
4550
|
-
var initRepoIfNeeded = (fs, path, root, input) => Effect.gen(function* (_) {
|
|
4628
|
+
var initRepoIfNeeded = (fs, path, root, input, env) => Effect.gen(function* (_) {
|
|
4551
4629
|
yield* _(fs.makeDirectory(root, { recursive: true }));
|
|
4552
4630
|
const gitDir = path.join(root, ".git");
|
|
4553
4631
|
if (yield* _(fs.exists(gitDir))) return;
|
|
4554
4632
|
if ((yield* _(fs.readDirectory(root))).length === 0) {
|
|
4555
|
-
yield* _(cloneStateRepo(root, input));
|
|
4633
|
+
yield* _(cloneStateRepo(root, input, env));
|
|
4556
4634
|
yield* _(Effect.log(`State dir cloned: ${root}`));
|
|
4557
4635
|
return;
|
|
4558
4636
|
}
|
|
4559
|
-
yield* _(git(root, ["init"],
|
|
4637
|
+
yield* _(git(root, ["init", "--initial-branch=main"], env));
|
|
4560
4638
|
}).pipe(Effect.asVoid);
|
|
4561
|
-
var ensureOriginRemote = (root, repoUrl) => Effect.gen(function* (_) {
|
|
4639
|
+
var ensureOriginRemote = (root, repoUrl, env) => Effect.gen(function* (_) {
|
|
4562
4640
|
if ((yield* _(gitExitCode(root, [
|
|
4563
4641
|
"remote",
|
|
4564
4642
|
"set-url",
|
|
4565
4643
|
"origin",
|
|
4566
4644
|
repoUrl
|
|
4567
|
-
],
|
|
4645
|
+
], env))) === successExitCode) return;
|
|
4568
4646
|
yield* _(git(root, [
|
|
4569
4647
|
"remote",
|
|
4570
4648
|
"add",
|
|
4571
4649
|
"origin",
|
|
4572
4650
|
repoUrl
|
|
4573
|
-
],
|
|
4651
|
+
], env));
|
|
4574
4652
|
});
|
|
4575
|
-
var checkoutBranchBestEffort = (root, repoRef) => Effect.gen(function* (_) {
|
|
4653
|
+
var checkoutBranchBestEffort = (root, repoRef, env) => Effect.gen(function* (_) {
|
|
4576
4654
|
const checkoutExit = yield* _(gitExitCode(root, [
|
|
4577
4655
|
"checkout",
|
|
4578
4656
|
"-B",
|
|
4579
4657
|
repoRef
|
|
4580
|
-
],
|
|
4658
|
+
], env));
|
|
4581
4659
|
if (checkoutExit === successExitCode) return;
|
|
4582
4660
|
yield* _(Effect.logWarning(`git checkout -B ${repoRef} failed (exit ${checkoutExit})`));
|
|
4583
4661
|
});
|
|
4584
|
-
var stateInit = (input) =>
|
|
4585
|
-
const
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4662
|
+
var stateInit = (input) => {
|
|
4663
|
+
const doInit = (env) => Effect.gen(function* (_) {
|
|
4664
|
+
const fs = yield* _(FileSystem.FileSystem);
|
|
4665
|
+
const path = yield* _(Path.Path);
|
|
4666
|
+
const root = resolveStateRoot(path, process.cwd());
|
|
4667
|
+
yield* _(initRepoIfNeeded(fs, path, root, input, env));
|
|
4668
|
+
yield* _(ensureOriginRemote(root, input.repoUrl, env));
|
|
4669
|
+
yield* _(adoptRemoteHistoryIfOrphan(root, input.repoRef, env));
|
|
4670
|
+
yield* _(checkoutBranchBestEffort(root, input.repoRef, env));
|
|
4671
|
+
yield* _(ensureStateGitignore(fs, path, root));
|
|
4672
|
+
yield* _(Effect.log(`State dir ready: ${root}`));
|
|
4673
|
+
yield* _(Effect.log(`Remote: ${input.repoUrl}`));
|
|
4674
|
+
}).pipe(Effect.asVoid);
|
|
4675
|
+
const token = input.token?.trim() ?? "";
|
|
4676
|
+
return token.length > 0 && isGithubHttpsRemote(input.repoUrl) ? withGithubAskpassEnv(token, doInit) : doInit(gitBaseEnv$1);
|
|
4677
|
+
};
|
|
4595
4678
|
var stateStatus = Effect.gen(function* (_) {
|
|
4596
4679
|
const output = yield* _(gitCapture$1(resolveStateRoot(yield* _(Path.Path), process.cwd()), [
|
|
4597
4680
|
"status",
|
|
@@ -6266,6 +6349,87 @@ var authCodexStatus = (command) => withCodexAuth(command, ({ accountPath, cwd })
|
|
|
6266
6349
|
}));
|
|
6267
6350
|
var authCodexLogout = (command) => withCodexAuth(command, ({ accountPath, cwd }) => runCodexLogout(cwd, accountPath)).pipe(Effect.zipRight(autoSyncState(`chore(state): auth codex logout ${normalizeAccountLabel(command.label, "default")}`)));
|
|
6268
6351
|
//#endregion
|
|
6352
|
+
//#region ../lib/src/usecases/state-repo-github.ts
|
|
6353
|
+
var dotDockerGitRepoName = ".docker-git";
|
|
6354
|
+
var defaultStateRef = "main";
|
|
6355
|
+
var resolveViewerLogin = (cwd, hostPath, token) => Effect.gen(function* (_) {
|
|
6356
|
+
const raw = yield* _(runGhApiCapture(cwd, hostPath, token, [
|
|
6357
|
+
"/user",
|
|
6358
|
+
"--jq",
|
|
6359
|
+
".login"
|
|
6360
|
+
]));
|
|
6361
|
+
if (raw.length === 0) return yield* _(Effect.fail(new CommandFailedError({
|
|
6362
|
+
command: "gh api /user --jq .login",
|
|
6363
|
+
exitCode: 1
|
|
6364
|
+
})));
|
|
6365
|
+
return raw;
|
|
6366
|
+
});
|
|
6367
|
+
var getRepoCloneUrl = (cwd, hostPath, token, login) => runGhApiNullable(cwd, hostPath, token, [
|
|
6368
|
+
`/repos/${login}/${dotDockerGitRepoName}`,
|
|
6369
|
+
"--jq",
|
|
6370
|
+
".clone_url"
|
|
6371
|
+
]);
|
|
6372
|
+
var createStateRepo = (cwd, hostPath, token) => runGhApiNullable(cwd, hostPath, token, [
|
|
6373
|
+
"-X",
|
|
6374
|
+
"POST",
|
|
6375
|
+
"/user/repos",
|
|
6376
|
+
"-f",
|
|
6377
|
+
`name=${dotDockerGitRepoName}`,
|
|
6378
|
+
"-f",
|
|
6379
|
+
"private=false",
|
|
6380
|
+
"-f",
|
|
6381
|
+
"auto_init=true",
|
|
6382
|
+
"--jq",
|
|
6383
|
+
".clone_url"
|
|
6384
|
+
]);
|
|
6385
|
+
/**
|
|
6386
|
+
* Ensures the .docker-git state repository exists on GitHub and is initialised locally.
|
|
6387
|
+
*
|
|
6388
|
+
* On GitHub auth, immediately:
|
|
6389
|
+
* 1. Resolve the authenticated user's login via the GitHub API
|
|
6390
|
+
* 2. Check whether `<login>/.docker-git` exists on GitHub
|
|
6391
|
+
* 3. If missing, create the repository (public, auto-initialised with a README)
|
|
6392
|
+
* 4. Initialise the local `~/.docker-git` directory as a clone of that repository
|
|
6393
|
+
*
|
|
6394
|
+
* All failures are swallowed and logged as warnings so they never abort the auth
|
|
6395
|
+
* flow itself.
|
|
6396
|
+
*
|
|
6397
|
+
* @param token - A valid GitHub personal-access or OAuth token
|
|
6398
|
+
* @returns Effect<void, never, GithubStateRepoRuntime>
|
|
6399
|
+
*
|
|
6400
|
+
* @pure false
|
|
6401
|
+
* @effect FileSystem, CommandExecutor (Docker gh CLI, git)
|
|
6402
|
+
* @invariant ∀token ∈ ValidTokens: ensureStateDotDockerGitRepo(token) → cloned(~/.docker-git) ∨ warned
|
|
6403
|
+
* @precondition token.length > 0
|
|
6404
|
+
* @postcondition ~/.docker-git is a git repo with origin pointing to github.com/<login>/.docker-git
|
|
6405
|
+
* @complexity O(1) API calls
|
|
6406
|
+
* @throws Never - all errors are caught and logged
|
|
6407
|
+
*/
|
|
6408
|
+
var ensureStateDotDockerGitRepo = (token) => withFsPathContext(({ cwd, fs, path }) => Effect.gen(function* (_) {
|
|
6409
|
+
const ghRoot = resolvePathFromCwd(path, cwd, ghAuthRoot);
|
|
6410
|
+
yield* _(fs.makeDirectory(ghRoot, { recursive: true }));
|
|
6411
|
+
yield* _(ensureGhAuthImage(fs, path, cwd, "gh api"));
|
|
6412
|
+
const login = yield* _(resolveViewerLogin(cwd, ghRoot, token));
|
|
6413
|
+
let cloneUrl = yield* _(getRepoCloneUrl(cwd, ghRoot, token, login));
|
|
6414
|
+
if (cloneUrl === null) {
|
|
6415
|
+
yield* _(Effect.log(`Creating .docker-git repository for ${login}...`));
|
|
6416
|
+
cloneUrl = yield* _(createStateRepo(cwd, ghRoot, token));
|
|
6417
|
+
}
|
|
6418
|
+
if (cloneUrl === null) {
|
|
6419
|
+
yield* _(Effect.logWarning(`Could not resolve or create .docker-git repository for ${login}`));
|
|
6420
|
+
return;
|
|
6421
|
+
}
|
|
6422
|
+
yield* _(Effect.log(`Initializing state repository: ${cloneUrl}`));
|
|
6423
|
+
yield* _(stateInit({
|
|
6424
|
+
repoUrl: cloneUrl,
|
|
6425
|
+
repoRef: defaultStateRef,
|
|
6426
|
+
token
|
|
6427
|
+
}));
|
|
6428
|
+
})).pipe(Effect.matchEffect({
|
|
6429
|
+
onFailure: (error) => Effect.logWarning(`State repo setup failed: ${error instanceof Error ? error.message : String(error)}`),
|
|
6430
|
+
onSuccess: () => Effect.void
|
|
6431
|
+
}));
|
|
6432
|
+
//#endregion
|
|
6269
6433
|
//#region ../lib/src/usecases/auth-github.ts
|
|
6270
6434
|
var ensureGithubOrchLayout = (cwd, envGlobalPath) => migrateLegacyOrchLayout(cwd, {
|
|
6271
6435
|
envGlobalPath,
|
|
@@ -6363,6 +6527,7 @@ var runGithubInteractiveLogin = (cwd, fs, path, envPath, command) => Effect.gen(
|
|
|
6363
6527
|
const resolved = yield* _(resolveGithubTokenFromGh(cwd, accountPath));
|
|
6364
6528
|
yield* _(ensureEnvFile$1(fs, path, envPath));
|
|
6365
6529
|
yield* _(persistGithubToken(fs, envPath, buildGithubTokenKey(command.label), resolved));
|
|
6530
|
+
return resolved;
|
|
6366
6531
|
});
|
|
6367
6532
|
var authGithubLogin = (command) => withFsPathContext(({ cwd, fs, path }) => Effect.gen(function* (_) {
|
|
6368
6533
|
yield* _(ensureGithubOrchLayout(cwd, command.envGlobalPath));
|
|
@@ -6373,10 +6538,11 @@ var authGithubLogin = (command) => withFsPathContext(({ cwd, fs, path }) => Effe
|
|
|
6373
6538
|
if (token.length > 0) {
|
|
6374
6539
|
yield* _(ensureEnvFile$1(fs, path, envPath));
|
|
6375
6540
|
yield* _(persistGithubToken(fs, envPath, key, token));
|
|
6541
|
+
yield* _(ensureStateDotDockerGitRepo(token));
|
|
6376
6542
|
yield* _(autoSyncState(`chore(state): auth gh ${label}`));
|
|
6377
6543
|
return;
|
|
6378
6544
|
}
|
|
6379
|
-
yield* _(runGithubInteractiveLogin(cwd, fs, path, envPath, command));
|
|
6545
|
+
yield* _(ensureStateDotDockerGitRepo(yield* _(runGithubInteractiveLogin(cwd, fs, path, envPath, command))));
|
|
6380
6546
|
yield* _(autoSyncState(`chore(state): auth gh ${label}`));
|
|
6381
6547
|
}));
|
|
6382
6548
|
var authGithubStatus = (command) => withEnvContext(command.envGlobalPath, ({ current, envPath }) => Effect.gen(function* (_) {
|