Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 33 additions & 15 deletions linter-bot/postLinterReport.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,21 +86,34 @@ ${reportContent}
*This comment was automatically generated by the linter bot.*`;
}

/**
* Resolve PR number from PR_ID env var or PR_NUMBER_PATH file.
* The file-based approach supports workflow_run triggers where PR context
* is passed via artifact instead of the event payload.
* @returns {string} PR number
*/
function resolvePRNumber() {
if (process.env.PR_ID) {
return process.env.PR_ID.trim();
}

const prNumberPath = process.env.PR_NUMBER_PATH;
if (prNumberPath && fs.existsSync(prNumberPath)) {
const prNumber = fs.readFileSync(prNumberPath, 'utf8').trim();
if (prNumber) return prNumber;
}

console.error('❌ Error: PR number is required. Set PR_ID env var or PR_NUMBER_PATH pointing to a file containing the PR number.');
process.exit(1);
}

/**
* Main execution function
*/
async function main() {
// Get required environment variables
const prId = process.env.PR_ID;
const githubToken = process.env.GITHUB_TOKEN;
const githubRepository = process.env.GITHUB_REPOSITORY; // format: owner/repo

// Validate required environment variables
if (!prId) {
console.error('❌ Error: PR_ID environment variable is required');
process.exit(1);
}

if (!githubToken) {
console.error('❌ Error: GITHUB_TOKEN environment variable is required');
process.exit(1);
Expand All @@ -111,14 +124,14 @@ async function main() {
process.exit(1);
}

// Parse owner and repo from GITHUB_REPOSITORY
const prId = resolvePRNumber();

const [owner, repo] = githubRepository.split('/');
if (!owner || !repo) {
console.error('❌ Error: GITHUB_REPOSITORY must be in format "owner/repo"');
process.exit(1);
}

// Determine report path (default to current working directory)
const reportPath = process.env.LINTER_REPORT_PATH || path.join(process.cwd(), 'linter-report.txt');

console.log('📋 Linter Report Bot');
Expand All @@ -129,22 +142,26 @@ async function main() {
console.log('─'.repeat(50));

try {
// Read the linter report
console.log('📖 Reading linter report...');
const reportContent = readLinterReport(reportPath);

// Format as markdown
const markdownComment = formatReportAsMarkdown(reportContent);

// Post comment to PR
console.log('📝 Posting comment to PR...');
const result = await createPRComment(owner, repo, parseInt(prId, 10), markdownComment, githubToken);

console.log('✅ Successfully posted linter report to PR!');
console.log(` Comment URL: ${result.html_url}`);

} catch (error) {
console.error(`❌ Failed to post linter report: ${error.message}`);
if (error.message.includes('403') && error.message.includes('Resource not accessible')) {
console.error('❌ Failed to post linter report: GITHUB_TOKEN lacks write permissions.');
console.error(' For fork PRs, the default GITHUB_TOKEN is read-only.');
console.error(' Use a workflow_run trigger so the comment step runs in the base repo context.');
console.error(' See: https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_run');
} else {
console.error(`❌ Failed to post linter report: ${error.message}`);
}
process.exit(1);
}
}
Expand All @@ -156,5 +173,6 @@ main();
export {
readLinterReport,
createPRComment,
formatReportAsMarkdown
formatReportAsMarkdown,
resolvePRNumber
};