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.
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +18 -17
- package/bin/api.d.mts +3 -2
- package/bin/api.mjs +13 -18
- package/bin/cli/args.mjs +13 -9
- package/bin/cli/fix-formatter.mjs +8 -6
- package/bin/cli/help-command-pages.d.mts +9 -6
- package/bin/cli/help-command-pages.mjs +7 -4
- package/bin/cli/help-iterate-poll-pages.d.mts +2 -2
- package/bin/cli/help-iterate-poll-pages.mjs +2 -2
- package/bin/cli/help-top-page.d.mts +1 -1
- package/bin/cli/help-top-page.mjs +2 -2
- package/bin/cli/help.d.mts +10 -7
- package/bin/cli/iterate-formatter.d.mts +1 -1
- package/bin/cli/iterate-formatter.mjs +5 -5
- package/bin/cli/iterate-lean.mjs +4 -0
- package/bin/cli/journal-formatter.mjs +3 -0
- package/bin/cli/journal-handler.mjs +11 -7
- package/bin/cli/list-formatters.d.mts +3 -1
- package/bin/cli/list-formatters.mjs +9 -7
- package/bin/cli/mark-files-as-viewed-formatter.mjs +7 -1
- package/bin/cli/mutate-formatter.mjs +4 -0
- package/bin/commands/check.mjs +22 -6
- package/bin/commands/commit-suggestion-instruction.d.mts +1 -1
- package/bin/commands/commit-suggestion-instruction.mjs +2 -2
- package/bin/commands/commit-suggestion.mjs +3 -1
- package/bin/commands/iterate/check-instructions.d.mts +5 -19
- package/bin/commands/iterate/check-instructions.mjs +24 -25
- package/bin/commands/iterate/classify.d.mts +2 -2
- package/bin/commands/iterate/classify.mjs +43 -25
- package/bin/commands/iterate/escalate.d.mts +1 -1
- package/bin/commands/iterate/escalate.mjs +11 -0
- package/bin/commands/iterate/fix-code.mjs +81 -42
- package/bin/commands/iterate/helpers.d.mts +0 -2
- package/bin/commands/iterate/helpers.mjs +0 -15
- package/bin/commands/iterate/index.mjs +6 -12
- package/bin/commands/iterate/mark-ready.d.mts +2 -0
- package/bin/commands/iterate/mark-ready.mjs +38 -0
- package/bin/commands/iterate/merge-state.mjs +38 -9
- package/bin/commands/iterate/merge.mjs +0 -1
- package/bin/commands/iterate/render.d.mts +2 -2
- package/bin/commands/iterate/render.mjs +19 -20
- package/bin/commands/iterate/stall.mjs +4 -2
- package/bin/commands/iterate/thread-mutation-routing.d.mts +9 -0
- package/bin/commands/iterate/thread-mutation-routing.mjs +29 -0
- package/bin/commands/journal/index.d.mts +5 -0
- package/bin/commands/journal/index.mjs +11 -2
- package/bin/commands/mark-files-as-viewed.d.mts +2 -1
- package/bin/commands/mark-files-as-viewed.mjs +5 -92
- package/bin/commands/resolve-mutate.mjs +51 -9
- package/bin/commands/shepherd-journal.d.mts +1 -1
- package/bin/commands/shepherd-journal.mjs +2 -2
- package/bin/commands/suggestion-patch-item.d.mts +1 -1
- package/bin/commands/suggestion-patch-item.mjs +3 -11
- package/bin/commands/suggestion-patches.mjs +3 -3
- package/bin/comments/authors.d.mts +6 -0
- package/bin/comments/authors.mjs +5 -0
- package/bin/comments/marker.d.mts +6 -1
- package/bin/comments/marker.mjs +8 -1
- package/bin/comments/resolve.d.mts +4 -0
- package/bin/comments/thread-visibility.mjs +10 -10
- package/bin/comments/visible-comments.mjs +2 -1
- package/bin/config/load.d.mts +1 -1
- package/bin/github/batch-parsers.d.mts +2 -2
- package/bin/github/batch-parsers.mjs +17 -1
- package/bin/github/batch-raw-types.d.mts +12 -0
- package/bin/github/batch.mjs +1 -1
- package/bin/github/client.d.mts +1 -0
- package/bin/github/client.mjs +8 -1
- package/bin/github/gql/batch-pr-page.gql +6 -0
- package/bin/github/gql/batch-pr.gql +13 -0
- package/bin/github/gql/get-pr-body.gql +1 -0
- package/bin/github/gql/review-thread-comments.gql +1 -0
- package/bin/github/gql/suggestion-threads.gql +1 -0
- package/bin/github/suggestion-thread.mjs +1 -0
- package/bin/mcp/server.mjs +12 -6
- package/bin/pr-reference.d.mts +13 -0
- package/bin/pr-reference.mjs +23 -1
- package/bin/reporters/agent.mjs +5 -0
- package/bin/threads/transcript.d.mts +2 -0
- package/bin/threads/transcript.mjs +2 -0
- package/bin/types/agent-thread.d.mts +1 -0
- package/bin/types/escalate.d.mts +6 -1
- package/bin/types/github.d.mts +19 -0
- package/bin/types/iterate.d.mts +9 -8
- package/bin/types/report.d.mts +14 -1
- package/bin/types/review-thread.d.mts +1 -0
- package/bin/types/suggestion-patch.d.mts +1 -1
- package/package.json +1 -1
- package/plugins/pr-shepherd/.codex-plugin/plugin.json +1 -1
- package/plugins/pr-shepherd/.codex.mcp.json +1 -1
- package/plugins/pr-shepherd/.mcp.json +1 -1
- package/plugins/pr-shepherd/skills/mark-files-as-viewed/SKILL.md +3 -3
- package/plugins/pr-shepherd/skills/pr-shepherd/SKILL.md +15 -13
- package/bin/commands/iterate/reruns.d.mts +0 -20
- package/bin/commands/iterate/reruns.mjs +0 -105
package/bin/types/report.d.mts
CHANGED
|
@@ -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
|
}
|
|
@@ -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
|
|
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: mark-files-as-viewed
|
|
3
|
-
description: "
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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,
|
|
46
|
-
| Transient infrastructure failure |
|
|
47
|
-
| Real test or build failure | Apply a code fix — do not rerun.
|
|
48
|
-
| `[conclusion: CANCELLED]` | No log excerpt is rendered
|
|
49
|
-
| `[conclusion: STARTUP_FAILURE]` | No log excerpt is rendered
|
|
50
|
-
| `external` (no run ID, has a URL) |
|
|
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
|
|
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.
|
|
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
|
-
}
|