master
sh 134 lines 3.78 KB
Raw
1 #!/usr/bin/env bash
2 # pr-issues.sh -- fetch Codacy issues for a PR and emit a clustered summary.
3 #
4 # Output:
5 # - Full JSON dump of issues:
6 # <repo>/.local/audits/codacy/pr-<NNN>-<timestamp>.json
7 # - TSV summary clustering by tool / pattern / severity / file
8 # printed to stdout.
9
10 set -euo pipefail
11
12 usage() {
13 cat <<'EOF'
14 pr-issues.sh <pr-number> [options]
15
16 Fetches the Codacy v3 PR issues list for the given PR, paginating
17 through every result, and writes a JSON dump under
18 <repo>/.local/audits/codacy/. Emits a TSV summary on stdout
19 clustering issues by tool / pattern / severity / file.
20
21 Options:
22 --output PATH explicit output path for the JSON dump
23 --by <dim> summary dimension: tool|pattern|severity|file|category
24 (default: pattern)
25 --top N top-N rows in the summary (default: 25)
26 -h, --help
27
28 Required env: CODACY_TOKEN (see <repo>/.agents/ENV.md)
29 Defaults: org=netdata, repo=netdata, provider=gh
30 (override via CODACY_ORG / CODACY_REPO / CODACY_PROVIDER in .env)
31 EOF
32 }
33
34 PR=
35 OUTPUT=
36 BY=pattern
37 TOP=25
38
39 while [ $# -gt 0 ]; do
40 case "$1" in
41 --output) OUTPUT="$2"; shift 2 ;;
42 --by) BY="$2"; shift 2 ;;
43 --top) TOP="$2"; shift 2 ;;
44 -h|--help) usage; exit 0 ;;
45 -*) echo "Unknown option: $1" >&2; usage >&2; exit 2 ;;
46 *)
47 if [ -z "$PR" ]; then PR="$1"
48 else echo "Unexpected positional arg: $1" >&2; usage >&2; exit 2
49 fi
50 shift
51 ;;
52 esac
53 done
54
55 if [ -z "$PR" ]; then
56 usage >&2
57 exit 2
58 fi
59
60 # shellcheck source=SCRIPTDIR/_lib.sh disable=SC1091
61 source "$(cd "$(dirname "$0")" && pwd)/_lib.sh"
62 codacyaudit_load_env
63
64 # ---------------------------------------------------------------
65 # Output path.
66
67 if [ -z "$OUTPUT" ]; then
68 audit_dir="$(codacyaudit_audit_dir)"
69 OUTPUT="${audit_dir}/pr-${PR}-$(date -u +%Y%m%dT%H%M%SZ).json"
70 fi
71
72 echo -e "${CA_GRAY}[pr-issues] fetching issues for PR #${PR} ...${CA_NC}" >&2
73
74 # Wrap raw issues array into an envelope with metadata.
75 issues_array="$(codacyaudit_pr_issues "$PR")"
76 total="$(printf '%s' "$issues_array" | jq 'length')"
77 issues_tmp="$(mktemp "${TMPDIR:-/tmp}/codacy-pr-issues-XXXXXX")"
78 trap 'rm -f "$issues_tmp"' EXIT
79 printf '%s' "$issues_array" > "$issues_tmp"
80
81 jq -n \
82 --arg pr "$PR" \
83 --arg fetched_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
84 --argjson total "$total" \
85 --slurpfile data "$issues_tmp" \
86 '{
87 pr: ($pr | tonumber),
88 fetched_at: $fetched_at,
89 total: $total,
90 data: $data[0]
91 }' > "$OUTPUT"
92
93 echo -e "${CA_GREEN}[pr-issues]${CA_NC} wrote ${total} issue(s) to ${OUTPUT}" >&2
94 echo "$OUTPUT"
95
96 # ---------------------------------------------------------------
97 # Summary.
98
99 if [ "$total" -eq 0 ]; then
100 echo
101 echo -e "${CA_GREEN}No issues on PR #${PR}.${CA_NC}"
102 exit 0
103 fi
104
105 field_for_dim() {
106 local dim="$1"
107 case "$dim" in
108 tool) echo '.commitIssue.toolInfo.name' ;;
109 pattern) echo '.commitIssue.patternInfo.id' ;;
110 severity) echo '.commitIssue.patternInfo.severityLevel' ;;
111 file) echo '.commitIssue.filePath' ;;
112 category) echo '.commitIssue.patternInfo.category' ;;
113 *) echo "Unknown --by '$dim'" >&2; exit 2 ;;
114 esac
115 }
116
117 field_path="$(field_for_dim "$BY")"
118
119 echo
120 echo -e "${CA_CYAN}Top ${TOP} by ${BY} (PR #${PR}, ${total} total issue(s)):${CA_NC}"
121 printf '%s\n' "------------------------------------------------------------"
122
123 jq -r --argjson top "$TOP" "
124 .data
125 | group_by(${field_path} // \"(none)\")
126 | map({key: (.[0] | ${field_path} // \"(none)\"), count: length})
127 | sort_by(-.count)
128 | .[:\$top]
129 | .[]
130 | [.count, .key] | @tsv
131 " "$OUTPUT" \
132 | awk -F'\t' '{ printf "%8d %s\n", $1, $2 }'
133
134 printf '%s\n' "------------------------------------------------------------"