Skip to content

Commit d78cc5e

Browse files
committed
fix: Refactors PR commenting into a separate script
Moves the logic for commenting on pull requests into a dedicated Node.js script. This improves maintainability and readability by separating the commenting functionality from the main workflow definition. The workflow now executes the script directly, passing necessary environment variables. This also allows for easier testing and debugging of the commenting logic.
1 parent fc9997a commit d78cc5e

File tree

2 files changed

+122
-73
lines changed

2 files changed

+122
-73
lines changed

.github/scripts/comment-on-pr.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
const fs = require('fs');
2+
const { Octokit } = require('@octokit/rest');
3+
4+
// Get environment variables
5+
const token = process.env.GITHUB_TOKEN;
6+
const repo = process.env.GITHUB_REPOSITORY.split('/');
7+
const owner = repo[0];
8+
const repoName = repo[1];
9+
const prNumber = process.env.PR_NUMBER;
10+
const isDryRun = process.env.DRY_RUN === 'true';
11+
12+
if (!token) {
13+
console.error('GITHUB_TOKEN environment variable is required');
14+
process.exit(1);
15+
}
16+
17+
if (!prNumber) {
18+
console.error('PR_NUMBER environment variable is required');
19+
process.exit(1);
20+
}
21+
22+
const octokit = new Octokit({ auth: token });
23+
24+
async function commentOnPR() {
25+
try {
26+
let results = {};
27+
let hasErrors = false;
28+
29+
if (fs.existsSync('validation-results.json')) {
30+
results = JSON.parse(fs.readFileSync('validation-results.json', 'utf8'));
31+
hasErrors = Object.values(results).some(issues => issues.length > 0);
32+
}
33+
34+
// Determine overall status
35+
const status = hasErrors ? '🚫 Entry Validation Failed' : '✅ Entry Validation Passed';
36+
let comment = `## ${status}\n\n`;
37+
38+
// Add requirements checklist
39+
comment += '### Requirements Checklist:\n\n';
40+
41+
// Check each requirement across all files
42+
let fileSizePass = true;
43+
let htmlStructurePass = true;
44+
let noExternalImportsPass = true;
45+
let noNetworkRequestsPass = true;
46+
let htmlSyntaxPass = true;
47+
let entryRegisteredPass = true;
48+
49+
for (const [file, issues] of Object.entries(results)) {
50+
issues.forEach(issue => {
51+
if (issue.includes('File size') && issue.includes('exceeds')) fileSizePass = false;
52+
if (issue.includes('File must have') || issue.includes('HTML structure')) htmlStructurePass = false;
53+
if (issue.includes('External') && (issue.includes('stylesheet') || issue.includes('script') || issue.includes('image') || issue.includes('resource'))) noExternalImportsPass = false;
54+
if (issue.includes('network request')) noNetworkRequestsPass = false;
55+
if (issue.includes('HTML syntax') || issue.includes('Unclosed')) htmlSyntaxPass = false;
56+
if (issue.includes('Entry not found') || issue.includes('entries.js')) entryRegisteredPass = false;
57+
});
58+
}
59+
60+
comment += `- ${fileSizePass ? '✅' : '❌'} File must be less than 1MB\n`;
61+
comment += `- ${htmlStructurePass ? '✅' : '❌'} Valid HTML file structure\n`;
62+
comment += `- ${noExternalImportsPass ? '✅' : '❌'} No external file imports (images, CSS, JS)\n`;
63+
comment += `- ${noNetworkRequestsPass ? '✅' : '❌'} No network requests\n`;
64+
comment += `- ${htmlSyntaxPass ? '✅' : '❌'} Valid HTML syntax\n`;
65+
comment += `- ${entryRegisteredPass ? '✅' : '❌'} Entry registered in entries.js\n\n`;
66+
67+
// Add detailed issues if any exist
68+
if (hasErrors) {
69+
comment += '### Issues Found:\n\n';
70+
for (const [file, issues] of Object.entries(results)) {
71+
if (issues.length > 0) {
72+
comment += `**${file}:**\n`;
73+
issues.forEach(issue => {
74+
comment += `- ${issue}\n`;
75+
});
76+
comment += '\n';
77+
}
78+
}
79+
comment += 'Please fix the issues above and update your pull request.';
80+
} else {
81+
comment += 'All entries meet the One HTML Page Challenge requirements! 🎉';
82+
}
83+
84+
// Log the comment for dry runs or post it
85+
if (isDryRun) {
86+
console.log('Dry run mode - comment would be:');
87+
console.log('---');
88+
console.log(comment);
89+
console.log('---');
90+
} else {
91+
console.log('Posting comment to PR #' + prNumber);
92+
await octokit.rest.issues.createComment({
93+
owner: owner,
94+
repo: repoName,
95+
issue_number: parseInt(prNumber),
96+
body: comment
97+
});
98+
console.log('Comment posted successfully');
99+
}
100+
101+
// Exit with error code if validation failed
102+
if (hasErrors) {
103+
process.exit(1);
104+
} else {
105+
process.exit(0);
106+
}
107+
108+
} catch (error) {
109+
console.error('Error posting comment:', error.message);
110+
process.exit(1);
111+
}
112+
}
113+
114+
commentOnPR();

.github/workflows/validate-entries.yml

Lines changed: 8 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ jobs:
6060
- name: Install dependencies
6161
if: steps.check-files.outputs.should_run == 'true'
6262
run: |
63-
npm install jsdom cheerio
63+
npm install jsdom cheerio @octokit/rest
6464
6565
- name: Get changed files
6666
if: steps.check-files.outputs.should_run == 'true'
@@ -75,75 +75,10 @@ jobs:
7575
CHANGED_FILES: ${{ steps.changed-files.outputs.files }}
7676

7777
- name: Comment on PR
78-
uses: actions/github-script@v7
79-
if: (success() || failure()) && steps.check-files.outputs.should_run == 'true' && github.event.inputs.dry_run != 'true'
80-
with:
81-
script: |
82-
const fs = require('fs');
83-
let results = {};
84-
let hasErrors = false;
85-
86-
if (fs.existsSync('validation-results.json')) {
87-
results = JSON.parse(fs.readFileSync('validation-results.json', 'utf8'));
88-
hasErrors = Object.values(results).some(issues => issues.length > 0);
89-
}
90-
91-
// Determine overall status
92-
const status = hasErrors ? '🚫 Entry Validation Failed' : '✅ Entry Validation Passed';
93-
let comment = `## ${status}\n\n`;
94-
95-
// Add requirements checklist
96-
comment += '### Requirements Checklist:\n\n';
97-
98-
// Check each requirement across all files
99-
let fileSizePass = true;
100-
let htmlStructurePass = true;
101-
let noExternalImportsPass = true;
102-
let noNetworkRequestsPass = true;
103-
let htmlSyntaxPass = true;
104-
let entryRegisteredPass = true;
105-
106-
for (const [file, issues] of Object.entries(results)) {
107-
issues.forEach(issue => {
108-
if (issue.includes('File size') && issue.includes('exceeds')) fileSizePass = false;
109-
if (issue.includes('File must have') || issue.includes('HTML structure')) htmlStructurePass = false;
110-
if (issue.includes('External') && (issue.includes('stylesheet') || issue.includes('script') || issue.includes('image') || issue.includes('resource'))) noExternalImportsPass = false;
111-
if (issue.includes('network request')) noNetworkRequestsPass = false;
112-
if (issue.includes('HTML syntax') || issue.includes('Unclosed')) htmlSyntaxPass = false;
113-
if (issue.includes('Entry not found') || issue.includes('entries.js')) entryRegisteredPass = false;
114-
});
115-
}
116-
117-
comment += `- ${fileSizePass ? '✅' : '❌'} File must be less than 1MB\n`;
118-
comment += `- ${htmlStructurePass ? '✅' : '❌'} Valid HTML file structure\n`;
119-
comment += `- ${noExternalImportsPass ? '✅' : '❌'} No external file imports (images, CSS, JS)\n`;
120-
comment += `- ${noNetworkRequestsPass ? '✅' : '❌'} No network requests\n`;
121-
comment += `- ${htmlSyntaxPass ? '✅' : '❌'} Valid HTML syntax\n`;
122-
comment += `- ${entryRegisteredPass ? '✅' : '❌'} Entry registered in entries.js\n\n`;
123-
124-
// Add detailed issues if any exist
125-
if (hasErrors) {
126-
comment += '### Issues Found:\n\n';
127-
for (const [file, issues] of Object.entries(results)) {
128-
if (issues.length > 0) {
129-
comment += `**${file}:**\n`;
130-
issues.forEach(issue => {
131-
comment += `- ${issue}\n`;
132-
});
133-
comment += '\n';
134-
}
135-
}
136-
comment += 'Please fix the issues above and update your pull request.';
137-
} else {
138-
comment += 'All entries meet the One HTML Page Challenge requirements! 🎉';
139-
}
140-
141-
// Determine which PR to comment on
142-
const issueNumber = context.issue.number || '${{ github.event.inputs.pr_number }}';
143-
144-
github.rest.issues.createComment({
145-
issue_number: issueNumber,
146-
owner: context.repo.owner,
147-
repo: context.repo.repo,
148-
body: comment
149-
});
78+
if: (success() || failure()) && steps.check-files.outputs.should_run == 'true'
79+
run: node .github/scripts/comment-on-pr.js
80+
env:
81+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
82+
GITHUB_REPOSITORY: ${{ github.repository }}
83+
PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }}
84+
DRY_RUN: ${{ github.event.inputs.dry_run || 'false' }}

0 commit comments

Comments
 (0)