|
4 | 4 | workflow_dispatch: |
5 | 5 | inputs: |
6 | 6 | dry_run: |
7 | | - description: "Run without creating GitHub issues" |
| 7 | + description: "Run without creating or modifying GitHub issues" |
8 | 8 | required: false |
9 | | - default: "false" |
| 9 | + default: false |
| 10 | + type: boolean |
10 | 11 | push: |
11 | 12 | branches: |
12 | | - - master |
13 | 13 | - main |
| 14 | + - master |
14 | 15 |
|
15 | 16 | jobs: |
16 | | - sync-codacy-issues: |
17 | | - runs-on: ubuntu-latest |
18 | | - permissions: |
19 | | - issues: write |
20 | | - contents: read |
21 | | - |
22 | | - steps: |
23 | | - - name: Checkout |
24 | | - uses: actions/checkout@v4 |
25 | | - |
26 | | - - name: Install jq and gh |
27 | | - run: | |
28 | | - sudo apt-get update -y |
29 | | - sudo apt-get install -y jq gh |
30 | | -
|
31 | | - # 🔹 STEP 1: Fetch Codacy Issues |
32 | | - - name: Fetch Codacy Issues |
33 | | - env: |
34 | | - CODACY_API_TOKEN: ${{ secrets.CODACY_API_TOKEN }} |
35 | | - run: | |
36 | | - curl --request POST \ |
37 | | - --url "https://app.codacy.com/api/v3/analysis/organizations/gh/${{ github.repository_owner }}/repositories/${{ github.event.repository.name }}/issues/search" \ |
38 | | - --header "api-token: $CODACY_API_TOKEN" \ |
39 | | - --header "content-type: application/json" \ |
40 | | - --data '{"levels":["Error","Warning","High"]}' \ |
41 | | - --silent \ |
42 | | - --fail \ |
43 | | - -o codacy_issues.json |
44 | | -
|
45 | | - # 🔹 STEP 2: Ensure standard labels exist with your colors |
46 | | - - name: Ensure standard labels exist |
47 | | - env: |
48 | | - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
49 | | - run: | |
50 | | - declare -A LABELS=( |
51 | | - ["task"]="Tasks and work items|#aefcde" |
52 | | - ["refactor"]="Code cleanup and best practices|#eb69a2" |
53 | | - ["bug"]="Bugs and error-prone code|#b60205" |
54 | | - ["security"]="Security-related issues|#d93f0b" |
55 | | - ["performance"]="Performance optimization issues|#e57504" |
56 | | - ) |
57 | | - for label in "${!LABELS[@]}"; do |
58 | | - desc=${LABELS[$label]%%|*} |
59 | | - color=${LABELS[$label]##*|} |
60 | | - echo "Creating/updating label '$label'" |
61 | | - gh label create "$label" --description "$desc" --color "$color" --repo ${{ github.repository }} --force |
62 | | - done |
63 | | -
|
64 | | - # 🔹 STEP 3: Sync Codacy Issues (create/update) |
65 | | - - name: Sync Codacy Issues |
66 | | - env: |
67 | | - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
68 | | - run: | |
69 | | - dry_run="${{ github.event.inputs.dry_run }}" |
70 | | - current_issues=$(gh issue list --repo ${{ github.repository }} --state open --json number,title,body,labels) |
71 | | - |
72 | | - jq -c '.data[]' codacy_issues.json | while read -r issue; do |
73 | | - id=$(echo "$issue" | jq -r '.issueId') |
74 | | - file=$(echo "$issue" | jq -r '.filePath') |
75 | | - line=$(echo "$issue" | jq -r '.lineNumber') |
76 | | - message=$(echo "$issue" | jq -r '.message') |
77 | | - line_text=$(echo "$issue" | jq -r '.lineText // empty') |
78 | | - category=$(echo "$issue" | jq -r '.patternInfo.category') |
79 | | - severity=$(echo "$issue" | jq -r '.patternInfo.severityLevel') |
80 | | - sha=$(echo "$issue" | jq -r '.commitInfo.sha') |
81 | | - |
82 | | - title="[$category] $message" |
83 | | - |
84 | | - # Prepare the code snippet inline |
85 | | - if [ -n "$line_text" ]; then |
86 | | - # Replace literal \n from JSON and real newlines with space |
87 | | - clean_line_text=$(echo "$line_text" | tr -d '\r' | tr '\n' ' ' | sed 's/\\n/ /g') |
88 | | - code_snippet="\`\`\` |
89 | | - $clean_line_text |
90 | | - \`\`\`" |
91 | | - else |
92 | | - code_snippet="" |
93 | | - fi |
94 | | - |
95 | | - # Build the full body with Codacy ID at the top |
96 | | - body="**Codacy ID:** \`$id\` |
97 | | - |
98 | | - **File:** \`$file\` |
99 | | - **Line:** $line |
100 | | - **Rule:** $category ($severity) |
101 | | - **Commit:** \`$sha\`" |
102 | | - |
103 | | - # Append code snippet if present |
104 | | - if [ -n "$code_snippet" ]; then |
105 | | - body+=" |
106 | | - |
107 | | - **Code Snippet:** |
108 | | - $code_snippet" |
109 | | - fi |
110 | | - |
111 | | - # Determine labels based on message/category |
112 | | - labels=() |
113 | | - if echo "$message" | grep -iq "todo"; then |
114 | | - labels+=("task") |
115 | | - elif echo "$category" | grep -Eiq "best[_ ]?practice|code[_ ]?style|complexity"; then |
116 | | - labels+=("refactor") |
117 | | - elif echo "$message" | grep -iq "security"; then |
118 | | - labels+=("task" "security") |
119 | | - elif echo "$category" | grep -iq "performance"; then |
120 | | - labels+=("task" "performance") |
121 | | - elif echo "$message" | grep -Eiq "error[_ ]?prone"; then |
122 | | - labels+=("bug") |
123 | | - fi |
124 | | - |
125 | | - label_string=$(IFS=,; echo "${labels[*]}") |
126 | | - |
127 | | - # Check if issue exists |
128 | | - existing_number=$(echo "$current_issues" | jq -r --arg id "$id" '.[] | select(.body | contains($id)) | .number') |
129 | | - |
130 | | - if [ -n "$existing_number" ]; then |
131 | | - echo "Updating existing issue #$existing_number ($id)" |
132 | | - if [ "$dry_run" != "true" ]; then |
133 | | - gh issue edit "$existing_number" \ |
134 | | - --body "$body" \ |
135 | | - --add-label "$label_string" \ |
136 | | - --repo ${{ github.repository }} |
137 | | - else |
138 | | - echo "[DRY RUN] Would update issue #$existing_number with labels: $label_string" |
139 | | - fi |
140 | | - else |
141 | | - echo "Creating new issue for Codacy ID $id" |
142 | | - if [ "$dry_run" != "true" ]; then |
143 | | - gh issue create \ |
144 | | - --title "$title" \ |
145 | | - --body "$body" \ |
146 | | - --label "$label_string" \ |
147 | | - --repo ${{ github.repository }} |
148 | | - else |
149 | | - echo "[DRY RUN] Would create issue '$title' with labels: $label_string" |
150 | | - fi |
151 | | - fi |
152 | | - done |
153 | | - |
154 | | - |
155 | | - # 🔹 STEP 4: Close resolved issues |
156 | | - - name: Close resolved issues |
157 | | - env: |
158 | | - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
159 | | - run: | |
160 | | - current_ids=$(jq -r '.data[].issueId' codacy_issues.json) |
161 | | - gh issue list --repo ${{ github.repository }} --state open --label codacy --json number,body | jq -c '.[]' | while read -r issue; do |
162 | | - number=$(echo "$issue" | jq -r '.number') |
163 | | - body=$(echo "$issue" | jq -r '.body') |
164 | | - id=$(echo "$body" | grep -oE 'Codacy ID: [a-f0-9]+' | awk '{print $3}') |
165 | | - if [ -n "$id" ] && ! echo "$current_ids" | grep -q "$id"; then |
166 | | - echo "Closing stale Codacy issue #$number ($id)" |
167 | | - if [ "$dry_run" != "true" ]; then |
168 | | - gh issue close "$number" --comment "This issue no longer appears in Codacy reports and has been auto-closed." --repo ${{ github.repository }} |
169 | | - else |
170 | | - echo "[DRY RUN] Would close issue #$number" |
171 | | - fi |
172 | | - fi |
173 | | - done |
| 17 | + sync-codacy: |
| 18 | + uses: TransactionProcessing/org-ci-workflows/.github/workflows/sync-codacy-issues.yml@main |
| 19 | + with: |
| 20 | + # Pass boolean to reusable workflow |
| 21 | + dry_run: ${{ github.event.inputs.dry_run == true }} |
| 22 | + secrets: |
| 23 | + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
| 24 | + CODACY_API_TOKEN: ${{ secrets.CODACY_API_TOKEN }} |
0 commit comments