merge-steward 0.17.0 → 0.18.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/dist/db/schema.js +1 -0
- package/dist/db/sqlite-store.js +3 -1
- package/dist/github/actions-runner.js +8 -1
- package/dist/github/pr-client.js +2 -1
- package/dist/service-queue.d.ts +1 -0
- package/dist/service-queue.js +2 -1
- package/dist/types.d.ts +3 -0
- package/dist/watch/ProjectDetailView.js +14 -1
- package/dist/watch/dashboard-model.d.ts +1 -0
- package/dist/watch/dashboard-model.js +3 -0
- package/package.json +1 -1
package/dist/db/schema.js
CHANGED
|
@@ -75,6 +75,7 @@ export function ensureSchema(connection) {
|
|
|
75
75
|
ensureColumn(connection, "queue_entries", "post_merge_summary", "TEXT");
|
|
76
76
|
ensureColumn(connection, "queue_entries", "post_merge_checked_at", "TEXT");
|
|
77
77
|
ensureColumn(connection, "queue_entries", "wait_detail", "TEXT");
|
|
78
|
+
ensureColumn(connection, "queue_entries", "pr_title", "TEXT");
|
|
78
79
|
connection.exec(`
|
|
79
80
|
UPDATE queue_entries
|
|
80
81
|
SET post_merge_status = 'pending'
|
package/dist/db/sqlite-store.js
CHANGED
|
@@ -29,6 +29,7 @@ function mapEntry(row) {
|
|
|
29
29
|
postMergeSha: row.post_merge_sha === null || row.post_merge_sha === undefined ? null : String(row.post_merge_sha),
|
|
30
30
|
postMergeSummary: row.post_merge_summary === null || row.post_merge_summary === undefined ? null : String(row.post_merge_summary),
|
|
31
31
|
postMergeCheckedAt: row.post_merge_checked_at === null || row.post_merge_checked_at === undefined ? null : String(row.post_merge_checked_at),
|
|
32
|
+
prTitle: row.pr_title === null || row.pr_title === undefined ? null : String(row.pr_title),
|
|
32
33
|
enqueuedAt: String(row.enqueued_at),
|
|
33
34
|
updatedAt: String(row.updated_at),
|
|
34
35
|
};
|
|
@@ -125,8 +126,9 @@ export class SqliteStore {
|
|
|
125
126
|
priority, generation, ci_run_id, ci_retries, retry_attempts,
|
|
126
127
|
max_retries, last_failed_base_sha, issue_key, wait_detail,
|
|
127
128
|
post_merge_status, post_merge_sha, post_merge_summary, post_merge_checked_at,
|
|
129
|
+
pr_title,
|
|
128
130
|
enqueued_at, updated_at)
|
|
129
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(entry.id, entry.repoId, entry.prNumber, entry.branch, entry.headSha, entry.baseSha, entry.status, entry.position, entry.priority, entry.generation, entry.ciRunId, entry.ciRetries, entry.retryAttempts, entry.maxRetries, entry.lastFailedBaseSha, entry.issueKey ?? null, entry.waitDetail ?? null, entry.postMergeStatus ?? null, entry.postMergeSha ?? null, entry.postMergeSummary ?? null, entry.postMergeCheckedAt ?? null, entry.enqueuedAt, entry.updatedAt);
|
|
131
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(entry.id, entry.repoId, entry.prNumber, entry.branch, entry.headSha, entry.baseSha, entry.status, entry.position, entry.priority, entry.generation, entry.ciRunId, entry.ciRetries, entry.retryAttempts, entry.maxRetries, entry.lastFailedBaseSha, entry.issueKey ?? null, entry.waitDetail ?? null, entry.postMergeStatus ?? null, entry.postMergeSha ?? null, entry.postMergeSummary ?? null, entry.postMergeCheckedAt ?? null, entry.prTitle ?? null, entry.enqueuedAt, entry.updatedAt);
|
|
130
132
|
this.writeEvent(entry.id, null, entry.status);
|
|
131
133
|
})();
|
|
132
134
|
}
|
|
@@ -55,7 +55,14 @@ export class GitHubActionsRunner {
|
|
|
55
55
|
// (e.g. deploy-stage on main), even though listChecksForRef treats
|
|
56
56
|
// those same checks as success, producing a "main_broken" block with
|
|
57
57
|
// an empty failing-check list and stalling the queue.
|
|
58
|
-
|
|
58
|
+
// Accept "skipped" whenever there are no named required checks,
|
|
59
|
+
// including strict-protection-with-empty-contexts mode. A skipped
|
|
60
|
+
// job is an `if:` or `on:` gate by the workflow author declaring
|
|
61
|
+
// the job does not apply here; it is not a failure. The bypass
|
|
62
|
+
// concern (a gate job reporting success while a required job was
|
|
63
|
+
// skipped) only matters when we have a named required-check set
|
|
64
|
+
// to gate against, i.e. `hasRequired === true`.
|
|
65
|
+
const acceptSkipped = !hasRequired;
|
|
59
66
|
if (relevant.some((c) => {
|
|
60
67
|
if (c.conclusion === "success" || c.conclusion === "neutral")
|
|
61
68
|
return false;
|
package/dist/github/pr-client.js
CHANGED
|
@@ -24,13 +24,14 @@ export class GitHubPRClient {
|
|
|
24
24
|
const result = await exec("gh", [
|
|
25
25
|
"pr", "view", String(prNumber),
|
|
26
26
|
"--repo", this.repoFullName,
|
|
27
|
-
"--json", "number,headRefName,headRefOid,reviewDecision,state,mergeStateStatus",
|
|
27
|
+
"--json", "number,title,headRefName,headRefOid,reviewDecision,state,mergeStateStatus",
|
|
28
28
|
], { githubRepoFullName: this.repoFullName });
|
|
29
29
|
const data = JSON.parse(result.stdout);
|
|
30
30
|
return {
|
|
31
31
|
number: data.number,
|
|
32
32
|
branch: data.headRefName,
|
|
33
33
|
headSha: data.headRefOid,
|
|
34
|
+
...(data.title ? { title: data.title } : {}),
|
|
34
35
|
mergeable: data.state === "OPEN",
|
|
35
36
|
mergeStateStatus: data.mergeStateStatus,
|
|
36
37
|
reviewDecision: data.reviewDecision,
|
package/dist/service-queue.d.ts
CHANGED
package/dist/service-queue.js
CHANGED
|
@@ -63,6 +63,7 @@ export class MergeStewardQueueCommands {
|
|
|
63
63
|
postMergeSha: null,
|
|
64
64
|
postMergeSummary: null,
|
|
65
65
|
postMergeCheckedAt: null,
|
|
66
|
+
prTitle: params.prTitle ?? null,
|
|
66
67
|
enqueuedAt: new Date().toISOString(),
|
|
67
68
|
updatedAt: new Date().toISOString(),
|
|
68
69
|
};
|
|
@@ -161,7 +162,7 @@ export class MergeStewardQueueCommands {
|
|
|
161
162
|
return false;
|
|
162
163
|
}
|
|
163
164
|
}
|
|
164
|
-
this.enqueue({ prNumber, branch, headSha });
|
|
165
|
+
this.enqueue({ prNumber, branch, headSha, ...(status.title ? { prTitle: status.title } : {}) });
|
|
165
166
|
return true;
|
|
166
167
|
}
|
|
167
168
|
catch (error) {
|
package/dist/types.d.ts
CHANGED
|
@@ -42,6 +42,8 @@ export interface QueueEntry {
|
|
|
42
42
|
waitDetail?: string | null;
|
|
43
43
|
/** Post-merge verification status for the landed commit on main. */
|
|
44
44
|
postMergeStatus: PostMergeStatus | null;
|
|
45
|
+
/** PR title captured at admission. Falls back to branch name in the UI. */
|
|
46
|
+
prTitle?: string | null;
|
|
45
47
|
/** Commit SHA used when checking post-merge status. */
|
|
46
48
|
postMergeSha: string | null;
|
|
47
49
|
/** Optional one-line summary of post-merge checks. */
|
|
@@ -180,6 +182,7 @@ export interface PRStatus {
|
|
|
180
182
|
number: number;
|
|
181
183
|
branch: string;
|
|
182
184
|
headSha: string;
|
|
185
|
+
title?: string | undefined;
|
|
183
186
|
mergeable: boolean;
|
|
184
187
|
mergeStateStatus?: string | undefined;
|
|
185
188
|
reviewDecision?: string | undefined;
|
|
@@ -3,13 +3,26 @@ import { Box, Text, useStdout } from "ink";
|
|
|
3
3
|
import { RepoRow } from "./OverviewView.js";
|
|
4
4
|
import { clipSummary } from "./dashboard-model.js";
|
|
5
5
|
const PR_ID_WIDTH = 7;
|
|
6
|
+
const PR_PHRASE_WIDTH = 20;
|
|
6
7
|
const SUMMARY_INDENT = 9;
|
|
7
8
|
function PrEntryRow({ entry, width, includeSummary, }) {
|
|
8
9
|
const idText = `#${entry.prNumber}`.padEnd(PR_ID_WIDTH, " ");
|
|
10
|
+
const paddedPhrase = entry.phrase.padEnd(PR_PHRASE_WIDTH, " ");
|
|
9
11
|
const summaryText = includeSummary
|
|
10
12
|
? clipSummary(entry.summary, { maxLines: 3, width: Math.max(20, width - SUMMARY_INDENT) })
|
|
11
13
|
: "";
|
|
12
|
-
|
|
14
|
+
const titleSpace = Math.max(0, width - (PR_ID_WIDTH + 3 + PR_PHRASE_WIDTH + 1));
|
|
15
|
+
const title = entry.title && entry.title !== entry.phrase && titleSpace >= 8
|
|
16
|
+
? truncate(entry.title, titleSpace)
|
|
17
|
+
: "";
|
|
18
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { children: [_jsx(Text, { color: entry.color, children: idText }), _jsx(Text, { color: entry.color, children: entry.glyph }), _jsx(Text, { children: ` ${paddedPhrase}` }), title ? _jsx(Text, { dimColor: true, children: ` ${title}` }) : null] }), summaryText ? (_jsxs(Box, { children: [_jsx(Text, { children: " ".repeat(SUMMARY_INDENT) }), _jsx(Text, { dimColor: true, children: summaryText })] })) : null] }));
|
|
19
|
+
}
|
|
20
|
+
function truncate(value, maxWidth) {
|
|
21
|
+
if (value.length <= maxWidth)
|
|
22
|
+
return value;
|
|
23
|
+
if (maxWidth <= 1)
|
|
24
|
+
return value.slice(0, maxWidth);
|
|
25
|
+
return `${value.slice(0, Math.max(0, maxWidth - 1))}\u2026`;
|
|
13
26
|
}
|
|
14
27
|
export function ProjectDetailView({ model, selectedRepoId }) {
|
|
15
28
|
const { stdout } = useStdout();
|
|
@@ -151,6 +151,9 @@ function repoEntriesFromSnapshot(snapshot, cutoff) {
|
|
|
151
151
|
const summary = entrySummary(entry);
|
|
152
152
|
if (summary)
|
|
153
153
|
item.summary = summary;
|
|
154
|
+
const title = entry.prTitle?.trim() || entry.branch;
|
|
155
|
+
if (title)
|
|
156
|
+
item.title = title;
|
|
154
157
|
byPr.set(entry.prNumber, item);
|
|
155
158
|
}
|
|
156
159
|
return [...byPr.values()].sort((left, right) => {
|