pr-shepherd 0.43.0 → 0.44.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.
Files changed (96) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +18 -17
  3. package/bin/api.d.mts +3 -2
  4. package/bin/api.mjs +13 -18
  5. package/bin/cli/args.mjs +13 -9
  6. package/bin/cli/fix-formatter.mjs +8 -6
  7. package/bin/cli/help-command-pages.d.mts +9 -6
  8. package/bin/cli/help-command-pages.mjs +7 -4
  9. package/bin/cli/help-iterate-poll-pages.d.mts +2 -2
  10. package/bin/cli/help-iterate-poll-pages.mjs +2 -2
  11. package/bin/cli/help-top-page.d.mts +1 -1
  12. package/bin/cli/help-top-page.mjs +2 -2
  13. package/bin/cli/help.d.mts +10 -7
  14. package/bin/cli/iterate-formatter.d.mts +1 -1
  15. package/bin/cli/iterate-formatter.mjs +5 -5
  16. package/bin/cli/iterate-lean.mjs +4 -0
  17. package/bin/cli/journal-formatter.mjs +3 -0
  18. package/bin/cli/journal-handler.mjs +11 -7
  19. package/bin/cli/list-formatters.d.mts +3 -1
  20. package/bin/cli/list-formatters.mjs +9 -7
  21. package/bin/cli/mark-files-as-viewed-formatter.mjs +7 -1
  22. package/bin/cli/mutate-formatter.mjs +4 -0
  23. package/bin/commands/check.mjs +22 -6
  24. package/bin/commands/commit-suggestion-instruction.d.mts +1 -1
  25. package/bin/commands/commit-suggestion-instruction.mjs +2 -2
  26. package/bin/commands/commit-suggestion.mjs +3 -1
  27. package/bin/commands/iterate/check-instructions.d.mts +5 -19
  28. package/bin/commands/iterate/check-instructions.mjs +24 -25
  29. package/bin/commands/iterate/classify.d.mts +2 -2
  30. package/bin/commands/iterate/classify.mjs +43 -25
  31. package/bin/commands/iterate/escalate.d.mts +1 -1
  32. package/bin/commands/iterate/escalate.mjs +11 -0
  33. package/bin/commands/iterate/fix-code.mjs +81 -42
  34. package/bin/commands/iterate/helpers.d.mts +0 -2
  35. package/bin/commands/iterate/helpers.mjs +0 -15
  36. package/bin/commands/iterate/index.mjs +6 -12
  37. package/bin/commands/iterate/mark-ready.d.mts +2 -0
  38. package/bin/commands/iterate/mark-ready.mjs +38 -0
  39. package/bin/commands/iterate/merge-state.mjs +38 -9
  40. package/bin/commands/iterate/merge.mjs +0 -1
  41. package/bin/commands/iterate/render.d.mts +2 -2
  42. package/bin/commands/iterate/render.mjs +19 -20
  43. package/bin/commands/iterate/stall.mjs +4 -2
  44. package/bin/commands/iterate/thread-mutation-routing.d.mts +9 -0
  45. package/bin/commands/iterate/thread-mutation-routing.mjs +29 -0
  46. package/bin/commands/journal/index.d.mts +5 -0
  47. package/bin/commands/journal/index.mjs +11 -2
  48. package/bin/commands/mark-files-as-viewed.d.mts +2 -1
  49. package/bin/commands/mark-files-as-viewed.mjs +5 -92
  50. package/bin/commands/resolve-mutate.mjs +51 -9
  51. package/bin/commands/shepherd-journal.d.mts +1 -1
  52. package/bin/commands/shepherd-journal.mjs +2 -2
  53. package/bin/commands/suggestion-patch-item.d.mts +1 -1
  54. package/bin/commands/suggestion-patch-item.mjs +3 -11
  55. package/bin/commands/suggestion-patches.mjs +3 -3
  56. package/bin/comments/authors.d.mts +6 -0
  57. package/bin/comments/authors.mjs +5 -0
  58. package/bin/comments/marker.d.mts +6 -1
  59. package/bin/comments/marker.mjs +8 -1
  60. package/bin/comments/resolve.d.mts +4 -0
  61. package/bin/comments/thread-visibility.mjs +10 -10
  62. package/bin/comments/visible-comments.mjs +2 -1
  63. package/bin/config/load.d.mts +1 -1
  64. package/bin/github/batch-parsers.d.mts +2 -2
  65. package/bin/github/batch-parsers.mjs +17 -1
  66. package/bin/github/batch-raw-types.d.mts +12 -0
  67. package/bin/github/batch.mjs +1 -1
  68. package/bin/github/client.d.mts +1 -0
  69. package/bin/github/client.mjs +8 -1
  70. package/bin/github/gql/batch-pr-page.gql +6 -0
  71. package/bin/github/gql/batch-pr.gql +13 -0
  72. package/bin/github/gql/get-pr-body.gql +1 -0
  73. package/bin/github/gql/review-thread-comments.gql +1 -0
  74. package/bin/github/gql/suggestion-threads.gql +1 -0
  75. package/bin/github/suggestion-thread.mjs +1 -0
  76. package/bin/mcp/server.mjs +12 -6
  77. package/bin/pr-reference.d.mts +13 -0
  78. package/bin/pr-reference.mjs +23 -1
  79. package/bin/reporters/agent.mjs +5 -0
  80. package/bin/threads/transcript.d.mts +2 -0
  81. package/bin/threads/transcript.mjs +2 -0
  82. package/bin/types/agent-thread.d.mts +1 -0
  83. package/bin/types/escalate.d.mts +6 -1
  84. package/bin/types/github.d.mts +19 -0
  85. package/bin/types/iterate.d.mts +9 -8
  86. package/bin/types/report.d.mts +14 -1
  87. package/bin/types/review-thread.d.mts +1 -0
  88. package/bin/types/suggestion-patch.d.mts +1 -1
  89. package/package.json +1 -1
  90. package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
  91. package/plugins/pr-shepherd/.codex.mcp.json +1 -1
  92. package/plugins/pr-shepherd/.mcp.json +1 -1
  93. package/plugins/pr-shepherd/skills/mark-files-as-viewed/SKILL.md +3 -3
  94. package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +15 -13
  95. package/bin/commands/iterate/reruns.d.mts +0 -20
  96. package/bin/commands/iterate/reruns.mjs +0 -105
@@ -1,4 +1,4 @@
1
- import type { AuthorType, ReviewThread, PrComment, Review, MergeStatusResult, CheckConclusion, SuggestionBlock } from "./github.mts";
1
+ import type { AuthorType, ReviewThread, PrComment, Review, MergeStatusResult, ViewerAuthorization, CheckConclusion, SuggestionBlock } from "./github.mts";
2
2
  import type { ClassifiedCheck, TriagedCheck } from "./check-classification.mts";
3
3
  import type { AgentThreadComment } from "./agent-thread.mts";
4
4
  import type { CheckAnnotation } from "./check-annotations.mts";
@@ -24,6 +24,8 @@ export interface ShepherdReport {
24
24
  /** GitHub PR head OID from the same batch used to decide the action. */
25
25
  headSha?: string;
26
26
  repo: string;
27
+ /** Raw GitHub viewer fields used to decide which remote actions may be offered. */
28
+ viewerAuthorization?: ViewerAuthorization;
27
29
  status: ShepherdStatus;
28
30
  /** PR base branch from the GraphQL batch. */
29
31
  baseBranch: string;
@@ -87,6 +89,10 @@ export interface ResolveOptions {
87
89
  }
88
90
  export interface AgentThread {
89
91
  id: string;
92
+ /** Raw GitHub capability; omitted only in legacy/incomplete snapshots. */
93
+ viewerCanReply?: boolean;
94
+ /** Raw GitHub capability; omitted only in legacy/incomplete snapshots. */
95
+ viewerCanResolve?: boolean;
90
96
  reviewId?: string;
91
97
  path: string | null;
92
98
  line: number | null;
@@ -94,6 +100,7 @@ export interface AgentThread {
94
100
  author: string;
95
101
  authorType?: AuthorType;
96
102
  authorAssociation?: import("./github.mts").CommentAuthorAssociation;
103
+ viewerDidAuthor?: true;
97
104
  body: string;
98
105
  url: string;
99
106
  comments?: AgentThreadComment[];
@@ -103,6 +110,8 @@ export interface AgentThread {
103
110
  /** Comment shape emitted to the iterate agent — stripped of always-false flags. */
104
111
  export interface AgentComment {
105
112
  id: string;
113
+ /** Raw GitHub capability; omitted only in legacy/incomplete snapshots. */
114
+ viewerCanMinimize?: boolean;
106
115
  author: string;
107
116
  authorType?: AuthorType;
108
117
  authorAssociation?: import("./github.mts").CommentAuthorAssociation;
@@ -160,6 +169,10 @@ export interface RelevantCheck {
160
169
  }
161
170
  export interface GlobalOptions {
162
171
  prNumber?: number;
172
+ targetRepository?: {
173
+ owner: string;
174
+ name: string;
175
+ };
163
176
  format: "text" | "json";
164
177
  verbose?: boolean;
165
178
  }
@@ -6,6 +6,7 @@ export interface ReviewThreadComment {
6
6
  author: string;
7
7
  authorType: AuthorType;
8
8
  authorAssociation?: CommentAuthorAssociation;
9
+ viewerDidAuthor?: true;
9
10
  body: string;
10
11
  url: string;
11
12
  createdAtUnix: number;
@@ -18,7 +18,7 @@ export interface BuildSuggestionPatchesResult {
18
18
  repo: string;
19
19
  /** Suggestion patches in caller-supplied application order. */
20
20
  patches: SuggestionPatchResult[];
21
- /** Steps for applying and committing every patch, then pushing once. */
21
+ /** Steps for applying and committing every patch; branch updates require separate authorization. */
22
22
  postActionInstructions: string[];
23
23
  }
24
24
  /** Compatibility result for the singular suggestion-patch adapter. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pr-shepherd",
3
- "version": "0.43.0",
3
+ "version": "0.44.0",
4
4
  "description": "Autonomous PR CI monitor and review-comment resolver for agentic coding tools",
5
5
  "keywords": [
6
6
  "automation",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pr-shepherd",
3
- "version": "0.43.0",
3
+ "version": "0.44.0",
4
4
  "description": "Autonomous PR CI monitor and review-comment resolver for Codex.",
5
5
  "author": {
6
6
  "name": "Jonathan Ong",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "pr-shepherd": {
4
4
  "command": "npx",
5
- "args": ["--yes", "--package", "pr-shepherd@0.43.0", "pr-shepherd-mcp"]
5
+ "args": ["--yes", "--package", "pr-shepherd@0.44.0", "pr-shepherd-mcp"]
6
6
  }
7
7
  }
8
8
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "pr-shepherd": {
3
3
  "command": "npx",
4
- "args": ["--yes", "--package", "pr-shepherd@0.43.0", "pr-shepherd-mcp"]
4
+ "args": ["--yes", "--package", "pr-shepherd@0.44.0", "pr-shepherd-mcp"]
5
5
  }
6
6
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: mark-files-as-viewed
3
- description: "Mark changed pull-request files as viewed with pr-shepherd (MCP or CLI)."
3
+ description: "Select changed pull-request files and report viewed-state authorization diagnostics with pr-shepherd (MCP or CLI)."
4
4
  user-invocable: true
5
5
  argument-hint: "[PR number or URL] [files|tests|--tests|--match REGEX]"
6
6
  allowed-tools: ["MCP", "Bash", "Read", "Grep", "Glob"]
@@ -8,10 +8,10 @@ allowed-tools: ["MCP", "Bash", "Read", "Grep", "Glob"]
8
8
 
9
9
  # mark-files-as-viewed
10
10
 
11
- Thin dispatcher for marking PR files viewed. Use the MCP server when it is available; otherwise use the CLI.
11
+ Thin dispatcher for selection-only file-view authorization diagnostics. GitHub exposes no exact viewer capability for marking a PR file viewed, so this operation never recommends or attempts that mutation. Use the MCP server when it is available; otherwise use the CLI.
12
12
 
13
13
  ## Arguments: $ARGUMENTS
14
14
 
15
15
  1. Parse an optional PR number, repository-qualified `owner/repo#N`, or GitHub PR URL. Treat standalone `tests` as `--tests`; preserve explicit paths and `--match <regex>` selectors.
16
16
 
17
- 2. If the `apply` MCP tool is available, first obtain a repository-qualified reference: use a supplied GitHub PR URL or `owner/repo#N` unchanged; for a bare number, run `gh pr view <number> --json url --jq .url`; when omitted, run `gh pr view --json url --jq .url`. If that does not produce one qualified PR reference, stop and report that MCP cannot safely determine the PR. Otherwise call `apply` with that qualified reference and one `mark_files_viewed` operation, then print the full result. If MCP is unavailable and the parsed PR is repository-qualified, run `gh repo view --json nameWithOwner --jq .nameWithOwner` and verify that repository matches the reference case-insensitively. Stop on a mismatch or failed lookup; the CLI does not validate the URL repository. Convert a verified `owner/repo#N` to `https://github.com/owner/repo/pull/N`, then run `pr-shepherd apply files` with the parsed PR and selectors and print the full result.
17
+ 2. If the `apply` MCP tool is available, first obtain a repository-qualified reference: use a supplied GitHub PR URL or `owner/repo#N` unchanged; for a bare number, run `gh pr view <number> --json url --jq .url`; when omitted, run `gh pr view --json url --jq .url`. If that does not produce one qualified PR reference, stop and report that MCP cannot safely determine the PR. Otherwise call `apply` with that qualified reference and one `mark_files_viewed` operation, then print the full result. If MCP is unavailable, convert a supplied `owner/repo#N` to `https://github.com/owner/repo/pull/N` and otherwise pass the parsed PR unchanged to `pr-shepherd apply files` with the selectors, then print the full result. A qualified reference may target a fork or upstream repository; the current checkout remains the local git/config/rules context.
@@ -14,7 +14,7 @@ Thin dispatcher for iterating a PR. Poll with the CLI; use MCP `iterate` only wh
14
14
 
15
15
  1. Parse an optional PR number, repository-qualified `owner/repo#N`, or GitHub PR URL and an optional `--merge` flag from `$ARGUMENTS`; otherwise let pr-shepherd infer the current branch PR. Reject any remaining argument. Follow the target repository's local `AGENTS.md` and `CLAUDE.md` standards while making changes.
16
16
 
17
- 2. Before passing a supplied GitHub PR URL or `owner/repo#N` to the CLI, run `gh repo view --json nameWithOwner --jq .nameWithOwner` and verify that repository matches the reference case-insensitively. Stop on a mismatch or failed lookup; the CLI does not validate the URL repository. Convert a verified `owner/repo#N` to `https://github.com/owner/repo/pull/N`, then run the poll command `pr-shepherd` with the optional PR argument and forward `--merge` when supplied; print its full result. Do not run `pr-shepherd iterate`. If the CLI is unavailable and the `iterate` MCP tool is available, first obtain a repository-qualified reference: use a supplied GitHub PR URL or `owner/repo#N` unchanged; for a bare number, run `gh pr view <number> --json url --jq .url`; when omitted, run `gh pr view --json url --jq .url`. If that does not produce one qualified PR reference, stop and report that MCP cannot safely determine the PR. Otherwise call `iterate` with that qualified reference, plus `merge: true` when `--merge` was supplied, and print its full result.
17
+ 2. For the CLI, convert supplied `owner/repo#N` to `https://github.com/owner/repo/pull/N`; otherwise pass the supplied URL or bare number unchanged, then run the poll command `pr-shepherd` with the optional PR argument and forward `--merge` when supplied. A qualified reference may name a fork or upstream repository: it is the GitHub target, while the current checkout continues to supply local git/config/rules context. Do not run `pr-shepherd iterate`. If the CLI is unavailable and the `iterate` MCP tool is available, first obtain a repository-qualified reference: use a supplied GitHub PR URL or `owner/repo#N` unchanged; for a bare number, run `gh pr view <number> --json url --jq .url`; when omitted, run `gh pr view --json url --jq .url`. If that does not produce one qualified PR reference, stop and report that MCP cannot safely determine the PR. Otherwise call `iterate` with that qualified reference, plus `merge: true` when `--merge` was supplied, and print its full result.
18
18
 
19
19
  3. Print the full result and follow every returned `## Instructions` step exactly. For CLI output, run each printed mutation command when instructed. For MCP output, use MCP `apply` and `build_suggestion_patches` with the same qualified PR reference; do not run a shell `pr-shepherd apply` command.
20
20
 
@@ -28,11 +28,11 @@ mechanics every tick. Apply the referenced playbook in full whenever a step poin
28
28
  ### Suggestion patches
29
29
 
30
30
  - Run one plural `build-suggestion-patches` command with a repeated `--thread-id … --message … [--description …]` group for every marked thread in displayed order.
31
- - The CLI only builds patches. Apply, stage, and commit the returned patches in order, then push once.
31
+ - The CLI only builds patches. Apply, stage, and commit the returned patches in order. Push only when authorization has been established outside Shepherd; GitHub viewer fields cannot verify the local Git credential.
32
32
  - The command builds from the fetched PR head and accepts a clean local descendant only when the complete ordered patch stream passes `git apply --check`.
33
33
  - If the command refuses because a suggestion is unsafe or no longer applies, inspect the current source, the displayed replacement block, and reviewer intent before editing manually. Do not apply a stale numeric range blindly or retry unchanged input.
34
34
  - A returned patch was checked against the then-current worktree. If it later fails, re-inspect the worktree because it changed after validation.
35
- - Keep human-authored thread IDs in `apply review:` so Shepherd replies instead of resolving them.
35
+ - Keep the generated thread IDs and flag placement unchanged. Viewer-authored human feedback may intentionally appear in both reply and resolve flags; unmarked other-human feedback remains reply-only. Marker-ended other-human feedback is already acknowledged and has no generated mutation.
36
36
 
37
37
  ### CI failure triage
38
38
 
@@ -40,18 +40,20 @@ Match each failure's `[conclusion: …]` tag under `## Failing checks` to a rule
40
40
 
41
41
  More specific rows win over the general "GitHub Actions failure" row — check conclusion first.
42
42
 
43
- | Tag / kind | Do |
44
- | ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
45
- | GitHub Actions failure (has a run ID, not `CANCELLED`/`STARTUP_FAILURE`) | Read the included log excerpt if one is rendered. If missing or insufficient, run a bounded command such as `gh run view <runId> --log-failed \| tail -n 200` the unbounded form can dump excessive log output into context. Open the run URL only if that still lacks detail. |
46
- | Transient infrastructure failure | Rerun with `gh run rerun <runId> --failed`. |
47
- | Real test or build failure | Apply a code fix — do not rerun. |
48
- | `[conclusion: CANCELLED]` | No log excerpt is rendered for this conclusion. Run `gh run rerun <runId>` unless this tick will push new commits. Not resolved by a rerun classification — `## Cancelled runs` is a different section. |
49
- | `[conclusion: STARTUP_FAILURE]` | No log excerpt is rendered for this conclusion. Inspect with `gh run view <runId>`, rerun with `gh run rerun <runId>` if warranted. |
50
- | `external` (no run ID, has a URL) | Open its URL and inspect it. |
43
+ | Tag / kind | Do |
44
+ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
45
+ | GitHub Actions failure (has a run ID, not `CANCELLED`/`STARTUP_FAILURE`) | Read the included log excerpt if one is rendered. If it is missing or insufficient, hand off the displayed run ID/URL; Shepherd cannot verify authorization for another Actions read or mutation. |
46
+ | Transient infrastructure failure | Record the diagnosis. Shepherd does not recommend a rerun because GitHub exposes no exact viewer capability for that workflow-run action. |
47
+ | Real test or build failure | Apply a code fix — do not rerun. |
48
+ | `[conclusion: CANCELLED]` | No log excerpt is rendered. Hand off the displayed metadata; Shepherd cannot verify authorization for another Actions read or mutation. |
49
+ | `[conclusion: STARTUP_FAILURE]` | No log excerpt is rendered. Hand off the displayed metadata; Shepherd cannot verify authorization for another Actions read or mutation. |
50
+ | `external` (no run ID, has a URL) | Preserve the URL in the handoff. Shepherd does not recommend opening it because it cannot verify the current viewer's access to the external system. |
51
51
 
52
52
  ### Review-mutation mechanics
53
53
 
54
- Applies to every `apply review:` / `resolve-only:` command the CLI prints. Covers only what stays safe if you run the printed command **unmodified** — `$HEAD_SHA`/`$DISMISS_MESSAGE` substitution and the self-reply exclusion rule are separate CLI-printed steps, not covered here, because the printed command is unsafe by default without them.
54
+ Applies to every `apply review:` / `resolve-only:` command the CLI prints. Covers only what stays safe if you run the printed command **unmodified** — `$HEAD_SHA`/`$DISMISS_MESSAGE` substitution remains a separate CLI-printed step because the command is unsafe by default without those placeholders.
55
+
56
+ The CLI only includes IDs whose per-object GitHub viewer capability authorizes the corresponding action, and `apply review` repeats that authorization check immediately before mutating.
55
57
 
56
58
  - Run every generated `apply review:` / `resolve-only:` command even when no code change is warranted. The command records the agent's disposition of the included review items; skipping it leaves bot threads active and can eventually trigger `fix-thrash`.
57
59
  - Never add first-look-only or check-annotation IDs to `--reply-thread-ids`, `--resolve-thread-ids`, `--dismiss-review-ids`, or `--minimize-comment-ids` — those flags are pre-populated by the CLI.
@@ -59,7 +61,7 @@ Applies to every `apply review:` / `resolve-only:` command the CLI prints. Cover
59
61
 
60
62
  ### Review-mutation routing
61
63
 
62
- For threads under both `## Review threads` and `## Review threads to resolve`, evaluate every thread before running mutations. Keep bot and non-human IDs in `--resolve-thread-ids`, including when the feedback is advisory, already satisfied, or otherwise warrants no code change. Human-authored IDs use `--reply-thread-ids`; Shepherd replies instead of resolving them. Never move a human-authored ID to `--resolve-thread-ids`. Use the commands as generated do not move an ID between flags.
64
+ For threads under both `## Review threads` and `## Review threads to resolve`, evaluate every thread before running mutations. Keep bot and non-human IDs in `--resolve-thread-ids`, including when the feedback is advisory, already satisfied, or otherwise warrants no code change. Unmarked other-human inline-thread IDs use `--reply-thread-ids` only. When the original human inline comment has `viewerDidAuthor: true` and its latest comment is unmarked, keep that same ID in both `--reply-thread-ids` and `--resolve-thread-ids`: the reply runs before the resolve. When the latest comment begins `<!-- pr-shepherd -->`, it is an established Shepherd reply—not merely a same-account comment. A marker-ended viewer-authored thread may be resolve-only for retry; a marker-ended other-human thread is already acknowledged and has no generated mutation. Do not add an unmarked human ID to `--resolve-thread-ids` without its paired generated reply, and do not move IDs between flags.
63
65
 
64
66
  ### Shepherd Journal
65
67
 
@@ -1,20 +0,0 @@
1
- import type { ShepherdReport } from "../../types.mts";
2
- import type { ProtectedRun } from "../../types/protected-run.mts";
3
- type FailingCheck = ShepherdReport["checks"]["failing"][number];
4
- type InProgressCheck = ShepherdReport["checks"]["inProgress"][number];
5
- type CancellableCheck = FailingCheck | InProgressCheck;
6
- interface RunProtection {
7
- protectedRunIds: Set<string>;
8
- protectedRuns: ProtectedRun[];
9
- }
10
- interface BuildRunIdOptions {
11
- protectedRunIds?: Set<string>;
12
- }
13
- export declare function buildAutoCancelRunIdsWithOptions(report: ShepherdReport, opts?: BuildRunIdOptions): string[];
14
- interface BuildInProgressRunIdOptions {
15
- suppressProtectedFreshReruns?: boolean;
16
- protectedRunIds?: Set<string>;
17
- }
18
- export declare function buildInProgressRunIds(report: ShepherdReport, cancelledSet: Set<string>, opts?: BuildInProgressRunIdOptions): string[];
19
- export declare function buildRunProtection(checks: CancellableCheck[], patterns?: string[]): RunProtection;
20
- export {};
@@ -1,105 +0,0 @@
1
- import picomatch from "picomatch";
2
- function matchesRerunCheck(failure, check) {
3
- if (failure.runId !== null && check.runId !== null) {
4
- return failure.runId === check.runId && failure.name === check.name;
5
- }
6
- return failure.runId === null && check.runId === null && failure.name === check.name;
7
- }
8
- function isProtectedByFreshRerun(failure, check) {
9
- const attemptStartedAt = check.startedAtUnix ?? check.updatedAtUnix ?? check.createdAtUnix;
10
- return (attemptStartedAt !== undefined &&
11
- matchesRerunCheck(failure, check) &&
12
- failure.completedAtUnix !== undefined &&
13
- attemptStartedAt >= failure.completedAtUnix &&
14
- (failure.startedAtUnix === undefined || failure.startedAtUnix < attemptStartedAt));
15
- }
16
- function hasProtectedFreshRerun(failure, checks) {
17
- return checks.some((check) => isProtectedByFreshRerun(failure, check));
18
- }
19
- function isProtectedFreshRerun(check, failures) {
20
- const matchingFailures = failures.filter((failure) => matchesRerunCheck(failure, check));
21
- return (matchingFailures.length > 0 &&
22
- matchingFailures.every((failure) => isProtectedByFreshRerun(failure, check)));
23
- }
24
- function protectedFreshRerunIds(report) {
25
- return new Set(report.checks.inProgress
26
- .filter((check) => isProtectedFreshRerun(check, report.checks.failing))
27
- .map((check) => check.runId)
28
- .filter((id) => id !== null));
29
- }
30
- export function buildAutoCancelRunIdsWithOptions(report, opts = {}) {
31
- return [
32
- ...new Set(report.checks.failing
33
- .filter((check) => !hasProtectedFreshRerun(check, report.checks.inProgress))
34
- .map((check) => check.runId)
35
- .filter((id) => id !== null && !(opts.protectedRunIds?.has(id) ?? false))),
36
- ];
37
- }
38
- export function buildInProgressRunIds(report, cancelledSet, opts = {}) {
39
- const protectedRunIds = opts.suppressProtectedFreshReruns === false ? new Set() : protectedFreshRerunIds(report);
40
- return [
41
- ...new Set(report.checks.inProgress
42
- .map((check) => check.runId)
43
- .filter((id) => id !== null &&
44
- !cancelledSet.has(id) &&
45
- !protectedRunIds.has(id) &&
46
- !(opts.protectedRunIds?.has(id) ?? false))),
47
- ];
48
- }
49
- export function buildRunProtection(checks, patterns = []) {
50
- if (patterns.length === 0)
51
- return { protectedRunIds: new Set(), protectedRuns: [] };
52
- const matchers = patterns.map((pattern) => ({
53
- pattern,
54
- isMatch: picomatch(pattern, { nocase: true }),
55
- }));
56
- const byRunId = new Map();
57
- for (const check of checks) {
58
- if (check.runId === null)
59
- continue;
60
- const match = findProtectionMatch(check, matchers);
61
- if (match === null)
62
- continue;
63
- addProtectedRun(byRunId, check.runId, check, match);
64
- }
65
- const protectedRuns = [...byRunId.values()];
66
- return {
67
- protectedRunIds: new Set(protectedRuns.map((run) => run.runId)),
68
- protectedRuns,
69
- };
70
- }
71
- function addProtectedRun(byRunId, runId, check, matchedPattern) {
72
- const existing = byRunId.get(runId);
73
- if (existing) {
74
- updateProtectedRun(existing, check);
75
- return;
76
- }
77
- byRunId.set(runId, createProtectedRun(runId, check, matchedPattern));
78
- }
79
- function updateProtectedRun(run, check) {
80
- if (!run.checkNames.includes(check.name))
81
- run.checkNames.push(check.name);
82
- if (run.workflowName === undefined && check.workflowName !== undefined) {
83
- run.workflowName = check.workflowName;
84
- }
85
- }
86
- function createProtectedRun(runId, check, matchedPattern) {
87
- return {
88
- runId,
89
- matchedPattern,
90
- checkNames: [check.name],
91
- ...(check.workflowName !== undefined && { workflowName: check.workflowName }),
92
- };
93
- }
94
- function findProtectionMatch(check, matchers) {
95
- const candidates = [
96
- check.workflowName,
97
- "jobName" in check ? check.jobName : undefined,
98
- check.name,
99
- ].filter((value) => value !== undefined && value.trim() !== "");
100
- for (const matcher of matchers) {
101
- if (candidates.some((candidate) => matcher.isMatch(candidate)))
102
- return matcher.pattern;
103
- }
104
- return null;
105
- }