@webpieces/pr-gate 0.3.354 → 0.3.356
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 +7 -2
- package/src/dashboard/dashboard.d.ts +12 -3
- package/src/dashboard/dashboard.js +136 -129
- package/src/dashboard/dashboard.js.map +1 -1
- package/src/index.d.ts +2 -1
- package/src/index.js +4 -4
- package/src/index.js.map +1 -1
- package/src/scripts/commands/finish-update-command.d.ts +10 -0
- package/src/scripts/commands/finish-update-command.js +51 -0
- package/src/scripts/commands/finish-update-command.js.map +1 -0
- package/src/scripts/commands/finish-upsert-pr-command.d.ts +22 -0
- package/src/scripts/commands/finish-upsert-pr-command.js +131 -0
- package/src/scripts/commands/finish-upsert-pr-command.js.map +1 -0
- package/src/scripts/commands/start-update-command.d.ts +9 -0
- package/src/scripts/commands/start-update-command.js +67 -0
- package/src/scripts/commands/start-update-command.js.map +1 -0
- package/src/scripts/commands/start-upsert-pr-command.d.ts +15 -0
- package/src/scripts/commands/start-upsert-pr-command.js +73 -0
- package/src/scripts/commands/start-upsert-pr-command.js.map +1 -0
- package/src/scripts/git-finishUpsertPr.d.ts +1 -1
- package/src/scripts/git-finishUpsertPr.js +11 -109
- package/src/scripts/git-finishUpsertPr.js.map +1 -1
- package/src/scripts/git-gatherInfo.d.ts +15 -1
- package/src/scripts/git-gatherInfo.js +79 -61
- package/src/scripts/git-gatherInfo.js.map +1 -1
- package/src/scripts/pr-gate-app.d.ts +25 -0
- package/src/scripts/pr-gate-app.js +56 -0
- package/src/scripts/pr-gate-app.js.map +1 -0
- package/src/scripts/workflow/branch-naming.d.ts +11 -8
- package/src/scripts/workflow/branch-naming.js +30 -21
- package/src/scripts/workflow/branch-naming.js.map +1 -1
- package/src/scripts/workflow/build-affected.d.ts +21 -30
- package/src/scripts/workflow/build-affected.js +57 -63
- package/src/scripts/workflow/build-affected.js.map +1 -1
- package/src/scripts/workflow/cleanTmp.d.ts +6 -1
- package/src/scripts/workflow/cleanTmp.js +83 -78
- package/src/scripts/workflow/cleanTmp.js.map +1 -1
- package/src/scripts/workflow/git-exec.d.ts +32 -28
- package/src/scripts/workflow/git-exec.js +92 -85
- package/src/scripts/workflow/git-exec.js.map +1 -1
- package/src/scripts/workflow/git-findForkPoint.d.ts +12 -3
- package/src/scripts/workflow/git-findForkPoint.js +116 -107
- package/src/scripts/workflow/git-findForkPoint.js.map +1 -1
- package/src/scripts/workflow/git-readAiBranchName.d.ts +7 -2
- package/src/scripts/workflow/git-readAiBranchName.js +24 -15
- package/src/scripts/workflow/git-readAiBranchName.js.map +1 -1
- package/src/scripts/workflow/merge-end.d.ts +21 -6
- package/src/scripts/workflow/merge-end.js +147 -133
- package/src/scripts/workflow/merge-end.js.map +1 -1
- package/src/scripts/workflow/merge-start.d.ts +22 -1
- package/src/scripts/workflow/merge-start.js +180 -186
- package/src/scripts/workflow/merge-start.js.map +1 -1
- package/src/scripts/workflow/merge-state.d.ts +26 -23
- package/src/scripts/workflow/merge-state.js +131 -137
- package/src/scripts/workflow/merge-state.js.map +1 -1
- package/src/scripts/workflow/open-pr-check.d.ts +7 -1
- package/src/scripts/workflow/open-pr-check.js +34 -23
- package/src/scripts/workflow/open-pr-check.js.map +1 -1
- package/src/scripts/workflow/run-update.d.ts +13 -1
- package/src/scripts/workflow/run-update.js +59 -28
- package/src/scripts/workflow/run-update.js.map +1 -1
- package/src/scripts/wp-finish-update.d.ts +1 -1
- package/src/scripts/wp-finish-update.js +11 -30
- package/src/scripts/wp-finish-update.js.map +1 -1
- package/src/scripts/wp-start-update.d.ts +1 -2
- package/src/scripts/wp-start-update.js +11 -51
- package/src/scripts/wp-start-update.js.map +1 -1
- package/src/scripts/wp-start-upsert-pr.d.ts +1 -1
- package/src/scripts/wp-start-upsert-pr.js +11 -47
- package/src/scripts/wp-start-upsert-pr.js.map +1 -1
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FinishUpsertPrCommand = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
7
|
+
const path = tslib_1.__importStar(require("path"));
|
|
8
|
+
const rules_config_1 = require("@webpieces/rules-config");
|
|
9
|
+
const core_context_1 = require("@webpieces/core-context");
|
|
10
|
+
const inversify_1 = require("inversify");
|
|
11
|
+
const git_readAiBranchName_1 = require("../workflow/git-readAiBranchName");
|
|
12
|
+
const branch_naming_1 = require("../workflow/branch-naming");
|
|
13
|
+
const git_exec_1 = require("../workflow/git-exec");
|
|
14
|
+
const build_affected_1 = require("../workflow/build-affected");
|
|
15
|
+
const merge_state_1 = require("../workflow/merge-state");
|
|
16
|
+
const merge_end_1 = require("../workflow/merge-end");
|
|
17
|
+
const merge_start_1 = require("../workflow/merge-start");
|
|
18
|
+
const dashboard_1 = require("../../dashboard/dashboard");
|
|
19
|
+
const SEP = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
|
|
20
|
+
// FINISH of the AI-first PR flow. Runs after the AI wrote review.json. In order: (1) if a 3-point merge
|
|
21
|
+
// was in progress, validate + commit + FINALIZE via merge-END; (2) REQUIRE review.json; (3) run the
|
|
22
|
+
// authoritative build gate; (4) render the dashboard; (5) create/update the PR via `gh`. The ONLY
|
|
23
|
+
// command that posts PRs.
|
|
24
|
+
let FinishUpsertPrCommand = class FinishUpsertPrCommand {
|
|
25
|
+
aiBranchName;
|
|
26
|
+
branchNaming;
|
|
27
|
+
gitExec;
|
|
28
|
+
buildAffected;
|
|
29
|
+
mergeState;
|
|
30
|
+
mergeEnd;
|
|
31
|
+
dashboard;
|
|
32
|
+
constructor(aiBranchName, branchNaming, gitExec, buildAffected, mergeState, mergeEnd, dashboard) {
|
|
33
|
+
this.aiBranchName = aiBranchName;
|
|
34
|
+
this.branchNaming = branchNaming;
|
|
35
|
+
this.gitExec = gitExec;
|
|
36
|
+
this.buildAffected = buildAffected;
|
|
37
|
+
this.mergeState = mergeState;
|
|
38
|
+
this.mergeEnd = mergeEnd;
|
|
39
|
+
this.dashboard = dashboard;
|
|
40
|
+
}
|
|
41
|
+
async run() {
|
|
42
|
+
const repoRoot = (0, child_process_1.execSync)('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
|
|
43
|
+
// Refresh the AI-facing workflow doc so it's present + current for any failure message to cite.
|
|
44
|
+
(0, rules_config_1.writeTemplate)(repoRoot, 'webpieces.git-workflow.md');
|
|
45
|
+
const home = this.mergeState.mergeDirFor(repoRoot, this.aiBranchName.getFeatureName());
|
|
46
|
+
// 1. Finish any in-progress conflict resolution: validate + commit + finalize the branch swap.
|
|
47
|
+
const activeDir = this.mergeState.findActiveMergeRunDir(home);
|
|
48
|
+
const marker = activeDir ? this.mergeState.readMergeMarker(activeDir) : null;
|
|
49
|
+
if (activeDir && marker && !marker.validated) {
|
|
50
|
+
await this.mergeEnd.mergeEnd(repoRoot, 'wp-finish-upsert-pr', activeDir, new merge_start_1.MergeContext(marker.currentBranch, marker.squashBranch, marker.backupBranch, marker.prNumber), marker.conflictedFiles);
|
|
51
|
+
}
|
|
52
|
+
// 2. REQUIRE the AI-authored review.json (throws InformAiError with the schema if missing/invalid).
|
|
53
|
+
const review = (0, rules_config_1.loadReviewJson)((0, rules_config_1.reviewJsonPath)(repoRoot, this.aiBranchName.getFeatureName()));
|
|
54
|
+
// 2b. The build gate validates the WORKING TREE but we push HEAD — so they MUST be identical.
|
|
55
|
+
this.gitExec.assertCleanTree(repoRoot);
|
|
56
|
+
// 3. Authoritative build gate, then push, then post.
|
|
57
|
+
this.buildAffected.runBuildGate(repoRoot, new build_affected_1.BuildGateOptions('🛠️ Build gate (authoritative)', 'pnpm wp-finish-upsert-pr', 'Build failed — no PR created/updated.'));
|
|
58
|
+
const base = this.branchNaming.baseBranchName((0, child_process_1.execSync)('git branch --show-current', { encoding: 'utf8' }).trim());
|
|
59
|
+
this.gitExec.ensurePushed(base);
|
|
60
|
+
process.stdout.write('\n' + SEP + '📋 Dashboard + PR\n' + SEP + '\n');
|
|
61
|
+
const title = this.prTitleFrom(review);
|
|
62
|
+
const body = this.buildDashboard(repoRoot, true, review, title);
|
|
63
|
+
const prNum = this.upsertPr(repoRoot, base, body, title);
|
|
64
|
+
process.stdout.write('\n' + SEP + '✅ PR finished — here is exactly what I did\n' + SEP + '\n' +
|
|
65
|
+
` 1. validated the build gate (authoritative)\n` +
|
|
66
|
+
` 2. force-pushed your work to origin/${base}\n` +
|
|
67
|
+
` 3. ${prNum ? `updated/created PR #${prNum}` : 'created the PR'} titled: "${title}"\n` +
|
|
68
|
+
` You are on ${base} — same name as the remote branch and the PR head.\n\n`);
|
|
69
|
+
}
|
|
70
|
+
gitOut(args) {
|
|
71
|
+
const result = (0, child_process_1.spawnSync)('git', args, { encoding: 'utf8' });
|
|
72
|
+
return result.status === 0 ? (result.stdout ?? '').trim() : '';
|
|
73
|
+
}
|
|
74
|
+
// The user-facing PR title: the AI-authored review.title, or — if omitted — a readable fallback
|
|
75
|
+
// derived from the stable feature name (NEVER the internal `Squash merge of <branch>` commit subject).
|
|
76
|
+
prTitleFrom(review) {
|
|
77
|
+
if (review.title !== '')
|
|
78
|
+
return review.title;
|
|
79
|
+
return this.aiBranchName.getFeatureName().replace(/[-/]+/g, ' ').trim();
|
|
80
|
+
}
|
|
81
|
+
buildDashboard(repoRoot, buildPassed, review, title) {
|
|
82
|
+
const config = (0, rules_config_1.loadAndValidate)(repoRoot).prGate;
|
|
83
|
+
const forkPoint = this.gitOut(['merge-base', 'origin/main', 'HEAD']);
|
|
84
|
+
const featureHead = this.gitOut(['rev-parse', 'HEAD']);
|
|
85
|
+
const mainHead = this.gitOut(['rev-parse', 'origin/main']);
|
|
86
|
+
const range = `${forkPoint}..${featureHead}`;
|
|
87
|
+
const changedFiles = this.gitOut(['diff', range, '--name-only']).split('\n').filter((f) => f.trim() !== '');
|
|
88
|
+
const patch = this.gitOut(['diff', range]);
|
|
89
|
+
const gateResults = this.dashboard.computeGateResults(config.gates, changedFiles);
|
|
90
|
+
const disables = this.dashboard.countAddedDisables(patch);
|
|
91
|
+
const input = new dashboard_1.DashboardInput(title, gateResults, disables, buildPassed, forkPoint, featureHead, mainHead, review);
|
|
92
|
+
return this.dashboard.renderDashboard(input);
|
|
93
|
+
}
|
|
94
|
+
// The PR, the remote branch, and the local branch all share the one stable feature name. Look up /
|
|
95
|
+
// create / merge against `baseBranch` (baseBranchName tolerates a leftover `…wpN` mid-transition).
|
|
96
|
+
upsertPr(repoRoot, baseBranch, body, title) {
|
|
97
|
+
const prDir = (0, rules_config_1.prDirFor)(repoRoot, this.aiBranchName.getFeatureName());
|
|
98
|
+
fs.mkdirSync(prDir, { recursive: true });
|
|
99
|
+
const bodyFile = path.join(prDir, 'pr-body.md');
|
|
100
|
+
fs.writeFileSync(bodyFile, body + '\n');
|
|
101
|
+
const prNumber = (0, child_process_1.spawnSync)('gh', ['pr', 'list', '--head', baseBranch, '--json', 'number', '--jq', '.[0].number'], { encoding: 'utf8' });
|
|
102
|
+
const num = prNumber.status === 0 ? (prNumber.stdout ?? '').trim() : '';
|
|
103
|
+
if (num === '') {
|
|
104
|
+
process.stdout.write('Creating PR...\n');
|
|
105
|
+
const create = (0, child_process_1.spawnSync)('gh', ['pr', 'create', '--head', baseBranch, '--base', 'main', '--title', title, '--body-file', bodyFile], { stdio: 'inherit' });
|
|
106
|
+
if (create.status !== 0) {
|
|
107
|
+
process.stderr.write('⚠️ gh pr create failed — create the PR manually with the body in:\n ' + bodyFile + '\n');
|
|
108
|
+
return '';
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
process.stdout.write(`Updating PR #${num}...\n`);
|
|
113
|
+
(0, child_process_1.spawnSync)('gh', ['pr', 'edit', num, '--title', title, '--body-file', bodyFile], { stdio: 'inherit' });
|
|
114
|
+
}
|
|
115
|
+
(0, child_process_1.spawnSync)('gh', ['pr', 'merge', baseBranch, '--auto', '--squash'], { stdio: 'inherit' });
|
|
116
|
+
return num;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
exports.FinishUpsertPrCommand = FinishUpsertPrCommand;
|
|
120
|
+
exports.FinishUpsertPrCommand = FinishUpsertPrCommand = tslib_1.__decorate([
|
|
121
|
+
(0, core_context_1.provideSingleton)(),
|
|
122
|
+
(0, inversify_1.injectable)(),
|
|
123
|
+
tslib_1.__metadata("design:paramtypes", [git_readAiBranchName_1.AiBranchName,
|
|
124
|
+
branch_naming_1.BranchNaming,
|
|
125
|
+
git_exec_1.GitExec,
|
|
126
|
+
build_affected_1.BuildAffected,
|
|
127
|
+
merge_state_1.MergeState,
|
|
128
|
+
merge_end_1.MergeEnd,
|
|
129
|
+
dashboard_1.Dashboard])
|
|
130
|
+
], FinishUpsertPrCommand);
|
|
131
|
+
//# sourceMappingURL=finish-upsert-pr-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"finish-upsert-pr-command.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/commands/finish-upsert-pr-command.ts"],"names":[],"mappings":"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","sourcesContent":["import { execSync, spawnSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport {\n loadAndValidate, loadReviewJson, prDirFor, reviewJsonPath, ReviewJson, writeTemplate,\n} from '@webpieces/rules-config';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { injectable } from 'inversify';\nimport { AiBranchName } from '../workflow/git-readAiBranchName';\nimport { BranchNaming } from '../workflow/branch-naming';\nimport { GitExec } from '../workflow/git-exec';\nimport { BuildAffected, BuildGateOptions } from '../workflow/build-affected';\nimport { MergeState } from '../workflow/merge-state';\nimport { MergeEnd } from '../workflow/merge-end';\nimport { MergeContext } from '../workflow/merge-start';\nimport { Dashboard, DashboardInput } from '../../dashboard/dashboard';\n\nconst SEP = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n';\n\n// FINISH of the AI-first PR flow. Runs after the AI wrote review.json. In order: (1) if a 3-point merge\n// was in progress, validate + commit + FINALIZE via merge-END; (2) REQUIRE review.json; (3) run the\n// authoritative build gate; (4) render the dashboard; (5) create/update the PR via `gh`. The ONLY\n// command that posts PRs.\n@provideSingleton()\n@injectable()\nexport class FinishUpsertPrCommand {\n constructor(\n private readonly aiBranchName: AiBranchName,\n private readonly branchNaming: BranchNaming,\n private readonly gitExec: GitExec,\n private readonly buildAffected: BuildAffected,\n private readonly mergeState: MergeState,\n private readonly mergeEnd: MergeEnd,\n private readonly dashboard: Dashboard,\n ) {}\n\n async run(): Promise<void> {\n const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();\n // Refresh the AI-facing workflow doc so it's present + current for any failure message to cite.\n writeTemplate(repoRoot, 'webpieces.git-workflow.md');\n const home = this.mergeState.mergeDirFor(repoRoot, this.aiBranchName.getFeatureName());\n\n // 1. Finish any in-progress conflict resolution: validate + commit + finalize the branch swap.\n const activeDir = this.mergeState.findActiveMergeRunDir(home);\n const marker = activeDir ? this.mergeState.readMergeMarker(activeDir) : null;\n if (activeDir && marker && !marker.validated) {\n await this.mergeEnd.mergeEnd(\n repoRoot, 'wp-finish-upsert-pr', activeDir,\n new MergeContext(marker.currentBranch, marker.squashBranch, marker.backupBranch, marker.prNumber),\n marker.conflictedFiles,\n );\n }\n\n // 2. REQUIRE the AI-authored review.json (throws InformAiError with the schema if missing/invalid).\n const review = loadReviewJson(reviewJsonPath(repoRoot, this.aiBranchName.getFeatureName()));\n\n // 2b. The build gate validates the WORKING TREE but we push HEAD — so they MUST be identical.\n this.gitExec.assertCleanTree(repoRoot);\n\n // 3. Authoritative build gate, then push, then post.\n this.buildAffected.runBuildGate(repoRoot, new BuildGateOptions(\n '🛠️ Build gate (authoritative)', 'pnpm wp-finish-upsert-pr', 'Build failed — no PR created/updated.',\n ));\n const base = this.branchNaming.baseBranchName(execSync('git branch --show-current', { encoding: 'utf8' }).trim());\n this.gitExec.ensurePushed(base);\n\n process.stdout.write('\\n' + SEP + '📋 Dashboard + PR\\n' + SEP + '\\n');\n const title = this.prTitleFrom(review);\n const body = this.buildDashboard(repoRoot, true, review, title);\n const prNum = this.upsertPr(repoRoot, base, body, title);\n\n process.stdout.write(\n '\\n' + SEP + '✅ PR finished — here is exactly what I did\\n' + SEP + '\\n' +\n ` 1. validated the build gate (authoritative)\\n` +\n ` 2. force-pushed your work to origin/${base}\\n` +\n ` 3. ${prNum ? `updated/created PR #${prNum}` : 'created the PR'} titled: \"${title}\"\\n` +\n ` You are on ${base} — same name as the remote branch and the PR head.\\n\\n`,\n );\n }\n\n private gitOut(args: string[]): string {\n const result = spawnSync('git', args, { encoding: 'utf8' });\n return result.status === 0 ? (result.stdout ?? '').trim() : '';\n }\n\n // The user-facing PR title: the AI-authored review.title, or — if omitted — a readable fallback\n // derived from the stable feature name (NEVER the internal `Squash merge of <branch>` commit subject).\n private prTitleFrom(review: ReviewJson): string {\n if (review.title !== '') return review.title;\n return this.aiBranchName.getFeatureName().replace(/[-/]+/g, ' ').trim();\n }\n\n private buildDashboard(repoRoot: string, buildPassed: boolean, review: ReviewJson, title: string): string {\n const config = loadAndValidate(repoRoot).prGate;\n const forkPoint = this.gitOut(['merge-base', 'origin/main', 'HEAD']);\n const featureHead = this.gitOut(['rev-parse', 'HEAD']);\n const mainHead = this.gitOut(['rev-parse', 'origin/main']);\n const range = `${forkPoint}..${featureHead}`;\n const changedFiles = this.gitOut(['diff', range, '--name-only']).split('\\n').filter((f: string): boolean => f.trim() !== '');\n const patch = this.gitOut(['diff', range]);\n\n const gateResults = this.dashboard.computeGateResults(config.gates, changedFiles);\n const disables = this.dashboard.countAddedDisables(patch);\n const input = new DashboardInput(title, gateResults, disables, buildPassed, forkPoint, featureHead, mainHead, review);\n return this.dashboard.renderDashboard(input);\n }\n\n // The PR, the remote branch, and the local branch all share the one stable feature name. Look up /\n // create / merge against `baseBranch` (baseBranchName tolerates a leftover `…wpN` mid-transition).\n private upsertPr(repoRoot: string, baseBranch: string, body: string, title: string): string {\n const prDir = prDirFor(repoRoot, this.aiBranchName.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 prNumber = spawnSync(\n 'gh', ['pr', 'list', '--head', baseBranch, '--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', baseBranch, '--base', 'main', '--title', title, '--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, '--title', title, '--body-file', bodyFile], { stdio: 'inherit' });\n }\n spawnSync('gh', ['pr', 'merge', baseBranch, '--auto', '--squash'], { stdio: 'inherit' });\n return num;\n }\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { OpenPrCheck } from '../workflow/open-pr-check';
|
|
2
|
+
import { RunUpdate } from '../workflow/run-update';
|
|
3
|
+
export declare class StartUpdateCommand {
|
|
4
|
+
private readonly openPrCheck;
|
|
5
|
+
private readonly runUpdate;
|
|
6
|
+
constructor(openPrCheck: OpenPrCheck, runUpdate: RunUpdate);
|
|
7
|
+
run(): Promise<void>;
|
|
8
|
+
assertNoOpenPr(repoRoot: string): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StartUpdateCommand = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
const rules_config_1 = require("@webpieces/rules-config");
|
|
7
|
+
const core_context_1 = require("@webpieces/core-context");
|
|
8
|
+
const inversify_1 = require("inversify");
|
|
9
|
+
const open_pr_check_1 = require("../workflow/open-pr-check");
|
|
10
|
+
const run_update_1 = require("../workflow/run-update");
|
|
11
|
+
const SEP = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
|
|
12
|
+
// wp-start-update: the "sync this feature branch from main" entry (the redirect target of the
|
|
13
|
+
// redirect-how-to-merge-main guard). Runs the FULL 3-point squash-update via RunUpdate: a CLEAN merge
|
|
14
|
+
// finalizes everything; CONFLICT writes the 3-point context + merge process doc and hands back. NEVER
|
|
15
|
+
// creates a PR (that is the wp-*-upsert-pr flow).
|
|
16
|
+
let StartUpdateCommand = class StartUpdateCommand {
|
|
17
|
+
openPrCheck;
|
|
18
|
+
runUpdate;
|
|
19
|
+
constructor(openPrCheck, runUpdate) {
|
|
20
|
+
this.openPrCheck = openPrCheck;
|
|
21
|
+
this.runUpdate = runUpdate;
|
|
22
|
+
}
|
|
23
|
+
async run() {
|
|
24
|
+
const repoRoot = (0, child_process_1.execSync)('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
|
|
25
|
+
// Refresh the AI-facing workflow doc so it's present + current for any failure message to cite.
|
|
26
|
+
(0, rules_config_1.writeTemplate)(repoRoot, 'webpieces.git-workflow.md');
|
|
27
|
+
// An open PR means the PR flow must be used — a 3-point update would strand the PR on the old
|
|
28
|
+
// branch generation. Fails fast if GitHub can't be reached (never guesses "no PR").
|
|
29
|
+
this.assertNoOpenPr(repoRoot);
|
|
30
|
+
const outcome = await this.runUpdate.runUpdateFromMain(repoRoot, 'wp-start-update', 'wp-finish-update');
|
|
31
|
+
if (outcome === 'conflict') {
|
|
32
|
+
// Context + marker + merge process doc already written by merge-start; hand back to the AI.
|
|
33
|
+
throw new rules_config_1.CliExitError(2, '');
|
|
34
|
+
}
|
|
35
|
+
if (outcome === 'unvalidatedResume') {
|
|
36
|
+
throw new rules_config_1.CliExitError(1, '\n' + SEP + '⏸️ Merge in progress — not yet validated\n' + SEP + '\n' +
|
|
37
|
+
'Resolve the remaining conflicts in the working tree, then run:\n' +
|
|
38
|
+
' pnpm wp-finish-update\n');
|
|
39
|
+
}
|
|
40
|
+
process.stdout.write('\n✅ Updated from main — clean. No need to call wp-finish-update.\n');
|
|
41
|
+
}
|
|
42
|
+
// If a PR is already OPEN for this branch, wp-start-update must refuse. The 3-point update
|
|
43
|
+
// re-squashes your branch onto main and force-pushes it to origin/<feature> — the PR head — but it
|
|
44
|
+
// does NOT refresh the PR body/review or run the authoritative build gate. Fail fast and steer to
|
|
45
|
+
// the PR flow, which re-merges main AND updates the PR.
|
|
46
|
+
assertNoOpenPr(repoRoot) {
|
|
47
|
+
const branch = (0, child_process_1.execSync)('git rev-parse --abbrev-ref HEAD', { cwd: repoRoot, encoding: 'utf8' }).trim();
|
|
48
|
+
const openPr = this.openPrCheck.openPrForBranch(repoRoot, branch);
|
|
49
|
+
if (openPr === '')
|
|
50
|
+
return;
|
|
51
|
+
throw new rules_config_1.CliExitError(2, '\n' + SEP + `⛔ An open PR (#${openPr}) already tracks this branch\n` + SEP + '\n' +
|
|
52
|
+
'wp-start-update re-squashes your branch onto main and force-pushes it, but it does NOT refresh\n' +
|
|
53
|
+
`the PR body/review — so PR #${openPr} would get new code without an updated review. Use the PR\n` +
|
|
54
|
+
'flow instead — it re-merges main AND updates the PR:\n' +
|
|
55
|
+
' 1. pnpm wp-start-upsert-pr\n' +
|
|
56
|
+
' 2. /wp-merge (only if conflicts)\n' +
|
|
57
|
+
' 3. pnpm wp-finish-upsert-pr\n');
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
exports.StartUpdateCommand = StartUpdateCommand;
|
|
61
|
+
exports.StartUpdateCommand = StartUpdateCommand = tslib_1.__decorate([
|
|
62
|
+
(0, core_context_1.provideSingleton)(),
|
|
63
|
+
(0, inversify_1.injectable)(),
|
|
64
|
+
tslib_1.__metadata("design:paramtypes", [open_pr_check_1.OpenPrCheck,
|
|
65
|
+
run_update_1.RunUpdate])
|
|
66
|
+
], StartUpdateCommand);
|
|
67
|
+
//# sourceMappingURL=start-update-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start-update-command.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/commands/start-update-command.ts"],"names":[],"mappings":";;;;AAAA,iDAAyC;AACzC,0DAAsE;AACtE,0DAA2D;AAC3D,yCAAuC;AACvC,6DAAwD;AACxD,uDAAmD;AAEnD,MAAM,GAAG,GAAG,0DAA0D,CAAC;AAEvE,8FAA8F;AAC9F,sGAAsG;AACtG,sGAAsG;AACtG,kDAAkD;AAG3C,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAEN;IACA;IAFrB,YACqB,WAAwB,EACxB,SAAoB;QADpB,gBAAW,GAAX,WAAW,CAAa;QACxB,cAAS,GAAT,SAAS,CAAW;IACtC,CAAC;IAEJ,KAAK,CAAC,GAAG;QACL,MAAM,QAAQ,GAAG,IAAA,wBAAQ,EAAC,+BAA+B,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACxF,gGAAgG;QAChG,IAAA,4BAAa,EAAC,QAAQ,EAAE,2BAA2B,CAAC,CAAC;QAErD,8FAA8F;QAC9F,oFAAoF;QACpF,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE9B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;QACxG,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;YACzB,4FAA4F;YAC5F,MAAM,IAAI,2BAAY,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAClC,CAAC;QACD,IAAI,OAAO,KAAK,mBAAmB,EAAE,CAAC;YAClC,MAAM,IAAI,2BAAY,CAAC,CAAC,EACpB,IAAI,GAAG,GAAG,GAAG,6CAA6C,GAAG,GAAG,GAAG,IAAI;gBACvE,kEAAkE;gBAClE,2BAA2B,CAC9B,CAAC;QACN,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oEAAoE,CAAC,CAAC;IAC/F,CAAC;IAED,2FAA2F;IAC3F,mGAAmG;IACnG,kGAAkG;IAClG,wDAAwD;IACxD,cAAc,CAAC,QAAgB;QAC3B,MAAM,MAAM,GAAG,IAAA,wBAAQ,EAAC,iCAAiC,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACvG,MAAM,MAAM,GAAG,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAClE,IAAI,MAAM,KAAK,EAAE;YAAE,OAAO;QAC1B,MAAM,IAAI,2BAAY,CAAC,CAAC,EACpB,IAAI,GAAG,GAAG,GAAG,kBAAkB,MAAM,gCAAgC,GAAG,GAAG,GAAG,IAAI;YAClF,kGAAkG;YAClG,+BAA+B,MAAM,6DAA6D;YAClG,wDAAwD;YACxD,gCAAgC;YAChC,wCAAwC;YACxC,iCAAiC,CACpC,CAAC;IACN,CAAC;CACJ,CAAA;AAhDY,gDAAkB;6BAAlB,kBAAkB;IAF9B,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;6CAGyB,2BAAW;QACb,sBAAS;GAHhC,kBAAkB,CAgD9B","sourcesContent":["import { execSync } from 'child_process';\nimport { writeTemplate, CliExitError } from '@webpieces/rules-config';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { injectable } from 'inversify';\nimport { OpenPrCheck } from '../workflow/open-pr-check';\nimport { RunUpdate } from '../workflow/run-update';\n\nconst SEP = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n';\n\n// wp-start-update: the \"sync this feature branch from main\" entry (the redirect target of the\n// redirect-how-to-merge-main guard). Runs the FULL 3-point squash-update via RunUpdate: a CLEAN merge\n// finalizes everything; CONFLICT writes the 3-point context + merge process doc and hands back. NEVER\n// creates a PR (that is the wp-*-upsert-pr flow).\n@provideSingleton()\n@injectable()\nexport class StartUpdateCommand {\n constructor(\n private readonly openPrCheck: OpenPrCheck,\n private readonly runUpdate: RunUpdate,\n ) {}\n\n async run(): Promise<void> {\n const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();\n // Refresh the AI-facing workflow doc so it's present + current for any failure message to cite.\n writeTemplate(repoRoot, 'webpieces.git-workflow.md');\n\n // An open PR means the PR flow must be used — a 3-point update would strand the PR on the old\n // branch generation. Fails fast if GitHub can't be reached (never guesses \"no PR\").\n this.assertNoOpenPr(repoRoot);\n\n const outcome = await this.runUpdate.runUpdateFromMain(repoRoot, 'wp-start-update', 'wp-finish-update');\n if (outcome === 'conflict') {\n // Context + marker + merge process doc already written by merge-start; hand back to the AI.\n throw new CliExitError(2, '');\n }\n if (outcome === 'unvalidatedResume') {\n throw new CliExitError(1,\n '\\n' + SEP + '⏸️ Merge in progress — not yet validated\\n' + SEP + '\\n' +\n 'Resolve the remaining conflicts in the working tree, then run:\\n' +\n ' pnpm wp-finish-update\\n',\n );\n }\n process.stdout.write('\\n✅ Updated from main — clean. No need to call wp-finish-update.\\n');\n }\n\n // If a PR is already OPEN for this branch, wp-start-update must refuse. The 3-point update\n // re-squashes your branch onto main and force-pushes it to origin/<feature> — the PR head — but it\n // does NOT refresh the PR body/review or run the authoritative build gate. Fail fast and steer to\n // the PR flow, which re-merges main AND updates the PR.\n assertNoOpenPr(repoRoot: string): void {\n const branch = execSync('git rev-parse --abbrev-ref HEAD', { cwd: repoRoot, encoding: 'utf8' }).trim();\n const openPr = this.openPrCheck.openPrForBranch(repoRoot, branch);\n if (openPr === '') return;\n throw new CliExitError(2,\n '\\n' + SEP + `⛔ An open PR (#${openPr}) already tracks this branch\\n` + SEP + '\\n' +\n 'wp-start-update re-squashes your branch onto main and force-pushes it, but it does NOT refresh\\n' +\n `the PR body/review — so PR #${openPr} would get new code without an updated review. Use the PR\\n` +\n 'flow instead — it re-merges main AND updates the PR:\\n' +\n ' 1. pnpm wp-start-upsert-pr\\n' +\n ' 2. /wp-merge (only if conflicts)\\n' +\n ' 3. pnpm wp-finish-upsert-pr\\n',\n );\n }\n}\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AiBranchName } from '../workflow/git-readAiBranchName';
|
|
2
|
+
import { BranchNaming } from '../workflow/branch-naming';
|
|
3
|
+
import { BuildAffected } from '../workflow/build-affected';
|
|
4
|
+
import { GitExec } from '../workflow/git-exec';
|
|
5
|
+
import { RunUpdate } from '../workflow/run-update';
|
|
6
|
+
export declare class StartUpsertPrCommand {
|
|
7
|
+
private readonly aiBranchName;
|
|
8
|
+
private readonly branchNaming;
|
|
9
|
+
private readonly buildAffected;
|
|
10
|
+
private readonly gitExec;
|
|
11
|
+
private readonly runUpdate;
|
|
12
|
+
constructor(aiBranchName: AiBranchName, branchNaming: BranchNaming, buildAffected: BuildAffected, gitExec: GitExec, runUpdate: RunUpdate);
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
private updateBranchFromMain;
|
|
15
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StartUpsertPrCommand = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
const rules_config_1 = require("@webpieces/rules-config");
|
|
7
|
+
const core_context_1 = require("@webpieces/core-context");
|
|
8
|
+
const inversify_1 = require("inversify");
|
|
9
|
+
const git_readAiBranchName_1 = require("../workflow/git-readAiBranchName");
|
|
10
|
+
const branch_naming_1 = require("../workflow/branch-naming");
|
|
11
|
+
const build_affected_1 = require("../workflow/build-affected");
|
|
12
|
+
const git_exec_1 = require("../workflow/git-exec");
|
|
13
|
+
const run_update_1 = require("../workflow/run-update");
|
|
14
|
+
const SEP = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
|
|
15
|
+
// START of the AI-first PR flow: the deterministic setup — update from main, push, run the advisory
|
|
16
|
+
// build gate — then hand the AI instructions to WRITE review.json and run `wp-finish-upsert-pr` (which
|
|
17
|
+
// reads it and posts the PR). This command NEVER creates/updates a PR; all `gh` posting lives in finish.
|
|
18
|
+
let StartUpsertPrCommand = class StartUpsertPrCommand {
|
|
19
|
+
aiBranchName;
|
|
20
|
+
branchNaming;
|
|
21
|
+
buildAffected;
|
|
22
|
+
gitExec;
|
|
23
|
+
runUpdate;
|
|
24
|
+
constructor(aiBranchName, branchNaming, buildAffected, gitExec, runUpdate) {
|
|
25
|
+
this.aiBranchName = aiBranchName;
|
|
26
|
+
this.branchNaming = branchNaming;
|
|
27
|
+
this.buildAffected = buildAffected;
|
|
28
|
+
this.gitExec = gitExec;
|
|
29
|
+
this.runUpdate = runUpdate;
|
|
30
|
+
}
|
|
31
|
+
async run() {
|
|
32
|
+
const repoRoot = (0, child_process_1.execSync)('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
|
|
33
|
+
// Refresh the AI-facing workflow doc so it's present + current for any failure message to cite.
|
|
34
|
+
(0, rules_config_1.writeTemplate)(repoRoot, 'webpieces.git-workflow.md');
|
|
35
|
+
// Precondition: a fully-committed tree. This flow updates, pushes HEAD, and builds — the tooling
|
|
36
|
+
// must not commit your work for you, and pushing HEAD while building the working tree would let
|
|
37
|
+
// an uncommitted change build green yet push a stale commit. Fail early if dirty.
|
|
38
|
+
this.gitExec.assertCleanTree(repoRoot);
|
|
39
|
+
await this.updateBranchFromMain(repoRoot);
|
|
40
|
+
// Local branch, remote branch, and PR share the one stable feature name.
|
|
41
|
+
this.gitExec.ensurePushed(this.branchNaming.baseBranchName((0, child_process_1.execSync)('git branch --show-current', { encoding: 'utf8' }).trim()));
|
|
42
|
+
// Advisory build gate — early feedback before the AI writes review.json. wp-finish-upsert-pr
|
|
43
|
+
// runs the authoritative one. Both go through the same runBuildGate (only the framing differs).
|
|
44
|
+
this.buildAffected.runBuildGate(repoRoot, new build_affected_1.BuildGateOptions('② Build gate (nx affected)', 'pnpm wp-start-upsert-pr', 'Build failed — fix it before reviewing.'));
|
|
45
|
+
// Hand the AI its next step: write review.json, then run finish (which posts the PR).
|
|
46
|
+
const reviewPath = (0, rules_config_1.reviewJsonPath)(repoRoot, this.aiBranchName.getFeatureName());
|
|
47
|
+
process.stdout.write('\n' + SEP + '③ Review the PR, then finish\n' + SEP + '\n');
|
|
48
|
+
process.stdout.write(`Branch is updated, pushed, and the build gate passed. Now review your own changes and\n` +
|
|
49
|
+
`${(0, rules_config_1.reviewJsonSchemaHint)(reviewPath)}\n\n` +
|
|
50
|
+
`Then run: pnpm wp-finish-upsert-pr\n` +
|
|
51
|
+
`(It re-validates the build, renders the dashboard with your risk/violations, and creates/updates the PR.)\n\n`);
|
|
52
|
+
}
|
|
53
|
+
// Bring the branch up to date with main via the shared 3-point engine (in-process). On conflict the
|
|
54
|
+
// merge process doc it writes names `wp-finish-upsert-pr` as the finish command.
|
|
55
|
+
async updateBranchFromMain(repoRoot) {
|
|
56
|
+
process.stdout.write('\n' + SEP + '① Updating branch from main\n' + SEP + '\n');
|
|
57
|
+
const outcome = await this.runUpdate.runUpdateFromMain(repoRoot, 'wp-start-upsert-pr', 'wp-finish-upsert-pr');
|
|
58
|
+
if (outcome === 'conflict' || outcome === 'unvalidatedResume') {
|
|
59
|
+
throw new rules_config_1.CliExitError(2, '\n⏸️ Conflicts — resolve them, then run pnpm wp-finish-upsert-pr (it validates the merge AND finishes the PR).');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
exports.StartUpsertPrCommand = StartUpsertPrCommand;
|
|
64
|
+
exports.StartUpsertPrCommand = StartUpsertPrCommand = tslib_1.__decorate([
|
|
65
|
+
(0, core_context_1.provideSingleton)(),
|
|
66
|
+
(0, inversify_1.injectable)(),
|
|
67
|
+
tslib_1.__metadata("design:paramtypes", [git_readAiBranchName_1.AiBranchName,
|
|
68
|
+
branch_naming_1.BranchNaming,
|
|
69
|
+
build_affected_1.BuildAffected,
|
|
70
|
+
git_exec_1.GitExec,
|
|
71
|
+
run_update_1.RunUpdate])
|
|
72
|
+
], StartUpsertPrCommand);
|
|
73
|
+
//# sourceMappingURL=start-upsert-pr-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start-upsert-pr-command.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/commands/start-upsert-pr-command.ts"],"names":[],"mappings":";;;;AAAA,iDAAyC;AACzC,0DAA4G;AAC5G,0DAA2D;AAC3D,yCAAuC;AACvC,2EAAgE;AAChE,6DAAyD;AACzD,+DAA6E;AAC7E,mDAA+C;AAC/C,uDAAmD;AAEnD,MAAM,GAAG,GAAG,0DAA0D,CAAC;AAEvE,oGAAoG;AACpG,uGAAuG;AACvG,yGAAyG;AAGlG,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAER;IACA;IACA;IACA;IACA;IALrB,YACqB,YAA0B,EAC1B,YAA0B,EAC1B,aAA4B,EAC5B,OAAgB,EAChB,SAAoB;QAJpB,iBAAY,GAAZ,YAAY,CAAc;QAC1B,iBAAY,GAAZ,YAAY,CAAc;QAC1B,kBAAa,GAAb,aAAa,CAAe;QAC5B,YAAO,GAAP,OAAO,CAAS;QAChB,cAAS,GAAT,SAAS,CAAW;IACtC,CAAC;IAEJ,KAAK,CAAC,GAAG;QACL,MAAM,QAAQ,GAAG,IAAA,wBAAQ,EAAC,+BAA+B,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACxF,gGAAgG;QAChG,IAAA,4BAAa,EAAC,QAAQ,EAAE,2BAA2B,CAAC,CAAC;QAErD,iGAAiG;QACjG,gGAAgG;QAChG,kFAAkF;QAClF,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;QAEvC,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QAC1C,yEAAyE;QACzE,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,IAAA,wBAAQ,EAAC,2BAA2B,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAEhI,6FAA6F;QAC7F,gGAAgG;QAChG,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,iCAAgB,CAC1D,4BAA4B,EAAE,yBAAyB,EAAE,yCAAyC,CACrG,CAAC,CAAC;QAEH,sFAAsF;QACtF,MAAM,UAAU,GAAG,IAAA,6BAAc,EAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC,CAAC;QAChF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,GAAG,gCAAgC,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;QACjF,OAAO,CAAC,MAAM,CAAC,KAAK,CAChB,yFAAyF;YACzF,GAAG,IAAA,mCAAoB,EAAC,UAAU,CAAC,MAAM;YACzC,uCAAuC;YACvC,+GAA+G,CAClH,CAAC;IACN,CAAC;IAED,oGAAoG;IACpG,iFAAiF;IACzE,KAAK,CAAC,oBAAoB,CAAC,QAAgB;QAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,GAAG,+BAA+B,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;QAChF,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,QAAQ,EAAE,oBAAoB,EAAE,qBAAqB,CAAC,CAAC;QAC9G,IAAI,OAAO,KAAK,UAAU,IAAI,OAAO,KAAK,mBAAmB,EAAE,CAAC;YAC5D,MAAM,IAAI,2BAAY,CAAC,CAAC,EACpB,iHAAiH,CACpH,CAAC;QACN,CAAC;IACL,CAAC;CACJ,CAAA;AAnDY,oDAAoB;+BAApB,oBAAoB;IAFhC,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;6CAG0B,mCAAY;QACZ,4BAAY;QACX,8BAAa;QACnB,kBAAO;QACL,sBAAS;GANhC,oBAAoB,CAmDhC","sourcesContent":["import { execSync } from 'child_process';\nimport { reviewJsonPath, reviewJsonSchemaHint, writeTemplate, CliExitError } from '@webpieces/rules-config';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { injectable } from 'inversify';\nimport { AiBranchName } from '../workflow/git-readAiBranchName';\nimport { BranchNaming } from '../workflow/branch-naming';\nimport { BuildAffected, BuildGateOptions } from '../workflow/build-affected';\nimport { GitExec } from '../workflow/git-exec';\nimport { RunUpdate } from '../workflow/run-update';\n\nconst SEP = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\\n';\n\n// START of the AI-first PR flow: the deterministic setup — update from main, push, run the advisory\n// build gate — then hand the AI instructions to WRITE review.json and run `wp-finish-upsert-pr` (which\n// reads it and posts the PR). This command NEVER creates/updates a PR; all `gh` posting lives in finish.\n@provideSingleton()\n@injectable()\nexport class StartUpsertPrCommand {\n constructor(\n private readonly aiBranchName: AiBranchName,\n private readonly branchNaming: BranchNaming,\n private readonly buildAffected: BuildAffected,\n private readonly gitExec: GitExec,\n private readonly runUpdate: RunUpdate,\n ) {}\n\n async run(): Promise<void> {\n const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();\n // Refresh the AI-facing workflow doc so it's present + current for any failure message to cite.\n writeTemplate(repoRoot, 'webpieces.git-workflow.md');\n\n // Precondition: a fully-committed tree. This flow updates, pushes HEAD, and builds — the tooling\n // must not commit your work for you, and pushing HEAD while building the working tree would let\n // an uncommitted change build green yet push a stale commit. Fail early if dirty.\n this.gitExec.assertCleanTree(repoRoot);\n\n await this.updateBranchFromMain(repoRoot);\n // Local branch, remote branch, and PR share the one stable feature name.\n this.gitExec.ensurePushed(this.branchNaming.baseBranchName(execSync('git branch --show-current', { encoding: 'utf8' }).trim()));\n\n // Advisory build gate — early feedback before the AI writes review.json. wp-finish-upsert-pr\n // runs the authoritative one. Both go through the same runBuildGate (only the framing differs).\n this.buildAffected.runBuildGate(repoRoot, new BuildGateOptions(\n '② Build gate (nx affected)', 'pnpm wp-start-upsert-pr', 'Build failed — fix it before reviewing.',\n ));\n\n // Hand the AI its next step: write review.json, then run finish (which posts the PR).\n const reviewPath = reviewJsonPath(repoRoot, this.aiBranchName.getFeatureName());\n process.stdout.write('\\n' + SEP + '③ Review the PR, then finish\\n' + SEP + '\\n');\n process.stdout.write(\n `Branch is updated, pushed, and the build gate passed. Now review your own changes and\\n` +\n `${reviewJsonSchemaHint(reviewPath)}\\n\\n` +\n `Then run: pnpm wp-finish-upsert-pr\\n` +\n `(It re-validates the build, renders the dashboard with your risk/violations, and creates/updates the PR.)\\n\\n`,\n );\n }\n\n // Bring the branch up to date with main via the shared 3-point engine (in-process). On conflict the\n // merge process doc it writes names `wp-finish-upsert-pr` as the finish command.\n private async updateBranchFromMain(repoRoot: string): Promise<void> {\n process.stdout.write('\\n' + SEP + '① Updating branch from main\\n' + SEP + '\\n');\n const outcome = await this.runUpdate.runUpdateFromMain(repoRoot, 'wp-start-upsert-pr', 'wp-finish-upsert-pr');\n if (outcome === 'conflict' || outcome === 'unvalidatedResume') {\n throw new CliExitError(2,\n '\\n⏸️ Conflicts — resolve them, then run pnpm wp-finish-upsert-pr (it validates the merge AND finishes the PR).',\n );\n }\n }\n}\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
import 'reflect-metadata';
|
|
@@ -1,114 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const fs = tslib_1.__importStar(require("fs"));
|
|
8
|
-
const path = tslib_1.__importStar(require("path"));
|
|
4
|
+
require("reflect-metadata");
|
|
5
|
+
const inversify_1 = require("inversify");
|
|
6
|
+
const binding_decorators_1 = require("@inversifyjs/binding-decorators");
|
|
9
7
|
const rules_config_1 = require("@webpieces/rules-config");
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
// FINISH of the AI-first PR flow. Runs after the AI has written review.json (see wp-start-upsert-pr).
|
|
19
|
-
// Responsibilities, in order: (1) if a 3-point merge was in progress, validate + commit + FINALIZE the
|
|
20
|
-
// AI's resolution via merge-END (so the PR is posted from the finalized feature branch, not the squash
|
|
21
|
-
// branch); (2) REQUIRE review.json (hard-fail with the schema if absent/invalid); (3) run the
|
|
22
|
-
// authoritative build gate; (4) render the dashboard; (5) create/update the PR via `gh`. This is the
|
|
23
|
-
// ONLY command that posts PRs.
|
|
24
|
-
const SEP = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n';
|
|
25
|
-
function gitOut(args) {
|
|
26
|
-
const result = (0, child_process_1.spawnSync)('git', args, { encoding: 'utf8' });
|
|
27
|
-
return result.status === 0 ? (result.stdout ?? '').trim() : '';
|
|
28
|
-
}
|
|
29
|
-
// The user-facing PR title: the AI-authored review.title, or — if the AI omitted it — a readable
|
|
30
|
-
// fallback derived from the stable feature name (NEVER the internal `Squash merge of <branch>` commit
|
|
31
|
-
// subject, which leaked bookkeeping into the PR title).
|
|
32
|
-
function prTitleFrom(review) {
|
|
33
|
-
if (review.title !== '')
|
|
34
|
-
return review.title;
|
|
35
|
-
return (0, git_readAiBranchName_1.getFeatureName)().replace(/[-/]+/g, ' ').trim();
|
|
36
|
-
}
|
|
37
|
-
function buildDashboard(repoRoot, buildPassed, review, title) {
|
|
38
|
-
const config = (0, rules_config_1.loadAndValidate)(repoRoot).prGate;
|
|
39
|
-
const forkPoint = gitOut(['merge-base', 'origin/main', 'HEAD']);
|
|
40
|
-
const featureHead = gitOut(['rev-parse', 'HEAD']);
|
|
41
|
-
const mainHead = gitOut(['rev-parse', 'origin/main']);
|
|
42
|
-
const range = `${forkPoint}..${featureHead}`;
|
|
43
|
-
const changedFiles = gitOut(['diff', range, '--name-only']).split('\n').filter((f) => f.trim() !== '');
|
|
44
|
-
const patch = gitOut(['diff', range]);
|
|
45
|
-
const gateResults = (0, dashboard_1.computeGateResults)(config.gates, changedFiles);
|
|
46
|
-
const disables = (0, dashboard_1.countAddedDisables)(patch);
|
|
47
|
-
const input = new dashboard_1.DashboardInput(title, gateResults, disables, buildPassed, forkPoint, featureHead, mainHead, review);
|
|
48
|
-
return (0, dashboard_1.renderDashboard)(input);
|
|
49
|
-
}
|
|
50
|
-
// The PR, the remote branch, and the local branch all share the one stable feature name now. Look up /
|
|
51
|
-
// create / merge against `baseBranch` (baseBranchName also tolerates a leftover `…wpN` mid-transition),
|
|
52
|
-
// or a resolve from such a leftover could fail to find its PR and open a duplicate.
|
|
53
|
-
function upsertPr(repoRoot, baseBranch, body, title) {
|
|
54
|
-
const prDir = (0, rules_config_1.prDirFor)(repoRoot, (0, git_readAiBranchName_1.getFeatureName)());
|
|
55
|
-
fs.mkdirSync(prDir, { recursive: true });
|
|
56
|
-
const bodyFile = path.join(prDir, 'pr-body.md');
|
|
57
|
-
fs.writeFileSync(bodyFile, body + '\n');
|
|
58
|
-
const prNumber = (0, child_process_1.spawnSync)('gh', ['pr', 'list', '--head', baseBranch, '--json', 'number', '--jq', '.[0].number'], { encoding: 'utf8' });
|
|
59
|
-
const num = prNumber.status === 0 ? (prNumber.stdout ?? '').trim() : '';
|
|
60
|
-
if (num === '') {
|
|
61
|
-
process.stdout.write('Creating PR...\n');
|
|
62
|
-
const create = (0, child_process_1.spawnSync)('gh', ['pr', 'create', '--head', baseBranch, '--base', 'main', '--title', title, '--body-file', bodyFile], { stdio: 'inherit' });
|
|
63
|
-
if (create.status !== 0) {
|
|
64
|
-
process.stderr.write('⚠️ gh pr create failed — create the PR manually with the body in:\n ' + bodyFile + '\n');
|
|
65
|
-
return '';
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
else {
|
|
69
|
-
process.stdout.write(`Updating PR #${num}...\n`);
|
|
70
|
-
// Keep the title in sync with the latest review.title (not just the body).
|
|
71
|
-
(0, child_process_1.spawnSync)('gh', ['pr', 'edit', num, '--title', title, '--body-file', bodyFile], { stdio: 'inherit' });
|
|
72
|
-
}
|
|
73
|
-
(0, child_process_1.spawnSync)('gh', ['pr', 'merge', baseBranch, '--auto', '--squash'], { stdio: 'inherit' });
|
|
74
|
-
return num;
|
|
75
|
-
}
|
|
76
|
-
async function main() {
|
|
77
|
-
const repoRoot = (0, child_process_1.execSync)('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
|
|
78
|
-
// Refresh the AI-facing workflow doc so it's present + current for any failure message to cite.
|
|
79
|
-
(0, rules_config_1.writeTemplate)(repoRoot, 'webpieces.git-workflow.md');
|
|
80
|
-
const home = (0, merge_state_1.mergeDirFor)(repoRoot, (0, git_readAiBranchName_1.getFeatureName)());
|
|
81
|
-
// 1. Finish any in-progress conflict resolution: validate + commit + finalize the branch swap.
|
|
82
|
-
// No active run dir (or its marker already validated) => no merge in progress => nothing to do
|
|
83
|
-
// (the common case). The active merge is the `merge-<n>/` run dir holding a marker.
|
|
84
|
-
const activeDir = (0, merge_state_1.findActiveMergeRunDir)(home);
|
|
85
|
-
const marker = activeDir ? (0, merge_state_1.readMergeMarker)(activeDir) : null;
|
|
86
|
-
if (activeDir && marker && !marker.validated) {
|
|
87
|
-
await (0, merge_end_1.mergeEnd)(repoRoot, 'wp-finish-upsert-pr', activeDir, new merge_start_1.MergeContext(marker.currentBranch, marker.squashBranch, marker.backupBranch, marker.prNumber), marker.conflictedFiles);
|
|
88
|
-
}
|
|
89
|
-
// 2. REQUIRE the AI-authored review.json (throws InformAiError with the schema if missing/invalid).
|
|
90
|
-
const review = (0, rules_config_1.loadReviewJson)((0, rules_config_1.reviewJsonPath)(repoRoot, (0, git_readAiBranchName_1.getFeatureName)()));
|
|
91
|
-
// 2b. The build gate validates the WORKING TREE but we push HEAD — so they MUST be identical, or a
|
|
92
|
-
// fix edited after the merge commit builds green yet a stale commit gets pushed (CI then fails on
|
|
93
|
-
// the committed tree). Require a clean tree here; the tooling won't commit your work for you.
|
|
94
|
-
(0, git_exec_1.assertCleanTree)(repoRoot);
|
|
95
|
-
// 3. Authoritative build gate, then push, then post.
|
|
96
|
-
(0, build_affected_1.runBuildGate)(repoRoot, new build_affected_1.BuildGateOptions('🛠️ Build gate (authoritative)', 'pnpm wp-finish-upsert-pr', 'Build failed — no PR created/updated.'));
|
|
97
|
-
// After finalize the local branch, the remote branch, and the PR all share the SAME stable name —
|
|
98
|
-
// push and upsert against it. (baseBranchName is a no-op on the already-stable name; it also
|
|
99
|
-
// tolerates a leftover `…wpN` mid-transition.)
|
|
100
|
-
const base = (0, branch_naming_1.baseBranchName)((0, child_process_1.execSync)('git branch --show-current', { encoding: 'utf8' }).trim());
|
|
101
|
-
(0, git_exec_1.ensurePushed)(base);
|
|
102
|
-
process.stdout.write('\n' + SEP + '📋 Dashboard + PR\n' + SEP + '\n');
|
|
103
|
-
const title = prTitleFrom(review);
|
|
104
|
-
const body = buildDashboard(repoRoot, true, review, title);
|
|
105
|
-
const prNum = upsertPr(repoRoot, base, body, title);
|
|
106
|
-
process.stdout.write('\n' + SEP + '✅ PR finished — here is exactly what I did\n' + SEP + '\n' +
|
|
107
|
-
` 1. validated the build gate (authoritative)\n` +
|
|
108
|
-
` 2. force-pushed your work to origin/${base}\n` +
|
|
109
|
-
` 3. ${prNum ? `updated/created PR #${prNum}` : 'created the PR'} titled: "${title}"\n` +
|
|
110
|
-
` You are on ${base} — same name as the remote branch and the PR head.\n\n`);
|
|
111
|
-
}
|
|
112
|
-
if (require.main === module)
|
|
113
|
-
(0, rules_config_1.runMain)(main);
|
|
8
|
+
const pr_gate_app_1 = require("./pr-gate-app");
|
|
9
|
+
// Composition root: build the container and resolve the app so inversify constructs the whole DAG.
|
|
10
|
+
(0, rules_config_1.runMain)(async () => {
|
|
11
|
+
const container = new inversify_1.Container();
|
|
12
|
+
container.bind(rules_config_1.RepoRootFinder).toConstantValue(new rules_config_1.RepoRootFinder());
|
|
13
|
+
await container.load((0, binding_decorators_1.buildProviderModule)());
|
|
14
|
+
await container.get(pr_gate_app_1.PrGateApp).finishUpsertPr();
|
|
15
|
+
});
|
|
114
16
|
//# sourceMappingURL=git-finishUpsertPr.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git-finishUpsertPr.js","sourceRoot":"","sources":["../../../../../../packages/tooling/pr-gate/src/scripts/git-finishUpsertPr.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 {\n loadAndValidate,\n loadReviewJson,\n prDirFor,\n reviewJsonPath,\n ReviewJson,\n writeTemplate,\n runMain,\n} from '@webpieces/rules-config';\nimport { getFeatureName } from './workflow/git-readAiBranchName';\nimport { baseBranchName } from './workflow/branch-naming';\nimport { assertCleanTree, ensurePushed } from './workflow/git-exec';\nimport { runBuildGate, BuildGateOptions } from './workflow/build-affected';\nimport { mergeDirFor, readMergeMarker, findActiveMergeRunDir } from './workflow/merge-state';\nimport { mergeEnd } from './workflow/merge-end';\nimport { MergeContext } from './workflow/merge-start';\nimport {\n computeGateResults,\n countAddedDisables,\n renderDashboard,\n DashboardInput,\n} from '../dashboard/dashboard';\n\n// FINISH of the AI-first PR flow. Runs after the AI has written review.json (see wp-start-upsert-pr).\n// Responsibilities, in order: (1) if a 3-point merge was in progress, validate + commit + FINALIZE the\n// AI's resolution via merge-END (so the PR is posted from the finalized feature branch, not the squash\n// branch); (2) REQUIRE review.json (hard-fail with the schema if absent/invalid); (3) run the\n// authoritative build gate; (4) render the dashboard; (5) create/update the PR via `gh`. This is the\n// ONLY command that posts PRs.\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// The user-facing PR title: the AI-authored review.title, or — if the AI omitted it — a readable\n// fallback derived from the stable feature name (NEVER the internal `Squash merge of <branch>` commit\n// subject, which leaked bookkeeping into the PR title).\nfunction prTitleFrom(review: ReviewJson): string {\n if (review.title !== '') return review.title;\n return getFeatureName().replace(/[-/]+/g, ' ').trim();\n}\n\nfunction buildDashboard(repoRoot: string, buildPassed: boolean, review: ReviewJson, title: string): string {\n const config = loadAndValidate(repoRoot).prGate;\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\n const gateResults = computeGateResults(config.gates, changedFiles);\n const disables = countAddedDisables(patch);\n const input = new DashboardInput(title, gateResults, disables, buildPassed, forkPoint, featureHead, mainHead, review);\n return renderDashboard(input);\n}\n\n// The PR, the remote branch, and the local branch all share the one stable feature name now. Look up /\n// create / merge against `baseBranch` (baseBranchName also tolerates a leftover `…wpN` mid-transition),\n// or a resolve from such a leftover could fail to find its PR and open a duplicate.\nfunction upsertPr(repoRoot: string, baseBranch: string, body: string, title: string): string {\n const prDir = prDirFor(repoRoot, 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 prNumber = spawnSync(\n 'gh', ['pr', 'list', '--head', baseBranch, '--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', baseBranch, '--base', 'main', '--title', title, '--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 // Keep the title in sync with the latest review.title (not just the body).\n spawnSync('gh', ['pr', 'edit', num, '--title', title, '--body-file', bodyFile], { stdio: 'inherit' });\n }\n spawnSync('gh', ['pr', 'merge', baseBranch, '--auto', '--squash'], { stdio: 'inherit' });\n return num;\n}\n\nexport async function main(): Promise<void> {\n const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();\n // Refresh the AI-facing workflow doc so it's present + current for any failure message to cite.\n writeTemplate(repoRoot, 'webpieces.git-workflow.md');\n const home = mergeDirFor(repoRoot, getFeatureName());\n\n // 1. Finish any in-progress conflict resolution: validate + commit + finalize the branch swap.\n // No active run dir (or its marker already validated) => no merge in progress => nothing to do\n // (the common case). The active merge is the `merge-<n>/` run dir holding a marker.\n const activeDir = findActiveMergeRunDir(home);\n const marker = activeDir ? readMergeMarker(activeDir) : null;\n if (activeDir && marker && !marker.validated) {\n await mergeEnd(\n repoRoot, 'wp-finish-upsert-pr', activeDir,\n new MergeContext(marker.currentBranch, marker.squashBranch, marker.backupBranch, marker.prNumber),\n marker.conflictedFiles,\n );\n }\n\n // 2. REQUIRE the AI-authored review.json (throws InformAiError with the schema if missing/invalid).\n const review = loadReviewJson(reviewJsonPath(repoRoot, getFeatureName()));\n\n // 2b. The build gate validates the WORKING TREE but we push HEAD — so they MUST be identical, or a\n // fix edited after the merge commit builds green yet a stale commit gets pushed (CI then fails on\n // the committed tree). Require a clean tree here; the tooling won't commit your work for you.\n assertCleanTree(repoRoot);\n\n // 3. Authoritative build gate, then push, then post.\n runBuildGate(repoRoot, new BuildGateOptions(\n '🛠️ Build gate (authoritative)', 'pnpm wp-finish-upsert-pr', 'Build failed — no PR created/updated.',\n ));\n // After finalize the local branch, the remote branch, and the PR all share the SAME stable name —\n // push and upsert against it. (baseBranchName is a no-op on the already-stable name; it also\n // tolerates a leftover `…wpN` mid-transition.)\n const base = baseBranchName(execSync('git branch --show-current', { encoding: 'utf8' }).trim());\n ensurePushed(base);\n\n process.stdout.write('\\n' + SEP + '📋 Dashboard + PR\\n' + SEP + '\\n');\n const title = prTitleFrom(review);\n const body = buildDashboard(repoRoot, true, review, title);\n const prNum = upsertPr(repoRoot, base, body, title);\n\n process.stdout.write(\n '\\n' + SEP + '✅ PR finished — here is exactly what I did\\n' + SEP + '\\n' +\n ` 1. validated the build gate (authoritative)\\n` +\n ` 2. force-pushed your work to origin/${base}\\n` +\n ` 3. ${prNum ? `updated/created PR #${prNum}` : 'created the PR'} titled: \"${title}\"\\n` +\n ` You are on ${base} — same name as the remote branch and the PR head.\\n\\n`,\n );\n}\n\nif (require.main === module) runMain(main);\n"]}
|
|
1
|
+
{"version":3,"file":"git-finishUpsertPr.js","sourceRoot":"","sources":["../../../../../../packages/tooling/pr-gate/src/scripts/git-finishUpsertPr.ts"],"names":[],"mappings":";;;AACA,4BAA0B;AAC1B,yCAAsC;AACtC,wEAAsE;AACtE,0DAAkE;AAClE,+CAA0C;AAE1C,mGAAmG;AACnG,IAAA,sBAAO,EAAC,KAAK,IAAmB,EAAE;IAC9B,MAAM,SAAS,GAAG,IAAI,qBAAS,EAAE,CAAC;IAClC,SAAS,CAAC,IAAI,CAAC,6BAAc,CAAC,CAAC,eAAe,CAAC,IAAI,6BAAc,EAAE,CAAC,CAAC;IACrE,MAAM,SAAS,CAAC,IAAI,CAAC,IAAA,wCAAmB,GAAE,CAAC,CAAC;IAC5C,MAAM,SAAS,CAAC,GAAG,CAAC,uBAAS,CAAC,CAAC,cAAc,EAAE,CAAC;AACpD,CAAC,CAAC,CAAC","sourcesContent":["#!/usr/bin/env node\nimport 'reflect-metadata';\nimport { Container } from 'inversify';\nimport { buildProviderModule } from '@inversifyjs/binding-decorators';\nimport { runMain, RepoRootFinder } from '@webpieces/rules-config';\nimport { PrGateApp } from './pr-gate-app';\n\n// Composition root: build the container and resolve the app so inversify constructs the whole DAG.\nrunMain(async (): Promise<void> => {\n const container = new Container();\n container.bind(RepoRootFinder).toConstantValue(new RepoRootFinder());\n await container.load(buildProviderModule());\n await container.get(PrGateApp).finishUpsertPr();\n});\n"]}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { AiBranchName } from './workflow/git-readAiBranchName';
|
|
2
|
+
import { ForkPoint } from './workflow/git-findForkPoint';
|
|
3
|
+
import { MergeState } from './workflow/merge-state';
|
|
4
|
+
import { GitExec } from './workflow/git-exec';
|
|
1
5
|
interface HashPoints {
|
|
2
6
|
hashForkPoint: string;
|
|
3
7
|
hashFeatureHead: string;
|
|
@@ -8,5 +12,15 @@ export declare class GatherInfoResult {
|
|
|
8
12
|
hashes: HashPoints;
|
|
9
13
|
constructor(alreadyUpToDate: boolean, hashes: HashPoints);
|
|
10
14
|
}
|
|
11
|
-
|
|
15
|
+
/** Gathers the 3-point merge context (fetch main, find fork point, write hashes) for merge-start. */
|
|
16
|
+
export declare class GatherInfo {
|
|
17
|
+
private readonly aiBranchName;
|
|
18
|
+
private readonly forkPoint;
|
|
19
|
+
private readonly mergeState;
|
|
20
|
+
private readonly gitExec;
|
|
21
|
+
constructor(aiBranchName: AiBranchName, forkPoint: ForkPoint, mergeState: MergeState, gitExec: GitExec);
|
|
22
|
+
gatherInfo(): Promise<GatherInfoResult>;
|
|
23
|
+
private validateCleanTree;
|
|
24
|
+
private printHashPoints;
|
|
25
|
+
}
|
|
12
26
|
export {};
|