forked from claude-did-this/claude-hub
fix: Fix syntax errors and code formatting issues
- Fixed missing catch clause in handleWebhook function - Removed extra closing braces causing syntax errors - Fixed indentation issues throughout githubController.js - Updated lint scripts for ESLint 9 flat config - Applied automatic formatting fixes - Fixed test data for check-suite tests All tests now pass and code meets linting standards. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
committed by
Cheffromspace
parent
7182855dbe
commit
78815925da
@@ -14,8 +14,8 @@
|
||||
"test:watch": "jest --watch",
|
||||
"test:ci": "jest --ci --coverage",
|
||||
"pretest": "./scripts/utils/ensure-test-dirs.sh",
|
||||
"lint": "eslint src/ test/ --ext .js --fix",
|
||||
"lint:check": "eslint src/ test/ --ext .js",
|
||||
"lint": "eslint src/ test/ --fix",
|
||||
"lint:check": "eslint src/ test/",
|
||||
"format": "prettier --write src/ test/",
|
||||
"format:check": "prettier --check src/ test/",
|
||||
"security:audit": "npm audit --audit-level=moderate",
|
||||
|
||||
@@ -426,89 +426,90 @@ Please check with an administrator to review the logs for more details.`
|
||||
|
||||
// Only proceed if the check suite is for a pull request and conclusion is success
|
||||
if (checkSuite.conclusion === 'success' && checkSuite.pull_requests && checkSuite.pull_requests.length > 0) {
|
||||
try {
|
||||
for (const pr of checkSuite.pull_requests) {
|
||||
// Verify ALL required status checks have passed using Combined Status API
|
||||
let combinedStatus;
|
||||
try {
|
||||
// Verify ALL required status checks have passed using Combined Status API
|
||||
let combinedStatus;
|
||||
try {
|
||||
// Use the check suite's head_sha if pr.head.sha is not available
|
||||
const commitSha = pr.head?.sha || checkSuite.head_sha;
|
||||
const commitSha = pr.head?.sha || checkSuite.head_sha;
|
||||
|
||||
if (!commitSha) {
|
||||
logger.error(
|
||||
{
|
||||
repo: repo.full_name,
|
||||
pr: pr.number,
|
||||
prData: JSON.stringify(pr),
|
||||
checkSuiteData: {
|
||||
id: checkSuite.id,
|
||||
head_sha: checkSuite.head_sha,
|
||||
head_branch: checkSuite.head_branch
|
||||
}
|
||||
},
|
||||
'No commit SHA available for PR - cannot check combined status'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (!commitSha) {
|
||||
logger.error(
|
||||
{
|
||||
repo: repo.full_name,
|
||||
pr: pr.number,
|
||||
prData: JSON.stringify(pr),
|
||||
checkSuiteData: {
|
||||
id: checkSuite.id,
|
||||
head_sha: checkSuite.head_sha,
|
||||
head_branch: checkSuite.head_branch
|
||||
}
|
||||
},
|
||||
'No commit SHA available for PR - cannot check combined status'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
logger.info(
|
||||
{
|
||||
repo: repo.full_name,
|
||||
pr: pr.number,
|
||||
prHeadSha: pr.head?.sha,
|
||||
checkSuiteHeadSha: checkSuite.head_sha,
|
||||
usingSha: commitSha
|
||||
},
|
||||
'Getting combined status for PR'
|
||||
);
|
||||
|
||||
combinedStatus = await githubService.getCombinedStatus({
|
||||
repoOwner: repo.owner.login,
|
||||
repoName: repo.name,
|
||||
ref: commitSha
|
||||
});
|
||||
|
||||
// Only proceed if ALL status checks are successful
|
||||
if (combinedStatus.state !== 'success') {
|
||||
logger.info(
|
||||
{
|
||||
repo: repo.full_name,
|
||||
pr: pr.number,
|
||||
checkSuite: checkSuite.id,
|
||||
combinedState: combinedStatus.state,
|
||||
totalChecks: combinedStatus.total_count
|
||||
prHeadSha: pr.head?.sha,
|
||||
checkSuiteHeadSha: checkSuite.head_sha,
|
||||
usingSha: commitSha
|
||||
},
|
||||
'Skipping PR review - not all required status checks have passed'
|
||||
'Getting combined status for PR'
|
||||
);
|
||||
|
||||
combinedStatus = await githubService.getCombinedStatus({
|
||||
repoOwner: repo.owner.login,
|
||||
repoName: repo.name,
|
||||
ref: commitSha
|
||||
});
|
||||
|
||||
// Only proceed if ALL status checks are successful
|
||||
if (combinedStatus.state !== 'success') {
|
||||
logger.info(
|
||||
{
|
||||
repo: repo.full_name,
|
||||
pr: pr.number,
|
||||
checkSuite: checkSuite.id,
|
||||
combinedState: combinedStatus.state,
|
||||
totalChecks: combinedStatus.total_count
|
||||
},
|
||||
'Skipping PR review - not all required status checks have passed'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
{
|
||||
err: error.message,
|
||||
repo: repo.full_name,
|
||||
pr: pr.number,
|
||||
checkSuite: checkSuite.id
|
||||
},
|
||||
'Error checking combined status - skipping PR review'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
|
||||
logger.info(
|
||||
{
|
||||
err: error.message,
|
||||
repo: repo.full_name,
|
||||
pr: pr.number,
|
||||
checkSuite: checkSuite.id
|
||||
checkSuite: checkSuite.id,
|
||||
conclusion: checkSuite.conclusion,
|
||||
combinedState: combinedStatus.state,
|
||||
totalChecks: combinedStatus.total_count
|
||||
},
|
||||
'Error checking combined status - skipping PR review'
|
||||
'All checks passed - triggering automated PR review'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
logger.info(
|
||||
{
|
||||
repo: repo.full_name,
|
||||
pr: pr.number,
|
||||
checkSuite: checkSuite.id,
|
||||
conclusion: checkSuite.conclusion,
|
||||
combinedState: combinedStatus.state,
|
||||
totalChecks: combinedStatus.total_count
|
||||
},
|
||||
'All checks passed - triggering automated PR review'
|
||||
);
|
||||
|
||||
try {
|
||||
try {
|
||||
// Create the PR review prompt
|
||||
const prReviewPrompt = `## PR Review Workflow Instructions
|
||||
const prReviewPrompt = `## PR Review Workflow Instructions
|
||||
|
||||
You are Claude, acting as a professional code reviewer through Claude Code CLI. Your task is to review GitHub pull requests and provide constructive feedback.
|
||||
|
||||
@@ -588,37 +589,37 @@ After completing the review, all output from this process will be automatically
|
||||
|
||||
Please perform a comprehensive review of PR #${pr.number} in repository ${repo.full_name}.`;
|
||||
|
||||
// Process the PR review with Claude
|
||||
logger.info('Sending PR for automated Claude review');
|
||||
const claudeResponse = await claudeService.processCommand({
|
||||
repoFullName: repo.full_name,
|
||||
issueNumber: pr.number,
|
||||
command: prReviewPrompt,
|
||||
isPullRequest: true,
|
||||
branchName: pr.head.ref
|
||||
});
|
||||
// Process the PR review with Claude
|
||||
logger.info('Sending PR for automated Claude review');
|
||||
const claudeResponse = await claudeService.processCommand({
|
||||
repoFullName: repo.full_name,
|
||||
issueNumber: pr.number,
|
||||
command: prReviewPrompt,
|
||||
isPullRequest: true,
|
||||
branchName: pr.head.ref
|
||||
});
|
||||
|
||||
logger.info(
|
||||
{
|
||||
repo: repo.full_name,
|
||||
pr: pr.number,
|
||||
responseLength: claudeResponse ? claudeResponse.length : 0
|
||||
},
|
||||
'Automated PR review completed successfully'
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
{
|
||||
errorMessage: error.message || 'Unknown error',
|
||||
errorType: error.constructor.name,
|
||||
repo: repo.full_name,
|
||||
pr: pr.number,
|
||||
checkSuite: checkSuite.id
|
||||
},
|
||||
'Error processing automated PR review'
|
||||
);
|
||||
logger.info(
|
||||
{
|
||||
repo: repo.full_name,
|
||||
pr: pr.number,
|
||||
responseLength: claudeResponse ? claudeResponse.length : 0
|
||||
},
|
||||
'Automated PR review completed successfully'
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
{
|
||||
errorMessage: error.message || 'Unknown error',
|
||||
errorType: error.constructor.name,
|
||||
repo: repo.full_name,
|
||||
pr: pr.number,
|
||||
checkSuite: checkSuite.id
|
||||
},
|
||||
'Error processing automated PR review'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return success after processing all PRs
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
@@ -630,32 +631,52 @@ Please perform a comprehensive review of PR #${pr.number} in repository ${repo.f
|
||||
pullRequests: checkSuite.pull_requests.map(pr => pr.number)
|
||||
}
|
||||
});
|
||||
} else if (checkSuite.head_branch) {
|
||||
// If no pull requests in payload but we have a head_branch,
|
||||
// this might be a PR from a fork - log for debugging
|
||||
logger.warn(
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
{
|
||||
err: error,
|
||||
repo: repo.full_name,
|
||||
checkSuite: checkSuite.id,
|
||||
headBranch: checkSuite.head_branch,
|
||||
headSha: checkSuite.head_sha
|
||||
checkSuite: checkSuite.id
|
||||
},
|
||||
'Check suite succeeded but no pull requests found in payload - possible fork PR'
|
||||
'Error processing check suite for PR reviews'
|
||||
);
|
||||
|
||||
// TODO: Could query GitHub API to find PRs for this branch/SHA
|
||||
// For now, just acknowledge the webhook
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
message: 'Check suite completed but no PRs found in payload',
|
||||
return res.status(500).json({
|
||||
success: false,
|
||||
error: 'Failed to process check suite',
|
||||
message: error.message,
|
||||
context: {
|
||||
repo: repo.full_name,
|
||||
checkSuite: checkSuite.id,
|
||||
conclusion: checkSuite.conclusion,
|
||||
headBranch: checkSuite.head_branch
|
||||
type: 'check_suite'
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (checkSuite.head_branch) {
|
||||
// If no pull requests in payload but we have a head_branch,
|
||||
// this might be a PR from a fork - log for debugging
|
||||
logger.warn(
|
||||
{
|
||||
repo: repo.full_name,
|
||||
checkSuite: checkSuite.id,
|
||||
headBranch: checkSuite.head_branch,
|
||||
headSha: checkSuite.head_sha
|
||||
},
|
||||
'Check suite succeeded but no pull requests found in payload - possible fork PR'
|
||||
);
|
||||
|
||||
// TODO: Could query GitHub API to find PRs for this branch/SHA
|
||||
// For now, just acknowledge the webhook
|
||||
return res.status(200).json({
|
||||
success: true,
|
||||
message: 'Check suite completed but no PRs found in payload',
|
||||
context: {
|
||||
repo: repo.full_name,
|
||||
checkSuite: checkSuite.id,
|
||||
conclusion: checkSuite.conclusion,
|
||||
headBranch: checkSuite.head_branch
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Log the specific reason why PR review was not triggered
|
||||
const reasons = [];
|
||||
|
||||
@@ -1,17 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites name="jest tests" tests="6" failures="0" errors="0" time="0.321">
|
||||
<testsuite name="GitHub Controller - Check Suite Events" errors="0" failures="0" skipped="0" timestamp="2025-05-22T21:32:17" time="0.279" tests="6">
|
||||
<testsuites name="jest tests" tests="30" failures="0" errors="0" time="0.65">
|
||||
<testsuite name="GitHub Controller - Check Suite Events" errors="0" failures="0" skipped="0" timestamp="2025-05-22T21:49:28" time="0.424" tests="6">
|
||||
<testcase classname="GitHub Controller - Check Suite Events should trigger PR review when check suite succeeds with PRs" name="GitHub Controller - Check Suite Events should trigger PR review when check suite succeeds with PRs" time="0.005">
|
||||
</testcase>
|
||||
<testcase classname="GitHub Controller - Check Suite Events should not trigger PR review when check suite fails" name="GitHub Controller - Check Suite Events should not trigger PR review when check suite fails" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="GitHub Controller - Check Suite Events should not trigger PR review when check suite succeeds but has no PRs" name="GitHub Controller - Check Suite Events should not trigger PR review when check suite succeeds but has no PRs" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="GitHub Controller - Check Suite Events should handle multiple PRs in check suite" name="GitHub Controller - Check Suite Events should handle multiple PRs in check suite" time="0.002">
|
||||
<testcase classname="GitHub Controller - Check Suite Events should handle multiple PRs in check suite" name="GitHub Controller - Check Suite Events should handle multiple PRs in check suite" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="GitHub Controller - Check Suite Events should handle Claude service errors gracefully" name="GitHub Controller - Check Suite Events should handle Claude service errors gracefully" time="0">
|
||||
</testcase>
|
||||
<testcase classname="GitHub Controller - Check Suite Events should use check suite head_sha when PR head.sha is missing" name="GitHub Controller - Check Suite Events should use check suite head_sha when PR head.sha is missing" time="0">
|
||||
</testcase>
|
||||
</testsuite>
|
||||
<testsuite name="githubService" errors="0" failures="0" skipped="0" timestamp="2025-05-22T21:49:29" time="0.044" tests="10">
|
||||
<testcase classname="githubService getFallbackLabels should identify bug labels correctly" name="githubService getFallbackLabels should identify bug labels correctly" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="githubService getFallbackLabels should identify feature labels correctly" name="githubService getFallbackLabels should identify feature labels correctly" time="0">
|
||||
</testcase>
|
||||
<testcase classname="githubService getFallbackLabels should identify enhancement labels correctly" name="githubService getFallbackLabels should identify enhancement labels correctly" time="0">
|
||||
</testcase>
|
||||
<testcase classname="githubService getFallbackLabels should identify question labels correctly" name="githubService getFallbackLabels should identify question labels correctly" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="githubService getFallbackLabels should identify documentation labels correctly" name="githubService getFallbackLabels should identify documentation labels correctly" time="0">
|
||||
</testcase>
|
||||
<testcase classname="githubService getFallbackLabels should default to medium priority when no specific priority keywords found" name="githubService getFallbackLabels should default to medium priority when no specific priority keywords found" time="0">
|
||||
</testcase>
|
||||
<testcase classname="githubService getFallbackLabels should handle empty descriptions gracefully" name="githubService getFallbackLabels should handle empty descriptions gracefully" time="0">
|
||||
</testcase>
|
||||
<testcase classname="githubService addLabelsToIssue - test mode should return mock data in test mode" name="githubService addLabelsToIssue - test mode should return mock data in test mode" time="0">
|
||||
</testcase>
|
||||
<testcase classname="githubService createRepositoryLabels - test mode should return labels array in test mode" name="githubService createRepositoryLabels - test mode should return labels array in test mode" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="githubService postComment - test mode should return mock comment data in test mode" name="githubService postComment - test mode should return mock comment data in test mode" time="0">
|
||||
</testcase>
|
||||
</testsuite>
|
||||
<testsuite name="AWS Credential Provider" errors="0" failures="0" skipped="0" timestamp="2025-05-22T21:49:29" time="0.044" tests="7">
|
||||
<testcase classname="AWS Credential Provider should get credentials from AWS profile" name="AWS Credential Provider should get credentials from AWS profile" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="AWS Credential Provider should cache credentials" name="AWS Credential Provider should cache credentials" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="AWS Credential Provider should clear credential cache" name="AWS Credential Provider should clear credential cache" time="0">
|
||||
</testcase>
|
||||
<testcase classname="AWS Credential Provider should get Docker environment variables" name="AWS Credential Provider should get Docker environment variables" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="AWS Credential Provider should throw error if AWS_PROFILE is not set" name="AWS Credential Provider should throw error if AWS_PROFILE is not set" time="0.008">
|
||||
</testcase>
|
||||
<testcase classname="AWS Credential Provider should throw error for non-existent profile" name="AWS Credential Provider should throw error for non-existent profile" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="AWS Credential Provider should throw error for incomplete credentials" name="AWS Credential Provider should throw error for incomplete credentials" time="0.001">
|
||||
</testcase>
|
||||
</testsuite>
|
||||
<testsuite name="GitHub Controller" errors="0" failures="0" skipped="0" timestamp="2025-05-22T21:49:29" time="0.043" tests="4">
|
||||
<testcase classname="GitHub Controller should process a valid webhook with @TestBot mention" name="GitHub Controller should process a valid webhook with @TestBot mention" time="0.002">
|
||||
</testcase>
|
||||
<testcase classname="GitHub Controller should reject a webhook with invalid signature" name="GitHub Controller should reject a webhook with invalid signature" time="0.008">
|
||||
</testcase>
|
||||
<testcase classname="GitHub Controller should ignore comments without @TestBot mention" name="GitHub Controller should ignore comments without @TestBot mention" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="GitHub Controller should handle errors from Claude service" name="GitHub Controller should handle errors from Claude service" time="0.005">
|
||||
</testcase>
|
||||
</testsuite>
|
||||
<testsuite name="Container Execution E2E Tests" errors="0" failures="0" skipped="0" timestamp="2025-05-22T21:49:29" time="0.022" tests="3">
|
||||
<testcase classname="Container Execution E2E Tests Container should be properly configured" name="Container Execution E2E Tests Container should be properly configured" time="0.001">
|
||||
</testcase>
|
||||
<testcase classname="Container Execution E2E Tests Should process a simple Claude request" name="Container Execution E2E Tests Should process a simple Claude request" time="0">
|
||||
</testcase>
|
||||
<testcase classname="Container Execution E2E Tests Should handle errors gracefully" name="Container Execution E2E Tests Should handle errors gracefully" time="0">
|
||||
</testcase>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
@@ -86,9 +86,9 @@ app.post('/webhook', (req, res) => {
|
||||
// Start server
|
||||
app.listen(PORT, () => {
|
||||
logger.info({ port: PORT }, `Debug webhook server listening on port ${PORT}`);
|
||||
console.log(`\nTo test this webhook receiver:`);
|
||||
console.log('\nTo test this webhook receiver:');
|
||||
console.log(`1. Configure your GitHub webhook to point to: http://YOUR_SERVER:${PORT}/webhook`);
|
||||
console.log(`2. Make sure to include check_suite events in the webhook configuration`);
|
||||
console.log(`3. Trigger a check suite completion in your repository`);
|
||||
console.log(`4. Check the logs above for detailed information\n`);
|
||||
console.log('2. Make sure to include check_suite events in the webhook configuration');
|
||||
console.log('3. Trigger a check suite completion in your repository');
|
||||
console.log('4. Check the logs above for detailed information\n');
|
||||
});
|
||||
Reference in New Issue
Block a user