-
Notifications
You must be signed in to change notification settings - Fork 3
270 lines (230 loc) · 10.2 KB
/
coverage.yml
File metadata and controls
270 lines (230 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
name: Generate Konflux Coverage Dashboard
on:
push:
branches:
- main
pull_request:
branches:
- main
schedule:
- cron: '0 3 * * *' # Daily at 03:00 UTC
workflow_dispatch:
jobs:
generate-coverage:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: read # Allow reading PR information
steps:
- name: Checkout this repo (dashboard)
uses: actions/checkout@v4
with:
# For pull requests, this will checkout the PR branch with merge commit
# For push events, this will checkout the pushed branch
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.23'
cache: false # Disable caching since this isn't a Go project
- name: Install tools
run: |
sudo apt-get update
sudo apt-get install -y jq
pip install yq
- name: Install and setup envtest
run: |
# Install setup-envtest
go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
# Setup envtest binaries and get the path
ENVTEST_ASSETS_DIR=$(setup-envtest use -p path)
echo "KUBEBUILDER_ASSETS=$ENVTEST_ASSETS_DIR" >> $GITHUB_ENV
echo "Envtest assets installed at: $ENVTEST_ASSETS_DIR"
- name: Prepare workspace
run: mkdir workspace
- name: Checkout gh-pages
uses: actions/checkout@v4
with:
ref: gh-pages
path: gh-pages
- name: Clone repos and calculate coverage
run: |
cd workspace
echo "[" > ../_temp_coverage.json
OLD_COVERAGE_JSON=$(cat ../gh-pages/coverage.json || echo "[]")
# Iterate through all repository configuration files
for config_file in ../repos/*.yaml; do
REPO=$(yq -r '.name' "$config_file")
REPO_NAME=$(basename "$REPO")
echo "→ Processing $REPO (from $(basename "$config_file"))..."
# Get exclude patterns BEFORE entering repo directory
EXCLUDE_DIRS_ARRAY=$(yq '.exclude_dirs // []' "$config_file")
EXCLUDE_FILES=$(yq '.exclude_files // []' "$config_file")
echo "→ Cloning $REPO..."
git clone --depth 1 "https://github.com/$REPO.git"
cd "$REPO_NAME"
# Build the exclude pattern more carefully
EXCLUDE_PATTERN=""
if [ "$EXCLUDE_DIRS_ARRAY" != "[]" ]; then
# Process each exclude pattern individually
PATTERN_COUNT=$(echo "$EXCLUDE_DIRS_ARRAY" | yq 'length')
PATTERNS=""
for k in $(seq 0 $((PATTERN_COUNT - 1))); do
PATTERN=$(echo "$EXCLUDE_DIRS_ARRAY" | yq ".[$k]" | tr -d '"')
echo " Processing exclude pattern: '$PATTERN'"
# Handle different pattern types
case "$PATTERN" in
*/*)
# Pattern with slashes - treat as path pattern
if [[ "$PATTERN" == /* ]]; then
# Starts with slash, use as-is but escape special chars
ESCAPED_PATTERN=$(echo "$PATTERN" | sed 's/[[\.*^$()+{}|]/\\&/g')
else
# Add leading slash and treat trailing slash specially
if [[ "$PATTERN" == */ ]]; then
# Ends with slash - match directory component
DIR_NAME=${PATTERN%/}
ESCAPED_PATTERN="/${DIR_NAME}(/|$)"
else
# Has slash but doesn't end with one
ESCAPED_PATTERN="/$(echo "$PATTERN" | sed 's/[[\.*^$()+{}|]/\\&/g')"
fi
fi
;;
*)
# Simple directory name - match as path component
ESCAPED_PATTERN="/${PATTERN}(/|$)"
;;
esac
echo " Escaped pattern: '$ESCAPED_PATTERN'"
if [ -z "$PATTERNS" ]; then
PATTERNS="$ESCAPED_PATTERN"
else
PATTERNS="$PATTERNS|$ESCAPED_PATTERN"
fi
done
EXCLUDE_PATTERN="$PATTERNS"
echo " Final exclude pattern: '$EXCLUDE_PATTERN'"
fi
# Get packages and apply exclusions
ALL_PACKAGES=$(go list ./... 2>/dev/null || true)
echo " All packages found:"
echo "$ALL_PACKAGES" | while read pkg; do echo " $pkg"; done
if [ -n "$EXCLUDE_PATTERN" ] && [ -n "$ALL_PACKAGES" ]; then
echo " Applying exclusion pattern: $EXCLUDE_PATTERN"
INCLUDED_PACKAGES=$(echo "$ALL_PACKAGES" | grep -vE "$EXCLUDE_PATTERN" || true)
echo " Packages after exclusion:"
echo "$INCLUDED_PACKAGES" | while read pkg; do [ -n "$pkg" ] && echo " $pkg"; done
echo " Original packages: $(echo "$ALL_PACKAGES" | wc -l)"
echo " Included packages: $(echo "$INCLUDED_PACKAGES" | wc -l)"
else
INCLUDED_PACKAGES="$ALL_PACKAGES"
echo " No exclusion pattern applied"
fi
STATUS="ok"
COVERAGE="0.0"
if [ -n "$INCLUDED_PACKAGES" ]; then
echo " Running tests with coverage..."
# Fail fast - let test failures fail the workflow for visibility
# Filter out packages with no test files to avoid covdata errors
TESTABLE_PACKAGES=""
for pkg in $INCLUDED_PACKAGES; do
if go list -f '{{if or .TestGoFiles .XTestGoFiles}}{{.ImportPath}}{{end}}' $pkg 2>/dev/null | grep -q .; then
TESTABLE_PACKAGES="$TESTABLE_PACKAGES $pkg"
fi
done
if [ -z "$TESTABLE_PACKAGES" ]; then
echo " ❌ No packages with test files found"
STATUS="failed"
COVERAGE=null
else
go test -coverprofile=coverage_raw.out $TESTABLE_PACKAGES
fi
if [ -f coverage_raw.out ]; then
cp coverage_raw.out coverage.out
# Remove excluded files from coverage
FILE_COUNT=$(echo "$EXCLUDE_FILES" | yq 'length')
for j in $(seq 0 $((FILE_COUNT - 1))); do
FILE=$(echo "$EXCLUDE_FILES" | yq ".[$j]" | tr -d '"')
echo " Removing $FILE from coverage"
sed -i "/$FILE/d" coverage.out || true
done
COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | tr -d '%')
# Extract per-package coverage by parsing coverage profile directly
# This gives statement-weighted coverage, not function-count average
PACKAGES_JSON=$(awk '
NR==1 { next } # Skip "mode: set" line
{
# Parse: file.go:start.col,end.col numStmts covered
split($1, parts, ":")
file = parts[1]
numStmts = $2
covered = ($3 > 0) ? numStmts : 0
# Extract package path (everything before last /)
n=split(file, pathParts, "/")
pkg=""
for(i=1; i<n; i++) {
if(i>1) pkg = pkg "/"
pkg = pkg pathParts[i]
}
# Accumulate covered and total statements per package
pkgTotal[pkg] += numStmts
pkgCovered[pkg] += covered
}
END {
printf "["
first=1
for(pkg in pkgTotal) {
if(!first) printf ","
cov = (pkgTotal[pkg] > 0) ? (pkgCovered[pkg] / pkgTotal[pkg] * 100) : 0
printf "{\"package\":\"%s\",\"coverage\":%.1f}", pkg, cov
first=0
}
printf "]"
}' coverage.out)
# Generate HTML report
go tool cover -html=coverage.out -o coverage.html
mkdir -p ../../gh-pages/coverage/$REPO
cp coverage.html ../../gh-pages/coverage/$REPO/index.html
else
echo " ❌ No coverage file generated - tests may not have run properly"
STATUS="failed"
COVERAGE=null
PACKAGES_JSON="[]"
fi
else
echo " ❌ No testable packages found"
STATUS="failed"
COVERAGE=null
PACKAGES_JSON="[]"
fi
echo " → $REPO coverage: $COVERAGE% (status: $STATUS)"
echo " {\"repo\": \"$REPO\", \"coverage\": $COVERAGE, \"status\": \"$STATUS\", \"packages\": $PACKAGES_JSON }," >> ../../_temp_coverage.json
cd ..
done
cd ..
sed -i '$ s/,$//' _temp_coverage.json
echo "]" >> _temp_coverage.json
- name: Wrap coverage.json with run_url
run: |
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
jq -n \
--arg run_url "$RUN_URL" \
--argjson data "$(cat _temp_coverage.json)" \
'{run_url: $run_url, data: $data}' > coverage.json
- name: Commit and push updated coverage.json
# Only push to gh-pages from main branch pushes and scheduled runs (not on PRs)
if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
run: |
cp coverage.json gh-pages/coverage.json
cp index.html gh-pages/index.html
cd gh-pages
git config user.name "github-actions"
git config user.email "github-actions@github.com"
git add coverage.json coverage/ index.html
if git diff --cached --quiet; then
echo "No changes to commit"
else
git commit -m "Update coverage data on $(date --utc)"
git push origin gh-pages
fi