@@ -178,32 +178,58 @@ jobs:
178178 steps :
179179 - uses : actions/checkout@v4
180180
181+ - name : Setup Go
182+ uses : actions/setup-go@v5
183+ with :
184+ go-version : ' stable'
185+
181186 - name : Download all coverage artifacts
182187 uses : actions/download-artifact@v4
183188 with :
184189 pattern : " *-results"
185190 path : coverage-artifacts
186- merge-multiple : true
191+ merge-multiple : false
187192
188193 - name : Consolidate coverage files
189194 run : |
195+ set -e
190196 echo "Consolidating coverage files from all components..."
191197 mkdir -p consolidated-coverage
192198
193- # Find all coverage.txt files and merge them
199+ # Initialize consolidated coverage with mode line
200+ echo "mode: set" > consolidated-coverage/coverage.txt
201+
202+ # Find all coverage.txt files and merge them properly
194203 find coverage-artifacts -name "coverage.txt" -type f | while read -r file; do
195204 echo "Processing: $file"
196- # Extract the mode line (first line) if it's the first file
197- if [ ! -f consolidated-coverage/coverage.txt ]; then
198- head -n 1 "$file" > consolidated-coverage/coverage.txt
205+
206+ # Validate file exists and is not empty
207+ if [[ ! -f "$file" || ! -s "$file" ]]; then
208+ echo "Warning: Skipping empty or missing file: $file"
209+ continue
210+ fi
211+
212+ # Validate coverage file format
213+ if ! head -n 1 "$file" | grep -q "^mode:"; then
214+ echo "Warning: Skipping file with invalid format (no mode line): $file"
215+ continue
199216 fi
200- # Append coverage data (skip mode line)
201- tail -n +2 "$file" >> consolidated-coverage/coverage.txt
217+
218+ # Extract coverage data (skip mode line) and validate each line
219+ tail -n +2 "$file" | while IFS= read -r line; do
220+ # Skip empty lines
221+ [[ -z "$line" ]] && continue
222+
223+ # Validate coverage line format: file.go:start.col,end.col numStmts count
224+ if [[ "$line" =~ ^[^:]+:[0-9]+\.[0-9]+,[0-9]+\.[0-9]+[[:space:]]+[0-9]+[[:space:]]+[0-9]+$ ]]; then
225+ echo "$line" >> consolidated-coverage/coverage.txt
226+ else
227+ echo "Warning: Skipping malformed coverage line: $line"
228+ fi
229+ done
202230 done
203231
204- echo "Consolidated coverage file created:"
205- ls -la consolidated-coverage/
206- head -n 10 consolidated-coverage/coverage.txt
232+ echo "✅ Coverage consolidation completed successfully"
207233
208234 - name : Upload consolidated coverage
209235 uses : actions/upload-artifact@v4
@@ -212,14 +238,125 @@ jobs:
212238 path : consolidated-coverage/coverage.txt
213239 retention-days : 30
214240
215- - name : Generate Go Coverage Report
216- uses : fgrosse/go-coverage-report@8c1d1a09864211d258937b1b1a5b849f7e4f2682 # v1.2.0
241+ - name : Extract PR number from branch name
242+ id : pr-number
243+ run : |
244+ if [[ "${{ github.ref }}" =~ pull-request/([0-9]+) ]]; then
245+ echo "pr_number=${BASH_REMATCH[1]}" >> $GITHUB_OUTPUT
246+ else
247+ echo "pr_number=" >> $GITHUB_OUTPUT
248+ fi
249+
250+ - name : Install go-coverage-report CLI tool
251+ run :
go install github.com/fgrosse/go-coverage-report/cmd/[email protected] 252+
253+ - name : Get changed files
254+ uses : tj-actions/changed-files@aa08304bd477b800d468db44fe10f6c61f7f7b11
255+ id : changed-files
217256 with :
218- coverage-artifact-name : " consolidated-code-coverage"
219- coverage-file-name : " coverage.txt"
220- root-package : " github.com/NVIDIA/nvsentinel"
221- skip-comment : false
222- continue-on-error : true # Don't fail if baseline coverage doesn't exist yet
257+ write_output_files : true
258+ json : true
259+ files : " **.go"
260+ files_ignore : " vendor/**"
261+ output_dir : .github/outputs
262+
263+ - name : Generate Coverage Report with Fixed PR Number
264+ run : |
265+ set -e # Exit on error
266+
267+ # Current coverage is already uploaded in this workflow
268+ echo "Downloading current coverage..."
269+ if ! gh run download "${{ github.run_id }}" --name=consolidated-code-coverage --dir=/tmp/current-coverage; then
270+ echo "❌ Failed to download current coverage artifacts"
271+ exit 1
272+ fi
273+
274+ if [[ ! -f /tmp/current-coverage/coverage.txt ]]; then
275+ echo "❌ Current coverage file not found"
276+ exit 1
277+ fi
278+
279+ mv /tmp/current-coverage/coverage.txt .github/outputs/new-coverage.txt
280+
281+ # Download baseline coverage from main (failure here is acceptable)
282+ echo "Downloading baseline coverage..."
283+ LAST_SUCCESSFUL_RUN=$(gh run list --status=success --branch=main --workflow=lint-test.yml --event=push --json=databaseId --limit=1 -q '.[] | .databaseId')
284+
285+ if [[ -n "$LAST_SUCCESSFUL_RUN" ]]; then
286+ echo "Found baseline run: $LAST_SUCCESSFUL_RUN"
287+ if gh run download "$LAST_SUCCESSFUL_RUN" --name=consolidated-code-coverage --dir=/tmp/baseline-coverage 2>/dev/null; then
288+ if [[ -f /tmp/baseline-coverage/coverage.txt ]]; then
289+ echo "✅ Baseline coverage found"
290+ mv /tmp/baseline-coverage/coverage.txt .github/outputs/old-coverage.txt
291+ else
292+ echo "⚠️ Baseline coverage file not found in artifact"
293+ touch .github/outputs/old-coverage.txt # Create empty file
294+ fi
295+ else
296+ echo "⚠️ Failed to download baseline coverage (creating empty baseline)"
297+ touch .github/outputs/old-coverage.txt # Create empty file
298+ fi
299+ else
300+ echo "⚠️ No successful baseline run found (creating empty baseline)"
301+ touch .github/outputs/old-coverage.txt # Create empty file
302+ fi
303+
304+ # Generate the report using fgrosse's CLI tool (same format!)
305+ echo "Generating coverage report..."
306+ if ! go-coverage-report -root=github.com/NVIDIA/nvsentinel \
307+ .github/outputs/old-coverage.txt \
308+ .github/outputs/new-coverage.txt \
309+ .github/outputs/all_modified_files.json > coverage-report.md 2> coverage-report.err; then
310+ echo "❌ Failed to generate coverage report"
311+ exit 1
312+ fi
313+
314+ # Check if report is empty and why
315+ if [[ ! -f coverage-report.md || ! -s coverage-report.md ]]; then
316+ if grep -q "no changed files" coverage-report.err 2>/dev/null; then
317+ echo "ℹ️ No Go files changed - skipping coverage report"
318+ echo "## 📊 Coverage Report" > coverage-report.md
319+ echo "No Go files were modified in this PR, so no coverage analysis is needed." >> coverage-report.md
320+ else
321+ echo "❌ Coverage report is empty or missing for unknown reason"
322+ echo "Error output from go-coverage-report:"
323+ cat coverage-report.err || echo "No error output"
324+ exit 1
325+ fi
326+ fi
327+
328+ echo "✅ Coverage report generated successfully"
329+
330+ # Post comment using our correct PR number
331+ if [[ -n "${{ steps.pr-number.outputs.pr_number }}" ]]; then
332+ echo "Posting coverage comment to PR #${{ steps.pr-number.outputs.pr_number }}..."
333+
334+ # Check for existing coverage comment
335+ EXISTING_COMMENT=$(gh api "repos/${{ github.repository }}/issues/${{ steps.pr-number.outputs.pr_number }}/comments" \
336+ --jq '.[] | select(.user.login=="github-actions[bot]" and (.body | test("Coverage Report|Coverage Δ"))) | .id' \
337+ | head -1 2>/dev/null || echo "")
338+
339+ if [[ -n "$EXISTING_COMMENT" ]]; then
340+ echo "Updating existing comment $EXISTING_COMMENT..."
341+ if ! gh api "repos/${{ github.repository }}/issues/${{ steps.pr-number.outputs.pr_number }}/comments/$EXISTING_COMMENT" \
342+ --method PATCH --input coverage-report.md; then
343+ echo "❌ Failed to update existing coverage comment"
344+ exit 1
345+ fi
346+ else
347+ echo "Creating new comment..."
348+ if ! gh pr comment "${{ steps.pr-number.outputs.pr_number }}" --body-file=coverage-report.md; then
349+ echo "❌ Failed to create coverage comment"
350+ exit 1
351+ fi
352+ fi
353+
354+ echo "✅ Coverage comment posted successfully"
355+ else
356+ echo "⚠️ No PR number found, skipping comment"
357+ fi
358+ env :
359+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
223360
224361 consolidated-coverage-baseline :
225362 if : github.ref == 'refs/heads/main' && github.event_name == 'push'
@@ -234,27 +371,48 @@ jobs:
234371 with :
235372 pattern : " *-results"
236373 path : coverage-artifacts
237- merge-multiple : true
374+ merge-multiple : false
238375
239376 - name : Consolidate coverage files
240377 run : |
378+ set -e
241379 echo "Consolidating coverage files from all components for baseline..."
242380 mkdir -p consolidated-coverage
243381
244- # Find all coverage.txt files and merge them
382+ # Initialize consolidated coverage with mode line
383+ echo "mode: set" > consolidated-coverage/coverage.txt
384+
385+ # Find all coverage.txt files and merge them properly
245386 find coverage-artifacts -name "coverage.txt" -type f | while read -r file; do
246387 echo "Processing: $file"
247- # Extract the mode line (first line) if it's the first file
248- if [ ! -f consolidated-coverage/coverage.txt ]; then
249- head -n 1 "$file" > consolidated-coverage/coverage.txt
388+
389+ # Validate file exists and is not empty
390+ if [[ ! -f "$file" || ! -s "$file" ]]; then
391+ echo "Warning: Skipping empty or missing file: $file"
392+ continue
393+ fi
394+
395+ # Validate coverage file format
396+ if ! head -n 1 "$file" | grep -q "^mode:"; then
397+ echo "Warning: Skipping file with invalid format (no mode line): $file"
398+ continue
250399 fi
251- # Append coverage data (skip mode line)
252- tail -n +2 "$file" >> consolidated-coverage/coverage.txt
400+
401+ # Extract coverage data (skip mode line) and validate each line
402+ tail -n +2 "$file" | while IFS= read -r line; do
403+ # Skip empty lines
404+ [[ -z "$line" ]] && continue
405+
406+ # Validate coverage line format: file.go:start.col,end.col numStmts count
407+ if [[ "$line" =~ ^[^:]+:[0-9]+\.[0-9]+,[0-9]+\.[0-9]+[[:space:]]+[0-9]+[[:space:]]+[0-9]+$ ]]; then
408+ echo "$line" >> consolidated-coverage/coverage.txt
409+ else
410+ echo "Warning: Skipping malformed coverage line: $line"
411+ fi
412+ done
253413 done
254414
255- echo "Baseline coverage file created:"
256- ls -la consolidated-coverage/
257- echo "Total coverage lines: $(wc -l < consolidated-coverage/coverage.txt)"
415+ echo "✅ Coverage consolidation completed successfully"
258416
259417 - name : Upload consolidated coverage baseline
260418 uses : actions/upload-artifact@v4
0 commit comments