Skip to content

Commit eedbf0c

Browse files
Create codacy.yml
1 parent 9cb9510 commit eedbf0c

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

.github/workflows/codacy.yml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
name: Codacy Bootstrap Issues
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
dry_run:
7+
description: "Run without creating GitHub issues"
8+
required: false
9+
default: "false"
10+
push:
11+
# branches to consider in the event; optional, defaults to all
12+
branches:
13+
- main
14+
jobs:
15+
sync-codacy-issues:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
21+
- name: Fetch Codacy Issues
22+
run: |
23+
curl --request POST \
24+
--url "https://app.codacy.com/api/v3/analysis/organizations/gh/${{ github.repository_owner }}/repositories/${{ github.event.repository.name }}/issues/search" \
25+
--header "api-token: ${{ secrets.CODACY_API_TOKEN }}" \
26+
--header "content-type: application/json" \
27+
--data '{"levels":["Error","Warning","High"]}' \
28+
--silent \
29+
--fail \
30+
-o issues.json
31+
32+
- name: Extract issues
33+
run: jq '.data' issues.json > filtered_issues.json
34+
35+
- name: Create GitHub Issues
36+
uses: actions/github-script@v7
37+
with:
38+
script: |
39+
const fs = require('fs');
40+
const dryRun = "${{ github.event.inputs.dry_run }}" === "true";
41+
42+
const rawIssues = JSON.parse(fs.readFileSync('filtered_issues.json', 'utf8'));
43+
44+
const grouped = {};
45+
for (const issue of rawIssues) {
46+
grouped[issue.issueId] = grouped[issue.issueId] || [];
47+
grouped[issue.issueId].push(issue);
48+
}
49+
50+
const openIssues = await github.paginate(
51+
github.rest.issues.listForRepo,
52+
{
53+
owner: context.repo.owner,
54+
repo: context.repo.repo,
55+
state: "open"
56+
}
57+
);
58+
59+
console.log(`Fetched ${openIssues.length} open issues from GitHub`);
60+
61+
const existingIds = new Set();
62+
for (const ghIssue of openIssues) {
63+
const matches = ghIssue.body?.match(/codacy-issue-([a-f0-9]+)/g);
64+
if (matches) {
65+
matches.forEach(m => existingIds.add(m.replace("codacy-issue-", "")));
66+
}
67+
}
68+
69+
console.log(`Found ${existingIds.size} existing Codacy issues in GitHub`);
70+
71+
for (const [issueId, issues] of Object.entries(grouped)) {
72+
if (existingIds.has(issueId)) {
73+
console.log(`Skipping duplicate Codacy issueId ${issueId}`);
74+
continue;
75+
}
76+
77+
const key = `codacy-issue-${issueId}`;
78+
const first = issues[0];
79+
const title = `[Codacy] ${first.patternInfo.severityLevel} issue(s) in ${first.filePath}`;
80+
81+
let body = `Codacy detected **${issues.length}** occurrence(s) of rule \`${first.patternInfo.id}\`:\n\n`;
82+
for (const issue of issues) {
83+
body += `- **${issue.patternInfo.severityLevel}** at \`${issue.filePath}:${issue.lineNumber}\` → ${issue.message}\n`;
84+
}
85+
body += `\nSee full details in [Codacy Report](https://app.codacy.com/gh/${context.repo.owner}/${context.repo.repo}/issues)\n\n`;
86+
body += `Unique ID: \`${key}\``;
87+
88+
if (dryRun) {
89+
console.log(`[DRY RUN] Would create issue: ${title}`);
90+
} else {
91+
await github.rest.issues.create({
92+
owner: context.repo.owner,
93+
repo: context.repo.repo,
94+
title,
95+
body,
96+
labels: ["codacy"]
97+
});
98+
console.log(`✅ Created GitHub issue for Codacy issueId ${issueId}`);
99+
await new Promise(resolve => setTimeout(resolve, 2000));
100+
}
101+
}

0 commit comments

Comments
 (0)