@webpieces/pr-gate 0.0.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/package.json +31 -0
- package/src/dashboard/dashboard.d.ts +27 -0
- package/src/dashboard/dashboard.js +155 -0
- package/src/dashboard/dashboard.js.map +1 -0
- package/src/index.d.ts +1 -0
- package/src/index.js +17 -0
- package/src/index.js.map +1 -0
- package/src/scripts/git-gatherInfo.d.ts +2 -0
- package/src/scripts/git-gatherInfo.js +98 -0
- package/src/scripts/git-gatherInfo.js.map +1 -0
- package/src/scripts/git-mergeComplete.d.ts +2 -0
- package/src/scripts/git-mergeComplete.js +77 -0
- package/src/scripts/git-mergeComplete.js.map +1 -0
- package/src/scripts/git-updateFromMain.d.ts +2 -0
- package/src/scripts/git-updateFromMain.js +157 -0
- package/src/scripts/git-updateFromMain.js.map +1 -0
- package/src/scripts/workflow/build-affected.d.ts +7 -0
- package/src/scripts/workflow/build-affected.js +22 -0
- package/src/scripts/workflow/build-affected.js.map +1 -0
- package/src/scripts/workflow/cleanTmp.d.ts +1 -0
- package/src/scripts/workflow/cleanTmp.js +57 -0
- package/src/scripts/workflow/cleanTmp.js.map +1 -0
- package/src/scripts/workflow/git-exec.d.ts +6 -0
- package/src/scripts/workflow/git-exec.js +17 -0
- package/src/scripts/workflow/git-exec.js.map +1 -0
- package/src/scripts/workflow/git-findForkPoint.d.ts +2 -0
- package/src/scripts/workflow/git-findForkPoint.js +120 -0
- package/src/scripts/workflow/git-findForkPoint.js.map +1 -0
- package/src/scripts/workflow/git-readAiBranchName.d.ts +2 -0
- package/src/scripts/workflow/git-readAiBranchName.js +20 -0
- package/src/scripts/workflow/git-readAiBranchName.js.map +1 -0
- package/src/scripts/workflow/git-validateUpToDate.d.ts +1 -0
- package/src/scripts/workflow/git-validateUpToDate.js +72 -0
- package/src/scripts/workflow/git-validateUpToDate.js.map +1 -0
- package/src/scripts/workflow/merge-state.d.ts +27 -0
- package/src/scripts/workflow/merge-state.js +88 -0
- package/src/scripts/workflow/merge-state.js.map +1 -0
- package/src/scripts/wp-build-affected.d.ts +2 -0
- package/src/scripts/wp-build-affected.js +20 -0
- package/src/scripts/wp-build-affected.js.map +1 -0
- package/src/scripts/wp-upsert-pr.d.ts +2 -0
- package/src/scripts/wp-upsert-pr.js +98 -0
- package/src/scripts/wp-upsert-pr.js.map +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-validateUpToDate.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/workflow/git-validateUpToDate.ts"],"names":[],"mappings":"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","sourcesContent":["import { execSync, spawnSync } from 'child_process';\n\nconst SEP = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n';\n\nexport async function main(): Promise<void> {\n const branch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();\n\n if (branch === 'main') {\n process.stdout.write('✅ On main branch - no validation needed\\n');\n return;\n }\n\n process.stdout.write('Validating branch is up to date with origin/main...\\n');\n process.stdout.write(`Current branch: ${branch}\\n`);\n process.stdout.write('\\n');\n\n process.stdout.write('Fetching latest from origin/main...\\n');\n spawnSync('git', ['fetch', 'origin', 'main', '--quiet'], { stdio: 'inherit' });\n\n const isUpToDate = spawnSync('git', ['merge-base', '--is-ancestor', 'origin/main', 'HEAD']).status === 0;\n\n if (isUpToDate) {\n process.stdout.write('✅ Branch is up to date with origin/main\\n');\n return;\n }\n\n const behindResult = spawnSync('git', ['rev-list', '--count', 'HEAD..origin/main'], { encoding: 'utf8' });\n const commitsBehind = (behindResult.stdout ?? '').trim();\n\n const recentResult = spawnSync('git', ['log', '--oneline', 'HEAD..origin/main'], { encoding: 'utf8' });\n const recentLines = (recentResult.stdout ?? '').split('\\n').filter((l: string) => l).slice(0, 5).join('\\n');\n\n process.stdout.write('\\n');\n process.stdout.write(SEP);\n process.stdout.write('❌ ERROR: Branch is NOT up to date with origin/main\\n');\n process.stdout.write(SEP);\n process.stdout.write('\\n');\n process.stdout.write(`Your branch is ${commitsBehind} commit(s) behind origin/main\\n`);\n process.stdout.write('\\n');\n process.stdout.write('Recent commits in origin/main not in your branch:\\n');\n process.stdout.write(recentLines + '\\n');\n process.stdout.write('\\n');\n process.stdout.write(SEP);\n process.stdout.write('⚠️ CRITICAL: You must update your branch first!\\n');\n process.stdout.write(SEP);\n process.stdout.write('\\n');\n process.stdout.write('1. Update your branch with latest main:\\n');\n process.stdout.write(' pnpm wp-git-update\\n');\n process.stdout.write('\\n');\n process.stdout.write('2. ⚠️ IMPORTANT: REVIEW THE CODE AFTER MERGE!\\n');\n process.stdout.write(' - Check for merge conflicts\\n');\n process.stdout.write(' - Review how your changes interact with new main code\\n');\n process.stdout.write(' - Test that everything still works\\n');\n process.stdout.write(' - This is where things often go wrong!\\n');\n process.stdout.write('\\n');\n process.stdout.write('3. After reviewing, run your command again\\n');\n process.stdout.write('\\n');\n process.stdout.write(SEP);\n process.stdout.write('Why this matters:\\n');\n process.stdout.write(SEP);\n process.stdout.write('\\n');\n process.stdout.write('- Your test plan should cover how your changes work with\\n');\n process.stdout.write(' the LATEST code from main, not outdated code\\n');\n process.stdout.write('- Merging main might introduce conflicts or integration\\n');\n process.stdout.write(' issues that need testing\\n');\n process.stdout.write('- Your changes might interact unexpectedly with new code\\n');\n process.stdout.write(' from main\\n');\n process.stdout.write('\\n');\n process.stdout.write(SEP);\n\n process.exit(1);\n}\n\nif (require.main === module) {\n main().catch((err) => {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(message + '\\n');\n process.exit(1);\n });\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare class MergeMarker {
|
|
2
|
+
currentBranch: string;
|
|
3
|
+
squashBranch: string;
|
|
4
|
+
backupBranch: string;
|
|
5
|
+
prNumber: string;
|
|
6
|
+
conflictedFiles: string[];
|
|
7
|
+
forkPoint: string;
|
|
8
|
+
featureHead: string;
|
|
9
|
+
mainHead: string;
|
|
10
|
+
validated: boolean;
|
|
11
|
+
constructor(currentBranch: string, squashBranch: string, backupBranch: string, prNumber: string, conflictedFiles: string[], forkPoint: string, featureHead: string, mainHead: string, validated: boolean);
|
|
12
|
+
}
|
|
13
|
+
export declare class MarkerScanResult {
|
|
14
|
+
clean: boolean;
|
|
15
|
+
filesWithMarkers: string[];
|
|
16
|
+
constructor(clean: boolean, filesWithMarkers: string[]);
|
|
17
|
+
}
|
|
18
|
+
export declare function mergeDirFor(repoRoot: string, featureName: string): string;
|
|
19
|
+
export declare function markerPath(mergeDir: string): string;
|
|
20
|
+
export declare function readMergeMarker(mergeDir: string): MergeMarker | null;
|
|
21
|
+
export declare function writeMergeMarker(mergeDir: string, marker: MergeMarker): void;
|
|
22
|
+
export declare function clearMergeMarker(mergeDir: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Scoped conflict-marker scan: reads ONLY the given conflicted files (relative to repo
|
|
25
|
+
* root), never the whole repo — stays O(conflicts) regardless of monorepo size.
|
|
26
|
+
*/
|
|
27
|
+
export declare function scanConflictMarkers(repoRoot: string, files: string[]): MarkerScanResult;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MarkerScanResult = exports.MergeMarker = void 0;
|
|
4
|
+
exports.mergeDirFor = mergeDirFor;
|
|
5
|
+
exports.markerPath = markerPath;
|
|
6
|
+
exports.readMergeMarker = readMergeMarker;
|
|
7
|
+
exports.writeMergeMarker = writeMergeMarker;
|
|
8
|
+
exports.clearMergeMarker = clearMergeMarker;
|
|
9
|
+
exports.scanConflictMarkers = scanConflictMarkers;
|
|
10
|
+
const tslib_1 = require("tslib");
|
|
11
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
12
|
+
const path = tslib_1.__importStar(require("path"));
|
|
13
|
+
const rules_config_1 = require("@webpieces/rules-config");
|
|
14
|
+
// Proof-obligation marker written when a 3-point squash-merge hits conflicts. Its mere
|
|
15
|
+
// presence (with validated=false) is what the merge-in-progress-guard hook uses to block
|
|
16
|
+
// commit/push/PR until `wp-git-merge-complete` validates the resolution and flips it true.
|
|
17
|
+
class MergeMarker {
|
|
18
|
+
currentBranch;
|
|
19
|
+
squashBranch;
|
|
20
|
+
backupBranch;
|
|
21
|
+
prNumber;
|
|
22
|
+
conflictedFiles;
|
|
23
|
+
forkPoint;
|
|
24
|
+
featureHead;
|
|
25
|
+
mainHead;
|
|
26
|
+
validated;
|
|
27
|
+
constructor(currentBranch, squashBranch, backupBranch, prNumber, conflictedFiles, forkPoint, featureHead, mainHead, validated) {
|
|
28
|
+
this.currentBranch = currentBranch;
|
|
29
|
+
this.squashBranch = squashBranch;
|
|
30
|
+
this.backupBranch = backupBranch;
|
|
31
|
+
this.prNumber = prNumber;
|
|
32
|
+
this.conflictedFiles = conflictedFiles;
|
|
33
|
+
this.forkPoint = forkPoint;
|
|
34
|
+
this.featureHead = featureHead;
|
|
35
|
+
this.mainHead = mainHead;
|
|
36
|
+
this.validated = validated;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.MergeMarker = MergeMarker;
|
|
40
|
+
class MarkerScanResult {
|
|
41
|
+
clean;
|
|
42
|
+
filesWithMarkers;
|
|
43
|
+
constructor(clean, filesWithMarkers) {
|
|
44
|
+
this.clean = clean;
|
|
45
|
+
this.filesWithMarkers = filesWithMarkers;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.MarkerScanResult = MarkerScanResult;
|
|
49
|
+
const CONFLICT_MARKER_RE = /^(<{7}|={7}|>{7})/m;
|
|
50
|
+
function mergeDirFor(repoRoot, featureName) {
|
|
51
|
+
return path.join(repoRoot, rules_config_1.WEBPIECES_TMP_DIR, `${rules_config_1.MERGE_DIR_PREFIX}${featureName}`);
|
|
52
|
+
}
|
|
53
|
+
function markerPath(mergeDir) {
|
|
54
|
+
return path.join(mergeDir, rules_config_1.MERGE_IN_PROGRESS_FILE);
|
|
55
|
+
}
|
|
56
|
+
function readMergeMarker(mergeDir) {
|
|
57
|
+
const filePath = markerPath(mergeDir);
|
|
58
|
+
if (!fs.existsSync(filePath))
|
|
59
|
+
return null;
|
|
60
|
+
const raw = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
61
|
+
return new MergeMarker(raw.currentBranch, raw.squashBranch, raw.backupBranch, raw.prNumber, raw.conflictedFiles ?? [], raw.forkPoint, raw.featureHead, raw.mainHead, raw.validated === true);
|
|
62
|
+
}
|
|
63
|
+
function writeMergeMarker(mergeDir, marker) {
|
|
64
|
+
fs.mkdirSync(mergeDir, { recursive: true });
|
|
65
|
+
fs.writeFileSync(markerPath(mergeDir), JSON.stringify(marker, null, 2) + '\n');
|
|
66
|
+
}
|
|
67
|
+
function clearMergeMarker(mergeDir) {
|
|
68
|
+
const filePath = markerPath(mergeDir);
|
|
69
|
+
if (fs.existsSync(filePath))
|
|
70
|
+
fs.rmSync(filePath);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Scoped conflict-marker scan: reads ONLY the given conflicted files (relative to repo
|
|
74
|
+
* root), never the whole repo — stays O(conflicts) regardless of monorepo size.
|
|
75
|
+
*/
|
|
76
|
+
function scanConflictMarkers(repoRoot, files) {
|
|
77
|
+
const filesWithMarkers = [];
|
|
78
|
+
for (const file of files) {
|
|
79
|
+
const abs = path.join(repoRoot, file);
|
|
80
|
+
if (!fs.existsSync(abs))
|
|
81
|
+
continue;
|
|
82
|
+
const content = fs.readFileSync(abs, 'utf8');
|
|
83
|
+
if (CONFLICT_MARKER_RE.test(content))
|
|
84
|
+
filesWithMarkers.push(file);
|
|
85
|
+
}
|
|
86
|
+
return new MarkerScanResult(filesWithMarkers.length === 0, filesWithMarkers);
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=merge-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge-state.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/workflow/merge-state.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport {\n WEBPIECES_TMP_DIR,\n MERGE_DIR_PREFIX,\n MERGE_IN_PROGRESS_FILE,\n} from '@webpieces/rules-config';\n\n// Proof-obligation marker written when a 3-point squash-merge hits conflicts. Its mere\n// presence (with validated=false) is what the merge-in-progress-guard hook uses to block\n// commit/push/PR until `wp-git-merge-complete` validates the resolution and flips it true.\nexport class MergeMarker {\n currentBranch: string;\n squashBranch: string;\n backupBranch: string;\n prNumber: string;\n conflictedFiles: string[];\n forkPoint: string;\n featureHead: string;\n mainHead: string;\n validated: boolean;\n\n constructor(\n currentBranch: string,\n squashBranch: string,\n backupBranch: string,\n prNumber: string,\n conflictedFiles: string[],\n forkPoint: string,\n featureHead: string,\n mainHead: string,\n validated: boolean,\n ) {\n this.currentBranch = currentBranch;\n this.squashBranch = squashBranch;\n this.backupBranch = backupBranch;\n this.prNumber = prNumber;\n this.conflictedFiles = conflictedFiles;\n this.forkPoint = forkPoint;\n this.featureHead = featureHead;\n this.mainHead = mainHead;\n this.validated = validated;\n }\n}\n\nexport class MarkerScanResult {\n clean: boolean;\n filesWithMarkers: string[];\n\n constructor(clean: boolean, filesWithMarkers: string[]) {\n this.clean = clean;\n this.filesWithMarkers = filesWithMarkers;\n }\n}\n\nconst CONFLICT_MARKER_RE = /^(<{7}|={7}|>{7})/m;\n\nexport function mergeDirFor(repoRoot: string, featureName: string): string {\n return path.join(repoRoot, WEBPIECES_TMP_DIR, `${MERGE_DIR_PREFIX}${featureName}`);\n}\n\nexport function markerPath(mergeDir: string): string {\n return path.join(mergeDir, MERGE_IN_PROGRESS_FILE);\n}\n\nexport function readMergeMarker(mergeDir: string): MergeMarker | null {\n const filePath = markerPath(mergeDir);\n if (!fs.existsSync(filePath)) return null;\n const raw = JSON.parse(fs.readFileSync(filePath, 'utf8')) as MergeMarker;\n return new MergeMarker(\n raw.currentBranch,\n raw.squashBranch,\n raw.backupBranch,\n raw.prNumber,\n raw.conflictedFiles ?? [],\n raw.forkPoint,\n raw.featureHead,\n raw.mainHead,\n raw.validated === true,\n );\n}\n\nexport function writeMergeMarker(mergeDir: string, marker: MergeMarker): void {\n fs.mkdirSync(mergeDir, { recursive: true });\n fs.writeFileSync(markerPath(mergeDir), JSON.stringify(marker, null, 2) + '\\n');\n}\n\nexport function clearMergeMarker(mergeDir: string): void {\n const filePath = markerPath(mergeDir);\n if (fs.existsSync(filePath)) fs.rmSync(filePath);\n}\n\n/**\n * Scoped conflict-marker scan: reads ONLY the given conflicted files (relative to repo\n * root), never the whole repo — stays O(conflicts) regardless of monorepo size.\n */\nexport function scanConflictMarkers(repoRoot: string, files: string[]): MarkerScanResult {\n const filesWithMarkers: string[] = [];\n for (const file of files) {\n const abs = path.join(repoRoot, file);\n if (!fs.existsSync(abs)) continue;\n const content = fs.readFileSync(abs, 'utf8');\n if (CONFLICT_MARKER_RE.test(content)) filesWithMarkers.push(file);\n }\n return new MarkerScanResult(filesWithMarkers.length === 0, filesWithMarkers);\n}\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.main = main;
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
const rules_config_1 = require("@webpieces/rules-config");
|
|
7
|
+
const build_affected_1 = require("./workflow/build-affected");
|
|
8
|
+
// Single shared build entry point. CI runs this AND the PR command runs this, so the two can
|
|
9
|
+
// never diverge. The build command is sourced from PrGateConfig.buildCommand (webpieces.config.json
|
|
10
|
+
// "pr-gate" section), defaulting to `pnpm nx affected --target=ci --base=origin/main`.
|
|
11
|
+
function main() {
|
|
12
|
+
const repoRoot = (0, child_process_1.execSync)('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
|
|
13
|
+
const config = (0, rules_config_1.loadPrGateConfig)(repoRoot);
|
|
14
|
+
const code = (0, build_affected_1.runBuildAffected)(repoRoot, config.buildCommand);
|
|
15
|
+
process.exit(code);
|
|
16
|
+
}
|
|
17
|
+
if (require.main === module) {
|
|
18
|
+
main();
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=wp-build-affected.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wp-build-affected.js","sourceRoot":"","sources":["../../../../../../packages/tooling/pr-gate/src/scripts/wp-build-affected.ts"],"names":[],"mappings":";;;AAQA,oBAKC;AAZD,iDAAyC;AACzC,0DAA2D;AAC3D,8DAA6D;AAE7D,6FAA6F;AAC7F,oGAAoG;AACpG,uFAAuF;AACvF,SAAgB,IAAI;IAChB,MAAM,QAAQ,GAAG,IAAA,wBAAQ,EAAC,+BAA+B,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxF,MAAM,MAAM,GAAG,IAAA,+BAAgB,EAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAA,iCAAgB,EAAC,QAAQ,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IAC7D,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;IAC1B,IAAI,EAAE,CAAC;AACX,CAAC","sourcesContent":["#!/usr/bin/env node\nimport { execSync } from 'child_process';\nimport { loadPrGateConfig } from '@webpieces/rules-config';\nimport { runBuildAffected } from './workflow/build-affected';\n\n// Single shared build entry point. CI runs this AND the PR command runs this, so the two can\n// never diverge. The build command is sourced from PrGateConfig.buildCommand (webpieces.config.json\n// \"pr-gate\" section), defaulting to `pnpm nx affected --target=ci --base=origin/main`.\nexport function main(): void {\n const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();\n const config = loadPrGateConfig(repoRoot);\n const code = runBuildAffected(repoRoot, config.buildCommand);\n process.exit(code);\n}\n\nif (require.main === module) {\n main();\n}\n"]}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.main = main;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const child_process_1 = require("child_process");
|
|
7
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
8
|
+
const path = tslib_1.__importStar(require("path"));
|
|
9
|
+
const rules_config_1 = require("@webpieces/rules-config");
|
|
10
|
+
const git_readAiBranchName_1 = require("./workflow/git-readAiBranchName");
|
|
11
|
+
const build_affected_1 = require("./workflow/build-affected");
|
|
12
|
+
const git_exec_1 = require("./workflow/git-exec");
|
|
13
|
+
const dashboard_1 = require("../dashboard/dashboard");
|
|
14
|
+
const SEP = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
|
|
15
|
+
function gitOut(args) {
|
|
16
|
+
const result = (0, child_process_1.spawnSync)('git', args, { encoding: 'utf8' });
|
|
17
|
+
return result.status === 0 ? (result.stdout ?? '').trim() : '';
|
|
18
|
+
}
|
|
19
|
+
// Step A — bring the branch up to date with main via the 3-point engine (child process, so
|
|
20
|
+
// its conflict handback / guard interplay is unaffected by this command's hook context).
|
|
21
|
+
function runUpdateFromMain() {
|
|
22
|
+
process.stdout.write('\n' + SEP + '① Updating branch from main\n' + SEP + '\n');
|
|
23
|
+
const result = (0, child_process_1.spawnSync)('pnpm', ['wp-git-update'], { stdio: 'inherit' });
|
|
24
|
+
if (result.status === 2) {
|
|
25
|
+
process.stdout.write('\n⏸️ Conflicts — resolve them, run pnpm wp-git-merge-complete, then re-run pnpm wp-upsert-pr.\n');
|
|
26
|
+
process.exit(2);
|
|
27
|
+
}
|
|
28
|
+
if (result.status !== 0) {
|
|
29
|
+
process.stderr.write('\n❌ Branch update failed — see output above.\n');
|
|
30
|
+
process.exit(result.status ?? 1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function ensurePushed(currentBranch) {
|
|
34
|
+
const remoteExists = (0, child_process_1.spawnSync)('git', ['ls-remote', '--exit-code', '--heads', 'origin', currentBranch]).status === 0;
|
|
35
|
+
if (remoteExists) {
|
|
36
|
+
(0, git_exec_1.runGitChecked)(['push', '--force-with-lease', 'origin', `HEAD:${currentBranch}`], 'Failed to push branch');
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
(0, git_exec_1.runGitChecked)(['push', '-u', 'origin', `HEAD:${currentBranch}`], 'Failed to push new branch');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function buildDashboard(repoRoot, buildPassed) {
|
|
43
|
+
const config = (0, rules_config_1.loadPrGateConfig)(repoRoot);
|
|
44
|
+
const forkPoint = gitOut(['merge-base', 'origin/main', 'HEAD']);
|
|
45
|
+
const featureHead = gitOut(['rev-parse', 'HEAD']);
|
|
46
|
+
const mainHead = gitOut(['rev-parse', 'origin/main']);
|
|
47
|
+
const range = `${forkPoint}..${featureHead}`;
|
|
48
|
+
const changedFiles = gitOut(['diff', range, '--name-only']).split('\n').filter((f) => f.trim() !== '');
|
|
49
|
+
const patch = gitOut(['diff', range]);
|
|
50
|
+
const title = gitOut(['log', '-1', '--format=%s']);
|
|
51
|
+
const gateResults = (0, dashboard_1.computeGateResults)(config.gates, changedFiles);
|
|
52
|
+
const disables = (0, dashboard_1.countAddedDisables)(patch);
|
|
53
|
+
const input = new dashboard_1.DashboardInput(title, gateResults, disables, buildPassed, forkPoint, featureHead, mainHead, '');
|
|
54
|
+
return (0, dashboard_1.renderDashboard)(input);
|
|
55
|
+
}
|
|
56
|
+
function upsertPr(repoRoot, currentBranch, body) {
|
|
57
|
+
const prDir = path.join(repoRoot, rules_config_1.WEBPIECES_TMP_DIR, `pr-${(0, git_readAiBranchName_1.getFeatureName)()}`);
|
|
58
|
+
fs.mkdirSync(prDir, { recursive: true });
|
|
59
|
+
const bodyFile = path.join(prDir, 'pr-body.md');
|
|
60
|
+
fs.writeFileSync(bodyFile, body + '\n');
|
|
61
|
+
const existing = gitOut(['log', '-1', '--format=%s']); // title fallback
|
|
62
|
+
const prNumber = (0, child_process_1.spawnSync)('gh', ['pr', 'list', '--head', currentBranch, '--json', 'number', '--jq', '.[0].number'], { encoding: 'utf8' });
|
|
63
|
+
const num = prNumber.status === 0 ? (prNumber.stdout ?? '').trim() : '';
|
|
64
|
+
if (num === '') {
|
|
65
|
+
process.stdout.write('Creating PR...\n');
|
|
66
|
+
const create = (0, child_process_1.spawnSync)('gh', ['pr', 'create', '--head', currentBranch, '--base', 'main', '--title', existing, '--body-file', bodyFile], { stdio: 'inherit' });
|
|
67
|
+
if (create.status !== 0) {
|
|
68
|
+
process.stderr.write('⚠️ gh pr create failed — create the PR manually with the body in:\n ' + bodyFile + '\n');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
process.stdout.write(`Updating PR #${num}...\n`);
|
|
74
|
+
(0, child_process_1.spawnSync)('gh', ['pr', 'edit', num, '--body-file', bodyFile], { stdio: 'inherit' });
|
|
75
|
+
}
|
|
76
|
+
(0, child_process_1.spawnSync)('gh', ['pr', 'merge', currentBranch, '--auto', '--squash'], { stdio: 'inherit' });
|
|
77
|
+
}
|
|
78
|
+
function main() {
|
|
79
|
+
const repoRoot = (0, child_process_1.execSync)('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
|
|
80
|
+
runUpdateFromMain();
|
|
81
|
+
ensurePushed((0, child_process_1.execSync)('git branch --show-current', { encoding: 'utf8' }).trim());
|
|
82
|
+
process.stdout.write('\n' + SEP + '② Build gate (nx affected)\n' + SEP + '\n');
|
|
83
|
+
const config = (0, rules_config_1.loadPrGateConfig)(repoRoot);
|
|
84
|
+
const buildCode = (0, build_affected_1.runBuildAffected)(repoRoot, config.buildCommand);
|
|
85
|
+
if (buildCode !== 0) {
|
|
86
|
+
process.stderr.write('\n❌ Build failed — no PR created/updated. Fix and re-run pnpm wp-upsert-pr.\n');
|
|
87
|
+
process.exit(buildCode);
|
|
88
|
+
}
|
|
89
|
+
process.stdout.write('\n' + SEP + '③ Dashboard + PR\n' + SEP + '\n');
|
|
90
|
+
const currentBranch = (0, child_process_1.execSync)('git branch --show-current', { encoding: 'utf8' }).trim();
|
|
91
|
+
const body = buildDashboard(repoRoot, true);
|
|
92
|
+
upsertPr(repoRoot, currentBranch, body);
|
|
93
|
+
process.stdout.write('\n✅ Done.\n');
|
|
94
|
+
}
|
|
95
|
+
if (require.main === module) {
|
|
96
|
+
main();
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=wp-upsert-pr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wp-upsert-pr.js","sourceRoot":"","sources":["../../../../../../packages/tooling/pr-gate/src/scripts/wp-upsert-pr.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\nimport { execSync, spawnSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { loadPrGateConfig, WEBPIECES_TMP_DIR } from '@webpieces/rules-config';\nimport { getFeatureName } from './workflow/git-readAiBranchName';\nimport { runBuildAffected } from './workflow/build-affected';\nimport { runGitChecked } from './workflow/git-exec';\nimport {\n computeGateResults,\n countAddedDisables,\n renderDashboard,\n DashboardInput,\n} from '../dashboard/dashboard';\n\nconst SEP = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n';\n\nfunction gitOut(args: string[]): string {\n const result = spawnSync('git', args, { encoding: 'utf8' });\n return result.status === 0 ? (result.stdout ?? '').trim() : '';\n}\n\n// Step A — bring the branch up to date with main via the 3-point engine (child process, so\n// its conflict handback / guard interplay is unaffected by this command's hook context).\nfunction runUpdateFromMain(): void {\n process.stdout.write('\\n' + SEP + '① Updating branch from main\\n' + SEP + '\\n');\n const result = spawnSync('pnpm', ['wp-git-update'], { stdio: 'inherit' });\n if (result.status === 2) {\n process.stdout.write('\\n⏸️ Conflicts — resolve them, run pnpm wp-git-merge-complete, then re-run pnpm wp-upsert-pr.\\n');\n process.exit(2);\n }\n if (result.status !== 0) {\n process.stderr.write('\\n❌ Branch update failed — see output above.\\n');\n process.exit(result.status ?? 1);\n }\n}\n\nfunction ensurePushed(currentBranch: string): void {\n const remoteExists = spawnSync('git', ['ls-remote', '--exit-code', '--heads', 'origin', currentBranch]).status === 0;\n if (remoteExists) {\n runGitChecked(['push', '--force-with-lease', 'origin', `HEAD:${currentBranch}`], 'Failed to push branch');\n } else {\n runGitChecked(['push', '-u', 'origin', `HEAD:${currentBranch}`], 'Failed to push new branch');\n }\n}\n\nfunction buildDashboard(repoRoot: string, buildPassed: boolean): string {\n const config = loadPrGateConfig(repoRoot);\n const forkPoint = gitOut(['merge-base', 'origin/main', 'HEAD']);\n const featureHead = gitOut(['rev-parse', 'HEAD']);\n const mainHead = gitOut(['rev-parse', 'origin/main']);\n const range = `${forkPoint}..${featureHead}`;\n const changedFiles = gitOut(['diff', range, '--name-only']).split('\\n').filter((f: string): boolean => f.trim() !== '');\n const patch = gitOut(['diff', range]);\n const title = gitOut(['log', '-1', '--format=%s']);\n\n const gateResults = computeGateResults(config.gates, changedFiles);\n const disables = countAddedDisables(patch);\n const input = new DashboardInput(title, gateResults, disables, buildPassed, forkPoint, featureHead, mainHead, '');\n return renderDashboard(input);\n}\n\nfunction upsertPr(repoRoot: string, currentBranch: string, body: string): void {\n const prDir = path.join(repoRoot, WEBPIECES_TMP_DIR, `pr-${getFeatureName()}`);\n fs.mkdirSync(prDir, { recursive: true });\n const bodyFile = path.join(prDir, 'pr-body.md');\n fs.writeFileSync(bodyFile, body + '\\n');\n\n const existing = gitOut(['log', '-1', '--format=%s']); // title fallback\n const prNumber = spawnSync(\n 'gh', ['pr', 'list', '--head', currentBranch, '--json', 'number', '--jq', '.[0].number'],\n { encoding: 'utf8' },\n );\n const num = prNumber.status === 0 ? (prNumber.stdout ?? '').trim() : '';\n\n if (num === '') {\n process.stdout.write('Creating PR...\\n');\n const create = spawnSync('gh', ['pr', 'create', '--head', currentBranch, '--base', 'main', '--title', existing, '--body-file', bodyFile], { stdio: 'inherit' });\n if (create.status !== 0) {\n process.stderr.write('⚠️ gh pr create failed — create the PR manually with the body in:\\n ' + bodyFile + '\\n');\n return;\n }\n } else {\n process.stdout.write(`Updating PR #${num}...\\n`);\n spawnSync('gh', ['pr', 'edit', num, '--body-file', bodyFile], { stdio: 'inherit' });\n }\n spawnSync('gh', ['pr', 'merge', currentBranch, '--auto', '--squash'], { stdio: 'inherit' });\n}\n\nexport function main(): void {\n const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();\n\n runUpdateFromMain();\n ensurePushed(execSync('git branch --show-current', { encoding: 'utf8' }).trim());\n\n process.stdout.write('\\n' + SEP + '② Build gate (nx affected)\\n' + SEP + '\\n');\n const config = loadPrGateConfig(repoRoot);\n const buildCode = runBuildAffected(repoRoot, config.buildCommand);\n if (buildCode !== 0) {\n process.stderr.write('\\n❌ Build failed — no PR created/updated. Fix and re-run pnpm wp-upsert-pr.\\n');\n process.exit(buildCode);\n }\n\n process.stdout.write('\\n' + SEP + '③ Dashboard + PR\\n' + SEP + '\\n');\n const currentBranch = execSync('git branch --show-current', { encoding: 'utf8' }).trim();\n const body = buildDashboard(repoRoot, true);\n upsertPr(repoRoot, currentBranch, body);\n process.stdout.write('\\n✅ Done.\\n');\n}\n\nif (require.main === module) {\n main();\n}\n"]}
|