@joshuafolkken/kit 1.1094.0 → 1.1128.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/workflow-commands/SKILL.md +1 -1
- package/.claude/skills/workflow-commands/background-commands.md +36 -85
- package/.claude/skills/workflow-commands/backlogrun-progress.md +29 -32
- package/.claude/skills/workflow-commands/backlogrun-steps.md +2 -2
- package/.claude/skills/workflow-commands/fullrun.md +5 -4
- package/.claude/skills/workflow-commands/halfrun.md +5 -4
- package/.claude/skills/workflow-commands/latest-gate.md +7 -15
- package/.claude/skills/workflow-commands/pre-gate-cut.md +4 -8
- package/.claude/skills/workflow-commands/split-assessment.md +4 -18
- package/.github/actions/setup-node/action.yml +33 -0
- package/.github/actions/setup-pnpm/action.yml +4 -4
- package/.github/workflows/auto-tag.yml +2 -3
- package/.github/workflows/ci.yml +7 -8
- package/.github/workflows/dependabot-auto-merge.yml +1 -0
- package/.github/workflows/pr-classification.yml +1 -3
- package/.github/workflows/production.yml +1 -0
- package/.github/workflows/publish.yml +10 -9
- package/.github/workflows/sonar-qube.yml +17 -13
- package/.pnpmfile.mjs +29 -0
- package/AGENTS.md +4 -11
- package/CLAUDE.md +24 -17
- package/GEMINI.md +4 -13
- package/README.md +8 -3
- package/SECURITY.md +1 -0
- package/cspell/index.yaml +4 -0
- package/dist/CLAUDE.basic.md +6 -6
- package/dist/CLAUDE.md +24 -17
- package/dist/CLAUDE.static.md +6 -6
- package/dist/config-merge/index.js +33 -9
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-NKOG3XAV.js → chunk-4JZDP5X5.js} +2 -2
- package/dist/hooks/{chunk-3C4YCCEF.js → chunk-5SD2YM7Z.js} +4 -4
- package/dist/hooks/{chunk-OIZUHPJI.js → chunk-77J7IEQM.js} +1 -1
- package/dist/hooks/{chunk-KHWHKJOM.js → chunk-7HVB7SZG.js} +3 -3
- package/dist/hooks/{chunk-UD24EAIL.js → chunk-AIOIOMPX.js} +1875 -104
- package/dist/hooks/{chunk-M2XDCUKD.js → chunk-M7QKEKWO.js} +88 -1783
- package/dist/hooks/{chunk-E54KGFEQ.js → chunk-MKVGBQPA.js} +1 -1
- package/dist/hooks/{chunk-7ZPFAVR7.js → chunk-NXYMNPUQ.js} +3 -3
- package/dist/hooks/{chunk-O4LL4HTI.js → chunk-QVLT52OV.js} +2 -2
- package/dist/hooks/{chunk-IL27YTPH.js → chunk-XYUIQOW3.js} +2 -2
- package/dist/hooks/codex-hook-adapter.js +12 -47
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +2 -2
- package/dist/hooks/inputs.json +180 -179
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +9 -9
- package/dist/hooks/stop-guard.js +17 -12
- package/dist/josh.js +79 -30
- package/dist/version/index.js +36 -20
- package/eslint/rules/unicorn.js +3 -2
- package/package.json +18 -2
- package/pnpm-workspace.yaml +5 -7
- package/prompts/collaboration-workflow/glossary.md +17 -0
- package/prompts/collaboration-workflow/issue-template.md +1 -1
- package/prompts/collaboration-workflow/operating-rules.md +1 -1
- package/prompts/collaboration-workflow/principles.md +9 -0
- package/prompts/collaboration-workflow.md +1 -0
- package/scripts/backlog/backlog-arrival.ts +30 -10
- package/scripts/backlog/backlog-budget-cli.ts +15 -16
- package/scripts/backlog/backlog-offer-cli.ts +6 -14
- package/scripts/backlog/backlog-plan.ts +29 -18
- package/scripts/backlog/backlog-ready.ts +20 -7
- package/scripts/config-merge/parse-jsonc.ts +33 -3
- package/scripts/config-merge/patch-json-key.ts +13 -6
- package/scripts/cost-runtime/cost-cli.ts +3 -7
- package/scripts/doctor/doctor-consumer.ts +3 -5
- package/scripts/doctor/doctor-io.ts +9 -13
- package/scripts/document/backlogrun-parent-read-set.ts +12 -1
- package/scripts/document/document-byte-budget.ts +1 -0
- package/scripts/document/entry-read-budget.ts +13 -7
- package/scripts/document/entry-read-set.ts +32 -8
- package/scripts/document/lane-child-read-set.ts +7 -0
- package/scripts/document/read-set-point-of-use.ts +8 -3
- package/scripts/document/read-set-trim.ts +3 -1
- package/scripts/epic/epic-audit.ts +3 -18
- package/scripts/gh/git-gh-issue-list.ts +12 -11
- package/scripts/gh/git-gh-issue-write.ts +4 -1
- package/scripts/gh/git-gh-pr-auto-merge.ts +4 -1
- package/scripts/git/git-command.ts +6 -1
- package/scripts/git/git-spawn-sync.ts +65 -0
- package/scripts/git/git-spawn.ts +5 -4
- package/scripts/git/stash/stash-pop-args.ts +1 -6
- package/scripts/init/init-file-action.ts +54 -0
- package/scripts/init/init-logic-migrate.ts +35 -17
- package/scripts/init/init-logic-secretlint.ts +1 -1
- package/scripts/init/init-logic.ts +6 -22
- package/scripts/init/init.ts +11 -68
- package/scripts/init/kit-written-paths.ts +2 -0
- package/scripts/init/project-profile.ts +3 -6
- package/scripts/init/start-steps.ts +2 -1
- package/scripts/issue/defect-rate-cli.ts +61 -20
- package/scripts/issue/issue-backlinks.ts +7 -14
- package/scripts/issue/issue-cite.ts +12 -6
- package/scripts/issue/issue-file.ts +5 -12
- package/scripts/issue/markdown-section.ts +21 -6
- package/scripts/issue/measure-rerun-cli.ts +73 -14
- package/scripts/josh/josh-commands-project.ts +1 -1
- package/scripts/josh/josh-commands-workflow.ts +1 -1
- package/scripts/josh/run-github-prerequisite.ts +3 -6
- package/scripts/lane/lane-await.ts +43 -13
- package/scripts/lane/lane-close.ts +4 -1
- package/scripts/lane/lane-launch-cli.ts +10 -16
- package/scripts/lane/openai-review-broker.ts +4 -1
- package/scripts/lib/cli-flags.ts +31 -2
- package/scripts/lib/error-message.ts +12 -1
- package/scripts/lines/line-targets.ts +0 -11
- package/scripts/lines/lines-command.ts +5 -3
- package/scripts/propagate/propagate-git.ts +3 -8
- package/scripts/refactor/refactor-scan.ts +2 -1
- package/scripts/registry-migration/migrate-logic.ts +28 -19
- package/scripts/registry-migration/migrate.ts +6 -5
- package/scripts/release/github-release-cli.ts +14 -3
- package/scripts/release/release-publish.ts +36 -2
- package/scripts/release/release-worktree.ts +97 -2
- package/scripts/review/review-checkout.ts +3 -2
- package/scripts/review/review-record-cli.ts +9 -16
- package/scripts/rules/early-heartbeat.ts +4 -3
- package/scripts/rules/lane-park.ts +9 -0
- package/scripts/rules/stop-rules.ts +7 -4
- package/scripts/run/run-carry-args.ts +8 -12
- package/scripts/run/run-cut-args.ts +1 -6
- package/scripts/run/run-ending-cli.ts +1 -5
- package/scripts/run/run-entry-cli.ts +40 -9
- package/scripts/run/run-entry-stop.ts +104 -0
- package/scripts/run/run-event-stream-emit.ts +7 -2
- package/scripts/run/run-hold.ts +4 -1
- package/scripts/run/run-liveness-cli.ts +1 -5
- package/scripts/run/run-merge-cli.ts +2 -10
- package/scripts/run/run-parent-cut-hook.ts +4 -1
- package/scripts/run/run-prep-cli.ts +4 -1
- package/scripts/run/run-progress-args.ts +20 -4
- package/scripts/run/run-progress-cli.ts +31 -29
- package/scripts/run/run-progress-clock.ts +4 -1
- package/scripts/run/run-ship-cli.ts +8 -16
- package/scripts/run/run-ship-probe.ts +4 -1
- package/scripts/run/run-status-cli.ts +2 -15
- package/scripts/run/run-tidy-lanes.ts +4 -1
- package/scripts/run/run-wake-cli.ts +2 -10
- package/scripts/run/run-watcher-guard.ts +9 -5
- package/scripts/safe-chain/pack-hook.ts +92 -0
- package/scripts/sync/sync-ai-files.ts +4 -0
- package/scripts/test/test-declared-changed.ts +13 -16
- package/scripts/test/test-declared.ts +3 -7
- package/scripts/version/version-commands.ts +11 -1
- package/templates/CLAUDE.basic.md +6 -6
- package/templates/workflows/ci.yml +16 -82
- package/templates/workflows/dependabot-auto-merge.yml +1 -0
- package/templates/workflows/github-release.yml +1 -3
- package/tsconfig.sonar.json +4 -22
|
@@ -1,32 +1,29 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ALREADY_DONE_LABEL,
|
|
3
|
-
BREAKING_CHANGE_LABEL,
|
|
4
|
-
BUGFIX_LABEL,
|
|
5
3
|
CONTEXT_CUT_THRESHOLD,
|
|
6
|
-
ENHANCEMENT_LABEL,
|
|
7
|
-
FULL_PAGE_QUERY,
|
|
8
4
|
IN_PROGRESS_LABEL,
|
|
9
5
|
NEEDS_DECISION_LABEL,
|
|
10
6
|
NEEDS_HUMAN_REVIEW_LABEL,
|
|
7
|
+
PORCELAIN_FLAG,
|
|
11
8
|
RECENT_REQUEST_WINDOW,
|
|
12
|
-
RELEASE_CLASSIFICATION_NAMES,
|
|
13
9
|
agent_role_profile,
|
|
14
10
|
agent_session_environment,
|
|
15
11
|
bash_triggers,
|
|
12
|
+
cli_flags,
|
|
16
13
|
error_text,
|
|
17
14
|
filing_cap,
|
|
18
|
-
gh_failure,
|
|
19
15
|
git_command,
|
|
20
16
|
git_common_directory,
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
git_gh_command,
|
|
18
|
+
git_gh_issue_read,
|
|
19
|
+
git_gh_pr_read,
|
|
20
|
+
git_spawn_sync,
|
|
23
21
|
has_any_label,
|
|
24
|
-
has_stderr_field,
|
|
25
22
|
issue_cite,
|
|
26
23
|
lane_background,
|
|
27
24
|
lane_park,
|
|
28
25
|
lane_registry,
|
|
29
|
-
|
|
26
|
+
open_issue_schema,
|
|
30
27
|
parse_json_object_safe,
|
|
31
28
|
read_json_listing,
|
|
32
29
|
repo_origin,
|
|
@@ -38,31 +35,31 @@ import {
|
|
|
38
35
|
run_tail,
|
|
39
36
|
shell_segments,
|
|
40
37
|
tail_commands
|
|
41
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-AIOIOMPX.js";
|
|
42
39
|
import {
|
|
43
40
|
find_local_bin_upwards
|
|
44
41
|
} from "./chunk-3V37IID6.js";
|
|
45
42
|
import {
|
|
46
43
|
batch_outcome
|
|
47
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-XYUIQOW3.js";
|
|
48
45
|
import {
|
|
49
46
|
investigation_refusal
|
|
50
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-7HVB7SZG.js";
|
|
51
48
|
import {
|
|
52
49
|
duplicate_read_outcome
|
|
53
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-5SD2YM7Z.js";
|
|
54
51
|
import {
|
|
55
52
|
investigation_reads
|
|
56
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-NXYMNPUQ.js";
|
|
57
54
|
import {
|
|
58
55
|
lane_guard_policy,
|
|
59
56
|
time_batch_guard
|
|
60
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-QVLT52OV.js";
|
|
61
58
|
import {
|
|
62
59
|
hook_decision,
|
|
63
60
|
lane_child_marker,
|
|
64
61
|
run_issue_number
|
|
65
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-MKVGBQPA.js";
|
|
66
63
|
import {
|
|
67
64
|
PLATFORM_TEMP_ROOT,
|
|
68
65
|
cost_attribute,
|
|
@@ -74,7 +71,7 @@ import {
|
|
|
74
71
|
lane_paths,
|
|
75
72
|
stamp_file,
|
|
76
73
|
time_shell
|
|
77
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-4JZDP5X5.js";
|
|
78
75
|
|
|
79
76
|
// scripts/rules/direct-filing.ts
|
|
80
77
|
var DIRECT_FILING_REASON = '\u26D4 direct filing: an Issue is filed with `pnpm josh issue:file "<title>" --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>]`, never with `gh api \u2026/issues` or `gh issue create`. The command runs every filing step in order \u2014 the duplicate scout, the body lint and its classification labels, the depth and `route:` labels, the `## Origin` check when filing into another repository, and `epic:bundle` after the create \u2014 so none of them is a step to remember. When the scout prints candidates it holds the filing: read each, then reissue with `--distinct <N,\u2026>` for the ones that are separate deliverables. Reference: `docs/josh-commands-automation.md` \u2192 "`josh issue:file`". **This rule fires on every occurrence, not once per run.**';
|
|
@@ -298,7 +295,8 @@ function is_life_fresh(target, threshold_ms) {
|
|
|
298
295
|
try {
|
|
299
296
|
const pinged_ms = parse_pinged_at(raw);
|
|
300
297
|
return pinged_ms !== void 0 && Date.now() - pinged_ms < threshold_ms;
|
|
301
|
-
} catch {
|
|
298
|
+
} catch (error) {
|
|
299
|
+
error_text.trace_swallowed("run_progress_clock.is_life_fresh", error);
|
|
302
300
|
return false;
|
|
303
301
|
}
|
|
304
302
|
}
|
|
@@ -442,7 +440,7 @@ function decide(call, run2, can_record) {
|
|
|
442
440
|
if (can_record) ARM_RECORD.record(target, lands_ms);
|
|
443
441
|
return false;
|
|
444
442
|
}
|
|
445
|
-
var EARLY_HEARTBEAT_REASON =
|
|
443
|
+
var EARLY_HEARTBEAT_REASON = "\u26D4 early heartbeat: this call arms a wait timer of its own, and the progress clock is not yours to keep. `pnpm josh run:progress --wait` keeps it for you (`JOSH_PROGRESS_INTERVAL_MINUTES`, or `josh.progress_interval_minutes` in `package.json`, default 20 minutes): start it once in the background and it reports the five labelled lines to the run's event stream on its own, without waking you \u2014 relay nothing, and start it again only after it exits, which it does when newly runnable work arrives. Two timers armed at once is what produced reports 3\u20135 minutes apart on a 15-minute setting (joshuafolkken/kit#1570): a new one was armed on the turn a timer fired and again on the turn a child's completion woke the run, and `--mark` recorded each report without anything refusing the early ones. **An explicit ask is not a heartbeat**: if the person asked for progress now, run `pnpm josh run:progress --once`, which prints the five labelled lines whatever the clock says. If you are waiting on something rather than on a clock, wait on the thing itself \u2014 `pnpm josh followup` waits for CI. The procedure is `.claude/skills/workflow-commands/backlogrun.md` \u2192 \"Progress while the run is quiet\". **This rule fires on every early arm, not once per run**, so reissuing the same sleep will be refused again.";
|
|
446
444
|
var PROGRESS_NAMES = /* @__PURE__ */ new Set(["run:progress"]);
|
|
447
445
|
var WATCH_FLAG = /(?:^|\s)--(?:wait|once)(?=\s|$)/u;
|
|
448
446
|
function is_progress_watch_segment(segment) {
|
|
@@ -671,7 +669,6 @@ var git_force = {
|
|
|
671
669
|
|
|
672
670
|
// scripts/cost-runtime/cost-cli.ts
|
|
673
671
|
import { fileURLToPath } from "node:url";
|
|
674
|
-
import { parseArgs } from "node:util";
|
|
675
672
|
|
|
676
673
|
// scripts/cost-runtime/codex-usage.ts
|
|
677
674
|
import { globSync, readFileSync as readFileSync2 } from "node:fs";
|
|
@@ -958,12 +955,8 @@ var PARSE_ARGS_OPTIONS = {
|
|
|
958
955
|
path: { type: "string" }
|
|
959
956
|
};
|
|
960
957
|
function parse_options(argv) {
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
return to_options(values);
|
|
964
|
-
} catch {
|
|
965
|
-
return void 0;
|
|
966
|
-
}
|
|
958
|
+
const values = cli_flags.values_of(argv, PARSE_ARGS_OPTIONS);
|
|
959
|
+
return values === void 0 ? void 0 : to_options(values);
|
|
967
960
|
}
|
|
968
961
|
function report_empty(cwd, session_id) {
|
|
969
962
|
const searched = cost_transcript.searched_directories(cost_transcript.transcript_directories(cwd));
|
|
@@ -2026,16 +2019,10 @@ import path5 from "node:path";
|
|
|
2026
2019
|
import { existsSync as existsSync2 } from "node:fs";
|
|
2027
2020
|
import path4 from "node:path";
|
|
2028
2021
|
|
|
2029
|
-
// scripts/lib/spawn-exit.ts
|
|
2030
|
-
function read_spawn_stdout(result) {
|
|
2031
|
-
return result.stdout ?? "";
|
|
2032
|
-
}
|
|
2033
|
-
|
|
2034
2022
|
// scripts/version/kit-descriptor.ts
|
|
2035
2023
|
var KIT_PACKAGE_NAME = "@joshuafolkken/kit";
|
|
2036
2024
|
|
|
2037
2025
|
// scripts/doctor/doctor-consumer.ts
|
|
2038
|
-
import { execaSync } from "execa";
|
|
2039
2026
|
import { z as z6 } from "zod";
|
|
2040
2027
|
var NODE_MODULES = "node_modules";
|
|
2041
2028
|
var SETTINGS_PATH = path4.join(".claude", "settings.json");
|
|
@@ -2077,11 +2064,9 @@ function is_plugin_declared(root) {
|
|
|
2077
2064
|
return parsed.success && parsed.data.enabledPlugins?.[PLUGIN_ID] === true;
|
|
2078
2065
|
}
|
|
2079
2066
|
function configured_hooks_path(root) {
|
|
2080
|
-
const
|
|
2081
|
-
reject: false,
|
|
2067
|
+
const value = git_spawn_sync.read(["-C", root, "config", "--get", "core.hooksPath"], {
|
|
2082
2068
|
timeout: GIT_TIMEOUT_MS
|
|
2083
2069
|
});
|
|
2084
|
-
const value = read_spawn_stdout(result).trim();
|
|
2085
2070
|
return value === "" ? void 0 : value;
|
|
2086
2071
|
}
|
|
2087
2072
|
function claude_md_state(root) {
|
|
@@ -2141,6 +2126,7 @@ function report_consumer_setup(root) {
|
|
|
2141
2126
|
var doctor_consumer = {
|
|
2142
2127
|
claude_md_line,
|
|
2143
2128
|
claude_md_state,
|
|
2129
|
+
configured_hooks_path,
|
|
2144
2130
|
hooks_path_line,
|
|
2145
2131
|
is_kit_consumer,
|
|
2146
2132
|
is_plugin_declared,
|
|
@@ -2543,9 +2529,6 @@ var shell_body_trigger = {
|
|
|
2543
2529
|
keeps_body_safe
|
|
2544
2530
|
};
|
|
2545
2531
|
|
|
2546
|
-
// scripts/test/test-declared-changed.ts
|
|
2547
|
-
import { execFileSync } from "node:child_process";
|
|
2548
|
-
|
|
2549
2532
|
// scripts/gate/project-checks.ts
|
|
2550
2533
|
import { existsSync as existsSync4, globSync as globSync2, readFileSync as readFileSync4 } from "node:fs";
|
|
2551
2534
|
import path7 from "node:path";
|
|
@@ -2553,7 +2536,6 @@ import path7 from "node:path";
|
|
|
2553
2536
|
// scripts/init/project-profile.ts
|
|
2554
2537
|
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3 } from "node:fs";
|
|
2555
2538
|
import path6 from "node:path";
|
|
2556
|
-
import { execaSync as execaSync2 } from "execa";
|
|
2557
2539
|
var IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", ".svelte-kit"]);
|
|
2558
2540
|
var WEB_EXTENSIONS = /* @__PURE__ */ new Set([".html", ".css", ".js", ".jsx", ".mjs", ".cjs"]);
|
|
2559
2541
|
var TYPESCRIPT_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx"]);
|
|
@@ -2644,11 +2626,8 @@ function scan_files(root) {
|
|
|
2644
2626
|
return { has_web, has_typescript };
|
|
2645
2627
|
}
|
|
2646
2628
|
function has_github_remote(root) {
|
|
2647
|
-
const
|
|
2648
|
-
|
|
2649
|
-
reject: false
|
|
2650
|
-
});
|
|
2651
|
-
return result.exitCode === 0 && repo_origin.parse_origin_url(result.stdout) !== void 0;
|
|
2629
|
+
const url = git_spawn_sync.origin_url(root);
|
|
2630
|
+
return url !== void 0 && repo_origin.parse_origin_url(url) !== void 0;
|
|
2652
2631
|
}
|
|
2653
2632
|
function inspect_project(root, requested) {
|
|
2654
2633
|
const profile = resolve_profile(root, requested);
|
|
@@ -2874,15 +2853,9 @@ function path_of(line) {
|
|
|
2874
2853
|
return arrow === -1 ? body : body.slice(arrow + RENAME_ARROW.length);
|
|
2875
2854
|
}
|
|
2876
2855
|
function read_changed_paths_sync() {
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
2881
|
-
});
|
|
2882
|
-
return output.split("\n").filter((line) => line.length > STATUS_PREFIX_LENGTH).map((line) => path_of(line));
|
|
2883
|
-
} catch {
|
|
2884
|
-
return [];
|
|
2885
|
-
}
|
|
2856
|
+
const output = git_spawn_sync.run(["status", PORCELAIN_FLAG], { timeout: 0 });
|
|
2857
|
+
if (output.exit_code !== 0) return [];
|
|
2858
|
+
return output.stdout.split("\n").filter((line) => line.length > STATUS_PREFIX_LENGTH).map((line) => path_of(line));
|
|
2886
2859
|
}
|
|
2887
2860
|
var injected = {};
|
|
2888
2861
|
function source_paths() {
|
|
@@ -3344,1680 +3317,11 @@ var delivered_rules = {
|
|
|
3344
3317
|
};
|
|
3345
3318
|
|
|
3346
3319
|
// scripts/run/run-watcher-hook.ts
|
|
3347
|
-
import { z as
|
|
3320
|
+
import { z as z12 } from "zod";
|
|
3348
3321
|
|
|
3349
3322
|
// scripts/run/run-progress-read.ts
|
|
3350
3323
|
import { loadavg } from "node:os";
|
|
3351
3324
|
|
|
3352
|
-
// scripts/gh/git-gh-helpers.ts
|
|
3353
|
-
function parse_pr_state_string(result) {
|
|
3354
|
-
const trimmed = result.trim();
|
|
3355
|
-
return trimmed.length > 0 ? trimmed : void 0;
|
|
3356
|
-
}
|
|
3357
|
-
function is_pr_already_exists_message(error_message) {
|
|
3358
|
-
return error_message.toLowerCase().includes("already exists");
|
|
3359
|
-
}
|
|
3360
|
-
function get_error_message_with_stderr(error) {
|
|
3361
|
-
if (!(error instanceof Error)) return String(error);
|
|
3362
|
-
if (has_stderr_field(error) && error.stderr.length > 0) return `${error.message}
|
|
3363
|
-
${error.stderr}`;
|
|
3364
|
-
return error.message;
|
|
3365
|
-
}
|
|
3366
|
-
function handle_pr_create_error(error) {
|
|
3367
|
-
const error_message = get_error_message_with_stderr(error);
|
|
3368
|
-
if (is_pr_already_exists_message(error_message)) {
|
|
3369
|
-
throw new Error("PR_ALREADY_EXISTS");
|
|
3370
|
-
}
|
|
3371
|
-
throw error;
|
|
3372
|
-
}
|
|
3373
|
-
var git_gh_helpers = {
|
|
3374
|
-
parse_pr_state_string,
|
|
3375
|
-
get_error_message_with_stderr,
|
|
3376
|
-
handle_pr_create_error
|
|
3377
|
-
};
|
|
3378
|
-
|
|
3379
|
-
// scripts/git/schemas.ts
|
|
3380
|
-
import { z as z8 } from "zod";
|
|
3381
|
-
var package_name_schema = z8.object({ name: z8.string().min(1) });
|
|
3382
|
-
var rollup_item_schema = z8.looseObject({
|
|
3383
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention -- GraphQL field name from GitHub API
|
|
3384
|
-
__typename: z8.string().optional(),
|
|
3385
|
-
state: z8.string().optional(),
|
|
3386
|
-
status: z8.string().optional(),
|
|
3387
|
-
conclusion: z8.string().optional(),
|
|
3388
|
-
name: z8.string().optional(),
|
|
3389
|
-
context: z8.string().optional()
|
|
3390
|
-
});
|
|
3391
|
-
var pr_raw_schema = z8.object({
|
|
3392
|
-
statusCheckRollup: z8.array(rollup_item_schema).optional(),
|
|
3393
|
-
mergeStateStatus: z8.string().optional(),
|
|
3394
|
-
reviewDecision: z8.string().optional()
|
|
3395
|
-
});
|
|
3396
|
-
var pull_comment_schema = z8.object({
|
|
3397
|
-
body: z8.string().optional(),
|
|
3398
|
-
html_url: z8.string().optional(),
|
|
3399
|
-
user: z8.object({ login: z8.string().optional() }).optional()
|
|
3400
|
-
});
|
|
3401
|
-
var ai_review_pull_comment_schema = z8.object({
|
|
3402
|
-
body: z8.string().optional(),
|
|
3403
|
-
url: z8.string().optional(),
|
|
3404
|
-
author: z8.object({ login: z8.string().optional() }).optional()
|
|
3405
|
-
});
|
|
3406
|
-
var pr_info_schema = z8.object({
|
|
3407
|
-
mergeable: z8.union([z8.boolean(), z8.string()]).nullable().optional(),
|
|
3408
|
-
mergeStateStatus: z8.string().nullable().optional(),
|
|
3409
|
-
state: z8.string().optional()
|
|
3410
|
-
});
|
|
3411
|
-
var epic_issue_schema = z8.object({
|
|
3412
|
-
number: z8.number(),
|
|
3413
|
-
body: z8.string().optional()
|
|
3414
|
-
});
|
|
3415
|
-
var blocking_issue_schema = z8.object({
|
|
3416
|
-
number: z8.number(),
|
|
3417
|
-
state: z8.string().optional(),
|
|
3418
|
-
repository_url: z8.string().optional()
|
|
3419
|
-
});
|
|
3420
|
-
var blocked_by_schema = z8.object({
|
|
3421
|
-
nodes: z8.array(blocking_issue_schema).default([]),
|
|
3422
|
-
totalCount: z8.number().optional()
|
|
3423
|
-
}).optional();
|
|
3424
|
-
var epic_child_schema = z8.object({
|
|
3425
|
-
state: z8.string().optional(),
|
|
3426
|
-
blockedBy: blocked_by_schema
|
|
3427
|
-
});
|
|
3428
|
-
var rest_comment_schema = z8.looseObject({
|
|
3429
|
-
body: z8.string().nullish(),
|
|
3430
|
-
html_url: z8.string().optional(),
|
|
3431
|
-
user: z8.looseObject({ login: z8.string().optional() }).nullish()
|
|
3432
|
-
});
|
|
3433
|
-
var issue_label_schema = z8.object({ name: z8.string() });
|
|
3434
|
-
var epic_subject_schema = z8.object({
|
|
3435
|
-
number: z8.number(),
|
|
3436
|
-
state: z8.string().optional(),
|
|
3437
|
-
labels: z8.array(issue_label_schema).optional(),
|
|
3438
|
-
body: z8.string().optional()
|
|
3439
|
-
});
|
|
3440
|
-
var open_issue_schema = z8.object({
|
|
3441
|
-
number: z8.number(),
|
|
3442
|
-
title: z8.string(),
|
|
3443
|
-
labels: z8.array(issue_label_schema).optional(),
|
|
3444
|
-
createdAt: z8.string(),
|
|
3445
|
-
blockedBy: blocked_by_schema
|
|
3446
|
-
});
|
|
3447
|
-
|
|
3448
|
-
// scripts/gh/git-gh-issue-rest.ts
|
|
3449
|
-
import { z as z9 } from "zod";
|
|
3450
|
-
|
|
3451
|
-
// scripts/gh/git-gh-rest-state.ts
|
|
3452
|
-
var MERGED_STATE = "MERGED";
|
|
3453
|
-
function to_gh_state(state) {
|
|
3454
|
-
return state?.toUpperCase();
|
|
3455
|
-
}
|
|
3456
|
-
|
|
3457
|
-
// scripts/gh/git-gh-issue-rest.ts
|
|
3458
|
-
var rest_issue_schema = z9.looseObject({
|
|
3459
|
-
number: z9.number(),
|
|
3460
|
-
issue_dependencies_summary: z9.looseObject({ total_blocked_by: z9.number().optional() }).nullish(),
|
|
3461
|
-
// Present only on a pull request, which this endpoint serves as readily as an issue.
|
|
3462
|
-
pull_request: z9.looseObject({ merged_at: z9.string().nullish() }).nullish()
|
|
3463
|
-
});
|
|
3464
|
-
var REPOSITORY_URL = /\/repos\/([\w.-]+\/[\w.-]+)$/u;
|
|
3465
|
-
var REPOSITORY_URL_GROUP = 1;
|
|
3466
|
-
var BLOCKED_BY_FIELD = "blockedBy";
|
|
3467
|
-
var BLOCKED_BY_COUNT_FIELD = "blocked_by_count";
|
|
3468
|
-
var STATE_FIELD = "state";
|
|
3469
|
-
var BODY_FIELD = "body";
|
|
3470
|
-
var FIELD_SEPARATOR = ",";
|
|
3471
|
-
var EMPTY_BODY = "";
|
|
3472
|
-
var REST_FIELD_NAMES = /* @__PURE__ */ new Map([
|
|
3473
|
-
["url", "html_url"],
|
|
3474
|
-
["createdAt", "created_at"]
|
|
3475
|
-
]);
|
|
3476
|
-
var NOT_AN_ISSUE_MESSAGE = "gh api answered something other than an issue object";
|
|
3477
|
-
var NOT_AN_ISSUE_LISTING_MESSAGE = "gh api answered something other than an issue listing";
|
|
3478
|
-
var NOT_A_BLOCKER_LISTING_MESSAGE = "gh api answered something other than a blocked-by listing";
|
|
3479
|
-
function rest_field_name(field) {
|
|
3480
|
-
return REST_FIELD_NAMES.get(field) ?? field;
|
|
3481
|
-
}
|
|
3482
|
-
function split_fields(fields) {
|
|
3483
|
-
return fields.split(FIELD_SEPARATOR).map((field) => field.trim()).filter((field) => field.length > 0);
|
|
3484
|
-
}
|
|
3485
|
-
function to_issue_state(rest, value) {
|
|
3486
|
-
if (typeof rest.pull_request?.merged_at === "string") return MERGED_STATE;
|
|
3487
|
-
return typeof value === "string" ? to_gh_state(value) : value;
|
|
3488
|
-
}
|
|
3489
|
-
function total_blocked_by(rest) {
|
|
3490
|
-
return rest.issue_dependencies_summary?.total_blocked_by;
|
|
3491
|
-
}
|
|
3492
|
-
function to_gh_field_value(field, rest) {
|
|
3493
|
-
if (field === BLOCKED_BY_COUNT_FIELD) return total_blocked_by(rest);
|
|
3494
|
-
const value = rest[rest_field_name(field)];
|
|
3495
|
-
if (field === STATE_FIELD) return to_issue_state(rest, value);
|
|
3496
|
-
return field === BODY_FIELD ? value ?? EMPTY_BODY : value;
|
|
3497
|
-
}
|
|
3498
|
-
function parse_rest_issue(rest_json) {
|
|
3499
|
-
const parsed = parse_json_object_safe(rest_json, rest_issue_schema);
|
|
3500
|
-
if (parsed === void 0) throw new Error(NOT_AN_ISSUE_MESSAGE);
|
|
3501
|
-
return parsed;
|
|
3502
|
-
}
|
|
3503
|
-
function is_pull_request(rest) {
|
|
3504
|
-
return rest.pull_request !== void 0 && rest.pull_request !== null;
|
|
3505
|
-
}
|
|
3506
|
-
function parse_rest_issues(rest_json) {
|
|
3507
|
-
const parsed = parse_json_array_or_undefined(rest_json, rest_issue_schema);
|
|
3508
|
-
if (parsed === void 0) throw new Error(NOT_AN_ISSUE_LISTING_MESSAGE);
|
|
3509
|
-
return parsed;
|
|
3510
|
-
}
|
|
3511
|
-
function empty_blocked_by() {
|
|
3512
|
-
return { nodes: [], totalCount: 0 };
|
|
3513
|
-
}
|
|
3514
|
-
function repo_of_url(repository_url) {
|
|
3515
|
-
const match = REPOSITORY_URL.exec(repository_url ?? "");
|
|
3516
|
-
return match?.[REPOSITORY_URL_GROUP];
|
|
3517
|
-
}
|
|
3518
|
-
function to_blocked_by(blockers_json, exact_total) {
|
|
3519
|
-
const parsed = parse_json_array_or_undefined(blockers_json, blocking_issue_schema);
|
|
3520
|
-
if (parsed === void 0) throw new Error(NOT_A_BLOCKER_LISTING_MESSAGE);
|
|
3521
|
-
const nodes = parsed.map((blocker) => ({ ...blocker, state: to_gh_state(blocker.state) }));
|
|
3522
|
-
return { nodes, totalCount: exact_total ?? nodes.length };
|
|
3523
|
-
}
|
|
3524
|
-
function to_gh_issue(rest, fields, blocked_by) {
|
|
3525
|
-
return Object.fromEntries(
|
|
3526
|
-
fields.map((field) => [
|
|
3527
|
-
field,
|
|
3528
|
-
field === BLOCKED_BY_FIELD ? blocked_by : to_gh_field_value(field, rest)
|
|
3529
|
-
])
|
|
3530
|
-
);
|
|
3531
|
-
}
|
|
3532
|
-
function to_field_text(value) {
|
|
3533
|
-
if (typeof value === "string") return value;
|
|
3534
|
-
return value === void 0 || value === null ? EMPTY_BODY : JSON.stringify(value);
|
|
3535
|
-
}
|
|
3536
|
-
var CLOSED = "CLOSED";
|
|
3537
|
-
function reference_of_blocker(node, fallback_repo) {
|
|
3538
|
-
const repo = repo_of_url(node.repository_url) ?? fallback_repo;
|
|
3539
|
-
if (node.state === void 0) return { repo, number: node.number };
|
|
3540
|
-
return { repo, number: node.number, state: node.state.toUpperCase() === CLOSED ? CLOSED : "OPEN" };
|
|
3541
|
-
}
|
|
3542
|
-
var git_gh_issue_rest = {
|
|
3543
|
-
empty_blocked_by,
|
|
3544
|
-
repo_of_url,
|
|
3545
|
-
reference_of_blocker,
|
|
3546
|
-
split_fields,
|
|
3547
|
-
is_pull_request,
|
|
3548
|
-
parse_rest_issue,
|
|
3549
|
-
parse_rest_issues,
|
|
3550
|
-
total_blocked_by,
|
|
3551
|
-
to_blocked_by,
|
|
3552
|
-
to_gh_issue,
|
|
3553
|
-
to_field_text
|
|
3554
|
-
};
|
|
3555
|
-
|
|
3556
|
-
// scripts/gh/git-gh-reachability.ts
|
|
3557
|
-
var RATE_LIMITED_STATUS = 429;
|
|
3558
|
-
var SERVER_ERROR_FLOOR = 500;
|
|
3559
|
-
function is_retryable_status(status) {
|
|
3560
|
-
if (status >= SERVER_ERROR_FLOOR) return true;
|
|
3561
|
-
return status === RATE_LIMITED_STATUS;
|
|
3562
|
-
}
|
|
3563
|
-
function classify_status(status) {
|
|
3564
|
-
if (status === void 0) return "unreachable";
|
|
3565
|
-
return is_retryable_status(status) ? "unreachable" : "reachable";
|
|
3566
|
-
}
|
|
3567
|
-
var gh_reachability = { classify_status };
|
|
3568
|
-
|
|
3569
|
-
// scripts/gh/git-gh-issue-read.ts
|
|
3570
|
-
async function read_blocked_by_listing(issue_number, repo, exact_total) {
|
|
3571
|
-
const json = await git_gh_exec.exec_gh_api({
|
|
3572
|
-
path: `${git_gh_api_path.blocked_by_api_path(issue_number, repo)}${git_gh_api_path.FULL_PAGE_QUERY}`
|
|
3573
|
-
});
|
|
3574
|
-
return git_gh_issue_rest.to_blocked_by(json, exact_total);
|
|
3575
|
-
}
|
|
3576
|
-
async function read_blocked_by(issue_number, rest, repo) {
|
|
3577
|
-
if (git_gh_issue_rest.is_pull_request(rest)) return git_gh_issue_rest.empty_blocked_by();
|
|
3578
|
-
const exact_total = git_gh_issue_rest.total_blocked_by(rest);
|
|
3579
|
-
if (exact_total === 0) return git_gh_issue_rest.empty_blocked_by();
|
|
3580
|
-
return await read_blocked_by_listing(issue_number, repo, exact_total);
|
|
3581
|
-
}
|
|
3582
|
-
function mark_followup(error) {
|
|
3583
|
-
if (!(error instanceof Error)) return error;
|
|
3584
|
-
const failure = gh_failure.failure_of(error);
|
|
3585
|
-
if (failure === void 0) return error;
|
|
3586
|
-
return gh_failure.attach(error, { ...failure, is_followup: true });
|
|
3587
|
-
}
|
|
3588
|
-
async function read_relations(issue_number, rest, repo) {
|
|
3589
|
-
try {
|
|
3590
|
-
return await read_blocked_by(issue_number, rest, repo);
|
|
3591
|
-
} catch (error) {
|
|
3592
|
-
throw mark_followup(error);
|
|
3593
|
-
}
|
|
3594
|
-
}
|
|
3595
|
-
async function read_issue_fields(issue_number, fields, repo) {
|
|
3596
|
-
const rest = git_gh_issue_rest.parse_rest_issue(
|
|
3597
|
-
await git_gh_exec.exec_gh_api({ path: git_gh_api_path.issue_api_path(issue_number, repo) })
|
|
3598
|
-
);
|
|
3599
|
-
const requested = git_gh_issue_rest.split_fields(fields);
|
|
3600
|
-
const blocked_by = requested.includes(BLOCKED_BY_FIELD) ? await read_relations(issue_number, rest, repo) : void 0;
|
|
3601
|
-
return git_gh_issue_rest.to_gh_issue(rest, requested, blocked_by);
|
|
3602
|
-
}
|
|
3603
|
-
var NOT_FOUND_STATUS = 404;
|
|
3604
|
-
function is_number_unresolved(failure) {
|
|
3605
|
-
return failure.status === NOT_FOUND_STATUS && failure.is_followup !== true;
|
|
3606
|
-
}
|
|
3607
|
-
function to_unreadable_reason(status) {
|
|
3608
|
-
return gh_reachability.classify_status(status) === "unreachable" ? "unreachable" : "rejected";
|
|
3609
|
-
}
|
|
3610
|
-
function to_read_failure(error) {
|
|
3611
|
-
const failure = gh_failure.failure_of(error);
|
|
3612
|
-
if (failure === void 0) return { kind: "unreadable", reason: "malformed", status: void 0 };
|
|
3613
|
-
if (is_number_unresolved(failure)) return { kind: "missing" };
|
|
3614
|
-
return {
|
|
3615
|
-
kind: "unreadable",
|
|
3616
|
-
reason: to_unreadable_reason(failure.status),
|
|
3617
|
-
status: failure.status
|
|
3618
|
-
};
|
|
3619
|
-
}
|
|
3620
|
-
async function issue_view_json_classified(issue_number, fields, repo) {
|
|
3621
|
-
try {
|
|
3622
|
-
const issue = await read_issue_fields(issue_number, fields, repo);
|
|
3623
|
-
return { kind: "read", json: JSON.stringify(issue) };
|
|
3624
|
-
} catch (error) {
|
|
3625
|
-
return to_read_failure(error);
|
|
3626
|
-
}
|
|
3627
|
-
}
|
|
3628
|
-
async function issue_view_field_classified(issue_number, field, repo) {
|
|
3629
|
-
try {
|
|
3630
|
-
const issue = await read_issue_fields(issue_number, field, repo);
|
|
3631
|
-
return { kind: "read", text: git_gh_issue_rest.to_field_text(issue[field]) };
|
|
3632
|
-
} catch (error) {
|
|
3633
|
-
return to_read_failure(error);
|
|
3634
|
-
}
|
|
3635
|
-
}
|
|
3636
|
-
async function issue_view_field(issue_number, field, repo) {
|
|
3637
|
-
const read2 = await issue_view_field_classified(issue_number, field, repo);
|
|
3638
|
-
return read2.kind === "read" ? read2.text : void 0;
|
|
3639
|
-
}
|
|
3640
|
-
async function issue_get_title(issue_number, repo) {
|
|
3641
|
-
const result = await issue_view_field(issue_number, "title", repo);
|
|
3642
|
-
return result === void 0 ? void 0 : git_gh_helpers.parse_pr_state_string(result);
|
|
3643
|
-
}
|
|
3644
|
-
async function issue_get_body(issue_number, repo) {
|
|
3645
|
-
return await issue_view_field(issue_number, "body", repo);
|
|
3646
|
-
}
|
|
3647
|
-
async function issue_get_body_classified(issue_number, repo) {
|
|
3648
|
-
return await issue_view_field_classified(issue_number, "body", repo);
|
|
3649
|
-
}
|
|
3650
|
-
async function issue_view_json(issue_number, fields, repo) {
|
|
3651
|
-
const read2 = await issue_view_json_classified(issue_number, fields, repo);
|
|
3652
|
-
return read2.kind === "read" ? read2.json : void 0;
|
|
3653
|
-
}
|
|
3654
|
-
var STATE_AND_RELATIONS_FIELDS = "number,state,labels,blockedBy";
|
|
3655
|
-
async function issue_get_state_and_relations(issue_number, repo) {
|
|
3656
|
-
return await issue_view_json(issue_number, STATE_AND_RELATIONS_FIELDS, repo);
|
|
3657
|
-
}
|
|
3658
|
-
async function issue_get_state_and_relations_classified(issue_number, repo) {
|
|
3659
|
-
return await issue_view_json_classified(issue_number, STATE_AND_RELATIONS_FIELDS, repo);
|
|
3660
|
-
}
|
|
3661
|
-
function is_unreachable_read(failure) {
|
|
3662
|
-
return failure.kind === "unreadable" && failure.reason === "unreachable";
|
|
3663
|
-
}
|
|
3664
|
-
var PLAN_FIELDS = "number,title,body,state,url,labels,blockedBy";
|
|
3665
|
-
async function issue_get_plan_fields(issue_number) {
|
|
3666
|
-
return await issue_view_json(issue_number, PLAN_FIELDS);
|
|
3667
|
-
}
|
|
3668
|
-
async function issue_get_plan_fields_classified(issue_number) {
|
|
3669
|
-
return await issue_view_json_classified(issue_number, PLAN_FIELDS);
|
|
3670
|
-
}
|
|
3671
|
-
async function issue_get_labels_and_body(issue_number) {
|
|
3672
|
-
return await issue_view_json(issue_number, "number,state,labels,body");
|
|
3673
|
-
}
|
|
3674
|
-
async function issue_list_comments(issue_number) {
|
|
3675
|
-
const path10 = `${git_gh_api_path.issue_comments_api_path(issue_number)}${git_gh_api_path.FULL_PAGE_QUERY}`;
|
|
3676
|
-
try {
|
|
3677
|
-
return await git_gh_exec.exec_gh_api({ path: path10, should_paginate: true });
|
|
3678
|
-
} catch {
|
|
3679
|
-
return void 0;
|
|
3680
|
-
}
|
|
3681
|
-
}
|
|
3682
|
-
async function has_no_relations_endpoint(issue_number, repo) {
|
|
3683
|
-
const status = await git_gh_exec.exec_gh_api_status(
|
|
3684
|
-
git_gh_api_path.blocked_by_api_path(issue_number, repo)
|
|
3685
|
-
);
|
|
3686
|
-
return status === NOT_FOUND_STATUS;
|
|
3687
|
-
}
|
|
3688
|
-
async function issue_blocked_by_references(issue_number, own_repo, repo) {
|
|
3689
|
-
try {
|
|
3690
|
-
const listing = await read_blocked_by_listing(issue_number, repo);
|
|
3691
|
-
return listing.nodes.map((blocker) => git_gh_issue_rest.reference_of_blocker(blocker, own_repo));
|
|
3692
|
-
} catch (error) {
|
|
3693
|
-
if (await has_no_relations_endpoint(issue_number, repo)) return [];
|
|
3694
|
-
throw error;
|
|
3695
|
-
}
|
|
3696
|
-
}
|
|
3697
|
-
async function issue_blocked_by_numbers(issue_number, repo) {
|
|
3698
|
-
const references = await issue_blocked_by_references(issue_number, "", repo);
|
|
3699
|
-
return references.map((blocker) => blocker.number);
|
|
3700
|
-
}
|
|
3701
|
-
var git_gh_issue_read = {
|
|
3702
|
-
issue_blocked_by_numbers,
|
|
3703
|
-
issue_blocked_by_references,
|
|
3704
|
-
issue_get_title,
|
|
3705
|
-
issue_get_body,
|
|
3706
|
-
issue_get_body_classified,
|
|
3707
|
-
issue_view_json,
|
|
3708
|
-
issue_view_json_classified,
|
|
3709
|
-
issue_get_state_and_relations,
|
|
3710
|
-
issue_get_state_and_relations_classified,
|
|
3711
|
-
is_unreachable_read,
|
|
3712
|
-
issue_get_plan_fields,
|
|
3713
|
-
issue_get_plan_fields_classified,
|
|
3714
|
-
issue_get_labels_and_body,
|
|
3715
|
-
issue_list_comments
|
|
3716
|
-
};
|
|
3717
|
-
|
|
3718
|
-
// scripts/gh/git-gh-issue-list.ts
|
|
3719
|
-
var PER_PAGE = 100;
|
|
3720
|
-
var FIRST_PAGE = 1;
|
|
3721
|
-
var DEFAULT_STATE = "open";
|
|
3722
|
-
var DEFAULT_SORT = "created";
|
|
3723
|
-
var LISTING_DIRECTION = "direction=desc";
|
|
3724
|
-
function listing_query(request) {
|
|
3725
|
-
const state = request.state ?? DEFAULT_STATE;
|
|
3726
|
-
const sort = request.sort ?? DEFAULT_SORT;
|
|
3727
|
-
return `state=${state}&sort=${sort}&${LISTING_DIRECTION}`;
|
|
3728
|
-
}
|
|
3729
|
-
function listing_path(request, page) {
|
|
3730
|
-
const label = request.label === void 0 ? "" : `&labels=${encodeURIComponent(request.label)}`;
|
|
3731
|
-
const paging = `&per_page=${String(PER_PAGE)}&page=${String(page)}`;
|
|
3732
|
-
return `${git_gh_api_path.issues_api_path(request.repo)}?${listing_query(request)}${label}${paging}`;
|
|
3733
|
-
}
|
|
3734
|
-
var DIGIT_PATTERN = /\d/u;
|
|
3735
|
-
function has_token_occurrence(body, term) {
|
|
3736
|
-
let index = body.indexOf(term);
|
|
3737
|
-
while (index !== -1) {
|
|
3738
|
-
if (!DIGIT_PATTERN.test(body.charAt(index + term.length))) return true;
|
|
3739
|
-
index = body.indexOf(term, index + 1);
|
|
3740
|
-
}
|
|
3741
|
-
return false;
|
|
3742
|
-
}
|
|
3743
|
-
function matches_body(rest, term) {
|
|
3744
|
-
if (term === void 0) return true;
|
|
3745
|
-
const { body } = rest;
|
|
3746
|
-
return typeof body === "string" && has_token_occurrence(body, term);
|
|
3747
|
-
}
|
|
3748
|
-
function is_selected(rest, request) {
|
|
3749
|
-
return !git_gh_issue_rest.is_pull_request(rest) && matches_body(rest, request.body_term);
|
|
3750
|
-
}
|
|
3751
|
-
async function fetch_page(request, page) {
|
|
3752
|
-
const path10 = listing_path(request, page);
|
|
3753
|
-
const rows = git_gh_issue_rest.parse_rest_issues(await git_gh_exec.exec_gh_api({ path: path10 }));
|
|
3754
|
-
return {
|
|
3755
|
-
selected: rows.filter((row) => is_selected(row, request)),
|
|
3756
|
-
is_full: rows.length >= PER_PAGE
|
|
3757
|
-
};
|
|
3758
|
-
}
|
|
3759
|
-
var MAX_PAGES = 5;
|
|
3760
|
-
var MAX_SCANNED = MAX_PAGES * PER_PAGE;
|
|
3761
|
-
function wants_more(has_more, selected_count, limit) {
|
|
3762
|
-
return has_more && selected_count < limit;
|
|
3763
|
-
}
|
|
3764
|
-
async function fetch_selected(request) {
|
|
3765
|
-
const selected = [];
|
|
3766
|
-
let page = FIRST_PAGE;
|
|
3767
|
-
let has_more = true;
|
|
3768
|
-
while (page <= MAX_PAGES && wants_more(has_more, selected.length, request.limit)) {
|
|
3769
|
-
const result = await fetch_page(request, page);
|
|
3770
|
-
selected.push(...result.selected);
|
|
3771
|
-
has_more = result.is_full;
|
|
3772
|
-
page += 1;
|
|
3773
|
-
}
|
|
3774
|
-
return {
|
|
3775
|
-
rows: selected.slice(0, request.limit),
|
|
3776
|
-
is_capped: wants_more(has_more, selected.length, request.limit)
|
|
3777
|
-
};
|
|
3778
|
-
}
|
|
3779
|
-
async function read_relations2(rows, repo) {
|
|
3780
|
-
const relations = [];
|
|
3781
|
-
for (const row of rows) {
|
|
3782
|
-
relations.push(await read_blocked_by(String(row.number), row, repo));
|
|
3783
|
-
}
|
|
3784
|
-
return relations;
|
|
3785
|
-
}
|
|
3786
|
-
async function issue_list(request) {
|
|
3787
|
-
try {
|
|
3788
|
-
const { rows, is_capped } = await fetch_selected(request);
|
|
3789
|
-
const fields = git_gh_issue_rest.split_fields(request.json_fields);
|
|
3790
|
-
const relations = fields.includes(BLOCKED_BY_FIELD) ? await read_relations2(rows, request.repo) : void 0;
|
|
3791
|
-
const mapped = rows.map(
|
|
3792
|
-
(row, index) => git_gh_issue_rest.to_gh_issue(row, fields, relations?.[index])
|
|
3793
|
-
);
|
|
3794
|
-
return { json: JSON.stringify(mapped), is_capped };
|
|
3795
|
-
} catch {
|
|
3796
|
-
return { json: void 0, is_capped: false };
|
|
3797
|
-
}
|
|
3798
|
-
}
|
|
3799
|
-
var git_gh_issue_list = {
|
|
3800
|
-
issue_list
|
|
3801
|
-
};
|
|
3802
|
-
|
|
3803
|
-
// scripts/gh/git-gh-issue-write.ts
|
|
3804
|
-
var PATCH_METHOD = "PATCH";
|
|
3805
|
-
var DELETE_METHOD2 = "DELETE";
|
|
3806
|
-
var HTML_URL_FILTER = ".html_url";
|
|
3807
|
-
var ID_FILTER = ".id";
|
|
3808
|
-
var LABELS_SEGMENT = "/labels";
|
|
3809
|
-
var COMMENTS_SEGMENT = "/comments";
|
|
3810
|
-
var CLOSED_STATE = "closed";
|
|
3811
|
-
var COLOR_HASH = "#";
|
|
3812
|
-
async function did_write_succeed(write) {
|
|
3813
|
-
try {
|
|
3814
|
-
await write();
|
|
3815
|
-
return true;
|
|
3816
|
-
} catch {
|
|
3817
|
-
return false;
|
|
3818
|
-
}
|
|
3819
|
-
}
|
|
3820
|
-
async function issue_edit_body(issue_number, body) {
|
|
3821
|
-
return await git_gh_exec.exec_gh_api({
|
|
3822
|
-
path: git_gh_api_path.issue_api_path(issue_number),
|
|
3823
|
-
method: PATCH_METHOD,
|
|
3824
|
-
body: JSON.stringify({ body }),
|
|
3825
|
-
jq_filter: HTML_URL_FILTER
|
|
3826
|
-
});
|
|
3827
|
-
}
|
|
3828
|
-
async function issue_comment(issue_number, body) {
|
|
3829
|
-
return await git_gh_exec.exec_gh_api({
|
|
3830
|
-
path: `${git_gh_api_path.issue_api_path(issue_number)}${COMMENTS_SEGMENT}`,
|
|
3831
|
-
body: JSON.stringify({ body }),
|
|
3832
|
-
jq_filter: HTML_URL_FILTER
|
|
3833
|
-
});
|
|
3834
|
-
}
|
|
3835
|
-
async function issue_try_comment(issue_number, body) {
|
|
3836
|
-
return await did_write_succeed(async () => await issue_comment(issue_number, body));
|
|
3837
|
-
}
|
|
3838
|
-
async function issue_close(issue_number, comment) {
|
|
3839
|
-
return await did_write_succeed(async () => {
|
|
3840
|
-
if (comment !== void 0) await issue_comment(issue_number, comment);
|
|
3841
|
-
await git_gh_exec.exec_gh_api({
|
|
3842
|
-
path: git_gh_api_path.issue_api_path(issue_number),
|
|
3843
|
-
method: PATCH_METHOD,
|
|
3844
|
-
body: JSON.stringify({ state: CLOSED_STATE })
|
|
3845
|
-
});
|
|
3846
|
-
});
|
|
3847
|
-
}
|
|
3848
|
-
function to_label_color(color) {
|
|
3849
|
-
return color.startsWith(COLOR_HASH) ? color.slice(COLOR_HASH.length) : color;
|
|
3850
|
-
}
|
|
3851
|
-
async function label_ensure(input) {
|
|
3852
|
-
try {
|
|
3853
|
-
await git_gh_exec.exec_gh_api({
|
|
3854
|
-
path: `${git_gh_api_path.repo_api_path()}${LABELS_SEGMENT}`,
|
|
3855
|
-
body: JSON.stringify({
|
|
3856
|
-
name: input.name,
|
|
3857
|
-
color: to_label_color(input.color),
|
|
3858
|
-
description: input.description
|
|
3859
|
-
})
|
|
3860
|
-
});
|
|
3861
|
-
} catch {
|
|
3862
|
-
}
|
|
3863
|
-
}
|
|
3864
|
-
function issue_create_request(input) {
|
|
3865
|
-
const { labels } = input;
|
|
3866
|
-
return {
|
|
3867
|
-
path: git_gh_api_path.issues_api_path(input.repo),
|
|
3868
|
-
body: JSON.stringify({
|
|
3869
|
-
title: input.title,
|
|
3870
|
-
...labels !== void 0 && { labels },
|
|
3871
|
-
body: input.body
|
|
3872
|
-
}),
|
|
3873
|
-
jq_filter: HTML_URL_FILTER
|
|
3874
|
-
};
|
|
3875
|
-
}
|
|
3876
|
-
async function issue_create_with_label(input) {
|
|
3877
|
-
return await git_gh_exec.exec_gh_api(
|
|
3878
|
-
issue_create_request({ title: input.title, body: input.body, labels: [input.label] })
|
|
3879
|
-
);
|
|
3880
|
-
}
|
|
3881
|
-
async function issue_add_label(issue_number, label) {
|
|
3882
|
-
return await did_write_succeed(
|
|
3883
|
-
async () => await git_gh_exec.exec_gh_api({
|
|
3884
|
-
path: `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`,
|
|
3885
|
-
body: JSON.stringify({ labels: [label] })
|
|
3886
|
-
})
|
|
3887
|
-
);
|
|
3888
|
-
}
|
|
3889
|
-
async function issue_remove_label(issue_number, label) {
|
|
3890
|
-
const labels_path = `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`;
|
|
3891
|
-
await git_gh_exec.exec_gh_api({
|
|
3892
|
-
path: `${labels_path}/${encodeURIComponent(label)}`,
|
|
3893
|
-
method: DELETE_METHOD2
|
|
3894
|
-
});
|
|
3895
|
-
}
|
|
3896
|
-
async function read_issue_id(issue_number) {
|
|
3897
|
-
const raw = await git_gh_exec.exec_gh_api({
|
|
3898
|
-
path: git_gh_api_path.issue_api_path(issue_number),
|
|
3899
|
-
jq_filter: ID_FILTER
|
|
3900
|
-
});
|
|
3901
|
-
const issue_id = Number(raw.trim());
|
|
3902
|
-
if (!Number.isSafeInteger(issue_id) || issue_id <= 0) {
|
|
3903
|
-
throw new Error(`gh api answered no database id for issue #${issue_number}`);
|
|
3904
|
-
}
|
|
3905
|
-
return issue_id;
|
|
3906
|
-
}
|
|
3907
|
-
async function issue_add_blocked_by(issue_number, blocker) {
|
|
3908
|
-
return await did_write_succeed(async () => {
|
|
3909
|
-
const issue_id = await read_issue_id(blocker);
|
|
3910
|
-
await git_gh_exec.exec_gh_api({
|
|
3911
|
-
path: git_gh_api_path.blocked_by_api_path(issue_number),
|
|
3912
|
-
body: JSON.stringify({ issue_id })
|
|
3913
|
-
});
|
|
3914
|
-
});
|
|
3915
|
-
}
|
|
3916
|
-
async function issue_remove_blocked_by(issue_number, blocker) {
|
|
3917
|
-
return await did_write_succeed(async () => {
|
|
3918
|
-
const issue_id = await read_issue_id(blocker);
|
|
3919
|
-
const relations_path = git_gh_api_path.blocked_by_api_path(issue_number);
|
|
3920
|
-
await git_gh_exec.exec_gh_api({
|
|
3921
|
-
path: `${relations_path}/${String(issue_id)}`,
|
|
3922
|
-
method: DELETE_METHOD2
|
|
3923
|
-
});
|
|
3924
|
-
});
|
|
3925
|
-
}
|
|
3926
|
-
var git_gh_issue_write = {
|
|
3927
|
-
issue_edit_body,
|
|
3928
|
-
issue_comment,
|
|
3929
|
-
issue_try_comment,
|
|
3930
|
-
issue_close,
|
|
3931
|
-
label_ensure,
|
|
3932
|
-
issue_create_request,
|
|
3933
|
-
issue_create_with_label,
|
|
3934
|
-
issue_add_label,
|
|
3935
|
-
issue_remove_label,
|
|
3936
|
-
issue_add_blocked_by,
|
|
3937
|
-
issue_remove_blocked_by
|
|
3938
|
-
};
|
|
3939
|
-
|
|
3940
|
-
// scripts/gh/git-gh-issue.ts
|
|
3941
|
-
var NUMBER_AND_BODY_FIELDS = "number,body";
|
|
3942
|
-
var BACKLOG_SCAN_FIELDS = `number,title,body,${BLOCKED_BY_COUNT_FIELD}`;
|
|
3943
|
-
var NUMBER_TITLE_AND_LABELS_FIELDS = "number,title,labels";
|
|
3944
|
-
var SUMMARY_FIELDS = "number,title,labels,createdAt";
|
|
3945
|
-
var PICKUP_FIELDS = `${SUMMARY_FIELDS},blockedBy`;
|
|
3946
|
-
var { issue_list: issue_list2 } = git_gh_issue_list;
|
|
3947
|
-
async function issue_list_recent(limit) {
|
|
3948
|
-
return await issue_list2({ json_fields: SUMMARY_FIELDS, limit });
|
|
3949
|
-
}
|
|
3950
|
-
async function issue_list_open_bodies(limit) {
|
|
3951
|
-
return await issue_list2({ json_fields: BACKLOG_SCAN_FIELDS, limit });
|
|
3952
|
-
}
|
|
3953
|
-
async function issue_list_recently_closed(limit) {
|
|
3954
|
-
return await issue_list2({
|
|
3955
|
-
json_fields: NUMBER_TITLE_AND_LABELS_FIELDS,
|
|
3956
|
-
limit,
|
|
3957
|
-
state: "closed",
|
|
3958
|
-
sort: "updated"
|
|
3959
|
-
});
|
|
3960
|
-
}
|
|
3961
|
-
async function issue_search_body(term, limit) {
|
|
3962
|
-
return await issue_list2({
|
|
3963
|
-
json_fields: NUMBER_AND_BODY_FIELDS,
|
|
3964
|
-
limit,
|
|
3965
|
-
body_term: term
|
|
3966
|
-
});
|
|
3967
|
-
}
|
|
3968
|
-
async function issue_list_by_label(label, limit) {
|
|
3969
|
-
return await issue_list2({ json_fields: NUMBER_AND_BODY_FIELDS, limit, label });
|
|
3970
|
-
}
|
|
3971
|
-
async function issue_list_by_label_summary(label, limit, options) {
|
|
3972
|
-
return await issue_list2({
|
|
3973
|
-
json_fields: options?.json_fields ?? PICKUP_FIELDS,
|
|
3974
|
-
limit,
|
|
3975
|
-
label
|
|
3976
|
-
});
|
|
3977
|
-
}
|
|
3978
|
-
async function issue_list_by_label_in_repo(label, limit, repo) {
|
|
3979
|
-
return await issue_list2({ json_fields: SUMMARY_FIELDS, limit, label, repo });
|
|
3980
|
-
}
|
|
3981
|
-
var git_gh_issue = {
|
|
3982
|
-
...git_gh_issue_read,
|
|
3983
|
-
...git_gh_issue_write,
|
|
3984
|
-
issue_list_recent,
|
|
3985
|
-
issue_list_by_label,
|
|
3986
|
-
issue_list_by_label_in_repo,
|
|
3987
|
-
issue_list_by_label_summary,
|
|
3988
|
-
issue_search_body,
|
|
3989
|
-
issue_list_open_bodies,
|
|
3990
|
-
issue_list_recently_closed
|
|
3991
|
-
};
|
|
3992
|
-
|
|
3993
|
-
// scripts/ci/pr-classification.ts
|
|
3994
|
-
import { readFileSync as readFileSync5 } from "node:fs";
|
|
3995
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
3996
|
-
import { z as z10 } from "zod";
|
|
3997
|
-
var CLASSIFICATION_SET = new Set(RELEASE_CLASSIFICATION_NAMES);
|
|
3998
|
-
var ISSUE_BUG_LABEL = "bug";
|
|
3999
|
-
var DECLARATION_PREFIX = "- \u30EA\u30EA\u30FC\u30B9\u5206\u985E: ";
|
|
4000
|
-
var DECLARATION = new RegExp(`^${DECLARATION_PREFIX}(.+)$`, "gmu");
|
|
4001
|
-
var LEGACY_LABELS = /* @__PURE__ */ new Set(["semver-major", "semver-minor"]);
|
|
4002
|
-
var LABEL = z10.object({ name: z10.string() });
|
|
4003
|
-
var USER = z10.object({ login: z10.string() });
|
|
4004
|
-
var PULL_REQUEST = z10.object({ number: z10.number(), user: USER });
|
|
4005
|
-
var EVENT = z10.object({
|
|
4006
|
-
pull_request: PULL_REQUEST,
|
|
4007
|
-
repository: z10.object({ full_name: z10.string() })
|
|
4008
|
-
});
|
|
4009
|
-
function classification_error(labels, author) {
|
|
4010
|
-
const legacy = labels.filter((label) => LEGACY_LABELS.has(label.toLowerCase()));
|
|
4011
|
-
if (legacy.length > 0) return `Remove legacy release labels: ${legacy.join(", ")}`;
|
|
4012
|
-
const selected = labels.filter((label) => CLASSIFICATION_SET.has(label.toLowerCase()));
|
|
4013
|
-
if (selected.length > 1) {
|
|
4014
|
-
return `Choose exactly one release classification; found: ${selected.join(", ")}`;
|
|
4015
|
-
}
|
|
4016
|
-
if (selected.length === 1 || author.endsWith("[bot]")) return void 0;
|
|
4017
|
-
return `Choose one release classification: ${RELEASE_CLASSIFICATION_NAMES.join(", ")}`;
|
|
4018
|
-
}
|
|
4019
|
-
function declaration(label) {
|
|
4020
|
-
return `${DECLARATION_PREFIX}${label}`;
|
|
4021
|
-
}
|
|
4022
|
-
function is_classification(value) {
|
|
4023
|
-
return CLASSIFICATION_SET.has(value);
|
|
4024
|
-
}
|
|
4025
|
-
function release_candidates(candidates) {
|
|
4026
|
-
if (!candidates.includes(BREAKING_CHANGE_LABEL)) return candidates;
|
|
4027
|
-
return candidates.filter((candidate) => candidate !== ENHANCEMENT_LABEL);
|
|
4028
|
-
}
|
|
4029
|
-
function issue_candidates(issue_json) {
|
|
4030
|
-
const issue = z10.object({ labels: z10.array(LABEL), body: z10.string().nullable() }).parse(JSON.parse(issue_json));
|
|
4031
|
-
const names = issue.labels.map((label) => label.name.toLowerCase());
|
|
4032
|
-
const declared = [...(issue.body ?? "").matchAll(DECLARATION)].map((match) => match[1] ?? "");
|
|
4033
|
-
const candidates = [...release_candidates([...names, ...declared].filter(is_classification))];
|
|
4034
|
-
const unknown = declared.filter((value) => !is_classification(value));
|
|
4035
|
-
if (unknown.length > 0) throw new Error(`Unknown release classification: ${unknown.join(", ")}`);
|
|
4036
|
-
if (names.includes(ISSUE_BUG_LABEL) && !candidates.includes(BREAKING_CHANGE_LABEL)) {
|
|
4037
|
-
candidates.push(BUGFIX_LABEL);
|
|
4038
|
-
}
|
|
4039
|
-
return candidates;
|
|
4040
|
-
}
|
|
4041
|
-
function select_issue_classification(issue_json) {
|
|
4042
|
-
const candidates = issue_candidates(issue_json);
|
|
4043
|
-
const selected = [...new Set(candidates)];
|
|
4044
|
-
const [label] = selected;
|
|
4045
|
-
if (label === void 0 || selected.length > 1) {
|
|
4046
|
-
throw new Error(
|
|
4047
|
-
`Choose one release classification before opening the PR: ${RELEASE_CLASSIFICATION_NAMES.join(", ")}; found: ${selected.join(", ") || "none"}. Add "${DECLARATION_PREFIX}<label>" to the Issue body.`
|
|
4048
|
-
);
|
|
4049
|
-
}
|
|
4050
|
-
return label;
|
|
4051
|
-
}
|
|
4052
|
-
function fetch_current_labels(repository, pull_number) {
|
|
4053
|
-
const path10 = `repos/${repository}/issues/${String(pull_number)}/labels`;
|
|
4054
|
-
try {
|
|
4055
|
-
const names = git_gh_exec.exec_gh_api_sync({ path: path10, jq_filter: ".[].name" });
|
|
4056
|
-
return names.split("\n").filter((name) => name !== "");
|
|
4057
|
-
} catch (error) {
|
|
4058
|
-
const detail = error_text.message_of(error);
|
|
4059
|
-
throw new Error(`Could not read the pull request labels: ${detail}`, { cause: error });
|
|
4060
|
-
}
|
|
4061
|
-
}
|
|
4062
|
-
function check_event(event_path, read_labels = fetch_current_labels) {
|
|
4063
|
-
const event = EVENT.parse(JSON.parse(readFileSync5(event_path, "utf8")));
|
|
4064
|
-
const labels = read_labels(event.repository.full_name, event.pull_request.number);
|
|
4065
|
-
return classification_error(labels, event.pull_request.user.login);
|
|
4066
|
-
}
|
|
4067
|
-
if (process.argv[1] === fileURLToPath2(import.meta.url)) {
|
|
4068
|
-
const event_path = process.env["GITHUB_EVENT_PATH"];
|
|
4069
|
-
if (!event_path) throw new Error("GITHUB_EVENT_PATH is required");
|
|
4070
|
-
const error = check_event(event_path);
|
|
4071
|
-
if (error) {
|
|
4072
|
-
console.error(`::error::${error}`);
|
|
4073
|
-
process.exitCode = 1;
|
|
4074
|
-
}
|
|
4075
|
-
}
|
|
4076
|
-
var pr_classification = {
|
|
4077
|
-
classification_error,
|
|
4078
|
-
check_event,
|
|
4079
|
-
fetch_current_labels,
|
|
4080
|
-
declaration,
|
|
4081
|
-
is_classification,
|
|
4082
|
-
select_issue_classification
|
|
4083
|
-
};
|
|
4084
|
-
|
|
4085
|
-
// scripts/lib/poll.ts
|
|
4086
|
-
async function sleep(duration_ms) {
|
|
4087
|
-
await new Promise((resolve2) => {
|
|
4088
|
-
setTimeout(resolve2, duration_ms);
|
|
4089
|
-
});
|
|
4090
|
-
}
|
|
4091
|
-
async function wait_between(wait, interval_ms, attempt, attempts) {
|
|
4092
|
-
if (attempt < attempts - 1) await wait(interval_ms);
|
|
4093
|
-
}
|
|
4094
|
-
async function poll_until(is_done, options) {
|
|
4095
|
-
const wait = options.sleeper ?? sleep;
|
|
4096
|
-
for (let attempt = 0; attempt < options.attempts; attempt += 1) {
|
|
4097
|
-
if (await is_done()) return true;
|
|
4098
|
-
await wait_between(wait, options.interval_ms, attempt, options.attempts);
|
|
4099
|
-
}
|
|
4100
|
-
return false;
|
|
4101
|
-
}
|
|
4102
|
-
var poll = { poll_until, sleep };
|
|
4103
|
-
|
|
4104
|
-
// scripts/gh/git-gh-pr.ts
|
|
4105
|
-
import { z as z14 } from "zod";
|
|
4106
|
-
|
|
4107
|
-
// scripts/gh/git-gh-pr-rest.ts
|
|
4108
|
-
import { z as z11 } from "zod";
|
|
4109
|
-
var rest_repo_schema = z11.looseObject({ full_name: z11.string().optional() }).nullish();
|
|
4110
|
-
var rest_pull_side_schema = z11.looseObject({ repo: rest_repo_schema });
|
|
4111
|
-
var rest_pull_schema = z11.looseObject({
|
|
4112
|
-
number: z11.number(),
|
|
4113
|
-
html_url: z11.string().optional(),
|
|
4114
|
-
body: z11.string().nullish(),
|
|
4115
|
-
state: z11.string().optional(),
|
|
4116
|
-
merged: z11.boolean().nullish(),
|
|
4117
|
-
merged_at: z11.string().nullish(),
|
|
4118
|
-
mergeable: z11.boolean().nullish(),
|
|
4119
|
-
mergeable_state: z11.string().optional(),
|
|
4120
|
-
// `sha` is the head commit, which is what both halves of the merge-gate rollup are keyed by —
|
|
4121
|
-
// REST hangs the check runs and the status contexts off the commit rather than off the pull
|
|
4122
|
-
// request (joshuafolkken/kit#1028).
|
|
4123
|
-
head: z11.looseObject({ ref: z11.string().optional(), sha: z11.string().optional(), repo: rest_repo_schema }).nullish(),
|
|
4124
|
-
base: rest_pull_side_schema.nullish(),
|
|
4125
|
-
// `node_id` is what the GraphQL auto-merge mutation addresses a pull request by, and `auto_merge`
|
|
4126
|
-
// is `null` until auto-merge is enabled — both read by `git-gh-pr-auto-merge.ts`
|
|
4127
|
-
// (joshuafolkken/kit#2497).
|
|
4128
|
-
node_id: z11.string().optional(),
|
|
4129
|
-
auto_merge: z11.looseObject({}).nullish()
|
|
4130
|
-
});
|
|
4131
|
-
var NOT_A_PULL_MESSAGE = "gh api answered something other than a pull request object";
|
|
4132
|
-
var NOT_A_PULL_LISTING_MESSAGE = "gh api answered something other than a pull request listing";
|
|
4133
|
-
var NOT_A_COMMENT_LISTING_MESSAGE = "gh api answered something other than a comment listing";
|
|
4134
|
-
var OPEN_STATE2 = "open";
|
|
4135
|
-
var EMPTY_BODY2 = "";
|
|
4136
|
-
function parse_rest_pull(rest_json) {
|
|
4137
|
-
const parsed = parse_json_object_safe(rest_json, rest_pull_schema);
|
|
4138
|
-
if (parsed === void 0) throw new Error(NOT_A_PULL_MESSAGE);
|
|
4139
|
-
return parsed;
|
|
4140
|
-
}
|
|
4141
|
-
function parse_rest_pulls(rest_json) {
|
|
4142
|
-
const parsed = parse_json_array_or_undefined(rest_json, rest_pull_schema);
|
|
4143
|
-
if (parsed === void 0) throw new Error(NOT_A_PULL_LISTING_MESSAGE);
|
|
4144
|
-
return parsed;
|
|
4145
|
-
}
|
|
4146
|
-
function select_pull(pulls) {
|
|
4147
|
-
return pulls.find((pull) => pull.state === OPEN_STATE2) ?? pulls[0];
|
|
4148
|
-
}
|
|
4149
|
-
function is_merged(pull) {
|
|
4150
|
-
return pull.merged === true || typeof pull.merged_at === "string";
|
|
4151
|
-
}
|
|
4152
|
-
function to_pr_state(pull) {
|
|
4153
|
-
return is_merged(pull) ? MERGED_STATE : to_gh_state(pull.state);
|
|
4154
|
-
}
|
|
4155
|
-
function to_repo_name(side) {
|
|
4156
|
-
return side?.repo?.full_name;
|
|
4157
|
-
}
|
|
4158
|
-
function is_same_repository_head(pull) {
|
|
4159
|
-
const head_repo = to_repo_name(pull.head);
|
|
4160
|
-
return head_repo !== void 0 && head_repo === to_repo_name(pull.base);
|
|
4161
|
-
}
|
|
4162
|
-
function to_pr_info(pull) {
|
|
4163
|
-
return {
|
|
4164
|
-
mergeable: pull.mergeable,
|
|
4165
|
-
mergeStateStatus: to_gh_state(pull.mergeable_state),
|
|
4166
|
-
state: to_pr_state(pull)
|
|
4167
|
-
};
|
|
4168
|
-
}
|
|
4169
|
-
function to_pr_comments(rest_json) {
|
|
4170
|
-
const parsed = parse_json_array_or_undefined(rest_json, rest_comment_schema);
|
|
4171
|
-
if (parsed === void 0) throw new Error(NOT_A_COMMENT_LISTING_MESSAGE);
|
|
4172
|
-
return parsed.map((comment) => ({
|
|
4173
|
-
body: comment.body ?? EMPTY_BODY2,
|
|
4174
|
-
url: comment.html_url,
|
|
4175
|
-
author: { login: comment.user?.login }
|
|
4176
|
-
}));
|
|
4177
|
-
}
|
|
4178
|
-
var git_gh_pr_rest = {
|
|
4179
|
-
parse_rest_pull,
|
|
4180
|
-
parse_rest_pulls,
|
|
4181
|
-
select_pull,
|
|
4182
|
-
is_same_repository_head,
|
|
4183
|
-
is_merged,
|
|
4184
|
-
to_pr_state,
|
|
4185
|
-
to_pr_info,
|
|
4186
|
-
to_pr_comments
|
|
4187
|
-
};
|
|
4188
|
-
|
|
4189
|
-
// scripts/gh/git-gh-pr-read.ts
|
|
4190
|
-
var pr_number_by_branch = /* @__PURE__ */ new Map();
|
|
4191
|
-
var LOOKUP_QUERY = "state=all&sort=created&direction=desc&per_page=100";
|
|
4192
|
-
var COMMENTS_QUERY = FULL_PAGE_QUERY;
|
|
4193
|
-
var OWNER_PLACEHOLDER = "{owner}";
|
|
4194
|
-
var NO_PULL_REQUEST_MESSAGE = "gh api found no pull request for branch";
|
|
4195
|
-
var UNREADABLE_PULL_REQUEST_MESSAGE = "gh api could not read the pull requests for branch";
|
|
4196
|
-
function lookup_path(branch_name) {
|
|
4197
|
-
const head = `${OWNER_PLACEHOLDER}:${encodeURIComponent(branch_name)}`;
|
|
4198
|
-
return `${git_gh_api_path.pulls_api_path()}?head=${head}&${LOOKUP_QUERY}`;
|
|
4199
|
-
}
|
|
4200
|
-
async function fetch_pr_number(branch_name) {
|
|
4201
|
-
const json = await git_gh_exec.exec_gh_api({ path: lookup_path(branch_name) });
|
|
4202
|
-
return git_gh_pr_rest.select_pull(git_gh_pr_rest.parse_rest_pulls(json))?.number;
|
|
4203
|
-
}
|
|
4204
|
-
var pending_pr_number_by_branch = /* @__PURE__ */ new Map();
|
|
4205
|
-
async function fetch_pr_number_read(branch_name) {
|
|
4206
|
-
try {
|
|
4207
|
-
const pr_number = await fetch_pr_number(branch_name);
|
|
4208
|
-
if (pr_number === void 0) return { kind: "missing" };
|
|
4209
|
-
pr_number_by_branch.set(branch_name, pr_number);
|
|
4210
|
-
return { kind: "read", pr_number };
|
|
4211
|
-
} catch (error) {
|
|
4212
|
-
return { kind: "unreadable", cause: error };
|
|
4213
|
-
}
|
|
4214
|
-
}
|
|
4215
|
-
async function start_pr_number_read(branch_name) {
|
|
4216
|
-
const pending = pending_pr_number_by_branch.get(branch_name);
|
|
4217
|
-
if (pending !== void 0) return await pending;
|
|
4218
|
-
const lookup = fetch_pr_number_read(branch_name);
|
|
4219
|
-
pending_pr_number_by_branch.set(branch_name, lookup);
|
|
4220
|
-
try {
|
|
4221
|
-
return await lookup;
|
|
4222
|
-
} finally {
|
|
4223
|
-
pending_pr_number_by_branch.delete(branch_name);
|
|
4224
|
-
}
|
|
4225
|
-
}
|
|
4226
|
-
function forget_pr_numbers() {
|
|
4227
|
-
pr_number_by_branch.clear();
|
|
4228
|
-
pending_pr_number_by_branch.clear();
|
|
4229
|
-
}
|
|
4230
|
-
async function read_pr_number(branch_name) {
|
|
4231
|
-
const cached = pr_number_by_branch.get(branch_name);
|
|
4232
|
-
if (cached !== void 0) return { kind: "read", pr_number: cached };
|
|
4233
|
-
return await start_pr_number_read(branch_name);
|
|
4234
|
-
}
|
|
4235
|
-
async function resolve_pr_number(branch_name) {
|
|
4236
|
-
const read2 = await read_pr_number(branch_name);
|
|
4237
|
-
return read2.kind === "read" ? read2.pr_number : void 0;
|
|
4238
|
-
}
|
|
4239
|
-
function to_unreadable_error(branch_name, cause) {
|
|
4240
|
-
return new Error(`${UNREADABLE_PULL_REQUEST_MESSAGE}: ${branch_name}`, { cause });
|
|
4241
|
-
}
|
|
4242
|
-
async function require_pr_number(branch_name) {
|
|
4243
|
-
const read2 = await read_pr_number(branch_name);
|
|
4244
|
-
if (read2.kind === "read") return read2.pr_number;
|
|
4245
|
-
if (read2.kind === "missing") throw new Error(`${NO_PULL_REQUEST_MESSAGE}: ${branch_name}`);
|
|
4246
|
-
throw to_unreadable_error(branch_name, read2.cause);
|
|
4247
|
-
}
|
|
4248
|
-
async function read_pull(pr_number) {
|
|
4249
|
-
const json = await git_gh_exec.exec_gh_api({
|
|
4250
|
-
path: git_gh_api_path.pull_api_path(String(pr_number))
|
|
4251
|
-
});
|
|
4252
|
-
return git_gh_pr_rest.parse_rest_pull(json);
|
|
4253
|
-
}
|
|
4254
|
-
async function read_pull_of_branch(branch_name) {
|
|
4255
|
-
const pr_number = await resolve_pr_number(branch_name);
|
|
4256
|
-
if (pr_number === void 0) return void 0;
|
|
4257
|
-
try {
|
|
4258
|
-
return await read_pull(pr_number);
|
|
4259
|
-
} catch {
|
|
4260
|
-
return void 0;
|
|
4261
|
-
}
|
|
4262
|
-
}
|
|
4263
|
-
async function pr_exists(branch_name) {
|
|
4264
|
-
const read2 = await read_pr_number(branch_name);
|
|
4265
|
-
if (read2.kind === "unreadable") throw to_unreadable_error(branch_name, read2.cause);
|
|
4266
|
-
return read2.kind === "read";
|
|
4267
|
-
}
|
|
4268
|
-
async function pr_get_number(branch_name) {
|
|
4269
|
-
return await resolve_pr_number(branch_name);
|
|
4270
|
-
}
|
|
4271
|
-
async function pr_get_url(branch_name) {
|
|
4272
|
-
const pull = await read_pull_of_branch(branch_name);
|
|
4273
|
-
if (pull?.html_url === void 0) return void 0;
|
|
4274
|
-
return git_gh_helpers.parse_pr_state_string(pull.html_url);
|
|
4275
|
-
}
|
|
4276
|
-
async function pr_get_merge_state(branch_name) {
|
|
4277
|
-
const pull = await read_pull_of_branch(branch_name);
|
|
4278
|
-
if (pull === void 0) return void 0;
|
|
4279
|
-
return {
|
|
4280
|
-
is_merged: git_gh_pr_rest.is_merged(pull),
|
|
4281
|
-
merged_at: pull.merged_at ?? void 0,
|
|
4282
|
-
head_sha: pull.head?.sha
|
|
4283
|
-
};
|
|
4284
|
-
}
|
|
4285
|
-
async function pr_get_body(branch_name) {
|
|
4286
|
-
const pull = await read_pull_of_branch(branch_name);
|
|
4287
|
-
const body = pull?.body;
|
|
4288
|
-
return typeof body === "string" && body.length > 0 ? body : void 0;
|
|
4289
|
-
}
|
|
4290
|
-
async function pr_view(branch_name) {
|
|
4291
|
-
const pull = await read_pull_of_branch(branch_name);
|
|
4292
|
-
if (pull === void 0) return "";
|
|
4293
|
-
return JSON.stringify(git_gh_pr_rest.to_pr_info(pull));
|
|
4294
|
-
}
|
|
4295
|
-
async function read_comments(branch_name, to_path, to_json) {
|
|
4296
|
-
const pr_number = await resolve_pr_number(branch_name);
|
|
4297
|
-
if (pr_number === void 0) return void 0;
|
|
4298
|
-
const path10 = `${to_path(String(pr_number))}${COMMENTS_QUERY}`;
|
|
4299
|
-
try {
|
|
4300
|
-
return to_json(await git_gh_exec.exec_gh_api({ path: path10, should_paginate: true }));
|
|
4301
|
-
} catch {
|
|
4302
|
-
return void 0;
|
|
4303
|
-
}
|
|
4304
|
-
}
|
|
4305
|
-
function to_comments_json(raw) {
|
|
4306
|
-
return JSON.stringify(git_gh_pr_rest.to_pr_comments(raw));
|
|
4307
|
-
}
|
|
4308
|
-
function as_served(raw) {
|
|
4309
|
-
return raw;
|
|
4310
|
-
}
|
|
4311
|
-
async function pr_get_comments(branch_name) {
|
|
4312
|
-
return await read_comments(branch_name, git_gh_api_path.issue_comments_api_path, to_comments_json);
|
|
4313
|
-
}
|
|
4314
|
-
async function pr_get_review_comments(branch_name) {
|
|
4315
|
-
return await read_comments(branch_name, git_gh_api_path.pull_comments_api_path, as_served);
|
|
4316
|
-
}
|
|
4317
|
-
var git_gh_pr_read = {
|
|
4318
|
-
pr_exists,
|
|
4319
|
-
pr_get_number,
|
|
4320
|
-
pr_get_url,
|
|
4321
|
-
pr_get_body,
|
|
4322
|
-
pr_get_merge_state,
|
|
4323
|
-
pr_view,
|
|
4324
|
-
pr_get_comments,
|
|
4325
|
-
pr_get_review_comments
|
|
4326
|
-
};
|
|
4327
|
-
|
|
4328
|
-
// scripts/gh/git-gh-pr-review.ts
|
|
4329
|
-
import { z as z12 } from "zod";
|
|
4330
|
-
var REVIEW_APPROVED = "APPROVED";
|
|
4331
|
-
var REVIEW_CHANGES_REQUESTED = "CHANGES_REQUESTED";
|
|
4332
|
-
var REVIEW_NONE = "";
|
|
4333
|
-
var STATE_CHANGING_REVIEWS = /* @__PURE__ */ new Set([REVIEW_APPROVED, REVIEW_CHANGES_REQUESTED]);
|
|
4334
|
-
var rest_review_schema = z12.looseObject({
|
|
4335
|
-
state: z12.string().optional(),
|
|
4336
|
-
user: z12.looseObject({ login: z12.string().optional() }).nullish()
|
|
4337
|
-
});
|
|
4338
|
-
var NOT_A_REVIEW_LISTING = "gh api answered something other than a review listing";
|
|
4339
|
-
function parse_rest_reviews(reviews_json) {
|
|
4340
|
-
const parsed = parse_json_array_or_undefined(reviews_json, rest_review_schema);
|
|
4341
|
-
if (parsed === void 0) throw new Error(NOT_A_REVIEW_LISTING);
|
|
4342
|
-
return parsed;
|
|
4343
|
-
}
|
|
4344
|
-
var UNATTRIBUTED_REVIEWER = "(no author)";
|
|
4345
|
-
function read_reviewer(review) {
|
|
4346
|
-
const login = review.user?.login;
|
|
4347
|
-
return typeof login === "string" && login.length > 0 ? login : UNATTRIBUTED_REVIEWER;
|
|
4348
|
-
}
|
|
4349
|
-
function read_state_changing(review) {
|
|
4350
|
-
const state = review.state?.toUpperCase();
|
|
4351
|
-
return state !== void 0 && STATE_CHANGING_REVIEWS.has(state) ? state : void 0;
|
|
4352
|
-
}
|
|
4353
|
-
function fold_latest_states(reviews) {
|
|
4354
|
-
const latest = /* @__PURE__ */ new Map();
|
|
4355
|
-
for (const review of reviews) {
|
|
4356
|
-
const state = read_state_changing(review);
|
|
4357
|
-
if (state !== void 0) latest.set(read_reviewer(review), state);
|
|
4358
|
-
}
|
|
4359
|
-
return latest;
|
|
4360
|
-
}
|
|
4361
|
-
function to_review_decision(reviews_json) {
|
|
4362
|
-
const latest = new Set(fold_latest_states(parse_rest_reviews(reviews_json)).values());
|
|
4363
|
-
if (latest.has(REVIEW_CHANGES_REQUESTED)) return REVIEW_CHANGES_REQUESTED;
|
|
4364
|
-
return latest.has(REVIEW_APPROVED) ? REVIEW_APPROVED : REVIEW_NONE;
|
|
4365
|
-
}
|
|
4366
|
-
var git_gh_pr_review = { to_review_decision };
|
|
4367
|
-
|
|
4368
|
-
// scripts/gh/git-gh-pr-rollup.ts
|
|
4369
|
-
import { z as z13 } from "zod";
|
|
4370
|
-
var STATUS_CONTEXT_TYPE_NAME = "StatusContext";
|
|
4371
|
-
var TYPE_NAME_KEY = "__typename";
|
|
4372
|
-
var rollup_element_schema = z13.looseObject({});
|
|
4373
|
-
var check_runs_page_schema = z13.looseObject({
|
|
4374
|
-
// Required, not optional: GitHub always names the key, and accepting a page without one would
|
|
4375
|
-
// answer an empty rollup — which `git-pr-followup.ts` reports as "this branch has no checks".
|
|
4376
|
-
check_runs: z13.array(rollup_element_schema)
|
|
4377
|
-
});
|
|
4378
|
-
var id_holder_schema = z13.object({ id: z13.number() });
|
|
4379
|
-
var status_page_schema = z13.looseObject({
|
|
4380
|
-
statuses: z13.array(rollup_element_schema)
|
|
4381
|
-
});
|
|
4382
|
-
var NOT_A_CHECK_RUNS_LISTING = "gh api answered something other than a check run listing";
|
|
4383
|
-
var NOT_A_STATUS_LISTING = "gh api answered something other than a commit status listing";
|
|
4384
|
-
function read_pages(raw_json, schema, message) {
|
|
4385
|
-
const pages = parse_json_array_or_undefined(raw_json, schema);
|
|
4386
|
-
if (pages === void 0) throw new Error(message);
|
|
4387
|
-
return pages;
|
|
4388
|
-
}
|
|
4389
|
-
var NO_SUITE = -1;
|
|
4390
|
-
function read_id(value) {
|
|
4391
|
-
const parsed = id_holder_schema.safeParse(value);
|
|
4392
|
-
return parsed.success ? parsed.data.id : void 0;
|
|
4393
|
-
}
|
|
4394
|
-
function check_run_group_key(run2) {
|
|
4395
|
-
const { name, app } = run2;
|
|
4396
|
-
if (typeof name !== "string") return void 0;
|
|
4397
|
-
return JSON.stringify([name, read_id(app)]);
|
|
4398
|
-
}
|
|
4399
|
-
function read_rank(run2) {
|
|
4400
|
-
const id = read_id(run2);
|
|
4401
|
-
if (id === void 0) return void 0;
|
|
4402
|
-
return { suite: read_id(run2["check_suite"]) ?? NO_SUITE, run: id };
|
|
4403
|
-
}
|
|
4404
|
-
function is_ranked_above(candidate, current) {
|
|
4405
|
-
if (candidate.suite !== current.suite) return candidate.suite > current.suite;
|
|
4406
|
-
return candidate.run > current.run;
|
|
4407
|
-
}
|
|
4408
|
-
function should_replace(previous, rank) {
|
|
4409
|
-
const previous_rank = previous === void 0 ? void 0 : read_rank(previous);
|
|
4410
|
-
return previous_rank === void 0 || is_ranked_above(rank, previous_rank);
|
|
4411
|
-
}
|
|
4412
|
-
function remember_newest_run(run2, newest) {
|
|
4413
|
-
const key = check_run_group_key(run2);
|
|
4414
|
-
const rank = read_rank(run2);
|
|
4415
|
-
if (key === void 0 || rank === void 0) return;
|
|
4416
|
-
if (should_replace(newest.get(key), rank)) newest.set(key, run2);
|
|
4417
|
-
}
|
|
4418
|
-
function is_newest_run(run2, newest) {
|
|
4419
|
-
const key = check_run_group_key(run2);
|
|
4420
|
-
if (key === void 0 || read_rank(run2) === void 0) return true;
|
|
4421
|
-
return newest.get(key) === run2;
|
|
4422
|
-
}
|
|
4423
|
-
function to_check_run_items(check_runs_json) {
|
|
4424
|
-
const pages = read_pages(check_runs_json, check_runs_page_schema, NOT_A_CHECK_RUNS_LISTING);
|
|
4425
|
-
const runs = pages.flatMap((page) => page.check_runs);
|
|
4426
|
-
const newest = /* @__PURE__ */ new Map();
|
|
4427
|
-
for (const run2 of runs) remember_newest_run(run2, newest);
|
|
4428
|
-
return runs.filter((run2) => is_newest_run(run2, newest));
|
|
4429
|
-
}
|
|
4430
|
-
function to_status_context_items(status_json) {
|
|
4431
|
-
const pages = read_pages(status_json, status_page_schema, NOT_A_STATUS_LISTING);
|
|
4432
|
-
return pages.flatMap((page) => page.statuses).map((status) => ({ ...status, [TYPE_NAME_KEY]: STATUS_CONTEXT_TYPE_NAME }));
|
|
4433
|
-
}
|
|
4434
|
-
function to_status_check_rollup(input) {
|
|
4435
|
-
return [
|
|
4436
|
-
...to_check_run_items(input.check_runs_json),
|
|
4437
|
-
...to_status_context_items(input.status_json)
|
|
4438
|
-
];
|
|
4439
|
-
}
|
|
4440
|
-
var git_gh_pr_rollup = {
|
|
4441
|
-
to_status_check_rollup
|
|
4442
|
-
};
|
|
4443
|
-
|
|
4444
|
-
// scripts/gh/git-gh-pr-snapshot.ts
|
|
4445
|
-
var NO_HEAD_SHA_MESSAGE = "gh api answered a pull request with no head commit";
|
|
4446
|
-
async function read_object_pages(path10) {
|
|
4447
|
-
return await git_gh_exec.exec_gh_api({
|
|
4448
|
-
path: `${path10}${FULL_PAGE_QUERY}`,
|
|
4449
|
-
should_paginate: true,
|
|
4450
|
-
should_slurp: true
|
|
4451
|
-
});
|
|
4452
|
-
}
|
|
4453
|
-
async function read_array_pages(path10) {
|
|
4454
|
-
return await git_gh_exec.exec_gh_api({
|
|
4455
|
-
path: `${path10}${FULL_PAGE_QUERY}`,
|
|
4456
|
-
should_paginate: true
|
|
4457
|
-
});
|
|
4458
|
-
}
|
|
4459
|
-
function read_head_sha(pull) {
|
|
4460
|
-
const sha = pull.head?.sha;
|
|
4461
|
-
if (sha === void 0) throw new Error(NO_HEAD_SHA_MESSAGE);
|
|
4462
|
-
return sha;
|
|
4463
|
-
}
|
|
4464
|
-
async function read_status_check_rollup(commit_sha) {
|
|
4465
|
-
const [check_runs_json, status_json] = await Promise.all([
|
|
4466
|
-
read_object_pages(git_gh_api_path.commit_check_runs_api_path(commit_sha)),
|
|
4467
|
-
read_object_pages(git_gh_api_path.commit_status_api_path(commit_sha))
|
|
4468
|
-
]);
|
|
4469
|
-
return git_gh_pr_rollup.to_status_check_rollup({ check_runs_json, status_json });
|
|
4470
|
-
}
|
|
4471
|
-
async function pr_get_review_decision(pr_number) {
|
|
4472
|
-
const path10 = git_gh_api_path.pull_reviews_api_path(String(pr_number));
|
|
4473
|
-
return git_gh_pr_review.to_review_decision(await read_array_pages(path10));
|
|
4474
|
-
}
|
|
4475
|
-
async function build_checks_fields(pull) {
|
|
4476
|
-
return {
|
|
4477
|
-
statusCheckRollup: await read_status_check_rollup(read_head_sha(pull)),
|
|
4478
|
-
mergeStateStatus: to_gh_state(pull.mergeable_state)
|
|
4479
|
-
};
|
|
4480
|
-
}
|
|
4481
|
-
async function resolve_pull(branch_name) {
|
|
4482
|
-
const pr_number = await require_pr_number(branch_name);
|
|
4483
|
-
return { pr_number, pull: await read_pull(pr_number) };
|
|
4484
|
-
}
|
|
4485
|
-
async function pr_get_checks_snapshot(branch_name) {
|
|
4486
|
-
const { pr_number, pull } = await resolve_pull(branch_name);
|
|
4487
|
-
return { pr_number, snapshot_json: JSON.stringify(await build_checks_fields(pull)) };
|
|
4488
|
-
}
|
|
4489
|
-
async function pr_get_state_snapshot(branch_name) {
|
|
4490
|
-
const { pr_number, pull } = await resolve_pull(branch_name);
|
|
4491
|
-
const [fields, review_decision] = await Promise.all([
|
|
4492
|
-
build_checks_fields(pull),
|
|
4493
|
-
pr_get_review_decision(pr_number)
|
|
4494
|
-
]);
|
|
4495
|
-
return JSON.stringify({ ...fields, reviewDecision: review_decision });
|
|
4496
|
-
}
|
|
4497
|
-
var git_gh_pr_snapshot = {
|
|
4498
|
-
pr_get_state_snapshot,
|
|
4499
|
-
pr_get_checks_snapshot,
|
|
4500
|
-
pr_get_review_decision
|
|
4501
|
-
};
|
|
4502
|
-
|
|
4503
|
-
// scripts/gh/git-gh-pr.ts
|
|
4504
|
-
var HTML_URL_FILTER2 = ".html_url";
|
|
4505
|
-
var PUT_METHOD = "PUT";
|
|
4506
|
-
var PATCH_METHOD2 = "PATCH";
|
|
4507
|
-
var MERGE_COMMIT_METHOD = "merge";
|
|
4508
|
-
var MERGE_REQUEST_TIMEOUT_MS = 18e4;
|
|
4509
|
-
var MERGE_UNCONFIRMED_MESSAGE = "gh api could not read the pull request back after the merge request failed";
|
|
4510
|
-
var MERGE_READ_BACK_ATTEMPTS = 3;
|
|
4511
|
-
var MERGE_READ_BACK_INTERVAL_MS = 1e3;
|
|
4512
|
-
var PR_NUMBER_PATTERN = /\/pull\/([1-9]\d*)$/u;
|
|
4513
|
-
var LABELS_SEGMENT2 = "/labels";
|
|
4514
|
-
var PR_LABELS = z14.array(z14.object({ name: z14.string() }));
|
|
4515
|
-
async function add_pr_classification(number, label) {
|
|
4516
|
-
await git_gh_exec.exec_gh_api({
|
|
4517
|
-
path: `${git_gh_api_path.issue_api_path(number)}${LABELS_SEGMENT2}`,
|
|
4518
|
-
body: JSON.stringify({ labels: [label] })
|
|
4519
|
-
});
|
|
4520
|
-
}
|
|
4521
|
-
async function pr_get_classification(branch_name) {
|
|
4522
|
-
const number = await require_pr_number(branch_name);
|
|
4523
|
-
const response = await git_gh_exec.exec_gh_api({
|
|
4524
|
-
path: `${git_gh_api_path.issue_api_path(String(number))}${LABELS_SEGMENT2}`
|
|
4525
|
-
});
|
|
4526
|
-
const names = PR_LABELS.parse(JSON.parse(response)).map((label) => label.name.toLowerCase());
|
|
4527
|
-
const selected = names.filter((name) => pr_classification.is_classification(name));
|
|
4528
|
-
if (selected.length === 0) return void 0;
|
|
4529
|
-
const error = pr_classification.classification_error(names, "human");
|
|
4530
|
-
if (error !== void 0) throw new Error(error);
|
|
4531
|
-
return selected[0];
|
|
4532
|
-
}
|
|
4533
|
-
async function pr_ensure_classification(branch_name, label) {
|
|
4534
|
-
if (await pr_get_classification(branch_name) !== void 0) return;
|
|
4535
|
-
const number = await require_pr_number(branch_name);
|
|
4536
|
-
await add_pr_classification(String(number), label);
|
|
4537
|
-
}
|
|
4538
|
-
async function post_pull_request(title, body) {
|
|
4539
|
-
const base = await git_command.get_default_branch();
|
|
4540
|
-
const head = await git_command.branch();
|
|
4541
|
-
forget_pr_numbers();
|
|
4542
|
-
try {
|
|
4543
|
-
return await git_gh_exec.exec_gh_api({
|
|
4544
|
-
path: git_gh_api_path.pulls_api_path(),
|
|
4545
|
-
body: JSON.stringify({ title, body, head, base }),
|
|
4546
|
-
jq_filter: HTML_URL_FILTER2
|
|
4547
|
-
});
|
|
4548
|
-
} catch (error) {
|
|
4549
|
-
return git_gh_helpers.handle_pr_create_error(error);
|
|
4550
|
-
}
|
|
4551
|
-
}
|
|
4552
|
-
async function pr_create(title, body, label) {
|
|
4553
|
-
const classification_error2 = pr_classification.classification_error([label], "human");
|
|
4554
|
-
if (classification_error2 !== void 0) throw new Error(classification_error2);
|
|
4555
|
-
const url = await post_pull_request(title, body);
|
|
4556
|
-
const number = PR_NUMBER_PATTERN.exec(url)?.[1];
|
|
4557
|
-
if (number === void 0) throw new Error(`Could not identify the created pull request: ${url}`);
|
|
4558
|
-
await add_pr_classification(number, label);
|
|
4559
|
-
return url;
|
|
4560
|
-
}
|
|
4561
|
-
async function pr_comment(branch_name, body) {
|
|
4562
|
-
const pr_number = await require_pr_number(branch_name);
|
|
4563
|
-
return await git_gh_issue_write.issue_comment(String(pr_number), body);
|
|
4564
|
-
}
|
|
4565
|
-
async function pr_update_body(branch_name, body) {
|
|
4566
|
-
const pr_number = await require_pr_number(branch_name);
|
|
4567
|
-
await git_gh_exec.exec_gh_api({
|
|
4568
|
-
path: git_gh_api_path.pull_api_path(String(pr_number)),
|
|
4569
|
-
method: PATCH_METHOD2,
|
|
4570
|
-
body: JSON.stringify({ body })
|
|
4571
|
-
});
|
|
4572
|
-
}
|
|
4573
|
-
async function put_merge(pr_number) {
|
|
4574
|
-
await git_gh_exec.exec_gh_api({
|
|
4575
|
-
path: git_gh_api_path.pull_merge_api_path(String(pr_number)),
|
|
4576
|
-
method: PUT_METHOD,
|
|
4577
|
-
body: JSON.stringify({ merge_method: MERGE_COMMIT_METHOD }),
|
|
4578
|
-
timeout_ms: MERGE_REQUEST_TIMEOUT_MS
|
|
4579
|
-
});
|
|
4580
|
-
}
|
|
4581
|
-
async function read_merge_state(pr_number) {
|
|
4582
|
-
try {
|
|
4583
|
-
return git_gh_pr_rest.is_merged(await read_pull(pr_number));
|
|
4584
|
-
} catch (error) {
|
|
4585
|
-
console.warn(`Could not read the pull request back: ${String(error)}`);
|
|
4586
|
-
return void 0;
|
|
4587
|
-
}
|
|
4588
|
-
}
|
|
4589
|
-
async function sleep_between_read_backs(attempt) {
|
|
4590
|
-
if (attempt < MERGE_READ_BACK_ATTEMPTS - 1) await poll.sleep(MERGE_READ_BACK_INTERVAL_MS);
|
|
4591
|
-
}
|
|
4592
|
-
async function has_merge_landed(pr_number, merge_error) {
|
|
4593
|
-
for (let attempt = 0; attempt < MERGE_READ_BACK_ATTEMPTS; attempt += 1) {
|
|
4594
|
-
const is_merged2 = await read_merge_state(pr_number);
|
|
4595
|
-
if (is_merged2 !== void 0) return is_merged2;
|
|
4596
|
-
await sleep_between_read_backs(attempt);
|
|
4597
|
-
}
|
|
4598
|
-
throw new Error(MERGE_UNCONFIRMED_MESSAGE, { cause: merge_error });
|
|
4599
|
-
}
|
|
4600
|
-
async function pr_merge(branch_name) {
|
|
4601
|
-
const pr_number = await require_pr_number(branch_name);
|
|
4602
|
-
try {
|
|
4603
|
-
await put_merge(pr_number);
|
|
4604
|
-
} catch (error) {
|
|
4605
|
-
if (!await has_merge_landed(pr_number, error)) throw error;
|
|
4606
|
-
}
|
|
4607
|
-
}
|
|
4608
|
-
var git_gh_pr = {
|
|
4609
|
-
...git_gh_pr_read,
|
|
4610
|
-
...git_gh_pr_snapshot,
|
|
4611
|
-
pr_create,
|
|
4612
|
-
pr_get_classification,
|
|
4613
|
-
pr_ensure_classification,
|
|
4614
|
-
pr_comment,
|
|
4615
|
-
pr_merge,
|
|
4616
|
-
pr_update_body
|
|
4617
|
-
};
|
|
4618
|
-
|
|
4619
|
-
// scripts/gh/git-gh-pr-auto-merge.ts
|
|
4620
|
-
var GRAPHQL_PATH = "graphql";
|
|
4621
|
-
var OPEN_PULLS_QUERY = `${git_gh_api_path.FULL_PAGE_QUERY}&state=open`;
|
|
4622
|
-
var MISSING_NODE_ID_MESSAGE = "gh api answered a pull request without a node_id";
|
|
4623
|
-
var ENABLE_AUTO_MERGE_MUTATION = "mutation($id: ID!) { enablePullRequestAutoMerge(input: { pullRequestId: $id, mergeMethod: MERGE }) { clientMutationId } }";
|
|
4624
|
-
async function pr_enable_auto_merge(branch_name) {
|
|
4625
|
-
const pull = await read_pull(await require_pr_number(branch_name));
|
|
4626
|
-
if (pull.node_id === void 0) throw new Error(MISSING_NODE_ID_MESSAGE);
|
|
4627
|
-
await git_gh_exec.exec_gh_api({
|
|
4628
|
-
path: GRAPHQL_PATH,
|
|
4629
|
-
body: JSON.stringify({ query: ENABLE_AUTO_MERGE_MUTATION, variables: { id: pull.node_id } })
|
|
4630
|
-
});
|
|
4631
|
-
}
|
|
4632
|
-
async function pr_is_merged(branch_name) {
|
|
4633
|
-
try {
|
|
4634
|
-
return git_gh_pr_rest.is_merged(await read_pull(await require_pr_number(branch_name)));
|
|
4635
|
-
} catch {
|
|
4636
|
-
return false;
|
|
4637
|
-
}
|
|
4638
|
-
}
|
|
4639
|
-
function head_reference_of(pull) {
|
|
4640
|
-
return pull.head?.ref ?? "";
|
|
4641
|
-
}
|
|
4642
|
-
function has_head_prefix(pull, prefix) {
|
|
4643
|
-
return git_gh_pr_rest.is_same_repository_head(pull) && head_reference_of(pull).startsWith(prefix);
|
|
4644
|
-
}
|
|
4645
|
-
function to_open_pull(pull) {
|
|
4646
|
-
return {
|
|
4647
|
-
number: pull.number,
|
|
4648
|
-
head_ref: head_reference_of(pull),
|
|
4649
|
-
has_auto_merge: pull.auto_merge !== null && pull.auto_merge !== void 0
|
|
4650
|
-
};
|
|
4651
|
-
}
|
|
4652
|
-
async function pr_list_open_with_head_prefix(prefix) {
|
|
4653
|
-
const json = await git_gh_exec.exec_gh_api({
|
|
4654
|
-
path: `${git_gh_api_path.pulls_api_path()}${OPEN_PULLS_QUERY}`,
|
|
4655
|
-
should_paginate: true
|
|
4656
|
-
});
|
|
4657
|
-
return git_gh_pr_rest.parse_rest_pulls(json).filter((pull) => has_head_prefix(pull, prefix)).map((pull) => to_open_pull(pull));
|
|
4658
|
-
}
|
|
4659
|
-
var git_gh_pr_auto_merge = {
|
|
4660
|
-
pr_enable_auto_merge,
|
|
4661
|
-
pr_is_merged,
|
|
4662
|
-
pr_list_open_with_head_prefix
|
|
4663
|
-
};
|
|
4664
|
-
|
|
4665
|
-
// scripts/gh/git-gh-repo.ts
|
|
4666
|
-
async function repo_get_name_with_owner() {
|
|
4667
|
-
try {
|
|
4668
|
-
const result = await git_gh_exec.exec_gh_api({
|
|
4669
|
-
path: git_gh_api_path.repo_api_path(),
|
|
4670
|
-
jq_filter: ".full_name"
|
|
4671
|
-
});
|
|
4672
|
-
return git_gh_helpers.parse_pr_state_string(result);
|
|
4673
|
-
} catch {
|
|
4674
|
-
return void 0;
|
|
4675
|
-
}
|
|
4676
|
-
}
|
|
4677
|
-
var git_gh_repo = {
|
|
4678
|
-
repo_get_name_with_owner
|
|
4679
|
-
};
|
|
4680
|
-
|
|
4681
|
-
// scripts/gh/git-pr-checks-parse.ts
|
|
4682
|
-
var CHECK_STATUS_PASS = "pass";
|
|
4683
|
-
var CHECK_STATUS_PENDING = "pending";
|
|
4684
|
-
var CHECK_STATUS_FAIL = "fail";
|
|
4685
|
-
var CHECK_STATUS_MISSING = "missing";
|
|
4686
|
-
var PASSING_CONCLUSIONS = /* @__PURE__ */ new Set(["success", "skipped", "neutral"]);
|
|
4687
|
-
var KEY_TYPE_NAME = "__typename";
|
|
4688
|
-
var KEY_STATE = "state";
|
|
4689
|
-
var KEY_STATUS = "status";
|
|
4690
|
-
var KEY_CONCLUSION = "conclusion";
|
|
4691
|
-
var KEY_NAME = "name";
|
|
4692
|
-
var KEY_CONTEXT = "context";
|
|
4693
|
-
function read_string(value) {
|
|
4694
|
-
if (typeof value !== "string") return void 0;
|
|
4695
|
-
const trimmed = value.trim();
|
|
4696
|
-
if (trimmed.length === 0) return void 0;
|
|
4697
|
-
return trimmed;
|
|
4698
|
-
}
|
|
4699
|
-
var PENDING_STATUS_STATES = /* @__PURE__ */ new Set(["pending", "expected"]);
|
|
4700
|
-
function parse_status_context(item) {
|
|
4701
|
-
const state = read_string(item[KEY_STATE])?.toLowerCase();
|
|
4702
|
-
if (state === "success") return CHECK_STATUS_PASS;
|
|
4703
|
-
if (state !== void 0 && PENDING_STATUS_STATES.has(state)) return CHECK_STATUS_PENDING;
|
|
4704
|
-
return CHECK_STATUS_FAIL;
|
|
4705
|
-
}
|
|
4706
|
-
function is_passing_conclusion(item) {
|
|
4707
|
-
const conclusion = read_string(item[KEY_CONCLUSION])?.toLowerCase();
|
|
4708
|
-
return conclusion !== void 0 && PASSING_CONCLUSIONS.has(conclusion);
|
|
4709
|
-
}
|
|
4710
|
-
function parse_check_run(item) {
|
|
4711
|
-
const status = read_string(item[KEY_STATUS])?.toLowerCase();
|
|
4712
|
-
if (status !== "completed") return CHECK_STATUS_PENDING;
|
|
4713
|
-
return is_passing_conclusion(item) ? CHECK_STATUS_PASS : CHECK_STATUS_FAIL;
|
|
4714
|
-
}
|
|
4715
|
-
function parse_rollup_status(item) {
|
|
4716
|
-
const type_name = read_string(item[KEY_TYPE_NAME]);
|
|
4717
|
-
if (type_name === "StatusContext") return parse_status_context(item);
|
|
4718
|
-
return parse_check_run(item);
|
|
4719
|
-
}
|
|
4720
|
-
function read_rollup_array(parsed) {
|
|
4721
|
-
const result = pr_raw_schema.safeParse(parsed);
|
|
4722
|
-
if (!result.success) return [];
|
|
4723
|
-
return result.data.statusCheckRollup ?? [];
|
|
4724
|
-
}
|
|
4725
|
-
function parse_rollup_item(item) {
|
|
4726
|
-
const name = read_string(item[KEY_NAME]) ?? read_string(item[KEY_CONTEXT]);
|
|
4727
|
-
if (name === void 0) return void 0;
|
|
4728
|
-
return { name, status: parse_rollup_status(item) };
|
|
4729
|
-
}
|
|
4730
|
-
function parse_rollup_checks(raw_json) {
|
|
4731
|
-
const parsed = json_value.parse_or_undefined(raw_json);
|
|
4732
|
-
const rollup = read_rollup_array(parsed);
|
|
4733
|
-
const checks = [];
|
|
4734
|
-
for (const item of rollup) {
|
|
4735
|
-
const parsed_item = parse_rollup_item(item);
|
|
4736
|
-
if (parsed_item !== void 0) checks.push(parsed_item);
|
|
4737
|
-
}
|
|
4738
|
-
return checks;
|
|
4739
|
-
}
|
|
4740
|
-
function parse_pr_state_snapshot(raw_json) {
|
|
4741
|
-
const parsed = json_value.parse_or_undefined(raw_json);
|
|
4742
|
-
const result = pr_raw_schema.safeParse(parsed);
|
|
4743
|
-
const data = result.success ? result.data : void 0;
|
|
4744
|
-
return {
|
|
4745
|
-
rollup: parse_rollup_checks(raw_json),
|
|
4746
|
-
merge_state_status: read_string(data?.mergeStateStatus),
|
|
4747
|
-
review_decision: read_string(data?.reviewDecision)
|
|
4748
|
-
};
|
|
4749
|
-
}
|
|
4750
|
-
|
|
4751
|
-
// scripts/gh/git-pr-checks-eval.ts
|
|
4752
|
-
var DEFAULT_REQUIRED_CHECKS = ["SonarQube"];
|
|
4753
|
-
var CODERABBIT_CHECK_NAME = "CodeRabbit";
|
|
4754
|
-
var REQUIRED_CHECKS_ENV_VAR = "JOSH_REQUIRED_CHECKS";
|
|
4755
|
-
function parse_required_checks() {
|
|
4756
|
-
const raw = process.env[REQUIRED_CHECKS_ENV_VAR];
|
|
4757
|
-
if (!raw) return DEFAULT_REQUIRED_CHECKS;
|
|
4758
|
-
return raw.split(",").map((check4) => check4.trim()).filter((check4) => check4.length > 0);
|
|
4759
|
-
}
|
|
4760
|
-
var REQUIRED_CHECKS = parse_required_checks();
|
|
4761
|
-
var MERGE_STATE_CLEAN = "CLEAN";
|
|
4762
|
-
var MERGE_STATE_UNSTABLE = "UNSTABLE";
|
|
4763
|
-
var MERGE_STATE_DIRTY = "DIRTY";
|
|
4764
|
-
var REVIEW_CHANGES_REQUESTED2 = "CHANGES_REQUESTED";
|
|
4765
|
-
var CHECK_SUITE_SEPARATOR = " / ";
|
|
4766
|
-
var FAILURE_MESSAGE_PREFIX = "PR checks failed";
|
|
4767
|
-
var FAILURE_REASON_REVIEW = "review requested changes";
|
|
4768
|
-
var FAILURE_REASON_CHECKS = "failed checks";
|
|
4769
|
-
var FAILURE_REASON_CONFLICT = "merge conflict";
|
|
4770
|
-
function is_required_match(check_name, required_name) {
|
|
4771
|
-
if (check_name === required_name) return true;
|
|
4772
|
-
return check_name.startsWith(`${required_name}${CHECK_SUITE_SEPARATOR}`);
|
|
4773
|
-
}
|
|
4774
|
-
function find_required_check(checks, required_name) {
|
|
4775
|
-
return checks.find((check4) => is_required_match(check4.name, required_name));
|
|
4776
|
-
}
|
|
4777
|
-
function read_required_statuses(checks) {
|
|
4778
|
-
return REQUIRED_CHECKS.map(
|
|
4779
|
-
(name) => find_required_check(checks, name)?.status ?? CHECK_STATUS_MISSING
|
|
4780
|
-
);
|
|
4781
|
-
}
|
|
4782
|
-
function is_review_blocked(review_decision) {
|
|
4783
|
-
return review_decision === REVIEW_CHANGES_REQUESTED2;
|
|
4784
|
-
}
|
|
4785
|
-
function is_merge_conflict(merge_state_status) {
|
|
4786
|
-
return merge_state_status === MERGE_STATE_DIRTY;
|
|
4787
|
-
}
|
|
4788
|
-
function evaluate_failure_state(input) {
|
|
4789
|
-
if (is_merge_conflict(input.merge_state_status) || is_review_blocked(input.review_decision) || input.failed_checks.length > 0) {
|
|
4790
|
-
return "failure";
|
|
4791
|
-
}
|
|
4792
|
-
return void 0;
|
|
4793
|
-
}
|
|
4794
|
-
function is_merge_state_clean(merge_state_status) {
|
|
4795
|
-
return merge_state_status === MERGE_STATE_CLEAN;
|
|
4796
|
-
}
|
|
4797
|
-
function is_every_required_passing(statuses) {
|
|
4798
|
-
return statuses.every((status) => status === CHECK_STATUS_PASS);
|
|
4799
|
-
}
|
|
4800
|
-
function is_coderabbit_check(check_name) {
|
|
4801
|
-
return is_required_match(check_name, CODERABBIT_CHECK_NAME);
|
|
4802
|
-
}
|
|
4803
|
-
function is_unstable_only_from_coderabbit(snapshot) {
|
|
4804
|
-
if (snapshot.merge_state_status !== MERGE_STATE_UNSTABLE) return false;
|
|
4805
|
-
const non_passing = snapshot.rollup.filter((check4) => check4.status !== CHECK_STATUS_PASS);
|
|
4806
|
-
if (non_passing.length === 0) return false;
|
|
4807
|
-
return non_passing.every((check4) => is_coderabbit_check(check4.name));
|
|
4808
|
-
}
|
|
4809
|
-
function is_required_check(check_name) {
|
|
4810
|
-
return REQUIRED_CHECKS.some((required) => is_required_match(check_name, required));
|
|
4811
|
-
}
|
|
4812
|
-
function is_blocking_failure(check4) {
|
|
4813
|
-
if (check4.status !== CHECK_STATUS_FAIL) return false;
|
|
4814
|
-
return !is_coderabbit_check(check4.name) || is_required_check(check4.name);
|
|
4815
|
-
}
|
|
4816
|
-
function collect_blocking_failures(snapshot) {
|
|
4817
|
-
return snapshot.rollup.filter((check4) => is_blocking_failure(check4)).map((check4) => check4.name);
|
|
4818
|
-
}
|
|
4819
|
-
function is_mergeable_state(snapshot) {
|
|
4820
|
-
if (is_merge_state_clean(snapshot.merge_state_status)) return true;
|
|
4821
|
-
return is_unstable_only_from_coderabbit(snapshot);
|
|
4822
|
-
}
|
|
4823
|
-
function collect_failure_reasons(snapshot) {
|
|
4824
|
-
const reasons = [];
|
|
4825
|
-
if (is_merge_conflict(snapshot.merge_state_status)) reasons.push(FAILURE_REASON_CONFLICT);
|
|
4826
|
-
if (is_review_blocked(snapshot.review_decision)) reasons.push(FAILURE_REASON_REVIEW);
|
|
4827
|
-
const failed = collect_blocking_failures(snapshot);
|
|
4828
|
-
if (failed.length > 0) reasons.push(`${FAILURE_REASON_CHECKS}: ${failed.join(", ")}`);
|
|
4829
|
-
return reasons;
|
|
4830
|
-
}
|
|
4831
|
-
function describe_pr_failure(snapshot) {
|
|
4832
|
-
const reasons = collect_failure_reasons(snapshot);
|
|
4833
|
-
if (reasons.length === 0) return `${FAILURE_MESSAGE_PREFIX}.`;
|
|
4834
|
-
return `${FAILURE_MESSAGE_PREFIX} (${reasons.join("; ")}).`;
|
|
4835
|
-
}
|
|
4836
|
-
function evaluate_pr_state(snapshot) {
|
|
4837
|
-
const statuses = read_required_statuses(snapshot.rollup);
|
|
4838
|
-
const failure = evaluate_failure_state({
|
|
4839
|
-
review_decision: snapshot.review_decision,
|
|
4840
|
-
failed_checks: collect_blocking_failures(snapshot),
|
|
4841
|
-
merge_state_status: snapshot.merge_state_status
|
|
4842
|
-
});
|
|
4843
|
-
if (failure !== void 0) return failure;
|
|
4844
|
-
if (is_mergeable_state(snapshot) && is_every_required_passing(statuses)) {
|
|
4845
|
-
return "success";
|
|
4846
|
-
}
|
|
4847
|
-
return "pending";
|
|
4848
|
-
}
|
|
4849
|
-
function is_review_decision_decisive(snapshot) {
|
|
4850
|
-
return evaluate_pr_state(snapshot) !== "pending";
|
|
4851
|
-
}
|
|
4852
|
-
|
|
4853
|
-
// scripts/gh/git-pr-checks.ts
|
|
4854
|
-
var SECONDS_TO_MS = 1e3;
|
|
4855
|
-
var CHECK_WAIT_INTERVAL_MS = 1e4;
|
|
4856
|
-
var DEFAULT_TIMEOUT_SECONDS = 1920;
|
|
4857
|
-
function compute_max_attempts(timeout_seconds, interval_ms) {
|
|
4858
|
-
return Math.ceil(timeout_seconds / (interval_ms / SECONDS_TO_MS)) + 1;
|
|
4859
|
-
}
|
|
4860
|
-
var DEFAULT_MAX_ATTEMPTS = compute_max_attempts(DEFAULT_TIMEOUT_SECONDS, CHECK_WAIT_INTERVAL_MS);
|
|
4861
|
-
function get_configured_max_attempts() {
|
|
4862
|
-
const environment_seconds = Number(process.env["JOSH_CI_TIMEOUT_SECONDS"]);
|
|
4863
|
-
return Number.isFinite(environment_seconds) && environment_seconds > 0 ? compute_max_attempts(environment_seconds, CHECK_WAIT_INTERVAL_MS) : DEFAULT_MAX_ATTEMPTS;
|
|
4864
|
-
}
|
|
4865
|
-
var CHECK_MAX_ATTEMPTS = get_configured_max_attempts();
|
|
4866
|
-
var DEFAULT_STABLE_READS = 2;
|
|
4867
|
-
var MAX_CONSECUTIVE_READ_FAILURES = 3;
|
|
4868
|
-
var PR_CHECKS_TIMEOUT_MESSAGE = "Timed out while waiting for PR checks to complete.";
|
|
4869
|
-
function is_pr_checks_timeout(error) {
|
|
4870
|
-
return error instanceof Error && error.message === PR_CHECKS_TIMEOUT_MESSAGE;
|
|
4871
|
-
}
|
|
4872
|
-
var SHOULD_ALWAYS_READ_REVIEW_DECISION = () => true;
|
|
4873
|
-
var MERGE_GATE_EVALUATOR = {
|
|
4874
|
-
evaluate: evaluate_pr_state,
|
|
4875
|
-
describe: describe_pr_failure,
|
|
4876
|
-
should_read_review_decision: is_review_decision_decisive
|
|
4877
|
-
};
|
|
4878
|
-
function advance_stable_count(previous, state) {
|
|
4879
|
-
return state === "success" ? previous + 1 : 0;
|
|
4880
|
-
}
|
|
4881
|
-
function classify_poll_result(input) {
|
|
4882
|
-
const state = input.evaluator.evaluate(input.snapshot);
|
|
4883
|
-
if (state === "failure") throw new Error(input.evaluator.describe(input.snapshot));
|
|
4884
|
-
const next_stable_count = advance_stable_count(input.stable_count, state);
|
|
4885
|
-
return {
|
|
4886
|
-
is_done: next_stable_count >= input.required_stable_reads,
|
|
4887
|
-
next_stable_count
|
|
4888
|
-
};
|
|
4889
|
-
}
|
|
4890
|
-
async function read_pr_state(input, evaluator) {
|
|
4891
|
-
try {
|
|
4892
|
-
const snapshot = await input.options.fetcher(
|
|
4893
|
-
input.options.branch_name,
|
|
4894
|
-
evaluator.should_read_review_decision ?? SHOULD_ALWAYS_READ_REVIEW_DECISION
|
|
4895
|
-
);
|
|
4896
|
-
return { kind: "read", snapshot };
|
|
4897
|
-
} catch (error) {
|
|
4898
|
-
return { kind: "unreadable", cause: error };
|
|
4899
|
-
}
|
|
4900
|
-
}
|
|
4901
|
-
async function sleep_before_next_attempt(input) {
|
|
4902
|
-
if (input.attempt < input.options.max_attempts - 1) {
|
|
4903
|
-
await poll.sleep(input.options.interval_ms);
|
|
4904
|
-
}
|
|
4905
|
-
}
|
|
4906
|
-
async function retry_after_unreadable(input, cause) {
|
|
4907
|
-
const next_failure_count = input.failure_count + 1;
|
|
4908
|
-
if (next_failure_count >= MAX_CONSECUTIVE_READ_FAILURES) throw cause;
|
|
4909
|
-
console.warn(
|
|
4910
|
-
`Could not read the PR state (${String(next_failure_count)}/${String(MAX_CONSECUTIVE_READ_FAILURES)}); asking again on the next poll: ${String(cause)}`
|
|
4911
|
-
);
|
|
4912
|
-
await sleep_before_next_attempt(input);
|
|
4913
|
-
return { next_stable_count: 0, next_failure_count, read_failure: cause };
|
|
4914
|
-
}
|
|
4915
|
-
function to_exhaustion_error(last_read_failure) {
|
|
4916
|
-
return last_read_failure ?? new Error(PR_CHECKS_TIMEOUT_MESSAGE);
|
|
4917
|
-
}
|
|
4918
|
-
async function attempt_pr_success_poll(input) {
|
|
4919
|
-
const evaluator = input.options.evaluator ?? MERGE_GATE_EVALUATOR;
|
|
4920
|
-
const read2 = await read_pr_state(input, evaluator);
|
|
4921
|
-
if (read2.kind === "unreadable") return await retry_after_unreadable(input, read2.cause);
|
|
4922
|
-
const classification = classify_poll_result({
|
|
4923
|
-
snapshot: read2.snapshot,
|
|
4924
|
-
stable_count: input.stable_count,
|
|
4925
|
-
required_stable_reads: input.options.required_stable_reads,
|
|
4926
|
-
evaluator
|
|
4927
|
-
});
|
|
4928
|
-
if (classification.is_done) {
|
|
4929
|
-
return { snapshot: read2.snapshot, next_stable_count: 0, next_failure_count: 0 };
|
|
4930
|
-
}
|
|
4931
|
-
await sleep_before_next_attempt(input);
|
|
4932
|
-
return { next_stable_count: classification.next_stable_count, next_failure_count: 0 };
|
|
4933
|
-
}
|
|
4934
|
-
async function wait_for_pr_success(options) {
|
|
4935
|
-
let carried = { next_stable_count: 0, next_failure_count: 0 };
|
|
4936
|
-
for (let attempt = 0; attempt < options.max_attempts; attempt += 1) {
|
|
4937
|
-
console.info(`Checking PR status\u2026 (${String(attempt + 1)}/${String(options.max_attempts)})`);
|
|
4938
|
-
carried = await attempt_pr_success_poll({
|
|
4939
|
-
options,
|
|
4940
|
-
stable_count: carried.next_stable_count,
|
|
4941
|
-
failure_count: carried.next_failure_count,
|
|
4942
|
-
attempt
|
|
4943
|
-
});
|
|
4944
|
-
if (carried.snapshot !== void 0) return carried.snapshot;
|
|
4945
|
-
}
|
|
4946
|
-
throw to_exhaustion_error(carried.read_failure);
|
|
4947
|
-
}
|
|
4948
|
-
async function default_fetch_pr_state(branch_name, should_read_review_decision = SHOULD_ALWAYS_READ_REVIEW_DECISION) {
|
|
4949
|
-
const checks = await git_gh_pr_snapshot.pr_get_checks_snapshot(branch_name);
|
|
4950
|
-
const snapshot = parse_pr_state_snapshot(checks.snapshot_json);
|
|
4951
|
-
if (!should_read_review_decision(snapshot)) return snapshot;
|
|
4952
|
-
const decision = await git_gh_pr_snapshot.pr_get_review_decision(checks.pr_number);
|
|
4953
|
-
return { ...snapshot, review_decision: read_string(decision) };
|
|
4954
|
-
}
|
|
4955
|
-
|
|
4956
|
-
// scripts/gh/git-pr-checks-watch.ts
|
|
4957
|
-
var PR_CHECKS_WATCH_TIMEOUT_MS = 12e4;
|
|
4958
|
-
var WATCH_TIMED_OUT_NOTE = "\u23F1\uFE0F pr checks --watch timed out.";
|
|
4959
|
-
var NO_CHECKS_MESSAGE = "gh api reported no checks on the branch";
|
|
4960
|
-
var CHECKS_FAILED_MESSAGE = "gh api reported a failing check on the branch";
|
|
4961
|
-
function is_awaited_check(check4) {
|
|
4962
|
-
return !is_coderabbit_check(check4.name) || is_required_check(check4.name);
|
|
4963
|
-
}
|
|
4964
|
-
function evaluate_checks_settled(snapshot) {
|
|
4965
|
-
const awaited = snapshot.rollup.filter((check4) => is_awaited_check(check4));
|
|
4966
|
-
const considered = awaited.length === 0 ? snapshot.rollup : awaited;
|
|
4967
|
-
if (considered.length === 0 || considered.some((check4) => check4.status === CHECK_STATUS_PENDING)) {
|
|
4968
|
-
return "pending";
|
|
4969
|
-
}
|
|
4970
|
-
return snapshot.rollup.some((check4) => check4.status === CHECK_STATUS_FAIL) ? "failure" : "success";
|
|
4971
|
-
}
|
|
4972
|
-
function describe_checks_failure(snapshot) {
|
|
4973
|
-
const failed = snapshot.rollup.filter((check4) => check4.status === CHECK_STATUS_FAIL);
|
|
4974
|
-
return `${CHECKS_FAILED_MESSAGE}: ${failed.map((check4) => check4.name).join(", ")}`;
|
|
4975
|
-
}
|
|
4976
|
-
var SHOULD_NEVER_READ_REVIEW_DECISION = () => false;
|
|
4977
|
-
var CHECKS_SETTLED_EVALUATOR = {
|
|
4978
|
-
evaluate: evaluate_checks_settled,
|
|
4979
|
-
describe: describe_checks_failure,
|
|
4980
|
-
should_read_review_decision: SHOULD_NEVER_READ_REVIEW_DECISION
|
|
4981
|
-
};
|
|
4982
|
-
async function watch_until_settled(branch_name) {
|
|
4983
|
-
await wait_for_pr_success({
|
|
4984
|
-
branch_name,
|
|
4985
|
-
fetcher: default_fetch_pr_state,
|
|
4986
|
-
interval_ms: CHECK_WAIT_INTERVAL_MS,
|
|
4987
|
-
max_attempts: compute_max_attempts(
|
|
4988
|
-
PR_CHECKS_WATCH_TIMEOUT_MS / SECONDS_TO_MS,
|
|
4989
|
-
CHECK_WAIT_INTERVAL_MS
|
|
4990
|
-
),
|
|
4991
|
-
required_stable_reads: DEFAULT_STABLE_READS,
|
|
4992
|
-
evaluator: CHECKS_SETTLED_EVALUATOR
|
|
4993
|
-
});
|
|
4994
|
-
}
|
|
4995
|
-
async function fail_when_no_checks(branch_name) {
|
|
4996
|
-
const snapshot = await default_fetch_pr_state(branch_name, SHOULD_NEVER_READ_REVIEW_DECISION);
|
|
4997
|
-
if (snapshot.rollup.length === 0) throw new Error(NO_CHECKS_MESSAGE);
|
|
4998
|
-
}
|
|
4999
|
-
async function pr_checks_watch(branch_name) {
|
|
5000
|
-
try {
|
|
5001
|
-
await watch_until_settled(branch_name);
|
|
5002
|
-
return { timed_out: false };
|
|
5003
|
-
} catch (error) {
|
|
5004
|
-
if (!is_pr_checks_timeout(error)) throw error;
|
|
5005
|
-
await fail_when_no_checks(branch_name);
|
|
5006
|
-
console.info(WATCH_TIMED_OUT_NOTE);
|
|
5007
|
-
return { timed_out: true };
|
|
5008
|
-
}
|
|
5009
|
-
}
|
|
5010
|
-
var git_pr_checks_watch = { pr_checks_watch };
|
|
5011
|
-
|
|
5012
|
-
// scripts/gh/git-gh-command.ts
|
|
5013
|
-
var git_gh_command = {
|
|
5014
|
-
...git_gh_pr,
|
|
5015
|
-
...git_gh_pr_auto_merge,
|
|
5016
|
-
pr_checks_watch: git_pr_checks_watch.pr_checks_watch,
|
|
5017
|
-
...git_gh_issue,
|
|
5018
|
-
...git_gh_repo
|
|
5019
|
-
};
|
|
5020
|
-
|
|
5021
3325
|
// scripts/epic/epic-busy.ts
|
|
5022
3326
|
var LISTING_LIMIT = 100;
|
|
5023
3327
|
var PARKED_LABELS = /* @__PURE__ */ new Set([NEEDS_DECISION_LABEL, ALREADY_DONE_LABEL]);
|
|
@@ -5080,30 +3384,30 @@ var epic_busy = {
|
|
|
5080
3384
|
};
|
|
5081
3385
|
|
|
5082
3386
|
// scripts/run/run-liveness.ts
|
|
5083
|
-
import { readFileSync as
|
|
3387
|
+
import { readFileSync as readFileSync5, realpathSync, statSync } from "node:fs";
|
|
5084
3388
|
import { homedir, tmpdir } from "node:os";
|
|
5085
3389
|
import path8 from "node:path";
|
|
5086
|
-
import { setTimeout as
|
|
3390
|
+
import { setTimeout as sleep } from "node:timers/promises";
|
|
5087
3391
|
|
|
5088
3392
|
// scripts/agent/agent-event.ts
|
|
5089
|
-
import { z as
|
|
3393
|
+
import { z as z9 } from "zod";
|
|
5090
3394
|
|
|
5091
3395
|
// scripts/agent/claude-result-event.ts
|
|
5092
|
-
import { z as
|
|
5093
|
-
var RESULT_EVENT_SCHEMA =
|
|
5094
|
-
type:
|
|
5095
|
-
is_error:
|
|
5096
|
-
subtype:
|
|
5097
|
-
num_turns:
|
|
5098
|
-
permission_denials:
|
|
5099
|
-
result:
|
|
5100
|
-
session_id:
|
|
5101
|
-
usage:
|
|
3396
|
+
import { z as z8 } from "zod";
|
|
3397
|
+
var RESULT_EVENT_SCHEMA = z8.looseObject({
|
|
3398
|
+
type: z8.literal("result"),
|
|
3399
|
+
is_error: z8.unknown().optional(),
|
|
3400
|
+
subtype: z8.unknown().optional(),
|
|
3401
|
+
num_turns: z8.unknown().optional(),
|
|
3402
|
+
permission_denials: z8.unknown().optional(),
|
|
3403
|
+
result: z8.unknown().optional(),
|
|
3404
|
+
session_id: z8.unknown().optional(),
|
|
3405
|
+
usage: z8.unknown().optional()
|
|
5102
3406
|
});
|
|
5103
|
-
var USAGE_SCHEMA =
|
|
5104
|
-
input_tokens:
|
|
5105
|
-
cache_read_input_tokens:
|
|
5106
|
-
output_tokens:
|
|
3407
|
+
var USAGE_SCHEMA = z8.looseObject({
|
|
3408
|
+
input_tokens: z8.unknown().optional(),
|
|
3409
|
+
cache_read_input_tokens: z8.unknown().optional(),
|
|
3410
|
+
output_tokens: z8.unknown().optional()
|
|
5107
3411
|
});
|
|
5108
3412
|
function usable_reason(value) {
|
|
5109
3413
|
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
@@ -5142,31 +3446,31 @@ function decode(value) {
|
|
|
5142
3446
|
var claude_result_event = { decode };
|
|
5143
3447
|
|
|
5144
3448
|
// scripts/agent/agent-event.ts
|
|
5145
|
-
var TEXT_BLOCK_SCHEMA =
|
|
5146
|
-
var CLAUDE_MESSAGE_SCHEMA =
|
|
5147
|
-
var CLAUDE_INIT_SCHEMA =
|
|
5148
|
-
var CLAUDE_ASSISTANT_SCHEMA =
|
|
5149
|
-
type:
|
|
3449
|
+
var TEXT_BLOCK_SCHEMA = z9.looseObject({ type: z9.literal("text"), text: z9.string() });
|
|
3450
|
+
var CLAUDE_MESSAGE_SCHEMA = z9.looseObject({ content: z9.array(z9.unknown()).optional() });
|
|
3451
|
+
var CLAUDE_INIT_SCHEMA = z9.looseObject({ type: z9.literal("system"), subtype: z9.literal("init") });
|
|
3452
|
+
var CLAUDE_ASSISTANT_SCHEMA = z9.looseObject({
|
|
3453
|
+
type: z9.literal("assistant"),
|
|
5150
3454
|
message: CLAUDE_MESSAGE_SCHEMA
|
|
5151
3455
|
});
|
|
5152
|
-
var USAGE_SCHEMA2 =
|
|
5153
|
-
input_tokens:
|
|
5154
|
-
cached_input_tokens:
|
|
5155
|
-
output_tokens:
|
|
3456
|
+
var USAGE_SCHEMA2 = z9.looseObject({
|
|
3457
|
+
input_tokens: z9.number().optional(),
|
|
3458
|
+
cached_input_tokens: z9.number().optional(),
|
|
3459
|
+
output_tokens: z9.number().optional()
|
|
5156
3460
|
});
|
|
5157
|
-
var CODEX_START_SCHEMA =
|
|
5158
|
-
var CODEX_PROGRESS_SCHEMA =
|
|
5159
|
-
type:
|
|
5160
|
-
item:
|
|
3461
|
+
var CODEX_START_SCHEMA = z9.looseObject({ type: z9.enum(["thread.started", "turn.started"]) });
|
|
3462
|
+
var CODEX_PROGRESS_SCHEMA = z9.looseObject({
|
|
3463
|
+
type: z9.enum(["item.started", "item.updated", "item.completed"]),
|
|
3464
|
+
item: z9.looseObject({ type: z9.string(), text: z9.string().optional() }).optional()
|
|
5161
3465
|
});
|
|
5162
|
-
var CODEX_COMPLETE_SCHEMA =
|
|
5163
|
-
type:
|
|
3466
|
+
var CODEX_COMPLETE_SCHEMA = z9.looseObject({
|
|
3467
|
+
type: z9.literal("turn.completed"),
|
|
5164
3468
|
usage: USAGE_SCHEMA2.optional()
|
|
5165
3469
|
});
|
|
5166
|
-
var CODEX_FAILURE_SCHEMA =
|
|
5167
|
-
type:
|
|
5168
|
-
error:
|
|
5169
|
-
message:
|
|
3470
|
+
var CODEX_FAILURE_SCHEMA = z9.looseObject({
|
|
3471
|
+
type: z9.enum(["turn.failed", "error"]),
|
|
3472
|
+
error: z9.looseObject({ message: z9.string().optional() }).optional(),
|
|
3473
|
+
message: z9.string().optional()
|
|
5170
3474
|
});
|
|
5171
3475
|
var EMPTY_STATE = {
|
|
5172
3476
|
provider: void 0,
|
|
@@ -5257,7 +3561,7 @@ function describe(state) {
|
|
|
5257
3561
|
var agent_event = { describe, read };
|
|
5258
3562
|
|
|
5259
3563
|
// scripts/issue/issue-state.ts
|
|
5260
|
-
import { z as
|
|
3564
|
+
import { z as z10 } from "zod";
|
|
5261
3565
|
var NO_LABELS = "(none)";
|
|
5262
3566
|
var LABEL_SEPARATOR = ", ";
|
|
5263
3567
|
var STATE_LABEL = "state: ";
|
|
@@ -5267,9 +3571,9 @@ var YES = "yes";
|
|
|
5267
3571
|
var NO = "no";
|
|
5268
3572
|
var ISSUE_LABEL = "issue: ";
|
|
5269
3573
|
var HUMAN_REVIEW_LABELS = /* @__PURE__ */ new Set([NEEDS_HUMAN_REVIEW_LABEL]);
|
|
5270
|
-
var label_schema =
|
|
5271
|
-
var issue_state_schema =
|
|
5272
|
-
state:
|
|
3574
|
+
var label_schema = z10.looseObject({ name: z10.string() });
|
|
3575
|
+
var issue_state_schema = z10.looseObject({
|
|
3576
|
+
state: z10.string(),
|
|
5273
3577
|
labels: label_schema.array().optional()
|
|
5274
3578
|
});
|
|
5275
3579
|
function parse_issue_state(json) {
|
|
@@ -5317,7 +3621,7 @@ var DEFAULT_SILENT_MINUTES = 30;
|
|
|
5317
3621
|
var DEFAULT_GAP_SECONDS = 5;
|
|
5318
3622
|
var MS_PER_MINUTE3 = 6e4;
|
|
5319
3623
|
var MS_PER_SECOND2 = 1e3;
|
|
5320
|
-
var
|
|
3624
|
+
var OPEN_STATE2 = "OPEN";
|
|
5321
3625
|
var STATE_FIELDS = "state,labels";
|
|
5322
3626
|
var REASONS = {
|
|
5323
3627
|
[ALIVE_VERDICT]: "The unit is still working: its output moved, or a process of the child is alive.",
|
|
@@ -5405,7 +3709,7 @@ function read_agent_state(output_path) {
|
|
|
5405
3709
|
const safe_path = to_safe_path(output_path);
|
|
5406
3710
|
if (safe_path === void 0) return void 0;
|
|
5407
3711
|
try {
|
|
5408
|
-
const state = agent_event.read(
|
|
3712
|
+
const state = agent_event.read(readFileSync5(safe_path, "utf8"));
|
|
5409
3713
|
return state.provider === void 0 ? void 0 : state;
|
|
5410
3714
|
} catch {
|
|
5411
3715
|
return void 0;
|
|
@@ -5419,7 +3723,7 @@ async function read_output_frozen(request) {
|
|
|
5419
3723
|
const first = sample_output(request.output_path);
|
|
5420
3724
|
if (first === void 0) return void 0;
|
|
5421
3725
|
if (request.now_ms - first.mtime_ms < request.silent_window_ms) return false;
|
|
5422
|
-
await
|
|
3726
|
+
await sleep(request.gap_ms);
|
|
5423
3727
|
const second = sample_output(request.output_path);
|
|
5424
3728
|
if (second === void 0) return void 0;
|
|
5425
3729
|
return second.mtime_ms === first.mtime_ms && second.size === first.size;
|
|
@@ -5436,7 +3740,7 @@ async function read_child_settled(issue, repo) {
|
|
|
5436
3740
|
if (json === void 0) return void 0;
|
|
5437
3741
|
const state = issue_state.parse_issue_state(json);
|
|
5438
3742
|
if (state === void 0) return void 0;
|
|
5439
|
-
return state.state !==
|
|
3743
|
+
return state.state !== OPEN_STATE2 || carries_settled_label(state.labels);
|
|
5440
3744
|
}
|
|
5441
3745
|
async function read_traces(request) {
|
|
5442
3746
|
const [is_initial_child_settled, is_output_frozen, is_tree_dirty] = await Promise.all([
|
|
@@ -5476,14 +3780,14 @@ var run_liveness = {
|
|
|
5476
3780
|
|
|
5477
3781
|
// scripts/lane/lane-report.ts
|
|
5478
3782
|
var NO_LANES2 = "No lanes are open.";
|
|
5479
|
-
var
|
|
3783
|
+
var OPEN_STATE3 = "open";
|
|
5480
3784
|
var STRANDED_STATE = "stranded";
|
|
5481
3785
|
var UNREADABLE_STATE = "unreadable";
|
|
5482
3786
|
var UNKNOWN_VALUE = "-";
|
|
5483
3787
|
var COLUMN_SEPARATOR = " ";
|
|
5484
3788
|
function lane_state(lane) {
|
|
5485
3789
|
if (lane.is_stranded) return STRANDED_STATE;
|
|
5486
|
-
return lane.seat === void 0 ? UNREADABLE_STATE :
|
|
3790
|
+
return lane.seat === void 0 ? UNREADABLE_STATE : OPEN_STATE3;
|
|
5487
3791
|
}
|
|
5488
3792
|
function value_or_unknown(value) {
|
|
5489
3793
|
return value === void 0 ? UNKNOWN_VALUE : String(value);
|
|
@@ -5527,7 +3831,7 @@ function describe_opened(lane) {
|
|
|
5527
3831
|
}
|
|
5528
3832
|
var lane_report = {
|
|
5529
3833
|
NO_LANES: NO_LANES2,
|
|
5530
|
-
OPEN_STATE:
|
|
3834
|
+
OPEN_STATE: OPEN_STATE3,
|
|
5531
3835
|
STRANDED_STATE,
|
|
5532
3836
|
UNREADABLE_STATE,
|
|
5533
3837
|
describe_lane,
|
|
@@ -5537,7 +3841,7 @@ var lane_report = {
|
|
|
5537
3841
|
};
|
|
5538
3842
|
|
|
5539
3843
|
// scripts/run/run-preflight.ts
|
|
5540
|
-
import { z as
|
|
3844
|
+
import { z as z11 } from "zod";
|
|
5541
3845
|
var CLEAN_VERDICT = "clean";
|
|
5542
3846
|
var RECLAIM_VERDICT = "reclaim";
|
|
5543
3847
|
var RESUME_VERDICT = "resume";
|
|
@@ -5547,7 +3851,7 @@ var OPEN_PR = "open";
|
|
|
5547
3851
|
var MERGED_PR = "merged";
|
|
5548
3852
|
var CLOSED_PR = "closed";
|
|
5549
3853
|
var NO_CHILD_WORK = { branch_name: void 0, pr_state: NO_PR };
|
|
5550
|
-
var
|
|
3854
|
+
var pr_info_schema = z11.object({ state: z11.string().optional() });
|
|
5551
3855
|
var GH_PR_STATES = /* @__PURE__ */ new Map([
|
|
5552
3856
|
["CLOSED", CLOSED_PR],
|
|
5553
3857
|
["MERGED", MERGED_PR],
|
|
@@ -5626,12 +3930,12 @@ function decide5(tree, child, issue) {
|
|
|
5626
3930
|
}
|
|
5627
3931
|
function read_pr_field(raw) {
|
|
5628
3932
|
try {
|
|
5629
|
-
return
|
|
3933
|
+
return pr_info_schema.parse(JSON.parse(raw)).state;
|
|
5630
3934
|
} catch {
|
|
5631
3935
|
return void 0;
|
|
5632
3936
|
}
|
|
5633
3937
|
}
|
|
5634
|
-
function
|
|
3938
|
+
function to_pr_state(raw) {
|
|
5635
3939
|
const state = read_pr_field(raw);
|
|
5636
3940
|
return (state === void 0 ? void 0 : GH_PR_STATES.get(state)) ?? NO_PR;
|
|
5637
3941
|
}
|
|
@@ -5643,17 +3947,17 @@ async function read_tree_state() {
|
|
|
5643
3947
|
]);
|
|
5644
3948
|
return { branch: current, default_branch, is_dirty };
|
|
5645
3949
|
}
|
|
5646
|
-
async function
|
|
3950
|
+
async function read_pr_state(branch_name) {
|
|
5647
3951
|
if (!await git_gh_pr_read.pr_exists(branch_name)) return NO_PR;
|
|
5648
3952
|
const raw = await git_gh_pr_read.pr_view(branch_name);
|
|
5649
3953
|
if (raw === "") throw new Error(`${UNREADABLE_PR_MESSAGE}${branch_name}`);
|
|
5650
|
-
return
|
|
3954
|
+
return to_pr_state(raw);
|
|
5651
3955
|
}
|
|
5652
3956
|
function is_pr_open(state) {
|
|
5653
3957
|
return state === OPEN_PR;
|
|
5654
3958
|
}
|
|
5655
3959
|
async function read_pr_of_branch(branch_name) {
|
|
5656
|
-
return { branch_name, pr_state: await
|
|
3960
|
+
return { branch_name, pr_state: await read_pr_state(branch_name) };
|
|
5657
3961
|
}
|
|
5658
3962
|
function pick_child_state(reads) {
|
|
5659
3963
|
const decided = reads.find((read2) => is_pr_decided(read2.pr_state));
|
|
@@ -5728,8 +4032,8 @@ var run_preflight = {
|
|
|
5728
4032
|
check: check2,
|
|
5729
4033
|
decide: decide5,
|
|
5730
4034
|
read_child_state,
|
|
5731
|
-
read_pr_state
|
|
5732
|
-
to_pr_state
|
|
4035
|
+
read_pr_state,
|
|
4036
|
+
to_pr_state
|
|
5733
4037
|
};
|
|
5734
4038
|
|
|
5735
4039
|
// scripts/run/run-progress-read.ts
|
|
@@ -5829,7 +4133,7 @@ var TICK_MULTIPLIER = 3;
|
|
|
5829
4133
|
var MS_PER_SECOND3 = 1e3;
|
|
5830
4134
|
var STALE_THRESHOLD_MS = WATCHER_TICK_MS * TICK_MULTIPLIER;
|
|
5831
4135
|
var STALE_THRESHOLD_S = STALE_THRESHOLD_MS / MS_PER_SECOND3;
|
|
5832
|
-
var STALE_NOTE = `Lane children are in-flight but the progress watcher has not pinged in the last ${String(STALE_THRESHOLD_S)}s \u2014 run \`pnpm josh run:progress --wait\` in the background before proceeding`;
|
|
4136
|
+
var STALE_NOTE = `Lane children are in-flight but the progress watcher has not pinged in the last ${String(STALE_THRESHOLD_S)}s \u2014 run \`pnpm josh run:progress --wait\` in the background before proceeding. It reports to the run event stream on its own and exits only when newly runnable work arrives, so start it once and relay nothing`;
|
|
5833
4137
|
var OK_RESULT = { kind: "ok" };
|
|
5834
4138
|
async function owes_watcher() {
|
|
5835
4139
|
if (!await run_headless.is_backlog_parent()) return false;
|
|
@@ -5849,7 +4153,7 @@ var run_watcher_guard = {
|
|
|
5849
4153
|
// scripts/run/run-watcher-hook.ts
|
|
5850
4154
|
var SWITCH_ENV_KEY2 = "JOSH_WATCHER_GUARD";
|
|
5851
4155
|
var STAMP_PREFIX2 = "josh-watcher-guard-";
|
|
5852
|
-
var payload_schema =
|
|
4156
|
+
var payload_schema = z12.object({ transcript_path: z12.string().min(1) });
|
|
5853
4157
|
function transcript_of(raw_payload) {
|
|
5854
4158
|
try {
|
|
5855
4159
|
const parsed = payload_schema.safeParse(JSON.parse(raw_payload));
|
|
@@ -5910,7 +4214,8 @@ async function refusal_for(transcript, now_ms, state) {
|
|
|
5910
4214
|
function is_unit_call(raw_payload) {
|
|
5911
4215
|
try {
|
|
5912
4216
|
return (hook_decision.parse_hook_payload(raw_payload)?.agent_id ?? "") !== "";
|
|
5913
|
-
} catch {
|
|
4217
|
+
} catch (error) {
|
|
4218
|
+
error_text.trace_swallowed("run_parent_cut_hook.is_unit_call", error);
|
|
5914
4219
|
return false;
|
|
5915
4220
|
}
|
|
5916
4221
|
}
|