@brainervirus/workit-core 0.8.2 → 0.8.3
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/package.json +1 -1
- package/src/core/pr-create.ts +34 -3
- package/src/core/vcs-config.ts +10 -3
package/package.json
CHANGED
package/src/core/pr-create.ts
CHANGED
|
@@ -147,9 +147,15 @@ export function prCreate(env: NodeJS.ProcessEnv, cwd: string): Record<string, an
|
|
|
147
147
|
// target is validated against the resolved branch policy so a PR can never
|
|
148
148
|
// be aimed at a protected or disallowed branch.
|
|
149
149
|
const targetOverride = env.WF_PR_TARGET;
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
const resolvedDefault = String(
|
|
151
|
+
cfg.defaultTargetBranch ?? policy.defaultTargetBranch ?? "develop",
|
|
152
|
+
);
|
|
153
|
+
const target = targetOverride || resolvedDefault;
|
|
154
|
+
// CA-06: an explicit override equal to the resolved default (e.g. WF_PR_TARGET
|
|
155
|
+
// "main" under github-flow) is authoritative — the same value flows
|
|
156
|
+
// unvalidated from config, so it must not be rejected as a protected
|
|
157
|
+
// override. Genuine differing overrides keep the strict validation.
|
|
158
|
+
if (targetOverride && targetOverride !== resolvedDefault) {
|
|
153
159
|
const { allowed, protected: protectedTargets } = policy;
|
|
154
160
|
if (protectedTargets.has(targetOverride.toLowerCase()))
|
|
155
161
|
return {
|
|
@@ -283,6 +289,31 @@ export function prCreate(env: NodeJS.ProcessEnv, cwd: string): Record<string, an
|
|
|
283
289
|
// uv_spawn fails with ENOENT even though the CLI is on PATH.
|
|
284
290
|
cmdEnv = { ...process.env, PATH: process.env.PATH ?? "", GITLAB_TOKEN: token };
|
|
285
291
|
} else {
|
|
292
|
+
// T2: GitHub has no --push flag — push the branch first so `gh pr create`
|
|
293
|
+
// never runs against an unpushed branch when pushBranch is enabled.
|
|
294
|
+
if (push) {
|
|
295
|
+
if (!branch) {
|
|
296
|
+
return {
|
|
297
|
+
error: "push failed",
|
|
298
|
+
provider,
|
|
299
|
+
mode: "push",
|
|
300
|
+
targetBranch: target,
|
|
301
|
+
stderr: "empty current branch (detached HEAD or unborn HEAD)",
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
const pushRes = spawnSync("git", ["push", "-u", "origin", branch], {
|
|
305
|
+
cwd: root,
|
|
306
|
+
encoding: "utf8",
|
|
307
|
+
});
|
|
308
|
+
if (pushRes.status !== 0) {
|
|
309
|
+
return {
|
|
310
|
+
error: "push failed",
|
|
311
|
+
provider,
|
|
312
|
+
targetBranch: target,
|
|
313
|
+
stderr: (pushRes.stderr ?? "").slice(0, 800),
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
}
|
|
286
317
|
cmd = ["gh", "pr", "create", "--title", title, "--base", target];
|
|
287
318
|
if (finalBody) cmd.push("--body", finalBody);
|
|
288
319
|
if (draft) cmd.push("--draft");
|
package/src/core/vcs-config.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { spawnSync } from "node:child_process";
|
|
4
|
-
import { configDir } from "./config";
|
|
4
|
+
import { configDir, PRESETS } from "./config";
|
|
5
5
|
import { resolveWorkspace } from "./workspaces";
|
|
6
6
|
import { resolveBranchPolicyFor } from "./branch";
|
|
7
7
|
// Ports of scripts/vcs/config.sh + verify-token.sh + token-create-urls.sh + merged-style.sh.
|
|
@@ -90,10 +90,17 @@ export function vcsConfig(mode: "load" | "summary" | "resolve", cwd?: string): R
|
|
|
90
90
|
// and resolve so both surfaces stay consistent.
|
|
91
91
|
// CA-09: the one resolver wrapper — same policy resolution every consumer
|
|
92
92
|
// uses, so the tightened gate in branch-policy-resolver.test.ts stays green.
|
|
93
|
+
// CA-02: a matched workspace's OWN branchPolicy default beats any global
|
|
94
|
+
// vcs.json default (PR #43: global develop shadowed the personal github-flow
|
|
95
|
+
// main). Explicit workspace vcs.defaultTargetBranch stays authoritative; a
|
|
96
|
+
// workspace without a branchPolicy still falls back to the global vcs.json
|
|
97
|
+
// default, and unmatched repos keep it too.
|
|
98
|
+
const wp = (ws?.branchPolicy ?? {}) as Record<string, any>;
|
|
99
|
+
const hasWorkspacePolicy = typeof wp.preset === "string" && Object.hasOwn(PRESETS, wp.preset);
|
|
100
|
+
const policyDefault = resolveBranchPolicyFor(root).defaultTargetBranch;
|
|
93
101
|
const defaultTarget = String(
|
|
94
102
|
wsVcs.defaultTargetBranch ??
|
|
95
|
-
cfg.defaultTargetBranch ??
|
|
96
|
-
resolveBranchPolicyFor(root).defaultTargetBranch ??
|
|
103
|
+
(hasWorkspacePolicy ? policyDefault : (cfg.defaultTargetBranch ?? policyDefault)) ??
|
|
97
104
|
"develop",
|
|
98
105
|
);
|
|
99
106
|
const linkIssues = typeof wsYt.link_issues === "boolean" ? wsYt.link_issues : null;
|