@brainervirus/workit-codex 7.0.0 → 7.2.0
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/.codex-plugin/plugin.json +1 -1
- package/dist/launch-mcp.js +555 -67
- package/dist/workit-hook.js +270 -37
- package/package.json +3 -3
- package/skills/workit-implement/SKILL.md +3 -2
- package/skills/workit-ship/SKILL.md +31 -13
package/dist/launch-mcp.js
CHANGED
|
@@ -6625,7 +6625,7 @@ import { existsSync as existsSync9, realpathSync as realpathSync7, statSync as s
|
|
|
6625
6625
|
import path21 from "node:path";
|
|
6626
6626
|
|
|
6627
6627
|
// packages/workit-core/src/core.ts
|
|
6628
|
-
import { spawnSync as
|
|
6628
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
6629
6629
|
import { existsSync as existsSync7, realpathSync as realpathSync5 } from "node:fs";
|
|
6630
6630
|
import path19 from "node:path";
|
|
6631
6631
|
|
|
@@ -18884,6 +18884,11 @@ function worktreeSignal(cwd, options = {}) {
|
|
|
18884
18884
|
}
|
|
18885
18885
|
return `sig:${hash.digest("hex")}`;
|
|
18886
18886
|
}
|
|
18887
|
+
function mergeBase(cwd, a, b) {
|
|
18888
|
+
if (!safeArg(a) || !safeArg(b))
|
|
18889
|
+
return null;
|
|
18890
|
+
return line(git2(cwd, ["merge-base", a, b]));
|
|
18891
|
+
}
|
|
18887
18892
|
function patchId(cwd, base, head) {
|
|
18888
18893
|
if (!safeArg(base) || !safeArg(head))
|
|
18889
18894
|
return null;
|
|
@@ -18907,9 +18912,33 @@ function patchId(cwd, base, head) {
|
|
|
18907
18912
|
const id = git2(cwd, ["patch-id", "--stable"], { input: diff.stdout });
|
|
18908
18913
|
return line(id)?.split(/\s+/u)[0] ?? null;
|
|
18909
18914
|
}
|
|
18915
|
+
function remoteNames(cwd) {
|
|
18916
|
+
return (git2(cwd, ["remote"]).stdout ?? "").split(/\r?\n/u).map((value) => value.trim()).filter(Boolean);
|
|
18917
|
+
}
|
|
18918
|
+
function resolveRef(cwd, ref) {
|
|
18919
|
+
if (!safeArg(ref))
|
|
18920
|
+
return null;
|
|
18921
|
+
return line(git2(cwd, ["rev-parse", "--verify", "-q", `${ref}^{commit}`]));
|
|
18922
|
+
}
|
|
18923
|
+
var config2 = (cwd, key) => line(git2(cwd, ["config", "--get", key]));
|
|
18910
18924
|
function currentBranch(cwd) {
|
|
18911
18925
|
return line(git2(cwd, ["symbolic-ref", "--short", "-q", "HEAD"]));
|
|
18912
18926
|
}
|
|
18927
|
+
function pushRemoteName(cwd, branch) {
|
|
18928
|
+
const name = branch ?? currentBranch(cwd);
|
|
18929
|
+
const remotes = remoteNames(cwd);
|
|
18930
|
+
const candidates = [
|
|
18931
|
+
name ? config2(cwd, `branch.${name}.pushRemote`) : null,
|
|
18932
|
+
config2(cwd, "remote.pushDefault"),
|
|
18933
|
+
name ? config2(cwd, `branch.${name}.remote`) : null
|
|
18934
|
+
];
|
|
18935
|
+
for (const candidate of candidates)
|
|
18936
|
+
if (candidate && candidate !== "." && remotes.includes(candidate))
|
|
18937
|
+
return candidate;
|
|
18938
|
+
if (remotes.includes("origin"))
|
|
18939
|
+
return "origin";
|
|
18940
|
+
return remotes.length === 1 ? remotes[0] : null;
|
|
18941
|
+
}
|
|
18913
18942
|
|
|
18914
18943
|
// packages/workit-core/src/core/policy/derive.ts
|
|
18915
18944
|
import { existsSync as existsSync3 } from "node:fs";
|
|
@@ -20523,6 +20552,8 @@ var readConfig = () => {
|
|
|
20523
20552
|
throw new Error(result.error);
|
|
20524
20553
|
return result.config ?? DEFAULTS;
|
|
20525
20554
|
};
|
|
20555
|
+
var vcsConfigPath = () => process.env.WORKFLOW_VCS_CONFIG ?? path12.join(configDir(), "vcs.json");
|
|
20556
|
+
var branchGlobPattern = (glob) => new RegExp(`^${glob.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")}$`, "i");
|
|
20526
20557
|
var resolveBranchPolicy = (config, workspace) => {
|
|
20527
20558
|
const wp = workspace?.branchPolicy ?? {};
|
|
20528
20559
|
const preset = Object.hasOwn(PRESETS, wp.preset) ? wp.preset : config.branchPolicy?.preset ?? "gitflow";
|
|
@@ -20530,7 +20561,7 @@ var resolveBranchPolicy = (config, workspace) => {
|
|
|
20530
20561
|
allowed: wp.allowed,
|
|
20531
20562
|
protectedNames: wp.protected
|
|
20532
20563
|
}, config);
|
|
20533
|
-
const allowed = merged.allowed.map(
|
|
20564
|
+
const allowed = merged.allowed.map(branchGlobPattern);
|
|
20534
20565
|
return {
|
|
20535
20566
|
preset,
|
|
20536
20567
|
allowed,
|
|
@@ -20547,16 +20578,6 @@ var COMMIT_PRESETS = [
|
|
|
20547
20578
|
"custom",
|
|
20548
20579
|
"auto"
|
|
20549
20580
|
];
|
|
20550
|
-
var resolveCommitPolicy = (config, workspace) => {
|
|
20551
|
-
const wp = workspace?.commitPolicy ?? {};
|
|
20552
|
-
if (COMMIT_PRESETS.includes(String(wp.preset ?? ""))) {
|
|
20553
|
-
return {
|
|
20554
|
-
preset: wp.preset,
|
|
20555
|
-
...typeof wp.pattern === "string" ? { pattern: wp.pattern } : {}
|
|
20556
|
-
};
|
|
20557
|
-
}
|
|
20558
|
-
return config.commitPolicy ?? { preset: "conventional" };
|
|
20559
|
-
};
|
|
20560
20581
|
|
|
20561
20582
|
// packages/workit-core/src/core/workspaces.ts
|
|
20562
20583
|
import { createHash as createHash8 } from "node:crypto";
|
|
@@ -20595,26 +20616,31 @@ var versionSourceSchema = discriminatedUnion("kind", [
|
|
|
20595
20616
|
object({ kind: literal("manual") }).strict()
|
|
20596
20617
|
]);
|
|
20597
20618
|
var releaseTrackSchema = object({
|
|
20598
|
-
strategy: branchPreset,
|
|
20619
|
+
strategy: branchPreset.optional(),
|
|
20599
20620
|
productionBranch: nonBlank,
|
|
20600
20621
|
integrationBranch: nonBlank,
|
|
20601
|
-
naming: object({
|
|
20602
|
-
|
|
20603
|
-
|
|
20604
|
-
|
|
20605
|
-
|
|
20606
|
-
|
|
20607
|
-
|
|
20608
|
-
|
|
20622
|
+
naming: object({
|
|
20623
|
+
feature: nonBlank.optional(),
|
|
20624
|
+
release: nonBlank.optional(),
|
|
20625
|
+
hotfix: nonBlank.optional()
|
|
20626
|
+
}).passthrough().optional(),
|
|
20627
|
+
baseBranch: nonBlank.optional(),
|
|
20628
|
+
mergeBackBranches: array(nonBlank).optional(),
|
|
20629
|
+
pullRequestTarget: nonBlank.optional(),
|
|
20630
|
+
tagNamespace: string2().optional(),
|
|
20631
|
+
versionSource: versionSourceSchema.optional(),
|
|
20632
|
+
requiredChecks: array(nonBlank).optional(),
|
|
20633
|
+
critical: array(nonBlank).optional()
|
|
20634
|
+
}).passthrough().superRefine((track, context) => {
|
|
20609
20635
|
for (const [field, values] of [
|
|
20610
|
-
["mergeBackBranches", track.mergeBackBranches],
|
|
20611
|
-
["requiredChecks", track.requiredChecks]
|
|
20636
|
+
["mergeBackBranches", track.mergeBackBranches ?? []],
|
|
20637
|
+
["requiredChecks", track.requiredChecks ?? []]
|
|
20612
20638
|
]) {
|
|
20613
20639
|
if (new Set(values).size !== values.length) {
|
|
20614
20640
|
context.addIssue({ code: "custom", path: [field], message: "entries must be unique" });
|
|
20615
20641
|
}
|
|
20616
20642
|
}
|
|
20617
|
-
if (track.versionSource
|
|
20643
|
+
if (track.versionSource?.kind === "package-json" && (path13.posix.isAbsolute(track.versionSource.path.replaceAll("\\", "/")) || /^[A-Za-z]:\//u.test(track.versionSource.path.replaceAll("\\", "/")) || track.versionSource.path.replaceAll("\\", "/").split("/").includes(".."))) {
|
|
20618
20644
|
context.addIssue({
|
|
20619
20645
|
code: "custom",
|
|
20620
20646
|
path: ["versionSource", "path"],
|
|
@@ -20632,7 +20658,7 @@ var workspaceConfigSchema = object({
|
|
|
20632
20658
|
account: nonBlank.optional()
|
|
20633
20659
|
}).passthrough().optional(),
|
|
20634
20660
|
autoApprove: union([boolean2(), array(nonBlank)]).optional(),
|
|
20635
|
-
defaultEndpoint:
|
|
20661
|
+
defaultEndpoint: unknown().optional(),
|
|
20636
20662
|
verification: _enum(["self", "independent"]).optional(),
|
|
20637
20663
|
autonomy: object(Object.fromEntries(["push", "pr", "merge", "release", "rerun"].map((kind) => [
|
|
20638
20664
|
kind,
|
|
@@ -20882,7 +20908,7 @@ var resolveRuntimeWorkspaceVcs = (cwd) => resolveRuntimeWorkspaceCandidate(cwd,
|
|
|
20882
20908
|
var runtimeWorkspaceIndexSchema = object({
|
|
20883
20909
|
workspaces: array(object({ name: nonBlank, glob: nonBlank }).passthrough()).optional()
|
|
20884
20910
|
}).passthrough();
|
|
20885
|
-
var
|
|
20911
|
+
var matchRuntimeWorkspace = (cwd) => {
|
|
20886
20912
|
const file = path13.join(configDir(), "workspaces.json");
|
|
20887
20913
|
let raw;
|
|
20888
20914
|
try {
|
|
@@ -20917,8 +20943,17 @@ var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
|
|
|
20917
20943
|
});
|
|
20918
20944
|
const workspaceName = process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined;
|
|
20919
20945
|
const selected = selectWorkspaceMatch(matches, cwd, workspaceName);
|
|
20920
|
-
|
|
20946
|
+
return selected ? { file, selected } : null;
|
|
20947
|
+
};
|
|
20948
|
+
var resolveRuntimeReleaseTracks = (cwd) => {
|
|
20949
|
+
const matched = matchRuntimeWorkspace(cwd);
|
|
20950
|
+
return matched ? { workspace: matched.selected.name, releaseTracks: matched.selected.releaseTracks } : null;
|
|
20951
|
+
};
|
|
20952
|
+
var resolveRuntimeWorkspaceCandidate = (cwd, kind) => {
|
|
20953
|
+
const matched = matchRuntimeWorkspace(cwd);
|
|
20954
|
+
if (!matched)
|
|
20921
20955
|
return null;
|
|
20956
|
+
const { file, selected } = matched;
|
|
20922
20957
|
const policy = runtimeWorkspacePolicySchema(kind).safeParse(selected);
|
|
20923
20958
|
if (!policy.success) {
|
|
20924
20959
|
const detail = policy.error.issues.map((issue) => `${issue.path.map(String).join(".") || "workspace"}: ${issue.message}`).join("; ");
|
|
@@ -20944,15 +20979,410 @@ var resolveRuntimeWorkspacePolicy = (cwd, kind, requestedProfile) => {
|
|
|
20944
20979
|
source: profilePolicy ? `profile:${profileName}` : workspacePolicy ? `workspace:${candidate.name}` : "user-default"
|
|
20945
20980
|
};
|
|
20946
20981
|
};
|
|
20982
|
+
function workspaceDefaultTarget(cwd, globalDefault) {
|
|
20983
|
+
const ws = resolveRuntimeWorkspaceVcs(cwd);
|
|
20984
|
+
const wp = ws?.branchPolicy ?? {};
|
|
20985
|
+
const hasWorkspacePolicy = typeof wp.preset === "string" && Object.hasOwn(PRESETS, wp.preset);
|
|
20986
|
+
const selected = resolveRuntimeWorkspacePolicy(cwd, "branch", process.env.WORKFLOW_PROFILE?.trim() || undefined);
|
|
20987
|
+
const policyDefault = resolveBranchPolicy(readConfig(), selected.policy ? { branchPolicy: selected.policy } : null).defaultTargetBranch;
|
|
20988
|
+
return String(ws?.vcs?.defaultTargetBranch ?? (hasWorkspacePolicy ? policyDefault : globalDefault ?? policyDefault) ?? "develop");
|
|
20989
|
+
}
|
|
20947
20990
|
|
|
20948
20991
|
// packages/workit-core/src/core/vcs-config.ts
|
|
20949
20992
|
import fs12 from "node:fs";
|
|
20950
20993
|
import path14 from "node:path";
|
|
20994
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
20995
|
+
|
|
20996
|
+
// packages/workit-core/src/core/release-tracks.ts
|
|
20997
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
20951
20998
|
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
20952
|
-
var
|
|
20999
|
+
var KNOWN_FIELDS = new Set([
|
|
21000
|
+
"strategy",
|
|
21001
|
+
"productionBranch",
|
|
21002
|
+
"integrationBranch",
|
|
21003
|
+
"naming",
|
|
21004
|
+
"baseBranch",
|
|
21005
|
+
"mergeBackBranches",
|
|
21006
|
+
"pullRequestTarget",
|
|
21007
|
+
"tagNamespace",
|
|
21008
|
+
"versionSource",
|
|
21009
|
+
"requiredChecks",
|
|
21010
|
+
"critical"
|
|
21011
|
+
]);
|
|
21012
|
+
var BRANCH_FIELDS = ["productionBranch", "integrationBranch", "baseBranch", "pullRequestTarget"];
|
|
21013
|
+
var PLACEHOLDER = /\{[^}]*\}/gu;
|
|
21014
|
+
var isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21015
|
+
var branchName = (value) => typeof value === "string" && value.trim() && !value.trim().startsWith("-") ? value.trim() : null;
|
|
21016
|
+
var namedBranches = (entry) => [
|
|
21017
|
+
...BRANCH_FIELDS.map((field) => branchName(entry[field])),
|
|
21018
|
+
...Array.isArray(entry.mergeBackBranches) ? entry.mergeBackBranches.map(branchName) : []
|
|
21019
|
+
].filter((name) => name !== null);
|
|
21020
|
+
var literalOf = (template) => template.replace(PLACEHOLDER, "").replace(/[*/]/gu, "").trim();
|
|
21021
|
+
function readReleaseTracks(raw) {
|
|
21022
|
+
const out = { tracks: [], issues: [], error: null, protectedBranches: [] };
|
|
21023
|
+
if (raw === undefined || raw === null)
|
|
21024
|
+
return out;
|
|
21025
|
+
if (!isRecord3(raw)) {
|
|
21026
|
+
out.issues.push("releaseTracks is not an object; ignored");
|
|
21027
|
+
return out;
|
|
21028
|
+
}
|
|
21029
|
+
const fatal = [];
|
|
21030
|
+
const protectedNames = new Set;
|
|
21031
|
+
for (const [name, entry] of Object.entries(raw).toSorted(([a], [b]) => a < b ? -1 : 1)) {
|
|
21032
|
+
const label = `release track ${JSON.stringify(name)}`;
|
|
21033
|
+
if (!isRecord3(entry)) {
|
|
21034
|
+
out.issues.push(`${label} is not an object; ignored`);
|
|
21035
|
+
continue;
|
|
21036
|
+
}
|
|
21037
|
+
for (const branch of namedBranches(entry))
|
|
21038
|
+
protectedNames.add(branch);
|
|
21039
|
+
if (!name.trim()) {
|
|
21040
|
+
out.issues.push("a release track with a blank name was ignored");
|
|
21041
|
+
continue;
|
|
21042
|
+
}
|
|
21043
|
+
let critical = [];
|
|
21044
|
+
if (Array.isArray(entry.critical))
|
|
21045
|
+
critical = entry.critical.filter((item) => typeof item === "string");
|
|
21046
|
+
else if (entry.critical !== undefined)
|
|
21047
|
+
out.issues.push(`${label} critical: must be a list of field names; ignored`);
|
|
21048
|
+
const isCritical = (field) => critical.some((item) => field === item || field.startsWith(`${item}.`));
|
|
21049
|
+
const problem = (field, message) => {
|
|
21050
|
+
if (isCritical(field))
|
|
21051
|
+
fatal.push(`${label} ${field}: ${message}`);
|
|
21052
|
+
else
|
|
21053
|
+
out.issues.push(`${label} ${field}: ${message}`);
|
|
21054
|
+
};
|
|
21055
|
+
for (const key of Object.keys(entry))
|
|
21056
|
+
if (!KNOWN_FIELDS.has(key))
|
|
21057
|
+
problem(key, "unknown field, ignored");
|
|
21058
|
+
const productionBranch = branchName(entry.productionBranch);
|
|
21059
|
+
const integrationBranch = branchName(entry.integrationBranch);
|
|
21060
|
+
if (!productionBranch)
|
|
21061
|
+
problem("productionBranch", "missing or not a branch name");
|
|
21062
|
+
if (!integrationBranch)
|
|
21063
|
+
problem("integrationBranch", "missing or not a branch name");
|
|
21064
|
+
const optionalBranch = (field) => {
|
|
21065
|
+
if (entry[field] === undefined)
|
|
21066
|
+
return null;
|
|
21067
|
+
const value = branchName(entry[field]);
|
|
21068
|
+
if (!value)
|
|
21069
|
+
problem(field, "not a branch name; using the integration branch");
|
|
21070
|
+
return value;
|
|
21071
|
+
};
|
|
21072
|
+
const baseBranch = optionalBranch("baseBranch");
|
|
21073
|
+
const pullRequestTarget = optionalBranch("pullRequestTarget");
|
|
21074
|
+
let mergeBackBranches = [];
|
|
21075
|
+
if (entry.mergeBackBranches !== undefined) {
|
|
21076
|
+
const list = Array.isArray(entry.mergeBackBranches) ? entry.mergeBackBranches.map(branchName) : [null];
|
|
21077
|
+
if (list.some((item) => item === null))
|
|
21078
|
+
problem("mergeBackBranches", "must be a list of branch names; ignored");
|
|
21079
|
+
else
|
|
21080
|
+
mergeBackBranches = [...new Set(list)];
|
|
21081
|
+
}
|
|
21082
|
+
const naming = {};
|
|
21083
|
+
if (entry.naming !== undefined) {
|
|
21084
|
+
if (!isRecord3(entry.naming))
|
|
21085
|
+
problem("naming", "not an object; ignored");
|
|
21086
|
+
else
|
|
21087
|
+
for (const kind of ["feature", "release", "hotfix"]) {
|
|
21088
|
+
const template = entry.naming[kind];
|
|
21089
|
+
if (template === undefined)
|
|
21090
|
+
continue;
|
|
21091
|
+
if (typeof template !== "string" || !template.trim())
|
|
21092
|
+
problem(`naming.${kind}`, "not a template string; ignored");
|
|
21093
|
+
else if (!literalOf(template))
|
|
21094
|
+
problem(`naming.${kind}`, "needs literal text besides placeholders; ignored");
|
|
21095
|
+
else
|
|
21096
|
+
naming[kind] = template.trim();
|
|
21097
|
+
}
|
|
21098
|
+
}
|
|
21099
|
+
if (!productionBranch || !integrationBranch) {
|
|
21100
|
+
out.issues.push(`${label} was skipped: it needs a productionBranch and integrationBranch`);
|
|
21101
|
+
continue;
|
|
21102
|
+
}
|
|
21103
|
+
out.tracks.push({
|
|
21104
|
+
name,
|
|
21105
|
+
productionBranch,
|
|
21106
|
+
integrationBranch,
|
|
21107
|
+
baseBranch: baseBranch ?? integrationBranch,
|
|
21108
|
+
pullRequestTarget: pullRequestTarget ?? integrationBranch,
|
|
21109
|
+
mergeBackBranches,
|
|
21110
|
+
naming
|
|
21111
|
+
});
|
|
21112
|
+
}
|
|
21113
|
+
out.protectedBranches = [...protectedNames];
|
|
21114
|
+
if (fatal.length)
|
|
21115
|
+
out.error = `workspace releaseTracks cannot be read by this Workit (${fatal.join("; ")}); upgrade Workit or fix the track`;
|
|
21116
|
+
return out;
|
|
21117
|
+
}
|
|
21118
|
+
var IMPLICIT = "";
|
|
21119
|
+
var ownedBy = (tracks, branch) => tracks.filter((track) => [track.integrationBranch, track.productionBranch, track.baseBranch].includes(branch));
|
|
21120
|
+
var shortRef = (ref, remotes) => {
|
|
21121
|
+
const bare = ref.replace(/^refs\/heads\//u, "").replace(/^refs\/remotes\/[^/]+\//u, "");
|
|
21122
|
+
const remote = remotes.find((name) => bare.startsWith(`${name}/`));
|
|
21123
|
+
return remote ? bare.slice(remote.length + 1) : bare;
|
|
21124
|
+
};
|
|
21125
|
+
var MAX_RECORDED_HOPS = 10;
|
|
21126
|
+
function resolveReleaseTrack(input) {
|
|
21127
|
+
const tracks = [...input.tracks];
|
|
21128
|
+
const issues = [...input.issues ?? []];
|
|
21129
|
+
const requested = input.requested?.trim();
|
|
21130
|
+
if (tracks.length === 0) {
|
|
21131
|
+
if (requested)
|
|
21132
|
+
return {
|
|
21133
|
+
status: "invalid",
|
|
21134
|
+
error: `no release tracks configured for this workspace; --track ${requested} cannot apply`,
|
|
21135
|
+
issues
|
|
21136
|
+
};
|
|
21137
|
+
return { status: "none", issues };
|
|
21138
|
+
}
|
|
21139
|
+
const names = tracks.map((track) => track.name).join(", ");
|
|
21140
|
+
let envProblem = null;
|
|
21141
|
+
const done = (track, source, detail, warnings = [], ambiguous = null) => ({
|
|
21142
|
+
status: "resolved",
|
|
21143
|
+
track: track && track.name !== IMPLICIT ? track : null,
|
|
21144
|
+
source,
|
|
21145
|
+
detail,
|
|
21146
|
+
warnings: [...issues, ...envProblem ? [envProblem] : [], ...warnings],
|
|
21147
|
+
tracks,
|
|
21148
|
+
blocking: envProblem ?? ambiguous
|
|
21149
|
+
});
|
|
21150
|
+
if (requested) {
|
|
21151
|
+
const named = tracks.find((track) => track.name === requested);
|
|
21152
|
+
if (!named)
|
|
21153
|
+
return {
|
|
21154
|
+
status: "invalid",
|
|
21155
|
+
error: `no release track ${JSON.stringify(requested)}; configured: ${names}`,
|
|
21156
|
+
issues
|
|
21157
|
+
};
|
|
21158
|
+
return done(named, "flag", `track ${named.name} was requested explicitly`);
|
|
21159
|
+
}
|
|
21160
|
+
const owned = (branch) => branch !== null && tracks.some((track) => [
|
|
21161
|
+
track.integrationBranch,
|
|
21162
|
+
track.productionBranch,
|
|
21163
|
+
track.baseBranch,
|
|
21164
|
+
track.pullRequestTarget
|
|
21165
|
+
].includes(branch));
|
|
21166
|
+
const implicit = input.defaultBranch && !owned(input.defaultBranch) ? {
|
|
21167
|
+
name: IMPLICIT,
|
|
21168
|
+
productionBranch: input.defaultBranch,
|
|
21169
|
+
integrationBranch: input.defaultBranch,
|
|
21170
|
+
baseBranch: input.defaultBranch,
|
|
21171
|
+
pullRequestTarget: input.defaultBranch,
|
|
21172
|
+
mergeBackBranches: [],
|
|
21173
|
+
naming: {}
|
|
21174
|
+
} : null;
|
|
21175
|
+
const candidates = implicit ? [...tracks, implicit] : tracks;
|
|
21176
|
+
const label = (track) => track.name === IMPLICIT ? `the workspace default line (${track.integrationBranch})` : `track ${track.name}`;
|
|
21177
|
+
const fallback = (why) => {
|
|
21178
|
+
const byDefault = input.defaultBranch ? tracks.filter((track) => track.integrationBranch === input.defaultBranch || track.pullRequestTarget === input.defaultBranch) : [];
|
|
21179
|
+
const track = byDefault.length === 1 ? byDefault[0] : null;
|
|
21180
|
+
const target = track ? `track ${track.name}` : `default target ${input.defaultBranch ?? "(none)"}`;
|
|
21181
|
+
const ambiguous = candidates.length >= 2 ? `can't tell which release line ${input.branch ?? "HEAD"} is on (${why}); pass --track <name> (${names}) or --base <branch>` : null;
|
|
21182
|
+
return done(track, "default", `${why}; using the workspace ${target}`, [
|
|
21183
|
+
`release track not determined: ${why}; using the workspace ${target} (pass --track <name> to choose)`
|
|
21184
|
+
], ambiguous);
|
|
21185
|
+
};
|
|
21186
|
+
const branch = input.branch;
|
|
21187
|
+
if (branch) {
|
|
21188
|
+
const owners = ownedBy(candidates, branch);
|
|
21189
|
+
if (owners.length === 1)
|
|
21190
|
+
return done(owners[0], "branch", `${branch} is a branch of ${label(owners[0])}`);
|
|
21191
|
+
if (owners.length > 1)
|
|
21192
|
+
return fallback(`${branch} belongs to more than one track (${owners.map((track) => track.name).join(", ")})`);
|
|
21193
|
+
}
|
|
21194
|
+
const env = input.envRequested?.trim();
|
|
21195
|
+
if (env) {
|
|
21196
|
+
const named = tracks.find((track) => track.name === env);
|
|
21197
|
+
if (named)
|
|
21198
|
+
return done(named, "env", `WORKFLOW_RELEASE_TRACK selects track ${named.name}`);
|
|
21199
|
+
envProblem = `WORKFLOW_RELEASE_TRACK=${env} names no release track of this workspace (${names}); ignored`;
|
|
21200
|
+
}
|
|
21201
|
+
if (!branch)
|
|
21202
|
+
return fallback("HEAD is detached");
|
|
21203
|
+
if (tracks.length === 1 && !implicit)
|
|
21204
|
+
return done(tracks[0], "only-track", `${tracks[0].name} is the only track`);
|
|
21205
|
+
let remotes = null;
|
|
21206
|
+
const short = (ref) => shortRef(ref, remotes ??= input.probe.remotes());
|
|
21207
|
+
const ownerOf = (ref) => {
|
|
21208
|
+
const owner = ownedBy(candidates, short(ref));
|
|
21209
|
+
return owner.length === 1 ? owner[0] : null;
|
|
21210
|
+
};
|
|
21211
|
+
const followRecorded = (start) => {
|
|
21212
|
+
let cursor = start;
|
|
21213
|
+
const seen = new Set([start]);
|
|
21214
|
+
for (let hop = 0;hop < MAX_RECORDED_HOPS; hop += 1) {
|
|
21215
|
+
const recorded = input.probe.recordedBase(cursor);
|
|
21216
|
+
if (!recorded)
|
|
21217
|
+
return null;
|
|
21218
|
+
const base = short(recorded);
|
|
21219
|
+
const owner = ownerOf(base);
|
|
21220
|
+
if (owner)
|
|
21221
|
+
return owner;
|
|
21222
|
+
if (ownedBy(candidates, base).length > 1 || seen.has(base))
|
|
21223
|
+
return null;
|
|
21224
|
+
seen.add(base);
|
|
21225
|
+
cursor = base;
|
|
21226
|
+
}
|
|
21227
|
+
return null;
|
|
21228
|
+
};
|
|
21229
|
+
const recordedOwner = followRecorded(branch);
|
|
21230
|
+
if (recordedOwner)
|
|
21231
|
+
return done(recordedOwner, "recorded-base", `${branch} was created on ${label(recordedOwner)}'s line (recorded base)`);
|
|
21232
|
+
for (const source of ["reflog", "checkout"]) {
|
|
21233
|
+
const ref = source === "reflog" ? input.probe.createdFrom(branch) : input.probe.checkedOutFrom(branch);
|
|
21234
|
+
if (!ref)
|
|
21235
|
+
continue;
|
|
21236
|
+
const owner = ownerOf(ref) ?? followRecorded(short(ref));
|
|
21237
|
+
if (owner)
|
|
21238
|
+
return done(owner, source, `${branch} was created from ${short(ref)} (${source === "reflog" ? "branch reflog" : "HEAD reflog"})`);
|
|
21239
|
+
}
|
|
21240
|
+
const forks = [];
|
|
21241
|
+
for (const track of candidates)
|
|
21242
|
+
for (const ref of new Set([track.integrationBranch, track.baseBranch])) {
|
|
21243
|
+
const sha = input.probe.mergeBase(branch, ref);
|
|
21244
|
+
if (sha)
|
|
21245
|
+
forks.push({ track, ref, sha });
|
|
21246
|
+
}
|
|
21247
|
+
if (forks.length === 0)
|
|
21248
|
+
return fallback(`no track branch could be compared with ${branch} (fetch the track branches)`);
|
|
21249
|
+
const ancestry = new Map;
|
|
21250
|
+
const descends = (older, newer) => {
|
|
21251
|
+
if (older === newer)
|
|
21252
|
+
return false;
|
|
21253
|
+
const key = `${older}>${newer}`;
|
|
21254
|
+
if (!ancestry.has(key))
|
|
21255
|
+
ancestry.set(key, input.probe.isAncestor(older, newer));
|
|
21256
|
+
return ancestry.get(key);
|
|
21257
|
+
};
|
|
21258
|
+
const winners = forks.filter((fork) => forks.every((other) => other.track === fork.track || descends(other.sha, fork.sha)));
|
|
21259
|
+
const winningTracks = [...new Set(winners.map((fork) => fork.track))];
|
|
21260
|
+
if (winningTracks.length === 1 && forks.some((fork) => fork.track !== winningTracks[0])) {
|
|
21261
|
+
const win = winners[0];
|
|
21262
|
+
return done(win.track, "ancestry", `${branch} forked from ${win.ref} at ${win.sha.slice(0, 12)}, after every other line's fork point`);
|
|
21263
|
+
}
|
|
21264
|
+
if (winningTracks.length === 1)
|
|
21265
|
+
return fallback(`only ${label(winningTracks[0])} could be compared with ${branch}`);
|
|
21266
|
+
const newest = forks.filter((fork) => !forks.some((other) => descends(fork.sha, other.sha)));
|
|
21267
|
+
return fallback(`${branch} has the same or unrelated fork points with ${[...new Set(newest.map((fork) => `${fork.ref} (${fork.track.name === IMPLICIT ? "workspace default" : fork.track.name})`))].join(" and ")}`);
|
|
21268
|
+
}
|
|
21269
|
+
var git4 = (cwd, args) => {
|
|
21270
|
+
const run = spawnSync7("git", args, {
|
|
21271
|
+
cwd,
|
|
21272
|
+
encoding: "utf8",
|
|
21273
|
+
timeout: 20000,
|
|
21274
|
+
windowsHide: true,
|
|
21275
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
21276
|
+
});
|
|
21277
|
+
return run.status === 0 ? (run.stdout ?? "").trim() : null;
|
|
21278
|
+
};
|
|
21279
|
+
var recordedBaseKey = (branch) => `branch.${branch}.workitBase`;
|
|
21280
|
+
var escapeRegExp = (text) => text.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
|
|
21281
|
+
var reflog = (cwd, ref) => (git4(cwd, ["log", "-g", "--date=unix", "--format=%H%x09%gd%x09%gs", ref, "--"]) ?? "").split(`
|
|
21282
|
+
`).map((line) => {
|
|
21283
|
+
const [sha = "", selector = "", ...subject] = line.split("\t");
|
|
21284
|
+
return {
|
|
21285
|
+
sha,
|
|
21286
|
+
time: Number(/@\{(\d+)\}$/u.exec(selector)?.[1] ?? Number.NaN),
|
|
21287
|
+
subject: subject.join("\t")
|
|
21288
|
+
};
|
|
21289
|
+
}).filter((entry) => entry.sha && Number.isFinite(entry.time));
|
|
21290
|
+
function gitTrackProbe(cwd) {
|
|
21291
|
+
let remote;
|
|
21292
|
+
let remotes;
|
|
21293
|
+
const tip = (branch) => {
|
|
21294
|
+
remote ??= pushRemoteName(cwd) ?? "origin";
|
|
21295
|
+
return resolveRef(cwd, `refs/remotes/${remote}/${branch}`) ?? resolveRef(cwd, `refs/heads/${branch}`);
|
|
21296
|
+
};
|
|
21297
|
+
return {
|
|
21298
|
+
remotes: () => remotes ??= remoteNames(cwd),
|
|
21299
|
+
recordedBase: (branch) => git4(cwd, ["config", "--get", recordedBaseKey(branch)]) || null,
|
|
21300
|
+
createdFrom: (branch) => {
|
|
21301
|
+
const log = git4(cwd, ["reflog", "show", "--format=%gs", `refs/heads/${branch}`, "--"]);
|
|
21302
|
+
const oldest = log?.split(`
|
|
21303
|
+
`).findLast(Boolean) ?? "";
|
|
21304
|
+
const match = /^branch: Created from (\S+)$/u.exec(oldest);
|
|
21305
|
+
return match && match[1] !== "HEAD" ? match[1] : null;
|
|
21306
|
+
},
|
|
21307
|
+
checkedOutFrom: (branch) => {
|
|
21308
|
+
const own = reflog(cwd, `refs/heads/${branch}`);
|
|
21309
|
+
const created = own.at(-1);
|
|
21310
|
+
if (!created || created.subject !== "branch: Created from HEAD")
|
|
21311
|
+
return null;
|
|
21312
|
+
const pattern = new RegExp(`^checkout: moving from (\\S+) to ${escapeRegExp(branch)}$`, "u");
|
|
21313
|
+
const entry = reflog(cwd, "HEAD").findLast((item) => item.time >= created.time && item.sha === created.sha && pattern.test(item.subject));
|
|
21314
|
+
return entry ? pattern.exec(entry.subject)?.[1] ?? null : null;
|
|
21315
|
+
},
|
|
21316
|
+
mergeBase: (branch, trackBranch) => {
|
|
21317
|
+
const base = tip(trackBranch);
|
|
21318
|
+
return base && resolveRef(cwd, `refs/heads/${branch}`) ? mergeBase(cwd, base, `refs/heads/${branch}`) : null;
|
|
21319
|
+
},
|
|
21320
|
+
isAncestor: (ancestor, descendant) => git4(cwd, ["merge-base", "--is-ancestor", ancestor, descendant]) !== null
|
|
21321
|
+
};
|
|
21322
|
+
}
|
|
21323
|
+
function workspaceReleaseTracks(cwd) {
|
|
21324
|
+
const raw = resolveRuntimeReleaseTracks(cwd);
|
|
21325
|
+
return { workspace: raw?.workspace ?? null, ...readReleaseTracks(raw?.releaseTracks) };
|
|
21326
|
+
}
|
|
21327
|
+
var memo3 = new Map;
|
|
21328
|
+
var MEMO_LIMIT = 64;
|
|
21329
|
+
function resolveTrackFor(cwd, options) {
|
|
21330
|
+
const read = workspaceReleaseTracks(cwd);
|
|
21331
|
+
if (read.error)
|
|
21332
|
+
return { status: "invalid", error: read.error, issues: read.issues };
|
|
21333
|
+
if (read.tracks.length === 0 && !options.track?.trim())
|
|
21334
|
+
return { status: "none", issues: read.issues };
|
|
21335
|
+
const branch = options.branch === undefined ? currentBranch(cwd) : options.branch;
|
|
21336
|
+
const envRequested = process.env.WORKFLOW_RELEASE_TRACK?.trim() || null;
|
|
21337
|
+
const input = {
|
|
21338
|
+
tracks: read.tracks,
|
|
21339
|
+
requested: options.track ?? null,
|
|
21340
|
+
envRequested,
|
|
21341
|
+
branch,
|
|
21342
|
+
defaultBranch: options.defaultBranch,
|
|
21343
|
+
issues: read.issues
|
|
21344
|
+
};
|
|
21345
|
+
let key = null;
|
|
21346
|
+
if (!options.probe) {
|
|
21347
|
+
const refs = git4(cwd, [
|
|
21348
|
+
"for-each-ref",
|
|
21349
|
+
"--format=%(refname) %(objectname)",
|
|
21350
|
+
"refs/heads",
|
|
21351
|
+
"refs/remotes"
|
|
21352
|
+
]) ?? "";
|
|
21353
|
+
const head = git4(cwd, ["reflog", "show", "-n", "1", "--format=%H %gs", "HEAD", "--"]) ?? "";
|
|
21354
|
+
const own = branch ? [
|
|
21355
|
+
git4(cwd, [
|
|
21356
|
+
"log",
|
|
21357
|
+
"-g",
|
|
21358
|
+
"-n",
|
|
21359
|
+
"1",
|
|
21360
|
+
"--date=unix",
|
|
21361
|
+
"--format=%H %gd %gs",
|
|
21362
|
+
`refs/heads/${branch}`,
|
|
21363
|
+
"--"
|
|
21364
|
+
]) ?? "",
|
|
21365
|
+
git4(cwd, ["config", "--get", recordedBaseKey(branch)]) ?? ""
|
|
21366
|
+
] : [];
|
|
21367
|
+
key = createHash9("sha256").update(JSON.stringify({ cwd, input, refs, head, own })).digest("hex");
|
|
21368
|
+
const hit = memo3.get(key);
|
|
21369
|
+
if (hit)
|
|
21370
|
+
return hit;
|
|
21371
|
+
}
|
|
21372
|
+
const resolution = resolveReleaseTrack({ ...input, probe: options.probe ?? gitTrackProbe(cwd) });
|
|
21373
|
+
if (key) {
|
|
21374
|
+
if (memo3.size >= MEMO_LIMIT)
|
|
21375
|
+
memo3.delete(memo3.keys().next().value);
|
|
21376
|
+
memo3.set(key, resolution);
|
|
21377
|
+
}
|
|
21378
|
+
return resolution;
|
|
21379
|
+
}
|
|
21380
|
+
|
|
21381
|
+
// packages/workit-core/src/core/vcs-config.ts
|
|
21382
|
+
var workspacesPath = () => path14.join(configDir(), "workspaces.json");
|
|
20953
21383
|
var vcsCwd = (cwd) => cwd ?? process.env.WORKFLOW_WORKSPACE_ROOT ?? process.cwd();
|
|
20954
21384
|
var remoteProvider = (cwd) => {
|
|
20955
|
-
const r =
|
|
21385
|
+
const r = spawnSync8("git", ["remote", "get-url", "origin"], { cwd, encoding: "utf8" });
|
|
20956
21386
|
if (r.status !== 0)
|
|
20957
21387
|
return null;
|
|
20958
21388
|
const url = (r.stdout ?? "").trim();
|
|
@@ -20989,7 +21419,7 @@ var remoteEndpoint = (remote) => {
|
|
|
20989
21419
|
var configuredSshEndpoint = (host) => {
|
|
20990
21420
|
if (host.startsWith("-"))
|
|
20991
21421
|
return null;
|
|
20992
|
-
const resolved =
|
|
21422
|
+
const resolved = spawnSync8("ssh", ["-G", host], {
|
|
20993
21423
|
encoding: "utf8",
|
|
20994
21424
|
timeout: 5000,
|
|
20995
21425
|
maxBuffer: 1024 * 1024,
|
|
@@ -21054,7 +21484,16 @@ var readVcsConfig = () => {
|
|
|
21054
21484
|
}
|
|
21055
21485
|
return { status: "malformed", path: file, config: {}, error: `${file} is not a JSON object` };
|
|
21056
21486
|
};
|
|
21057
|
-
|
|
21487
|
+
var trackSummary = (resolution) => resolution.status === "resolved" ? {
|
|
21488
|
+
name: resolution.track?.name ?? null,
|
|
21489
|
+
source: resolution.source,
|
|
21490
|
+
detail: resolution.detail,
|
|
21491
|
+
warnings: resolution.warnings,
|
|
21492
|
+
track: resolution.track,
|
|
21493
|
+
tracks: resolution.tracks,
|
|
21494
|
+
blocking: resolution.blocking
|
|
21495
|
+
} : null;
|
|
21496
|
+
function vcsConfig(mode, cwd, options = {}) {
|
|
21058
21497
|
const ws = resolveRuntimeWorkspaceVcs(vcsCwd(cwd));
|
|
21059
21498
|
const wsVcs = ws?.vcs ?? {};
|
|
21060
21499
|
const wsYt = ws?.youtrack ?? {};
|
|
@@ -21064,10 +21503,7 @@ function vcsConfig(mode, cwd) {
|
|
|
21064
21503
|
const determinateRoot = cwd !== undefined || process.env.WORKFLOW_WORKSPACE_ROOT !== undefined;
|
|
21065
21504
|
const rawProvider = wsVcs.provider ?? (determinateRoot ? remoteProvider(root) : null) ?? cfg.provider ?? null;
|
|
21066
21505
|
const provider = rawProvider === null || rawProvider === undefined ? null : String(rawProvider).toLowerCase() || null;
|
|
21067
|
-
const
|
|
21068
|
-
const hasWorkspacePolicy = typeof wp.preset === "string" && Object.hasOwn(PRESETS, wp.preset);
|
|
21069
|
-
const policyDefault = resolveBranchPolicyFor(root).defaultTargetBranch;
|
|
21070
|
-
const defaultTarget = String(wsVcs.defaultTargetBranch ?? (hasWorkspacePolicy ? policyDefault : cfg.defaultTargetBranch ?? policyDefault) ?? "develop");
|
|
21506
|
+
const workspaceDefault = workspaceDefaultTarget(root, cfg.defaultTargetBranch);
|
|
21071
21507
|
const linkIssues = typeof wsYt.link_issues === "boolean" ? wsYt.link_issues : null;
|
|
21072
21508
|
const youtrackBaseUrl = typeof wsYt.baseUrl === "string" ? wsYt.baseUrl : null;
|
|
21073
21509
|
let issuesProvider = null;
|
|
@@ -21079,11 +21515,24 @@ function vcsConfig(mode, cwd) {
|
|
|
21079
21515
|
if (mode === "resolve") {
|
|
21080
21516
|
if (cfgStatus === "malformed")
|
|
21081
21517
|
return { ok: false, error: cfgError, configPath: cfgPath };
|
|
21518
|
+
const trackResolution = resolveTrackFor(root, {
|
|
21519
|
+
track: options.track,
|
|
21520
|
+
...options.branch !== undefined ? { branch: options.branch } : {},
|
|
21521
|
+
defaultBranch: workspaceDefault
|
|
21522
|
+
});
|
|
21523
|
+
if (trackResolution.status === "invalid")
|
|
21524
|
+
return { ok: false, error: trackResolution.error, configPath: workspacesPath() };
|
|
21525
|
+
const releaseTrack = trackSummary(trackResolution);
|
|
21526
|
+
const defaultTarget = releaseTrack?.track?.pullRequestTarget ?? workspaceDefault;
|
|
21527
|
+
const baseBranch = releaseTrack?.track?.baseBranch ?? defaultTarget;
|
|
21082
21528
|
return {
|
|
21083
21529
|
ok: true,
|
|
21084
21530
|
workspace_name: ws?.name ?? null,
|
|
21085
21531
|
provider,
|
|
21086
21532
|
defaultTargetBranch: defaultTarget,
|
|
21533
|
+
workspaceDefaultTargetBranch: workspaceDefault,
|
|
21534
|
+
baseBranch,
|
|
21535
|
+
releaseTrack,
|
|
21087
21536
|
link_issues: linkIssues,
|
|
21088
21537
|
youtrack_base_url: youtrackBaseUrl,
|
|
21089
21538
|
issues_provider: issuesProvider,
|
|
@@ -21107,7 +21556,7 @@ function vcsConfig(mode, cwd) {
|
|
|
21107
21556
|
ok: true,
|
|
21108
21557
|
configPath: path14.resolve(cfgPath),
|
|
21109
21558
|
provider,
|
|
21110
|
-
defaultTargetBranch:
|
|
21559
|
+
defaultTargetBranch: workspaceDefault,
|
|
21111
21560
|
pr: cfg.pr ?? {},
|
|
21112
21561
|
workspace_name: ws?.name ?? null,
|
|
21113
21562
|
link_issues: linkIssues,
|
|
@@ -21143,7 +21592,7 @@ function mergedPrStyle(limit = 6, cwd) {
|
|
|
21143
21592
|
`).filter((l) => l.startsWith("## ")).map((l) => l.trim()),
|
|
21144
21593
|
descriptionPreview: desc.slice(0, 600)
|
|
21145
21594
|
});
|
|
21146
|
-
const remoteResult =
|
|
21595
|
+
const remoteResult = spawnSync8("git", ["remote", "get-url", "--push", "--all", "origin"], {
|
|
21147
21596
|
cwd,
|
|
21148
21597
|
encoding: "utf8"
|
|
21149
21598
|
});
|
|
@@ -21159,7 +21608,7 @@ function mergedPrStyle(limit = 6, cwd) {
|
|
|
21159
21608
|
if (!hostingApiHostMatches(remote, host))
|
|
21160
21609
|
return { ok: false, error: "PR style target does not match the provider host" };
|
|
21161
21610
|
if (provider === "gitlab") {
|
|
21162
|
-
const run = (args) =>
|
|
21611
|
+
const run = (args) => spawnSync8("glab", ["api", ...args], {
|
|
21163
21612
|
cwd,
|
|
21164
21613
|
encoding: "utf8",
|
|
21165
21614
|
env
|
|
@@ -21179,7 +21628,7 @@ function mergedPrStyle(limit = 6, cwd) {
|
|
|
21179
21628
|
});
|
|
21180
21629
|
}
|
|
21181
21630
|
} else if (provider === "github") {
|
|
21182
|
-
const r =
|
|
21631
|
+
const r = spawnSync8("gh", [
|
|
21183
21632
|
"pr",
|
|
21184
21633
|
"list",
|
|
21185
21634
|
"--repo",
|
|
@@ -21210,20 +21659,6 @@ function mergedPrStyle(limit = 6, cwd) {
|
|
|
21210
21659
|
examples
|
|
21211
21660
|
};
|
|
21212
21661
|
}
|
|
21213
|
-
|
|
21214
|
-
// packages/workit-core/src/core/branch.ts
|
|
21215
|
-
function effectiveWorkspacePolicy(workspaceRoot, kind, profileName) {
|
|
21216
|
-
const selected = resolveRuntimeWorkspacePolicy(workspaceRoot, kind, profileName?.trim() || process.env.WORKFLOW_PROFILE?.trim() || undefined);
|
|
21217
|
-
const config = readConfig();
|
|
21218
|
-
return kind === "branch" ? {
|
|
21219
|
-
branchPolicy: resolveBranchPolicy(config, selected.policy ? { branchPolicy: selected.policy } : null),
|
|
21220
|
-
provenance: { branchPolicy: selected.source }
|
|
21221
|
-
} : {
|
|
21222
|
-
commitPolicy: resolveCommitPolicy(config, selected.policy ? { commitPolicy: selected.policy } : null),
|
|
21223
|
-
provenance: { commitPolicy: selected.source }
|
|
21224
|
-
};
|
|
21225
|
-
}
|
|
21226
|
-
var resolveBranchPolicyFor = (workspaceRoot, profileName) => effectiveWorkspacePolicy(workspaceRoot, "branch", profileName).branchPolicy;
|
|
21227
21662
|
// packages/workit-core/src/core/task-engine.ts
|
|
21228
21663
|
import { realpathSync as realpathSync4 } from "node:fs";
|
|
21229
21664
|
|
|
@@ -21431,10 +21866,51 @@ var DEFAULT_GRANTS = Object.freeze({
|
|
|
21431
21866
|
release: false,
|
|
21432
21867
|
rerun: true
|
|
21433
21868
|
});
|
|
21869
|
+
var DEFAULT_ENDPOINTS = ["commit", "pr", "green", "merged"];
|
|
21434
21870
|
var DEFAULT_ENDPOINT = "commit";
|
|
21871
|
+
var isDefaultEndpoint = (value) => typeof value === "string" && DEFAULT_ENDPOINTS.includes(value);
|
|
21872
|
+
function endpointOf(entry) {
|
|
21873
|
+
const raw = entry?.defaultEndpoint;
|
|
21874
|
+
if (raw === undefined)
|
|
21875
|
+
return { raw, endpoint: DEFAULT_ENDPOINT };
|
|
21876
|
+
if (isDefaultEndpoint(raw))
|
|
21877
|
+
return { raw, endpoint: raw };
|
|
21878
|
+
return {
|
|
21879
|
+
raw,
|
|
21880
|
+
endpoint: DEFAULT_ENDPOINT,
|
|
21881
|
+
issue: `defaultEndpoint ${JSON.stringify(raw)} is not one of ${DEFAULT_ENDPOINTS.join(", ")}; using ${DEFAULT_ENDPOINT}`
|
|
21882
|
+
};
|
|
21883
|
+
}
|
|
21884
|
+
function effectiveEndpoint(endpoint, context) {
|
|
21885
|
+
if (endpoint === "commit")
|
|
21886
|
+
return { endpoint };
|
|
21887
|
+
const missing = (kind) => `${kind} grant missing; ${grantHint(context.workspace, kind)}`;
|
|
21888
|
+
if (context.grants.push === false)
|
|
21889
|
+
return { endpoint: "commit", reason: missing("push") };
|
|
21890
|
+
if (context.grants.pr === false)
|
|
21891
|
+
return { endpoint: "commit", reason: missing("pr") };
|
|
21892
|
+
if (context.configured.length > 0 && !context.accountConfigured)
|
|
21893
|
+
return {
|
|
21894
|
+
endpoint: "commit",
|
|
21895
|
+
reason: `vcs.account missing; set vcs.account for workspace "${context.workspace ?? "?"}" in ~/.config/workit/workspaces.json`
|
|
21896
|
+
};
|
|
21897
|
+
if (endpoint === "merged" && context.grants.merge === false)
|
|
21898
|
+
return { endpoint: "green", reason: missing("merge") };
|
|
21899
|
+
return { endpoint };
|
|
21900
|
+
}
|
|
21901
|
+
function endpointView(entry, context) {
|
|
21902
|
+
const { raw, endpoint, issue } = endpointOf(entry);
|
|
21903
|
+
const effective = effectiveEndpoint(endpoint, context);
|
|
21904
|
+
return {
|
|
21905
|
+
defaultEndpoint: endpoint,
|
|
21906
|
+
configuredEndpoint: raw ?? null,
|
|
21907
|
+
effectiveEndpoint: effective.endpoint,
|
|
21908
|
+
...effective.reason ? { endpointReason: effective.reason } : {},
|
|
21909
|
+
...issue ? { endpointIssue: issue } : {}
|
|
21910
|
+
};
|
|
21911
|
+
}
|
|
21435
21912
|
var DEFAULT_VERIFICATION = "self";
|
|
21436
21913
|
var verificationOf = (entry) => entry?.verification === "independent" ? "independent" : "self";
|
|
21437
|
-
var endpointOf = (entry) => entry?.defaultEndpoint === "pr" ? "pr" : "commit";
|
|
21438
21914
|
var isGrantValue = (value) => value === true || value === false || value === "verified";
|
|
21439
21915
|
var normalized = (kind, value) => value === "verified" && kind !== "merge" ? true : value;
|
|
21440
21916
|
var fromAutoApprove = (value) => {
|
|
@@ -21475,21 +21951,33 @@ function resolveAutonomy(cwd) {
|
|
|
21475
21951
|
source: "default",
|
|
21476
21952
|
accountConfigured: false,
|
|
21477
21953
|
defaultEndpoint: DEFAULT_ENDPOINT,
|
|
21954
|
+
configuredEndpoint: null,
|
|
21955
|
+
effectiveEndpoint: DEFAULT_ENDPOINT,
|
|
21478
21956
|
verification: DEFAULT_VERIFICATION,
|
|
21479
21957
|
note: override
|
|
21480
21958
|
};
|
|
21481
21959
|
const workspace = resolveWorkspaceFrom(cwd, grantsDir(), process.env.WORKFLOW_WORKSPACE_NAME?.trim() || undefined);
|
|
21482
21960
|
const { grants, source } = configuredGrants(workspace);
|
|
21961
|
+
const full = { ...DEFAULT_GRANTS, ...grants };
|
|
21962
|
+
const configured = GRANT_KINDS.filter((kind) => grants[kind] !== undefined);
|
|
21963
|
+
const accountConfigured = Boolean(workspace?.vcs?.account);
|
|
21483
21964
|
return {
|
|
21484
21965
|
workspace: workspace?.name ?? null,
|
|
21485
|
-
grants:
|
|
21486
|
-
configured
|
|
21966
|
+
grants: full,
|
|
21967
|
+
configured,
|
|
21487
21968
|
source,
|
|
21488
|
-
accountConfigured
|
|
21489
|
-
|
|
21969
|
+
accountConfigured,
|
|
21970
|
+
...endpointView(workspace, {
|
|
21971
|
+
workspace: workspace?.name ?? null,
|
|
21972
|
+
grants: full,
|
|
21973
|
+
configured,
|
|
21974
|
+
accountConfigured
|
|
21975
|
+
}),
|
|
21490
21976
|
verification: verificationOf(workspace)
|
|
21491
21977
|
};
|
|
21492
21978
|
}
|
|
21979
|
+
var suggested = (kind) => kind === "merge" ? "verified" : "true";
|
|
21980
|
+
var grantHint = (workspace, kind) => `ask the user to run, in their own terminal: workit grant set ${workspace ?? "<workspace>"} ${kind}=${suggested(kind)}`;
|
|
21493
21981
|
|
|
21494
21982
|
// packages/workit-core/src/core/task-engine.ts
|
|
21495
21983
|
var workspaceVerification = (root) => {
|
|
@@ -23077,7 +23565,7 @@ class WorkitCore {
|
|
|
23077
23565
|
}
|
|
23078
23566
|
}
|
|
23079
23567
|
// packages/workit-core/src/core/repo-context.ts
|
|
23080
|
-
import { spawnSync as
|
|
23568
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
23081
23569
|
import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync4 } from "node:fs";
|
|
23082
23570
|
import path16 from "node:path";
|
|
23083
23571
|
var isSafeContextRange = (value) => value.length <= 4096 && (() => {
|
|
@@ -23106,7 +23594,7 @@ var invalidRange = (cwd) => ({
|
|
|
23106
23594
|
cwd
|
|
23107
23595
|
});
|
|
23108
23596
|
var runGit = (cwd, args) => {
|
|
23109
|
-
const result =
|
|
23597
|
+
const result = spawnSync9("git", args, { cwd, encoding: "utf8" });
|
|
23110
23598
|
return {
|
|
23111
23599
|
stdout: (result.stdout ?? "").trimEnd(),
|
|
23112
23600
|
stderr: (result.stderr ?? "").trimEnd(),
|
|
@@ -23547,12 +24035,12 @@ function releaseNotesContext(root, rangeOrTag) {
|
|
|
23547
24035
|
}
|
|
23548
24036
|
|
|
23549
24037
|
// packages/workit-core/src/core/tracker-issues.ts
|
|
23550
|
-
import { spawnSync as
|
|
24038
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
23551
24039
|
|
|
23552
24040
|
// packages/workit-core/src/core/pr-create.ts
|
|
23553
24041
|
import fs13 from "node:fs";
|
|
23554
24042
|
import path17 from "node:path";
|
|
23555
|
-
import { spawnSync as
|
|
24043
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
23556
24044
|
// packages/workit-core/src/forge/pr-body.ts
|
|
23557
24045
|
function parseGhIssue(value) {
|
|
23558
24046
|
const m = /issues\/(\d+)/.exec(value);
|
|
@@ -23577,7 +24065,7 @@ function whichOnPath(tool) {
|
|
|
23577
24065
|
}
|
|
23578
24066
|
var hostingCliAvailable = (provider) => whichOnPath(provider === "gitlab" ? "glab" : "gh") !== null;
|
|
23579
24067
|
var pushRemote = (cwd) => {
|
|
23580
|
-
const result =
|
|
24068
|
+
const result = spawnSync10("git", ["remote", "get-url", "--push", "--all", "origin"], {
|
|
23581
24069
|
cwd,
|
|
23582
24070
|
encoding: "utf8"
|
|
23583
24071
|
});
|
|
@@ -23608,7 +24096,7 @@ var defaultCli = (bin, available) => {
|
|
|
23608
24096
|
if (!available)
|
|
23609
24097
|
return null;
|
|
23610
24098
|
return (args, root) => {
|
|
23611
|
-
const out =
|
|
24099
|
+
const out = spawnSync11(bin, args, {
|
|
23612
24100
|
cwd: root,
|
|
23613
24101
|
encoding: "utf8",
|
|
23614
24102
|
env: { ...process.env, PATH: process.env.PATH ?? "" }
|
|
@@ -24126,7 +24614,7 @@ function resolveInside(root, candidate) {
|
|
|
24126
24614
|
}
|
|
24127
24615
|
function run2(root, executable, args, env = {}) {
|
|
24128
24616
|
const cwd = realpathSync5(root);
|
|
24129
|
-
const result =
|
|
24617
|
+
const result = spawnSync12(executable, args, {
|
|
24130
24618
|
cwd,
|
|
24131
24619
|
encoding: "utf8",
|
|
24132
24620
|
env: { ...process.env, ...env }
|
|
@@ -26572,8 +27060,8 @@ var SENSITIVE_WORDS = new Set([
|
|
|
26572
27060
|
"query"
|
|
26573
27061
|
]);
|
|
26574
27062
|
var STACK_WORDS = new Set(["stack", "stacktrace", "trace"]);
|
|
26575
|
-
var
|
|
26576
|
-
var homePattern = new RegExp(`${
|
|
27063
|
+
var escapeRegExp2 = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
27064
|
+
var homePattern = new RegExp(`${escapeRegExp2(os4.homedir())}(?=[/\\\\]|$)|\\$HOME(?=[/\\\\]|$)`, "g");
|
|
26577
27065
|
var applyPatterns = (value) => {
|
|
26578
27066
|
let out = value;
|
|
26579
27067
|
out = out.replace(SECRET_VALUE, REDACTED);
|