@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.
Files changed (70) hide show
  1. package/package.json +7 -2
  2. package/src/dashboard/dashboard.d.ts +12 -3
  3. package/src/dashboard/dashboard.js +136 -129
  4. package/src/dashboard/dashboard.js.map +1 -1
  5. package/src/index.d.ts +2 -1
  6. package/src/index.js +4 -4
  7. package/src/index.js.map +1 -1
  8. package/src/scripts/commands/finish-update-command.d.ts +10 -0
  9. package/src/scripts/commands/finish-update-command.js +51 -0
  10. package/src/scripts/commands/finish-update-command.js.map +1 -0
  11. package/src/scripts/commands/finish-upsert-pr-command.d.ts +22 -0
  12. package/src/scripts/commands/finish-upsert-pr-command.js +131 -0
  13. package/src/scripts/commands/finish-upsert-pr-command.js.map +1 -0
  14. package/src/scripts/commands/start-update-command.d.ts +9 -0
  15. package/src/scripts/commands/start-update-command.js +67 -0
  16. package/src/scripts/commands/start-update-command.js.map +1 -0
  17. package/src/scripts/commands/start-upsert-pr-command.d.ts +15 -0
  18. package/src/scripts/commands/start-upsert-pr-command.js +73 -0
  19. package/src/scripts/commands/start-upsert-pr-command.js.map +1 -0
  20. package/src/scripts/git-finishUpsertPr.d.ts +1 -1
  21. package/src/scripts/git-finishUpsertPr.js +11 -109
  22. package/src/scripts/git-finishUpsertPr.js.map +1 -1
  23. package/src/scripts/git-gatherInfo.d.ts +15 -1
  24. package/src/scripts/git-gatherInfo.js +79 -61
  25. package/src/scripts/git-gatherInfo.js.map +1 -1
  26. package/src/scripts/pr-gate-app.d.ts +25 -0
  27. package/src/scripts/pr-gate-app.js +56 -0
  28. package/src/scripts/pr-gate-app.js.map +1 -0
  29. package/src/scripts/workflow/branch-naming.d.ts +11 -8
  30. package/src/scripts/workflow/branch-naming.js +30 -21
  31. package/src/scripts/workflow/branch-naming.js.map +1 -1
  32. package/src/scripts/workflow/build-affected.d.ts +21 -30
  33. package/src/scripts/workflow/build-affected.js +57 -63
  34. package/src/scripts/workflow/build-affected.js.map +1 -1
  35. package/src/scripts/workflow/cleanTmp.d.ts +6 -1
  36. package/src/scripts/workflow/cleanTmp.js +83 -78
  37. package/src/scripts/workflow/cleanTmp.js.map +1 -1
  38. package/src/scripts/workflow/git-exec.d.ts +32 -28
  39. package/src/scripts/workflow/git-exec.js +92 -85
  40. package/src/scripts/workflow/git-exec.js.map +1 -1
  41. package/src/scripts/workflow/git-findForkPoint.d.ts +12 -3
  42. package/src/scripts/workflow/git-findForkPoint.js +116 -107
  43. package/src/scripts/workflow/git-findForkPoint.js.map +1 -1
  44. package/src/scripts/workflow/git-readAiBranchName.d.ts +7 -2
  45. package/src/scripts/workflow/git-readAiBranchName.js +24 -15
  46. package/src/scripts/workflow/git-readAiBranchName.js.map +1 -1
  47. package/src/scripts/workflow/merge-end.d.ts +21 -6
  48. package/src/scripts/workflow/merge-end.js +147 -133
  49. package/src/scripts/workflow/merge-end.js.map +1 -1
  50. package/src/scripts/workflow/merge-start.d.ts +22 -1
  51. package/src/scripts/workflow/merge-start.js +180 -186
  52. package/src/scripts/workflow/merge-start.js.map +1 -1
  53. package/src/scripts/workflow/merge-state.d.ts +26 -23
  54. package/src/scripts/workflow/merge-state.js +131 -137
  55. package/src/scripts/workflow/merge-state.js.map +1 -1
  56. package/src/scripts/workflow/open-pr-check.d.ts +7 -1
  57. package/src/scripts/workflow/open-pr-check.js +34 -23
  58. package/src/scripts/workflow/open-pr-check.js.map +1 -1
  59. package/src/scripts/workflow/run-update.d.ts +13 -1
  60. package/src/scripts/workflow/run-update.js +59 -28
  61. package/src/scripts/workflow/run-update.js.map +1 -1
  62. package/src/scripts/wp-finish-update.d.ts +1 -1
  63. package/src/scripts/wp-finish-update.js +11 -30
  64. package/src/scripts/wp-finish-update.js.map +1 -1
  65. package/src/scripts/wp-start-update.d.ts +1 -2
  66. package/src/scripts/wp-start-update.js +11 -51
  67. package/src/scripts/wp-start-update.js.map +1 -1
  68. package/src/scripts/wp-start-upsert-pr.d.ts +1 -1
  69. package/src/scripts/wp-start-upsert-pr.js +11 -47
  70. package/src/scripts/wp-start-upsert-pr.js.map +1 -1
@@ -1,55 +1,23 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.BuildGateOptions = exports.DEFAULT_BUILD_COMMAND = void 0;
4
- exports.resolveBuildCommand = resolveBuildCommand;
5
- exports.runBuildAffected = runBuildAffected;
6
- exports.runConfiguredBuildGate = runConfiguredBuildGate;
7
- exports.runBuildGate = runBuildGate;
3
+ exports.BuildAffected = exports.BuildGateOptions = exports.DEFAULT_BUILD_COMMAND = void 0;
4
+ const tslib_1 = require("tslib");
8
5
  const child_process_1 = require("child_process");
9
6
  const rules_config_1 = require("@webpieces/rules-config");
10
- // Single source of truth for the build gate. The PR flow's advisory gate (`wp-start-upsert-pr`)
11
- // and authoritative merge gate (`wp-finish-upsert-pr`) both run THIS, so the two can never drift.
12
- // nx `affected` only rebuilds changed projects, so this stays fast on a large monorepo.
13
- // `--base=$(git merge-base origin/main HEAD)` (the fork point) instead of `--base=origin/main`:
14
- // origin/main rebuilds projects touched by OTHER people's merged PRs (your branch still holds the
15
- // pre-merge versions, so nx sees them as "affected"). The fork point scopes affected to only YOUR
16
- // branch's changes. The `$(...)` resolves because runBuildAffected runs with shell: true.
7
+ const core_context_1 = require("@webpieces/core-context");
8
+ const inversify_1 = require("inversify");
9
+ // Single source of truth for the build gate. The PR flow's advisory gate (`wp-start-upsert-pr`) and
10
+ // authoritative merge gate (`wp-finish-upsert-pr`) both run THIS, so the two can never drift. nx
11
+ // `affected` only rebuilds changed projects. `--base=$(git merge-base origin/main HEAD)` (the fork
12
+ // point) instead of `--base=origin/main`: origin/main rebuilds projects touched by OTHER people's
13
+ // merged PRs. The fork point scopes affected to only YOUR branch's changes. The `$(...)` resolves
14
+ // because runBuildAffected runs with shell: true.
17
15
  exports.DEFAULT_BUILD_COMMAND = 'pnpm nx affected --target=ci --base=$(git merge-base origin/main HEAD)';
18
- /**
19
- * Resolve the exact build command this gate will run for a repo: the project's configured
20
- * PrGateConfig.buildCommand, or the default affected-ci command when none is set. Callers
21
- * print this so the AI knows precisely which command to run locally to get the gate passing.
22
- */
23
- function resolveBuildCommand(repoRoot) {
24
- const configured = (0, rules_config_1.loadAndValidate)(repoRoot).prGate.buildCommand;
25
- return configured !== undefined && configured.trim() !== '' ? configured : exports.DEFAULT_BUILD_COMMAND;
26
- }
27
- /**
28
- * Run the build gate. Returns the process exit code (0 = pass). `buildCommand` overrides
29
- * the default (sourced from PrGateConfig.buildCommand by callers); empty/undefined uses the
30
- * default affected-ci command.
31
- */
32
- function runBuildAffected(repoRoot, buildCommand) {
33
- const cmd = buildCommand !== undefined && buildCommand.trim() !== '' ? buildCommand : exports.DEFAULT_BUILD_COMMAND;
34
- process.stdout.write(`\nโ–ถ Build gate: ${cmd}\n\n`);
35
- const result = (0, child_process_1.spawnSync)(cmd, { stdio: 'inherit', cwd: repoRoot, shell: true });
36
- return result.status ?? 1;
37
- }
38
- /**
39
- * Run the build gate using the project's configured command (PrGateConfig.buildCommand). The
40
- * finish-upsert-pr gate and wp-start-upsert-pr both call THIS so they provably build with the same
41
- * command โ€” the resolution the AI validates is built exactly as the PR command builds it.
42
- * Returns the exit code; callers print their own re-run hint.
43
- */
44
- function runConfiguredBuildGate(repoRoot) {
45
- return runBuildAffected(repoRoot, (0, rules_config_1.loadAndValidate)(repoRoot).prGate.buildCommand);
46
- }
47
16
  const SEP = 'โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n';
48
17
  /**
49
- * The two facts that differ between the wp-start (advisory) and wp-finish (authoritative) build
50
- * gates. Everything else โ€” resolve command, run it, print the re-run hint, exit non-zero on failure
51
- * โ€” is identical, so it lives once in runBuildGate and the difference is passed in here. A class (not
52
- * an object literal) per the codebase's data-structure convention.
18
+ * The two facts that differ between the wp-start (advisory) and wp-finish (authoritative) build gates.
19
+ * Everything else is identical, so it lives once in runBuildGate and the difference is passed in here.
20
+ * A class (not an object literal) per the codebase's data-structure convention.
53
21
  */
54
22
  class BuildGateOptions {
55
23
  label; // section header shown above the gate
@@ -62,23 +30,49 @@ class BuildGateOptions {
62
30
  }
63
31
  }
64
32
  exports.BuildGateOptions = BuildGateOptions;
65
- /**
66
- * Run the configured build gate with consistent framing, throwing CliExitError(buildCode) on failure
67
- * so the bin's main()/runMain owns the exit. Single source of truth: wp-start-upsert-pr and
68
- * wp-finish-upsert-pr both call THIS (only the BuildGateOptions differ) so a fix to the gate flow is
69
- * made once, not in two near-identical copies.
70
- */
71
- function runBuildGate(repoRoot, opts) {
72
- const buildCommand = resolveBuildCommand(repoRoot);
73
- process.stdout.write('\n' + SEP + opts.label + '\n' + SEP + '\n');
74
- process.stdout.write(`Running the build gate. To get it passing, run the SAME command yourself and fix everything it reports:\n\n` +
75
- ` ${buildCommand}\n\n`);
76
- const buildCode = runConfiguredBuildGate(repoRoot);
77
- if (buildCode !== 0) {
78
- throw new rules_config_1.CliExitError(buildCode, `\nโŒ ${opts.failureHeadline}\n\n` +
79
- `Run THIS exact command to reproduce and fix all errors, then re-run ${opts.rerunCommand}:\n\n` +
80
- ` ${buildCommand}\n`);
33
+ /** Runs the nx-affected build gate the same way for the advisory and authoritative PR gates. */
34
+ let BuildAffected = class BuildAffected {
35
+ /**
36
+ * Resolve the exact build command this gate will run: the project's configured
37
+ * PrGateConfig.buildCommand, or the default affected-ci command when none is set.
38
+ */
39
+ resolveBuildCommand(repoRoot) {
40
+ const configured = (0, rules_config_1.loadAndValidate)(repoRoot).prGate.buildCommand;
41
+ return configured !== undefined && configured.trim() !== '' ? configured : exports.DEFAULT_BUILD_COMMAND;
81
42
  }
82
- process.stdout.write('\nโœ… Build passed.\n');
83
- }
43
+ /** Run the build gate. Returns the process exit code (0 = pass). */
44
+ runBuildAffected(repoRoot, buildCommand) {
45
+ const cmd = buildCommand !== undefined && buildCommand.trim() !== '' ? buildCommand : exports.DEFAULT_BUILD_COMMAND;
46
+ process.stdout.write(`\nโ–ถ Build gate: ${cmd}\n\n`);
47
+ const result = (0, child_process_1.spawnSync)(cmd, { stdio: 'inherit', cwd: repoRoot, shell: true });
48
+ return result.status ?? 1;
49
+ }
50
+ /** Run the build gate using the project's configured command (PrGateConfig.buildCommand). */
51
+ runConfiguredBuildGate(repoRoot) {
52
+ return this.runBuildAffected(repoRoot, (0, rules_config_1.loadAndValidate)(repoRoot).prGate.buildCommand);
53
+ }
54
+ /**
55
+ * Run the configured build gate with consistent framing, throwing CliExitError(buildCode) on
56
+ * failure so the bin's main()/runMain owns the exit. Single source of truth: wp-start-upsert-pr and
57
+ * wp-finish-upsert-pr both call THIS (only the BuildGateOptions differ).
58
+ */
59
+ runBuildGate(repoRoot, opts) {
60
+ const buildCommand = this.resolveBuildCommand(repoRoot);
61
+ process.stdout.write('\n' + SEP + opts.label + '\n' + SEP + '\n');
62
+ process.stdout.write(`Running the build gate. To get it passing, run the SAME command yourself and fix everything it reports:\n\n` +
63
+ ` ${buildCommand}\n\n`);
64
+ const buildCode = this.runConfiguredBuildGate(repoRoot);
65
+ if (buildCode !== 0) {
66
+ throw new rules_config_1.CliExitError(buildCode, `\nโŒ ${opts.failureHeadline}\n\n` +
67
+ `Run THIS exact command to reproduce and fix all errors, then re-run ${opts.rerunCommand}:\n\n` +
68
+ ` ${buildCommand}\n`);
69
+ }
70
+ process.stdout.write('\nโœ… Build passed.\n');
71
+ }
72
+ };
73
+ exports.BuildAffected = BuildAffected;
74
+ exports.BuildAffected = BuildAffected = tslib_1.__decorate([
75
+ (0, core_context_1.provideSingleton)(),
76
+ (0, inversify_1.injectable)()
77
+ ], BuildAffected);
84
78
  //# sourceMappingURL=build-affected.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"build-affected.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/workflow/build-affected.ts"],"names":[],"mappings":";;;AAiBA,kDAGC;AAOD,4CAKC;AAQD,wDAEC;AA4BD,oCAgBC;AAtFD,iDAA0C;AAC1C,0DAAwE;AAExE,gGAAgG;AAChG,kGAAkG;AAClG,wFAAwF;AACxF,gGAAgG;AAChG,kGAAkG;AAClG,kGAAkG;AAClG,0FAA0F;AAC7E,QAAA,qBAAqB,GAAG,wEAAwE,CAAC;AAE9G;;;;GAIG;AACH,SAAgB,mBAAmB,CAAC,QAAgB;IAChD,MAAM,UAAU,GAAG,IAAA,8BAAe,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;IACjE,OAAO,UAAU,KAAK,SAAS,IAAI,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,6BAAqB,CAAC;AACrG,CAAC;AAED;;;;GAIG;AACH,SAAgB,gBAAgB,CAAC,QAAgB,EAAE,YAAqB;IACpE,MAAM,GAAG,GAAG,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,6BAAqB,CAAC;IAC5G,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,GAAG,MAAM,CAAC,CAAC;IACnD,MAAM,MAAM,GAAG,IAAA,yBAAS,EAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAChF,OAAO,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED;;;;;GAKG;AACH,SAAgB,sBAAsB,CAAC,QAAgB;IACnD,OAAO,gBAAgB,CAAC,QAAQ,EAAE,IAAA,8BAAe,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AACrF,CAAC;AAED,MAAM,GAAG,GAAG,0DAA0D,CAAC;AAEvE;;;;;GAKG;AACH,MAAa,gBAAgB;IACzB,KAAK,CAAS,CAAY,sCAAsC;IAChE,YAAY,CAAS,CAAK,gDAAgD;IAC1E,eAAe,CAAS,CAAE,gCAAgC;IAE1D,YAAY,KAAa,EAAE,YAAoB,EAAE,eAAuB;QACpE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;IAC3C,CAAC;CACJ;AAVD,4CAUC;AAED;;;;;GAKG;AACH,SAAgB,YAAY,CAAC,QAAgB,EAAE,IAAsB;IACjE,MAAM,YAAY,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IACnD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;IAClE,OAAO,CAAC,MAAM,CAAC,KAAK,CAChB,6GAA6G;QAC7G,OAAO,YAAY,MAAM,CAC5B,CAAC;IACF,MAAM,SAAS,GAAG,sBAAsB,CAAC,QAAQ,CAAC,CAAC;IACnD,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;QAClB,MAAM,IAAI,2BAAY,CAAC,SAAS,EAC5B,OAAO,IAAI,CAAC,eAAe,MAAM;YACjC,uEAAuE,IAAI,CAAC,YAAY,OAAO;YAC/F,OAAO,YAAY,IAAI,CAC1B,CAAC;IACN,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;AAChD,CAAC","sourcesContent":["import { spawnSync } from 'child_process';\nimport { loadAndValidate, CliExitError } from '@webpieces/rules-config';\n\n// Single source of truth for the build gate. The PR flow's advisory gate (`wp-start-upsert-pr`)\n// and authoritative merge gate (`wp-finish-upsert-pr`) both run THIS, so the two can never drift.\n// nx `affected` only rebuilds changed projects, so this stays fast on a large monorepo.\n// `--base=$(git merge-base origin/main HEAD)` (the fork point) instead of `--base=origin/main`:\n// origin/main rebuilds projects touched by OTHER people's merged PRs (your branch still holds the\n// pre-merge versions, so nx sees them as \"affected\"). The fork point scopes affected to only YOUR\n// branch's changes. The `$(...)` resolves because runBuildAffected runs with shell: true.\nexport const DEFAULT_BUILD_COMMAND = 'pnpm nx affected --target=ci --base=$(git merge-base origin/main HEAD)';\n\n/**\n * Resolve the exact build command this gate will run for a repo: the project's configured\n * PrGateConfig.buildCommand, or the default affected-ci command when none is set. Callers\n * print this so the AI knows precisely which command to run locally to get the gate passing.\n */\nexport function resolveBuildCommand(repoRoot: string): string {\n const configured = loadAndValidate(repoRoot).prGate.buildCommand;\n return configured !== undefined && configured.trim() !== '' ? configured : DEFAULT_BUILD_COMMAND;\n}\n\n/**\n * Run the build gate. Returns the process exit code (0 = pass). `buildCommand` overrides\n * the default (sourced from PrGateConfig.buildCommand by callers); empty/undefined uses the\n * default affected-ci command.\n */\nexport function runBuildAffected(repoRoot: string, buildCommand?: string): number {\n const cmd = buildCommand !== undefined && buildCommand.trim() !== '' ? buildCommand : DEFAULT_BUILD_COMMAND;\n process.stdout.write(`\\nโ–ถ Build gate: ${cmd}\\n\\n`);\n const result = spawnSync(cmd, { stdio: 'inherit', cwd: repoRoot, shell: true });\n return result.status ?? 1;\n}\n\n/**\n * Run the build gate using the project's configured command (PrGateConfig.buildCommand). The\n * finish-upsert-pr gate and wp-start-upsert-pr both call THIS so they provably build with the same\n * command โ€” the resolution the AI validates is built exactly as the PR command builds it.\n * Returns the exit code; callers print their own re-run hint.\n */\nexport function runConfiguredBuildGate(repoRoot: string): number {\n return runBuildAffected(repoRoot, loadAndValidate(repoRoot).prGate.buildCommand);\n}\n\nconst SEP = 'โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\\n';\n\n/**\n * The two facts that differ between the wp-start (advisory) and wp-finish (authoritative) build\n * gates. Everything else โ€” resolve command, run it, print the re-run hint, exit non-zero on failure\n * โ€” is identical, so it lives once in runBuildGate and the difference is passed in here. A class (not\n * an object literal) per the codebase's data-structure convention.\n */\nexport class BuildGateOptions {\n label: string; // section header shown above the gate\n rerunCommand: string; // command the AI re-runs after fixing the build\n failureHeadline: string; // first line printed on failure\n\n constructor(label: string, rerunCommand: string, failureHeadline: string) {\n this.label = label;\n this.rerunCommand = rerunCommand;\n this.failureHeadline = failureHeadline;\n }\n}\n\n/**\n * Run the configured build gate with consistent framing, throwing CliExitError(buildCode) on failure\n * so the bin's main()/runMain owns the exit. Single source of truth: wp-start-upsert-pr and\n * wp-finish-upsert-pr both call THIS (only the BuildGateOptions differ) so a fix to the gate flow is\n * made once, not in two near-identical copies.\n */\nexport function runBuildGate(repoRoot: string, opts: BuildGateOptions): void {\n const buildCommand = resolveBuildCommand(repoRoot);\n process.stdout.write('\\n' + SEP + opts.label + '\\n' + SEP + '\\n');\n process.stdout.write(\n `Running the build gate. To get it passing, run the SAME command yourself and fix everything it reports:\\n\\n` +\n ` ${buildCommand}\\n\\n`,\n );\n const buildCode = runConfiguredBuildGate(repoRoot);\n if (buildCode !== 0) {\n throw new CliExitError(buildCode,\n `\\nโŒ ${opts.failureHeadline}\\n\\n` +\n `Run THIS exact command to reproduce and fix all errors, then re-run ${opts.rerunCommand}:\\n\\n` +\n ` ${buildCommand}\\n`,\n );\n }\n process.stdout.write('\\nโœ… Build passed.\\n');\n}\n"]}
1
+ {"version":3,"file":"build-affected.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/workflow/build-affected.ts"],"names":[],"mappings":";;;;AAAA,iDAA0C;AAC1C,0DAAwE;AACxE,0DAA2D;AAC3D,yCAAuC;AAEvC,oGAAoG;AACpG,iGAAiG;AACjG,mGAAmG;AACnG,kGAAkG;AAClG,kGAAkG;AAClG,kDAAkD;AACrC,QAAA,qBAAqB,GAAG,wEAAwE,CAAC;AAE9G,MAAM,GAAG,GAAG,0DAA0D,CAAC;AAEvE;;;;GAIG;AACH,MAAa,gBAAgB;IACzB,KAAK,CAAS,CAAY,sCAAsC;IAChE,YAAY,CAAS,CAAK,gDAAgD;IAC1E,eAAe,CAAS,CAAE,gCAAgC;IAE1D,YAAY,KAAa,EAAE,YAAoB,EAAE,eAAuB;QACpE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;IAC3C,CAAC;CACJ;AAVD,4CAUC;AAED,gGAAgG;AAGzF,IAAM,aAAa,GAAnB,MAAM,aAAa;IACtB;;;OAGG;IACH,mBAAmB,CAAC,QAAgB;QAChC,MAAM,UAAU,GAAG,IAAA,8BAAe,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;QACjE,OAAO,UAAU,KAAK,SAAS,IAAI,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,6BAAqB,CAAC;IACrG,CAAC;IAED,oEAAoE;IACpE,gBAAgB,CAAC,QAAgB,EAAE,YAAqB;QACpD,MAAM,GAAG,GAAG,YAAY,KAAK,SAAS,IAAI,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,6BAAqB,CAAC;QAC5G,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,GAAG,MAAM,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,IAAA,yBAAS,EAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAChF,OAAO,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,6FAA6F;IAC7F,sBAAsB,CAAC,QAAgB;QACnC,OAAO,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAA,8BAAe,EAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;IAC1F,CAAC;IAED;;;;OAIG;IACH,YAAY,CAAC,QAAgB,EAAE,IAAsB;QACjD,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QACxD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;QAClE,OAAO,CAAC,MAAM,CAAC,KAAK,CAChB,6GAA6G;YAC7G,OAAO,YAAY,MAAM,CAC5B,CAAC;QACF,MAAM,SAAS,GAAG,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QACxD,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;YAClB,MAAM,IAAI,2BAAY,CAAC,SAAS,EAC5B,OAAO,IAAI,CAAC,eAAe,MAAM;gBACjC,uEAAuE,IAAI,CAAC,YAAY,OAAO;gBAC/F,OAAO,YAAY,IAAI,CAC1B,CAAC;QACN,CAAC;QACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IAChD,CAAC;CACJ,CAAA;AA7CY,sCAAa;wBAAb,aAAa;IAFzB,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;GACA,aAAa,CA6CzB","sourcesContent":["import { spawnSync } from 'child_process';\nimport { loadAndValidate, CliExitError } from '@webpieces/rules-config';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { injectable } from 'inversify';\n\n// Single source of truth for the build gate. The PR flow's advisory gate (`wp-start-upsert-pr`) and\n// authoritative merge gate (`wp-finish-upsert-pr`) both run THIS, so the two can never drift. nx\n// `affected` only rebuilds changed projects. `--base=$(git merge-base origin/main HEAD)` (the fork\n// point) instead of `--base=origin/main`: origin/main rebuilds projects touched by OTHER people's\n// merged PRs. The fork point scopes affected to only YOUR branch's changes. The `$(...)` resolves\n// because runBuildAffected runs with shell: true.\nexport const DEFAULT_BUILD_COMMAND = 'pnpm nx affected --target=ci --base=$(git merge-base origin/main HEAD)';\n\nconst SEP = 'โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\\n';\n\n/**\n * The two facts that differ between the wp-start (advisory) and wp-finish (authoritative) build gates.\n * Everything else is identical, so it lives once in runBuildGate and the difference is passed in here.\n * A class (not an object literal) per the codebase's data-structure convention.\n */\nexport class BuildGateOptions {\n label: string; // section header shown above the gate\n rerunCommand: string; // command the AI re-runs after fixing the build\n failureHeadline: string; // first line printed on failure\n\n constructor(label: string, rerunCommand: string, failureHeadline: string) {\n this.label = label;\n this.rerunCommand = rerunCommand;\n this.failureHeadline = failureHeadline;\n }\n}\n\n/** Runs the nx-affected build gate the same way for the advisory and authoritative PR gates. */\n@provideSingleton()\n@injectable()\nexport class BuildAffected {\n /**\n * Resolve the exact build command this gate will run: the project's configured\n * PrGateConfig.buildCommand, or the default affected-ci command when none is set.\n */\n resolveBuildCommand(repoRoot: string): string {\n const configured = loadAndValidate(repoRoot).prGate.buildCommand;\n return configured !== undefined && configured.trim() !== '' ? configured : DEFAULT_BUILD_COMMAND;\n }\n\n /** Run the build gate. Returns the process exit code (0 = pass). */\n runBuildAffected(repoRoot: string, buildCommand?: string): number {\n const cmd = buildCommand !== undefined && buildCommand.trim() !== '' ? buildCommand : DEFAULT_BUILD_COMMAND;\n process.stdout.write(`\\nโ–ถ Build gate: ${cmd}\\n\\n`);\n const result = spawnSync(cmd, { stdio: 'inherit', cwd: repoRoot, shell: true });\n return result.status ?? 1;\n }\n\n /** Run the build gate using the project's configured command (PrGateConfig.buildCommand). */\n runConfiguredBuildGate(repoRoot: string): number {\n return this.runBuildAffected(repoRoot, loadAndValidate(repoRoot).prGate.buildCommand);\n }\n\n /**\n * Run the configured build gate with consistent framing, throwing CliExitError(buildCode) on\n * failure so the bin's main()/runMain owns the exit. Single source of truth: wp-start-upsert-pr and\n * wp-finish-upsert-pr both call THIS (only the BuildGateOptions differ).\n */\n runBuildGate(repoRoot: string, opts: BuildGateOptions): void {\n const buildCommand = this.resolveBuildCommand(repoRoot);\n process.stdout.write('\\n' + SEP + opts.label + '\\n' + SEP + '\\n');\n process.stdout.write(\n `Running the build gate. To get it passing, run the SAME command yourself and fix everything it reports:\\n\\n` +\n ` ${buildCommand}\\n\\n`,\n );\n const buildCode = this.runConfiguredBuildGate(repoRoot);\n if (buildCode !== 0) {\n throw new CliExitError(buildCode,\n `\\nโŒ ${opts.failureHeadline}\\n\\n` +\n `Run THIS exact command to reproduce and fix all errors, then re-run ${opts.rerunCommand}:\\n\\n` +\n ` ${buildCommand}\\n`,\n );\n }\n process.stdout.write('\\nโœ… Build passed.\\n');\n }\n}\n"]}
@@ -1 +1,6 @@
1
- export declare function cleanTmp(): Promise<void>;
1
+ /** 30-day cleanup of stale per-feature merge/pr-review dirs (and the legacy flat layout). */
2
+ export declare class CleanTmp {
3
+ cleanTmp(): Promise<void>;
4
+ private cleanStaleSubdirs;
5
+ private cleanLegacyTopLevel;
6
+ }
@@ -1,93 +1,98 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.cleanTmp = cleanTmp;
3
+ exports.CleanTmp = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const child_process_1 = require("child_process");
6
6
  const fs = tslib_1.__importStar(require("fs"));
7
7
  const path = tslib_1.__importStar(require("path"));
8
8
  const rules_config_1 = require("@webpieces/rules-config");
9
+ const core_context_1 = require("@webpieces/core-context");
10
+ const inversify_1 = require("inversify");
9
11
  const CUTOFF_DAYS = 30;
10
12
  const SEP = 'โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\n';
11
- // Per-feature workflow dirs now live under `.webpieces/merge-info/<feature>` and
12
- // `.webpieces/pr-review/<feature>`; those two homes are permanent (like hooks/ and instruct-ai/) and
13
- // only their stale subdirs are cleaned. `LEGACY_PREFIXES` sweeps the old flat top-level layout
14
- // (`merge-<feature>`/`review-<feature>`/`pr-<feature>`) so it self-clears after the move โ€” which also
15
- // reaps the retired `pr-info/` home (it matches the `pr-` prefix and is no longer the active PR home).
13
+ // Per-feature workflow dirs live under `.webpieces/merge-info/<feature>` and `.webpieces/pr-review/
14
+ // <feature>`; those two homes are permanent (like hooks/ and instruct-ai/) and only their stale
15
+ // subdirs are cleaned. `LEGACY_PREFIXES` sweeps the old flat top-level layout so it self-clears โ€” which
16
+ // also reaps the retired `pr-info/` home (it matches `pr-` and is no longer the active PR home).
16
17
  const LEGACY_PREFIXES = ['merge-', 'review-', 'pr-'];
17
- async function cleanTmp() {
18
- const repoRoot = (0, child_process_1.execSync)('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
19
- const tmpBase = path.join(repoRoot, rules_config_1.WEBPIECES_TMP_DIR);
20
- if (!fs.existsSync(tmpBase)) {
21
- return;
22
- }
23
- process.stdout.write('\n');
24
- process.stdout.write(SEP);
25
- process.stdout.write('๐Ÿงน Cleaning Old Temporary Directories\n');
26
- process.stdout.write(SEP);
27
- process.stdout.write('\n');
28
- process.stdout.write(`Location: ${tmpBase}\n`);
29
- process.stdout.write(`Retention: ${CUTOFF_DAYS} days\n`);
30
- process.stdout.write('\n');
31
- const cutoffMs = CUTOFF_DAYS * 24 * 60 * 60 * 1000;
32
- const now = Date.now();
33
- let deletedCount = 0;
34
- // Stale per-feature subdirs under each permanent home.
35
- deletedCount += cleanStaleSubdirs(path.join(tmpBase, rules_config_1.MERGE_INFO_DIR), rules_config_1.MERGE_INFO_DIR, now, cutoffMs);
36
- deletedCount += cleanStaleSubdirs(path.join(tmpBase, rules_config_1.PR_REVIEW_DIR), rules_config_1.PR_REVIEW_DIR, now, cutoffMs);
37
- // Legacy flat top-level dirs from before the merge-info/pr-review nesting (also reaps old pr-info/).
38
- deletedCount += cleanLegacyTopLevel(tmpBase, now, cutoffMs);
39
- if (deletedCount === 0) {
40
- process.stdout.write(` โœ… No directories older than ${CUTOFF_DAYS} days found\n`);
41
- }
42
- else {
18
+ /** 30-day cleanup of stale per-feature merge/pr-review dirs (and the legacy flat layout). */
19
+ let CleanTmp = class CleanTmp {
20
+ async cleanTmp() {
21
+ const repoRoot = (0, child_process_1.execSync)('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();
22
+ const tmpBase = path.join(repoRoot, rules_config_1.WEBPIECES_TMP_DIR);
23
+ if (!fs.existsSync(tmpBase)) {
24
+ return;
25
+ }
26
+ process.stdout.write('\n');
27
+ process.stdout.write(SEP);
28
+ process.stdout.write('๐Ÿงน Cleaning Old Temporary Directories\n');
29
+ process.stdout.write(SEP);
30
+ process.stdout.write('\n');
31
+ process.stdout.write(`Location: ${tmpBase}\n`);
32
+ process.stdout.write(`Retention: ${CUTOFF_DAYS} days\n`);
33
+ process.stdout.write('\n');
34
+ const cutoffMs = CUTOFF_DAYS * 24 * 60 * 60 * 1000;
35
+ const now = Date.now();
36
+ let deletedCount = 0;
37
+ // Stale per-feature subdirs under each permanent home.
38
+ deletedCount += this.cleanStaleSubdirs(path.join(tmpBase, rules_config_1.MERGE_INFO_DIR), rules_config_1.MERGE_INFO_DIR, now, cutoffMs);
39
+ deletedCount += this.cleanStaleSubdirs(path.join(tmpBase, rules_config_1.PR_REVIEW_DIR), rules_config_1.PR_REVIEW_DIR, now, cutoffMs);
40
+ // Legacy flat top-level dirs from before the merge-info/pr-review nesting (also reaps old pr-info/).
41
+ deletedCount += this.cleanLegacyTopLevel(tmpBase, now, cutoffMs);
42
+ if (deletedCount === 0) {
43
+ process.stdout.write(` โœ… No directories older than ${CUTOFF_DAYS} days found\n`);
44
+ }
45
+ else {
46
+ process.stdout.write('\n');
47
+ process.stdout.write(` โœ… Deleted ${deletedCount} old director${deletedCount === 1 ? 'y' : 'ies'}\n`);
48
+ }
49
+ process.stdout.write('\n');
50
+ process.stdout.write(SEP);
43
51
  process.stdout.write('\n');
44
- process.stdout.write(` โœ… Deleted ${deletedCount} old director${deletedCount === 1 ? 'y' : 'ies'}\n`);
45
52
  }
46
- process.stdout.write('\n');
47
- process.stdout.write(SEP);
48
- process.stdout.write('\n');
49
- }
50
- // Delete immediate subdirs of `parentDir` whose mtime is older than the cutoff. `label` prefixes
51
- // the printed path so output reads e.g. `merge-info/dean-foo`. No-op if the home doesn't exist.
52
- function cleanStaleSubdirs(parentDir, label, now, cutoffMs) {
53
- if (!fs.existsSync(parentDir))
54
- return 0;
55
- let count = 0;
56
- for (const entry of fs.readdirSync(parentDir)) {
57
- const fullPath = path.join(parentDir, entry);
58
- const stat = fs.statSync(fullPath);
59
- if (!stat.isDirectory())
60
- continue;
61
- if (now - stat.mtimeMs < cutoffMs)
62
- continue;
63
- process.stdout.write(` ๐Ÿ—‘๏ธ Deleting: ${label}/${entry}\n`);
64
- fs.rmSync(fullPath, { recursive: true, force: true });
65
- count += 1;
53
+ // Delete immediate subdirs of `parentDir` whose mtime is older than the cutoff. No-op if absent.
54
+ cleanStaleSubdirs(parentDir, label, now, cutoffMs) {
55
+ if (!fs.existsSync(parentDir))
56
+ return 0;
57
+ let count = 0;
58
+ for (const entry of fs.readdirSync(parentDir)) {
59
+ const fullPath = path.join(parentDir, entry);
60
+ const stat = fs.statSync(fullPath);
61
+ if (!stat.isDirectory())
62
+ continue;
63
+ if (now - stat.mtimeMs < cutoffMs)
64
+ continue;
65
+ process.stdout.write(` ๐Ÿ—‘๏ธ Deleting: ${label}/${entry}\n`);
66
+ fs.rmSync(fullPath, { recursive: true, force: true });
67
+ count += 1;
68
+ }
69
+ return count;
66
70
  }
67
- return count;
68
- }
69
- // Sweep the pre-nesting flat layout (`merge-<feature>` etc.), skipping the current homes (whose
70
- // names also start with `merge-`/`pr-`) so this never deletes merge-info/ or pr-review/ themselves.
71
- // The retired `pr-info/` home is deliberately NOT skipped โ€” it matches `pr-` and self-clears here.
72
- function cleanLegacyTopLevel(tmpBase, now, cutoffMs) {
73
- let count = 0;
74
- for (const entry of fs.readdirSync(tmpBase)) {
75
- if (entry === rules_config_1.MERGE_INFO_DIR || entry === rules_config_1.PR_REVIEW_DIR)
76
- continue;
77
- if (!LEGACY_PREFIXES.some((prefix) => entry.startsWith(prefix)))
78
- continue;
79
- const fullPath = path.join(tmpBase, entry);
80
- const stat = fs.statSync(fullPath);
81
- if (!stat.isDirectory())
82
- continue;
83
- if (now - stat.mtimeMs < cutoffMs)
84
- continue;
85
- process.stdout.write(` ๐Ÿ—‘๏ธ Deleting: ${entry}\n`);
86
- fs.rmSync(fullPath, { recursive: true, force: true });
87
- count += 1;
71
+ // Sweep the pre-nesting flat layout (`merge-<feature>` etc.), skipping the current homes so this
72
+ // never deletes merge-info/ or pr-review/ themselves. Retired `pr-info/` IS swept (matches `pr-`).
73
+ cleanLegacyTopLevel(tmpBase, now, cutoffMs) {
74
+ let count = 0;
75
+ for (const entry of fs.readdirSync(tmpBase)) {
76
+ if (entry === rules_config_1.MERGE_INFO_DIR || entry === rules_config_1.PR_REVIEW_DIR)
77
+ continue;
78
+ if (!LEGACY_PREFIXES.some((prefix) => entry.startsWith(prefix)))
79
+ continue;
80
+ const fullPath = path.join(tmpBase, entry);
81
+ const stat = fs.statSync(fullPath);
82
+ if (!stat.isDirectory())
83
+ continue;
84
+ if (now - stat.mtimeMs < cutoffMs)
85
+ continue;
86
+ process.stdout.write(` ๐Ÿ—‘๏ธ Deleting: ${entry}\n`);
87
+ fs.rmSync(fullPath, { recursive: true, force: true });
88
+ count += 1;
89
+ }
90
+ return count;
88
91
  }
89
- return count;
90
- }
91
- if (require.main === module)
92
- (0, rules_config_1.runMain)(cleanTmp);
92
+ };
93
+ exports.CleanTmp = CleanTmp;
94
+ exports.CleanTmp = CleanTmp = tslib_1.__decorate([
95
+ (0, core_context_1.provideSingleton)(),
96
+ (0, inversify_1.injectable)()
97
+ ], CleanTmp);
93
98
  //# sourceMappingURL=cleanTmp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cleanTmp.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/workflow/cleanTmp.ts"],"names":[],"mappings":";;AAeA,4BAqCC;;AApDD,iDAAyC;AACzC,+CAAyB;AACzB,mDAA6B;AAC7B,0DAAoG;AAEpG,MAAM,WAAW,GAAG,EAAE,CAAC;AACvB,MAAM,GAAG,GAAG,0DAA0D,CAAC;AAEvE,iFAAiF;AACjF,qGAAqG;AACrG,+FAA+F;AAC/F,sGAAsG;AACtG,uGAAuG;AACvG,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;AAE9C,KAAK,UAAU,QAAQ;IAC1B,MAAM,QAAQ,GAAG,IAAA,wBAAQ,EAAC,+BAA+B,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACxF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,gCAAiB,CAAC,CAAC;IAEvD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1B,OAAO;IACX,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAChE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,OAAO,IAAI,CAAC,CAAC;IAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,WAAW,SAAS,CAAC,CAAC;IACzD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE3B,MAAM,QAAQ,GAAG,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IACnD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,uDAAuD;IACvD,YAAY,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,6BAAc,CAAC,EAAE,6BAAc,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;IACrG,YAAY,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,4BAAa,CAAC,EAAE,4BAAa,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;IACnG,qGAAqG;IACrG,YAAY,IAAI,mBAAmB,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC;IAE5D,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,WAAW,eAAe,CAAC,CAAC;IACtF,CAAC;SAAM,CAAC;QACJ,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,YAAY,gBAAgB,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IAC1G,CAAC;IAED,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC;AAED,iGAAiG;AACjG,gGAAgG;AAChG,SAAS,iBAAiB,CAAC,SAAiB,EAAE,KAAa,EAAE,GAAW,EAAE,QAAgB;IACtF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,CAAC,CAAC;IACxC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QAC7C,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;YAAE,SAAS;QAClC,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,QAAQ;YAAE,SAAS;QAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,KAAK,IAAI,KAAK,IAAI,CAAC,CAAC;QAC7D,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,KAAK,IAAI,CAAC,CAAC;IACf,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,gGAAgG;AAChG,oGAAoG;AACpG,mGAAmG;AACnG,SAAS,mBAAmB,CAAC,OAAe,EAAE,GAAW,EAAE,QAAgB;IACvE,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;QAC1C,IAAI,KAAK,KAAK,6BAAc,IAAI,KAAK,KAAK,4BAAa;YAAE,SAAS;QAClE,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,MAAc,EAAW,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAAE,SAAS;QAC3F,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;YAAE,SAAS;QAClC,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,QAAQ;YAAE,SAAS;QAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,oBAAoB,KAAK,IAAI,CAAC,CAAC;QACpD,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACtD,KAAK,IAAI,CAAC,CAAC;IACf,CAAC;IACD,OAAO,KAAK,CAAC;AACjB,CAAC;AAED,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM;IAAE,IAAA,sBAAO,EAAC,QAAQ,CAAC,CAAC","sourcesContent":["import { execSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { WEBPIECES_TMP_DIR, MERGE_INFO_DIR, PR_REVIEW_DIR, runMain } from '@webpieces/rules-config';\n\nconst CUTOFF_DAYS = 30;\nconst SEP = 'โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\\n';\n\n// Per-feature workflow dirs now live under `.webpieces/merge-info/<feature>` and\n// `.webpieces/pr-review/<feature>`; those two homes are permanent (like hooks/ and instruct-ai/) and\n// only their stale subdirs are cleaned. `LEGACY_PREFIXES` sweeps the old flat top-level layout\n// (`merge-<feature>`/`review-<feature>`/`pr-<feature>`) so it self-clears after the move โ€” which also\n// reaps the retired `pr-info/` home (it matches the `pr-` prefix and is no longer the active PR home).\nconst LEGACY_PREFIXES = ['merge-', 'review-', 'pr-'];\n\nexport async function cleanTmp(): Promise<void> {\n const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();\n const tmpBase = path.join(repoRoot, WEBPIECES_TMP_DIR);\n\n if (!fs.existsSync(tmpBase)) {\n return;\n }\n\n process.stdout.write('\\n');\n process.stdout.write(SEP);\n process.stdout.write('๐Ÿงน Cleaning Old Temporary Directories\\n');\n process.stdout.write(SEP);\n process.stdout.write('\\n');\n process.stdout.write(`Location: ${tmpBase}\\n`);\n process.stdout.write(`Retention: ${CUTOFF_DAYS} days\\n`);\n process.stdout.write('\\n');\n\n const cutoffMs = CUTOFF_DAYS * 24 * 60 * 60 * 1000;\n const now = Date.now();\n let deletedCount = 0;\n\n // Stale per-feature subdirs under each permanent home.\n deletedCount += cleanStaleSubdirs(path.join(tmpBase, MERGE_INFO_DIR), MERGE_INFO_DIR, now, cutoffMs);\n deletedCount += cleanStaleSubdirs(path.join(tmpBase, PR_REVIEW_DIR), PR_REVIEW_DIR, now, cutoffMs);\n // Legacy flat top-level dirs from before the merge-info/pr-review nesting (also reaps old pr-info/).\n deletedCount += cleanLegacyTopLevel(tmpBase, now, cutoffMs);\n\n if (deletedCount === 0) {\n process.stdout.write(` โœ… No directories older than ${CUTOFF_DAYS} days found\\n`);\n } else {\n process.stdout.write('\\n');\n process.stdout.write(` โœ… Deleted ${deletedCount} old director${deletedCount === 1 ? 'y' : 'ies'}\\n`);\n }\n\n process.stdout.write('\\n');\n process.stdout.write(SEP);\n process.stdout.write('\\n');\n}\n\n// Delete immediate subdirs of `parentDir` whose mtime is older than the cutoff. `label` prefixes\n// the printed path so output reads e.g. `merge-info/dean-foo`. No-op if the home doesn't exist.\nfunction cleanStaleSubdirs(parentDir: string, label: string, now: number, cutoffMs: number): number {\n if (!fs.existsSync(parentDir)) return 0;\n let count = 0;\n for (const entry of fs.readdirSync(parentDir)) {\n const fullPath = path.join(parentDir, entry);\n const stat = fs.statSync(fullPath);\n if (!stat.isDirectory()) continue;\n if (now - stat.mtimeMs < cutoffMs) continue;\n process.stdout.write(` ๐Ÿ—‘๏ธ Deleting: ${label}/${entry}\\n`);\n fs.rmSync(fullPath, { recursive: true, force: true });\n count += 1;\n }\n return count;\n}\n\n// Sweep the pre-nesting flat layout (`merge-<feature>` etc.), skipping the current homes (whose\n// names also start with `merge-`/`pr-`) so this never deletes merge-info/ or pr-review/ themselves.\n// The retired `pr-info/` home is deliberately NOT skipped โ€” it matches `pr-` and self-clears here.\nfunction cleanLegacyTopLevel(tmpBase: string, now: number, cutoffMs: number): number {\n let count = 0;\n for (const entry of fs.readdirSync(tmpBase)) {\n if (entry === MERGE_INFO_DIR || entry === PR_REVIEW_DIR) continue;\n if (!LEGACY_PREFIXES.some((prefix: string): boolean => entry.startsWith(prefix))) continue;\n const fullPath = path.join(tmpBase, entry);\n const stat = fs.statSync(fullPath);\n if (!stat.isDirectory()) continue;\n if (now - stat.mtimeMs < cutoffMs) continue;\n process.stdout.write(` ๐Ÿ—‘๏ธ Deleting: ${entry}\\n`);\n fs.rmSync(fullPath, { recursive: true, force: true });\n count += 1;\n }\n return count;\n}\n\nif (require.main === module) runMain(cleanTmp);\n"]}
1
+ {"version":3,"file":"cleanTmp.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/pr-gate/src/scripts/workflow/cleanTmp.ts"],"names":[],"mappings":"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","sourcesContent":["import { execSync } from 'child_process';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { WEBPIECES_TMP_DIR, MERGE_INFO_DIR, PR_REVIEW_DIR } from '@webpieces/rules-config';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { injectable } from 'inversify';\n\nconst CUTOFF_DAYS = 30;\nconst SEP = 'โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”\\n';\n\n// Per-feature workflow dirs live under `.webpieces/merge-info/<feature>` and `.webpieces/pr-review/\n// <feature>`; those two homes are permanent (like hooks/ and instruct-ai/) and only their stale\n// subdirs are cleaned. `LEGACY_PREFIXES` sweeps the old flat top-level layout so it self-clears โ€” which\n// also reaps the retired `pr-info/` home (it matches `pr-` and is no longer the active PR home).\nconst LEGACY_PREFIXES = ['merge-', 'review-', 'pr-'];\n\n/** 30-day cleanup of stale per-feature merge/pr-review dirs (and the legacy flat layout). */\n@provideSingleton()\n@injectable()\nexport class CleanTmp {\n async cleanTmp(): Promise<void> {\n const repoRoot = execSync('git rev-parse --show-toplevel', { encoding: 'utf8' }).trim();\n const tmpBase = path.join(repoRoot, WEBPIECES_TMP_DIR);\n\n if (!fs.existsSync(tmpBase)) {\n return;\n }\n\n process.stdout.write('\\n');\n process.stdout.write(SEP);\n process.stdout.write('๐Ÿงน Cleaning Old Temporary Directories\\n');\n process.stdout.write(SEP);\n process.stdout.write('\\n');\n process.stdout.write(`Location: ${tmpBase}\\n`);\n process.stdout.write(`Retention: ${CUTOFF_DAYS} days\\n`);\n process.stdout.write('\\n');\n\n const cutoffMs = CUTOFF_DAYS * 24 * 60 * 60 * 1000;\n const now = Date.now();\n let deletedCount = 0;\n\n // Stale per-feature subdirs under each permanent home.\n deletedCount += this.cleanStaleSubdirs(path.join(tmpBase, MERGE_INFO_DIR), MERGE_INFO_DIR, now, cutoffMs);\n deletedCount += this.cleanStaleSubdirs(path.join(tmpBase, PR_REVIEW_DIR), PR_REVIEW_DIR, now, cutoffMs);\n // Legacy flat top-level dirs from before the merge-info/pr-review nesting (also reaps old pr-info/).\n deletedCount += this.cleanLegacyTopLevel(tmpBase, now, cutoffMs);\n\n if (deletedCount === 0) {\n process.stdout.write(` โœ… No directories older than ${CUTOFF_DAYS} days found\\n`);\n } else {\n process.stdout.write('\\n');\n process.stdout.write(` โœ… Deleted ${deletedCount} old director${deletedCount === 1 ? 'y' : 'ies'}\\n`);\n }\n\n process.stdout.write('\\n');\n process.stdout.write(SEP);\n process.stdout.write('\\n');\n }\n\n // Delete immediate subdirs of `parentDir` whose mtime is older than the cutoff. No-op if absent.\n private cleanStaleSubdirs(parentDir: string, label: string, now: number, cutoffMs: number): number {\n if (!fs.existsSync(parentDir)) return 0;\n let count = 0;\n for (const entry of fs.readdirSync(parentDir)) {\n const fullPath = path.join(parentDir, entry);\n const stat = fs.statSync(fullPath);\n if (!stat.isDirectory()) continue;\n if (now - stat.mtimeMs < cutoffMs) continue;\n process.stdout.write(` ๐Ÿ—‘๏ธ Deleting: ${label}/${entry}\\n`);\n fs.rmSync(fullPath, { recursive: true, force: true });\n count += 1;\n }\n return count;\n }\n\n // Sweep the pre-nesting flat layout (`merge-<feature>` etc.), skipping the current homes so this\n // never deletes merge-info/ or pr-review/ themselves. Retired `pr-info/` IS swept (matches `pr-`).\n private cleanLegacyTopLevel(tmpBase: string, now: number, cutoffMs: number): number {\n let count = 0;\n for (const entry of fs.readdirSync(tmpBase)) {\n if (entry === MERGE_INFO_DIR || entry === PR_REVIEW_DIR) continue;\n if (!LEGACY_PREFIXES.some((prefix: string): boolean => entry.startsWith(prefix))) continue;\n const fullPath = path.join(tmpBase, entry);\n const stat = fs.statSync(fullPath);\n if (!stat.isDirectory()) continue;\n if (now - stat.mtimeMs < cutoffMs) continue;\n process.stdout.write(` ๐Ÿ—‘๏ธ Deleting: ${entry}\\n`);\n fs.rmSync(fullPath, { recursive: true, force: true });\n count += 1;\n }\n return count;\n }\n}\n"]}
@@ -1,28 +1,32 @@
1
- export declare function uncommittedFiles(cwd: string): string;
2
- export declare function untrackedFiles(cwd: string): string;
3
- /**
4
- * Precondition for every PR/merge entry point: the working tree must be fully committed. The webpieces
5
- * tooling deliberately does NOT `git add`/`commit` the developer's work for them โ€” a blanket `git add
6
- * -A` once swept a stale untracked directory into a squash commit, and building the working tree while
7
- * pushing HEAD let an uncommitted fix pass the build gate yet push a stale commit. Aborts with
8
- * instructions if anything is uncommitted (tracked or untracked, excluding gitignored).
9
- */
10
- export declare function assertCleanTree(cwd: string): void;
11
- /**
12
- * Narrower guard for the merge-resolve commit point, where tracked resolutions are legitimately in the
13
- * tree but untracked files must NOT be swept into the squash commit (replaces the old blanket `git add
14
- * -A`). Lists any untracked files and aborts so the AI commits or deletes them explicitly.
15
- */
16
- export declare function assertNoUntracked(cwd: string): void;
17
- /**
18
- * Run a git command that is expected to succeed; abort the process with a clear message
19
- * if it fails. Used for fetch/pull/checkout/commit where silently continuing on failure
20
- * would operate on stale or wrong state.
21
- */
22
- export declare function runGitChecked(args: string[], errMsg: string): void;
23
- /**
24
- * Push HEAD to origin/<currentBranch>. Single source of truth shared by wp-start-upsert-pr and
25
- * wp-finish-upsert-pr (they pushed with identical copy-pasted logic). Uses --force-with-lease for an
26
- * existing remote branch (the 3-point squash rewrites history) and -u for a brand-new branch.
27
- */
28
- export declare function ensurePushed(currentBranch: string): void;
1
+ import { RepoRootFinder } from '@webpieces/rules-config';
2
+ /** Shared git precondition checks + push logic for the PR/merge workflow. */
3
+ export declare class GitExec {
4
+ private readonly repoRootFinder;
5
+ constructor(repoRootFinder: RepoRootFinder);
6
+ uncommittedFiles(cwd: string): string;
7
+ untrackedFiles(cwd: string): string;
8
+ /**
9
+ * Precondition for every PR/merge entry point: the working tree must be fully committed. The
10
+ * webpieces tooling deliberately does NOT `git add`/`commit` the developer's work for them. Aborts
11
+ * with instructions if anything is uncommitted (tracked or untracked, excluding gitignored).
12
+ */
13
+ assertCleanTree(cwd: string): void;
14
+ /**
15
+ * Narrower guard for the merge-resolve commit point, where tracked resolutions are legitimately in
16
+ * the tree but untracked files must NOT be swept into the squash commit. Lists any untracked files
17
+ * and aborts so the AI commits or deletes them explicitly.
18
+ */
19
+ assertNoUntracked(cwd: string): void;
20
+ /**
21
+ * Run a git command that is expected to succeed; abort the process with a clear message if it
22
+ * fails. Used for fetch/pull/checkout/commit where silently continuing on failure would operate on
23
+ * stale or wrong state.
24
+ */
25
+ runGitChecked(args: string[], errMsg: string): void;
26
+ /**
27
+ * Push HEAD to origin/<currentBranch>. Uses --force-with-lease for an existing remote branch (the
28
+ * 3-point squash rewrites history) and -u for a brand-new branch.
29
+ */
30
+ ensurePushed(currentBranch: string): void;
31
+ private gitQuery;
32
+ }