dep-brain 1.6.0 → 1.7.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/CHANGELOG.md +8 -0
- package/README.md +19 -4
- package/action.yml +19 -0
- package/dist/cli.js +39 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/reporters/pr-comment.d.ts +6 -0
- package/dist/reporters/pr-comment.js +46 -0
- package/dist/utils/github.d.ts +25 -0
- package/dist/utils/github.js +112 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 1.7.0
|
|
6
|
+
|
|
7
|
+
- Added idempotent GitHub PR comments with `--pr-comment`.
|
|
8
|
+
- Added `--comment-on` trigger support for `always`, `failure`, and `new-findings`.
|
|
9
|
+
- Added PR comment markdown renderer with top issues, policy reasons, upgrade priorities, and baseline delta counts.
|
|
10
|
+
- Added GitHub Action inputs for PR comment runs.
|
|
11
|
+
- Kept analysis output contract at `1.6` because no JSON result fields changed.
|
|
12
|
+
|
|
5
13
|
## 1.6.0
|
|
6
14
|
|
|
7
15
|
- Added Slack and Discord webhook notification summaries.
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
`dep-brain` is a CLI and library for explainable dependency intelligence in JavaScript and TypeScript projects.
|
|
8
8
|
|
|
9
|
-
Current release `1.
|
|
9
|
+
Current release `1.7.0` adds idempotent GitHub PR comments while keeping analysis output contract `1.6`.
|
|
10
10
|
|
|
11
11
|
## Vision
|
|
12
12
|
|
|
@@ -29,6 +29,7 @@ Current release `1.6.0` adds Slack and Discord notification summaries while keep
|
|
|
29
29
|
- Output reports in console, JSON, Markdown, SARIF, dashboard, and top-issues formats
|
|
30
30
|
- Output upgrade-advice reports via `--advise`
|
|
31
31
|
- Send Slack and Discord webhook summaries for CI runs
|
|
32
|
+
- Create or update GitHub PR comments for pull request checks
|
|
32
33
|
- Gate CI with score and finding policies
|
|
33
34
|
- Compare new findings against a baseline report
|
|
34
35
|
|
|
@@ -38,7 +39,7 @@ The long-term goal is not just to list problems, but to answer:
|
|
|
38
39
|
- Can I remove it safely?
|
|
39
40
|
- What should I fix first?
|
|
40
41
|
|
|
41
|
-
## 1.
|
|
42
|
+
## 1.7 Highlights
|
|
42
43
|
|
|
43
44
|
- Duplicate dependency detection with lockfile instance tracking
|
|
44
45
|
- Unused dependency detection with runtime vs dev-tool heuristics
|
|
@@ -57,6 +58,7 @@ The long-term goal is not just to list problems, but to answer:
|
|
|
57
58
|
- Static HTML dashboard via `--dashboard`
|
|
58
59
|
- Upgrade advisor output via `--advise`
|
|
59
60
|
- Slack and Discord notification summaries via `--notify`
|
|
61
|
+
- GitHub PR comments via `--pr-comment`
|
|
60
62
|
- Ranked top issues via `--top`
|
|
61
63
|
- Baseline mode via `--baseline`
|
|
62
64
|
- Focused analysis via `--focus`
|
|
@@ -88,6 +90,8 @@ npx dep-brain analyze --dashboard
|
|
|
88
90
|
npx dep-brain analyze --dashboard --dashboard-out reports/depbrain.html
|
|
89
91
|
npx dep-brain analyze --notify
|
|
90
92
|
npx dep-brain analyze --notify --notify-on always
|
|
93
|
+
npx dep-brain analyze --pr-comment
|
|
94
|
+
npx dep-brain analyze --pr-comment --comment-on new-findings
|
|
91
95
|
npx dep-brain analyze --focus duplicates
|
|
92
96
|
npx dep-brain analyze --ci
|
|
93
97
|
npx dep-brain analyze --baseline depbrain-baseline.json
|
|
@@ -173,7 +177,7 @@ Suggestions:
|
|
|
173
177
|
dep-brain analyze --json
|
|
174
178
|
```
|
|
175
179
|
|
|
176
|
-
Output includes `outputVersion` for schema stability. `dep-brain@1.
|
|
180
|
+
Output includes `outputVersion` for schema stability. `dep-brain@1.7.0` writes contract version `1.6`.
|
|
177
181
|
|
|
178
182
|
Validate against:
|
|
179
183
|
|
|
@@ -219,6 +223,15 @@ DEPBRAIN_DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/... dep-brain anal
|
|
|
219
223
|
|
|
220
224
|
`--notify` sends compact summaries to configured Slack and Discord webhook URLs. Default trigger is `failure`, so passing runs stay quiet unless `--notify-on always` is set.
|
|
221
225
|
|
|
226
|
+
## PR Comments
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
dep-brain analyze --ci --pr-comment
|
|
230
|
+
dep-brain analyze --ci --baseline depbrain-baseline.json --pr-comment --comment-on new-findings
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
`--pr-comment` creates or updates one GitHub pull request comment using `GITHUB_TOKEN`, `GITHUB_REPOSITORY`, and `GITHUB_EVENT_PATH`. The comment includes policy status, health score, top issues, upgrade priorities, and baseline delta counts when `--baseline` is used.
|
|
234
|
+
|
|
222
235
|
## Plugins
|
|
223
236
|
|
|
224
237
|
```json
|
|
@@ -360,6 +373,7 @@ dep-brain analyze --min-score 85 --fail-on-risks
|
|
|
360
373
|
dep-brain analyze --config depbrain.config.json
|
|
361
374
|
dep-brain analyze --baseline depbrain-baseline.json --fail-on-unused
|
|
362
375
|
dep-brain analyze --ci --notify
|
|
376
|
+
dep-brain analyze --ci --pr-comment
|
|
363
377
|
```
|
|
364
378
|
|
|
365
379
|
## Config Debugging
|
|
@@ -406,7 +420,7 @@ src/
|
|
|
406
420
|
|
|
407
421
|
## Product Direction
|
|
408
422
|
|
|
409
|
-
`dep-brain` is in `v1.
|
|
423
|
+
`dep-brain` is in `v1.7.0` production CLI stage, with current focus on actionable dependency decisions and PR workflow integration.
|
|
410
424
|
|
|
411
425
|
Recent releases added:
|
|
412
426
|
|
|
@@ -415,6 +429,7 @@ Recent releases added:
|
|
|
415
429
|
- baseline, focus, and CI workflows
|
|
416
430
|
- structured upgrade advice with release-note links
|
|
417
431
|
- Slack and Discord notification summaries
|
|
432
|
+
- idempotent GitHub PR comments
|
|
418
433
|
|
|
419
434
|
Project should optimize for trust, clarity, and actionability over flashy UI, generic graphs, or simply adding more checks.
|
|
420
435
|
|
package/action.yml
CHANGED
|
@@ -59,6 +59,18 @@ inputs:
|
|
|
59
59
|
description: Notification trigger. Use always, failure, or never.
|
|
60
60
|
required: false
|
|
61
61
|
default: "failure"
|
|
62
|
+
pr-comment:
|
|
63
|
+
description: Create or update a GitHub PR comment.
|
|
64
|
+
required: false
|
|
65
|
+
default: "false"
|
|
66
|
+
comment-on:
|
|
67
|
+
description: PR comment trigger. Use always, failure, or new-findings.
|
|
68
|
+
required: false
|
|
69
|
+
default: "failure"
|
|
70
|
+
github-token:
|
|
71
|
+
description: GitHub token for PR comments.
|
|
72
|
+
required: false
|
|
73
|
+
default: ""
|
|
62
74
|
|
|
63
75
|
runs:
|
|
64
76
|
using: composite
|
|
@@ -80,6 +92,9 @@ runs:
|
|
|
80
92
|
INPUT_FAIL_ON_RISKS: ${{ inputs.fail-on-risks }}
|
|
81
93
|
INPUT_NOTIFY: ${{ inputs.notify }}
|
|
82
94
|
INPUT_NOTIFY_ON: ${{ inputs.notify-on }}
|
|
95
|
+
INPUT_PR_COMMENT: ${{ inputs.pr-comment }}
|
|
96
|
+
INPUT_COMMENT_ON: ${{ inputs.comment-on }}
|
|
97
|
+
GITHUB_TOKEN: ${{ inputs.github-token || github.token }}
|
|
83
98
|
run: |
|
|
84
99
|
set -euo pipefail
|
|
85
100
|
|
|
@@ -141,6 +156,10 @@ runs:
|
|
|
141
156
|
args+=("--notify" "--notify-on" "$INPUT_NOTIFY_ON")
|
|
142
157
|
fi
|
|
143
158
|
|
|
159
|
+
if [ "$INPUT_PR_COMMENT" = "true" ]; then
|
|
160
|
+
args+=("--pr-comment" "--comment-on" "$INPUT_COMMENT_ON")
|
|
161
|
+
fi
|
|
162
|
+
|
|
144
163
|
node "$GITHUB_ACTION_PATH/dist/cli.js" "${args[@]}"
|
|
145
164
|
|
|
146
165
|
branding:
|
package/dist/cli.js
CHANGED
|
@@ -3,8 +3,10 @@ import { analyzeProject } from "./core/analyzer.js";
|
|
|
3
3
|
import { renderConsoleReport } from "./reporters/console.js";
|
|
4
4
|
import { renderJsonReport } from "./reporters/json.js";
|
|
5
5
|
import { renderMarkdownReport } from "./reporters/markdown.js";
|
|
6
|
+
import { renderPrCommentReport } from "./reporters/pr-comment.js";
|
|
6
7
|
import { renderSarifReport } from "./reporters/sarif.js";
|
|
7
8
|
import { renderDashboardReport } from "./reporters/dashboard.js";
|
|
9
|
+
import { shouldPostPrComment, upsertGitHubPrComment } from "./utils/github.js";
|
|
8
10
|
import { sendConfiguredNotifications } from "./utils/notifications.js";
|
|
9
11
|
import { defaultConfig } from "./utils/config.js";
|
|
10
12
|
import { promises as fs } from "node:fs";
|
|
@@ -175,6 +177,28 @@ async function main() {
|
|
|
175
177
|
}
|
|
176
178
|
}
|
|
177
179
|
}
|
|
180
|
+
if (flags.has("--pr-comment")) {
|
|
181
|
+
const trigger = parsePrCommentTrigger(optionValues.get("--comment-on"));
|
|
182
|
+
const newFindingsCount = countFindings(result);
|
|
183
|
+
if (shouldPostPrComment({
|
|
184
|
+
trigger,
|
|
185
|
+
policyPassed: result.policy.passed,
|
|
186
|
+
newFindingsCount
|
|
187
|
+
})) {
|
|
188
|
+
const commentResult = await upsertGitHubPrComment({
|
|
189
|
+
body: renderPrCommentReport(result, { hasBaseline: Boolean(baseline) })
|
|
190
|
+
});
|
|
191
|
+
if (commentResult.status === "created" || commentResult.status === "updated") {
|
|
192
|
+
console.error(`PR comment ${commentResult.status}.`);
|
|
193
|
+
}
|
|
194
|
+
else {
|
|
195
|
+
console.error(`PR comment skipped: ${commentResult.reason ?? "unknown reason"}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
console.error(`PR comment skipped: ${trigger} trigger did not match.`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
178
202
|
if (!result.policy.passed) {
|
|
179
203
|
process.exitCode = 1;
|
|
180
204
|
}
|
|
@@ -246,7 +270,7 @@ function printHelp() {
|
|
|
246
270
|
console.log("Dependency Brain");
|
|
247
271
|
console.log("");
|
|
248
272
|
console.log("Usage:");
|
|
249
|
-
console.log(" dep-brain analyze [path] [--json] [--md] [--sarif] [--top] [--dashboard] [--notify] [--
|
|
273
|
+
console.log(" dep-brain analyze [path] [--json] [--md] [--sarif] [--top] [--dashboard] [--notify] [--pr-comment] [--comment-on kind] [--focus kind] [--ci] [--out path] [--config path] [--baseline path] [--min-score n] [--fail-on-risks]");
|
|
250
274
|
console.log(" dep-brain report --from <file> [--md] [--json] [--sarif] [--top] [--advise] [--dashboard] [--out path]");
|
|
251
275
|
console.log(" dep-brain config [path] [--config path]");
|
|
252
276
|
console.log(" dep-brain init [--out depbrain.config.json]");
|
|
@@ -263,6 +287,8 @@ function printHelp() {
|
|
|
263
287
|
console.log(" --dashboard-out <path> Write dashboard HTML to a custom path");
|
|
264
288
|
console.log(" --notify Send Slack or Discord webhook summaries");
|
|
265
289
|
console.log(" --notify-on <kind> Send notifications on always, failure, or never");
|
|
290
|
+
console.log(" --pr-comment Create or update a GitHub PR comment");
|
|
291
|
+
console.log(" --comment-on <kind> Post PR comment on always, failure, or new-findings");
|
|
266
292
|
console.log(" --focus <kind> Run all, health, duplicates, unused, outdated, or risks");
|
|
267
293
|
console.log(" --ci Apply low-noise CI defaults");
|
|
268
294
|
console.log(" --config <path> Path to depbrain.config.json");
|
|
@@ -396,3 +422,15 @@ function compareAdviceRisk(left, right) {
|
|
|
396
422
|
const rank = { high: 3, medium: 2, low: 1 };
|
|
397
423
|
return rank[left] - rank[right];
|
|
398
424
|
}
|
|
425
|
+
function parsePrCommentTrigger(value) {
|
|
426
|
+
if (value === "always" || value === "failure" || value === "new-findings") {
|
|
427
|
+
return value;
|
|
428
|
+
}
|
|
429
|
+
return "failure";
|
|
430
|
+
}
|
|
431
|
+
function countFindings(result) {
|
|
432
|
+
return (result.duplicates.length +
|
|
433
|
+
result.unused.length +
|
|
434
|
+
result.outdated.length +
|
|
435
|
+
result.risks.length);
|
|
436
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,8 @@ export type { DepBrainPlugin, PluginDiagnostic, ProjectContext } from "./core/pl
|
|
|
6
6
|
export type { AnalysisContext, CheckResult, Issue } from "./core/types.js";
|
|
7
7
|
export type { DepBrainConfig, DepBrainConfigOverrides } from "./utils/config.js";
|
|
8
8
|
export { renderNotificationMessage, sendConfiguredNotifications, shouldSendNotification } from "./utils/notifications.js";
|
|
9
|
+
export { shouldPostPrComment, upsertGitHubPrComment } from "./utils/github.js";
|
|
10
|
+
export { PR_COMMENT_MARKER, renderPrCommentReport } from "./reporters/pr-comment.js";
|
|
9
11
|
export type { NotificationChannel, NotificationResult, NotificationSendInput, NotificationSender } from "./utils/notifications.js";
|
|
12
|
+
export type { GitHubPrCommentInput, GitHubPrCommentResult, GitHubRequest, PrCommentTrigger } from "./utils/github.js";
|
|
10
13
|
export type { WorkspacePackage } from "./utils/workspaces.js";
|
package/dist/index.js
CHANGED
|
@@ -2,3 +2,5 @@ export { analyzeProject } from "./core/analyzer.js";
|
|
|
2
2
|
export { OUTPUT_VERSION } from "./core/analyzer.js";
|
|
3
3
|
export { PluginManager } from "./core/plugin-manager.js";
|
|
4
4
|
export { renderNotificationMessage, sendConfiguredNotifications, shouldSendNotification } from "./utils/notifications.js";
|
|
5
|
+
export { shouldPostPrComment, upsertGitHubPrComment } from "./utils/github.js";
|
|
6
|
+
export { PR_COMMENT_MARKER, renderPrCommentReport } from "./reporters/pr-comment.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AnalysisResult } from "../core/analyzer.js";
|
|
2
|
+
export declare const PR_COMMENT_MARKER = "<!-- dep-brain-report -->";
|
|
3
|
+
export interface PrCommentOptions {
|
|
4
|
+
hasBaseline?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function renderPrCommentReport(result: AnalysisResult, options?: PrCommentOptions): string;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export const PR_COMMENT_MARKER = "<!-- dep-brain-report -->";
|
|
2
|
+
export function renderPrCommentReport(result, options = {}) {
|
|
3
|
+
const lines = [
|
|
4
|
+
PR_COMMENT_MARKER,
|
|
5
|
+
"## Dependency Brain",
|
|
6
|
+
"",
|
|
7
|
+
`**Policy:** ${result.policy.passed ? "PASS" : "FAIL"}`,
|
|
8
|
+
`**Project Health:** ${result.score}/100`,
|
|
9
|
+
`**Findings:** duplicates ${result.duplicates.length}, unused ${result.unused.length}, outdated ${result.outdated.length}, risks ${result.risks.length}`
|
|
10
|
+
];
|
|
11
|
+
if (options.hasBaseline) {
|
|
12
|
+
lines.push(`**New since baseline:** duplicates ${result.duplicates.length}, unused ${result.unused.length}, outdated ${result.outdated.length}, risks ${result.risks.length}`);
|
|
13
|
+
}
|
|
14
|
+
if (result.policy.reasons.length > 0) {
|
|
15
|
+
lines.push("");
|
|
16
|
+
lines.push("### Policy Reasons");
|
|
17
|
+
for (const reason of result.policy.reasons) {
|
|
18
|
+
lines.push(`- ${reason}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (result.topIssues.length > 0) {
|
|
22
|
+
lines.push("");
|
|
23
|
+
lines.push("### Top Issues");
|
|
24
|
+
for (const item of result.topIssues.slice(0, 5)) {
|
|
25
|
+
lines.push(`- **${item.priority.toUpperCase()}** ${item.kind} \`${item.name}\`${item.package ? ` [${item.package}]` : ""}: ${item.summary}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const upgradePriorities = summarizeUpgradePriorities(result);
|
|
29
|
+
if (upgradePriorities) {
|
|
30
|
+
lines.push("");
|
|
31
|
+
lines.push("### Upgrade Priorities");
|
|
32
|
+
lines.push(upgradePriorities);
|
|
33
|
+
}
|
|
34
|
+
lines.push("");
|
|
35
|
+
lines.push("_Generated by dep-brain._");
|
|
36
|
+
return lines.join("\n");
|
|
37
|
+
}
|
|
38
|
+
function summarizeUpgradePriorities(result) {
|
|
39
|
+
const counts = result.outdated.reduce((acc, item) => {
|
|
40
|
+
acc[item.advice.risk] += 1;
|
|
41
|
+
return acc;
|
|
42
|
+
}, { high: 0, medium: 0, low: 0 });
|
|
43
|
+
return [`high ${counts.high}`, `medium ${counts.medium}`, `low ${counts.low}`]
|
|
44
|
+
.filter((entry) => !entry.endsWith(" 0"))
|
|
45
|
+
.join(", ");
|
|
46
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export type PrCommentTrigger = "always" | "failure" | "new-findings";
|
|
2
|
+
export interface GitHubPrCommentInput {
|
|
3
|
+
body: string;
|
|
4
|
+
env?: Record<string, string | undefined>;
|
|
5
|
+
request?: GitHubRequest;
|
|
6
|
+
}
|
|
7
|
+
export interface GitHubPrCommentResult {
|
|
8
|
+
status: "created" | "updated" | "skipped";
|
|
9
|
+
reason?: string;
|
|
10
|
+
}
|
|
11
|
+
export type GitHubRequest = (url: string, init: {
|
|
12
|
+
method: "GET" | "POST" | "PATCH";
|
|
13
|
+
headers: Record<string, string>;
|
|
14
|
+
body?: string;
|
|
15
|
+
}) => Promise<{
|
|
16
|
+
ok: boolean;
|
|
17
|
+
status: number;
|
|
18
|
+
json: () => Promise<unknown>;
|
|
19
|
+
}>;
|
|
20
|
+
export declare function upsertGitHubPrComment(input: GitHubPrCommentInput): Promise<GitHubPrCommentResult>;
|
|
21
|
+
export declare function shouldPostPrComment(input: {
|
|
22
|
+
trigger: PrCommentTrigger;
|
|
23
|
+
policyPassed: boolean;
|
|
24
|
+
newFindingsCount: number;
|
|
25
|
+
}): boolean;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { PR_COMMENT_MARKER } from "../reporters/pr-comment.js";
|
|
3
|
+
export async function upsertGitHubPrComment(input) {
|
|
4
|
+
const env = input.env ?? process.env;
|
|
5
|
+
const token = env.GITHUB_TOKEN;
|
|
6
|
+
const repository = env.GITHUB_REPOSITORY;
|
|
7
|
+
const eventPath = env.GITHUB_EVENT_PATH;
|
|
8
|
+
if (!token) {
|
|
9
|
+
return { status: "skipped", reason: "GITHUB_TOKEN is not set" };
|
|
10
|
+
}
|
|
11
|
+
if (!repository) {
|
|
12
|
+
return { status: "skipped", reason: "GITHUB_REPOSITORY is not set" };
|
|
13
|
+
}
|
|
14
|
+
if (!eventPath) {
|
|
15
|
+
return { status: "skipped", reason: "GITHUB_EVENT_PATH is not set" };
|
|
16
|
+
}
|
|
17
|
+
const pullNumber = await readPullNumber(eventPath);
|
|
18
|
+
if (!pullNumber) {
|
|
19
|
+
return { status: "skipped", reason: "pull request event not found" };
|
|
20
|
+
}
|
|
21
|
+
const request = input.request ?? defaultGitHubRequest;
|
|
22
|
+
const commentsUrl = `https://api.github.com/repos/${repository}/issues/${pullNumber}/comments`;
|
|
23
|
+
const headers = buildHeaders(token);
|
|
24
|
+
const existingResponse = await request(commentsUrl, {
|
|
25
|
+
method: "GET",
|
|
26
|
+
headers
|
|
27
|
+
});
|
|
28
|
+
if (!existingResponse.ok) {
|
|
29
|
+
return {
|
|
30
|
+
status: "skipped",
|
|
31
|
+
reason: `failed to list comments: HTTP ${existingResponse.status}`
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
const comments = normalizeComments(await existingResponse.json());
|
|
35
|
+
const existing = comments.find((comment) => typeof comment.body === "string" && comment.body.includes(PR_COMMENT_MARKER));
|
|
36
|
+
if (existing) {
|
|
37
|
+
const updateResponse = await request(`https://api.github.com/repos/${repository}/issues/comments/${existing.id}`, {
|
|
38
|
+
method: "PATCH",
|
|
39
|
+
headers,
|
|
40
|
+
body: JSON.stringify({ body: input.body })
|
|
41
|
+
});
|
|
42
|
+
return updateResponse.ok
|
|
43
|
+
? { status: "updated" }
|
|
44
|
+
: {
|
|
45
|
+
status: "skipped",
|
|
46
|
+
reason: `failed to update comment: HTTP ${updateResponse.status}`
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const createResponse = await request(commentsUrl, {
|
|
50
|
+
method: "POST",
|
|
51
|
+
headers,
|
|
52
|
+
body: JSON.stringify({ body: input.body })
|
|
53
|
+
});
|
|
54
|
+
return createResponse.ok
|
|
55
|
+
? { status: "created" }
|
|
56
|
+
: {
|
|
57
|
+
status: "skipped",
|
|
58
|
+
reason: `failed to create comment: HTTP ${createResponse.status}`
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export function shouldPostPrComment(input) {
|
|
62
|
+
if (input.trigger === "always") {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
if (input.trigger === "failure") {
|
|
66
|
+
return !input.policyPassed;
|
|
67
|
+
}
|
|
68
|
+
return input.newFindingsCount > 0;
|
|
69
|
+
}
|
|
70
|
+
async function readPullNumber(eventPath) {
|
|
71
|
+
try {
|
|
72
|
+
const raw = await fs.readFile(eventPath, "utf8");
|
|
73
|
+
const event = JSON.parse(raw);
|
|
74
|
+
const value = event.pull_request?.number ?? event.number;
|
|
75
|
+
return typeof value === "number" ? value : null;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async function defaultGitHubRequest(url, init) {
|
|
82
|
+
const response = await fetch(url, init);
|
|
83
|
+
return {
|
|
84
|
+
ok: response.ok,
|
|
85
|
+
status: response.status,
|
|
86
|
+
json: () => response.json()
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function buildHeaders(token) {
|
|
90
|
+
return {
|
|
91
|
+
accept: "application/vnd.github+json",
|
|
92
|
+
authorization: `Bearer ${token}`,
|
|
93
|
+
"content-type": "application/json",
|
|
94
|
+
"x-github-api-version": "2022-11-28"
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function normalizeComments(value) {
|
|
98
|
+
if (!Array.isArray(value)) {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
return value
|
|
102
|
+
.map((item) => {
|
|
103
|
+
if (!item || typeof item !== "object") {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const comment = item;
|
|
107
|
+
return typeof comment.id === "number"
|
|
108
|
+
? { id: comment.id, body: comment.body }
|
|
109
|
+
: null;
|
|
110
|
+
})
|
|
111
|
+
.filter((item) => item !== null);
|
|
112
|
+
}
|