-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathreviewer.agent.js
More file actions
97 lines (88 loc) · 3.51 KB
/
reviewer.agent.js
File metadata and controls
97 lines (88 loc) · 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/**
* ============================================================================
* Agent: reviewer.agent.js
* Location: reviewer.agent.js
* Description:
* - Posts automated review summaries for PRs, including CI status, changelog presence, and recommendations.
* - Main functions: run(), CI status check, file analysis, markdown summary/comment.
* - Uses shared utilities: label-reporting.
* - Shared test helpers: mockOctokit, mockContext, mockChangedFiles, expectCommentPosted, expectDryRun, etc.
* - Coverage: Review summary posting, changelog checks, CI state, dry-run, error handling.
* Standards:
* - Follows [LightSpeed Coding Standards](https://github.com/lightspeedwp/.github/blob/HEAD/instructions/coding-standards.instructions.md)
* - See org instructions: [Custom Instructions](https://github.com/lightspeedwp/.github/blob/master/.github/custom-instructions.md)
* Contribution:
* - Update docblock with new logic or helper usage
* - Add new helpers to tests/utility/test-helpers.js as needed
* ============================================================================
* @module scripts/agents/reviewer.agent.js
* @see ../../agents/reviewer.agent.md
*/
const core = require("@actions/core");
const github = require("@actions/github");
/**
* Main orchestrator for Reviewer Agent.
* Posts a summary comment on PRs with CI status and file analysis.
* @param {Object} context - GitHub Actions context object.
* @returns {Promise<void>}
*/
async function run(context = github.context) {
try {
const token = core.getInput("github-token") || process.env.GITHUB_TOKEN;
if (!token) throw new Error("Missing token");
const requireChangelog =
(core.getInput("require-changelog") || "false") === "true";
const octokit = github.getOctokit(token);
const pr = context.payload.pull_request;
if (!pr) {
core.info("No PR in context; exiting.");
return;
}
let state = "unknown";
try {
const { data } = await octokit.rest.repos.getCombinedStatusForRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: pr.head.sha,
});
state = data.state;
} catch (e) {
core.info("Could not fetch CI status.");
}
const { data: files } = await octokit.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pr.number,
per_page: 100,
});
const changed = files.map((f) => f.filename);
const srcTouched = changed.some(
(f) => f.startsWith("src/") || /\.(js|ts|php|py)$/i.test(f),
);
const hasChangelog = changed.some(
(f) => f.toLowerCase() === "changelog.md",
);
const blockers = [];
if (state !== "success") blockers.push("CI checks not green");
if (requireChangelog && srcTouched && !hasChangelog)
blockers.push("CHANGELOG.md missing for code change");
const emoji = blockers.length ? "❌" : state === "success" ? "✅" : "⚠️";
const summary = `## 🔍 Reviewer Summary for PR #${pr.number}
**CI Status:** ${emoji} \`${state}\`
**Files changed:** ${files.length}
### Recommendations
${blockers.length ? blockers.map((b) => `- ${b}`).join("\n") : "- Ready to proceed pending human review"}
`;
await octokit.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: pr.number,
body: summary,
});
core.info("Reviewer comment posted.");
} catch (e) {
core.setFailed(e.message);
}
}
if (require.main === module) run();
module.exports = { run };