1+ # Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
2+ #
3+ # Licensed under the Apache License, Version 2.0 (the "License");
4+ # you may not use this file except in compliance with the License.
5+ # You may obtain a copy of the License at
6+ #
7+ # http://www.apache.org/licenses/LICENSE-2.0
8+ #
9+ # Unless required by applicable law or agreed to in writing, software
10+ # distributed under the License is distributed on an "AS IS" BASIS,
11+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ # See the License for the specific language governing permissions and
13+ # limitations under the License.
14+
15+ name : Coverage Report
16+
17+ on :
18+ workflow_run :
19+ workflows : ["Lint and Test"]
20+ types :
21+ - completed
22+ branches :
23+ - main
24+ - " pull-request/[0-9]+"
25+
26+ permissions :
27+ contents : read # Required for checking out code
28+ actions : write # Required for downloading artifacts
29+ pull-requests : write # Required for coverage report comments
30+
31+ env :
32+ # Go cache settings (specific to this workflow)
33+ GOPATH : /home/runner/go
34+ GOCACHE : /home/runner/.cache/go-build
35+
36+ jobs :
37+ coverage-report :
38+ # Only run on successful completion of lint-test workflow for PR branches
39+ if : github.event.workflow_run.conclusion == 'success' && (github.event.workflow_run.event == 'pull_request' || startsWith(github.event.workflow_run.head_branch, 'pull-request/'))
40+ runs-on : linux-amd64-cpu4
41+ timeout-minutes : 15
42+ steps :
43+ - uses : actions/checkout@v4
44+ with :
45+ ref : ${{ github.event.workflow_run.head_sha }}
46+
47+ - name : Download all coverage artifacts from completed workflow
48+ uses : actions/download-artifact@v4
49+ with :
50+ pattern : " *-results"
51+ path : coverage-artifacts
52+ merge-multiple : true
53+ run-id : ${{ github.event.workflow_run.id }}
54+
55+ - name : Consolidate coverage files
56+ run : |
57+ echo "Consolidating coverage files from all components..."
58+ mkdir -p consolidated-coverage
59+
60+ # Find all coverage.txt files and merge them
61+ find coverage-artifacts -name "coverage.txt" -type f | while read -r file; do
62+ echo "Processing: $file"
63+ # Extract the mode line (first line) if it's the first file
64+ if [ ! -f consolidated-coverage/coverage.txt ]; then
65+ head -n 1 "$file" > consolidated-coverage/coverage.txt
66+ fi
67+ # Append coverage data (skip mode line)
68+ tail -n +2 "$file" >> consolidated-coverage/coverage.txt
69+ done
70+
71+ echo "Consolidated coverage file created:"
72+ ls -la consolidated-coverage/
73+ head -n 10 consolidated-coverage/coverage.txt
74+
75+ - name : Upload consolidated coverage
76+ uses : actions/upload-artifact@v4
77+ with :
78+ name : consolidated-code-coverage
79+ path : consolidated-coverage/coverage.txt
80+ retention-days : 30
81+
82+ - name : Extract PR number from branch name
83+ id : pr-number
84+ run : |
85+ if [[ "${{ github.event.workflow_run.head_branch }}" =~ pull-request/([0-9]+) ]]; then
86+ echo "pr_number=${BASH_REMATCH[1]}" >> $GITHUB_OUTPUT
87+ else
88+ echo "pr_number=" >> $GITHUB_OUTPUT
89+ fi
90+
91+ - name : Setup Go
92+ uses : actions/setup-go@v5
93+ with :
94+ go-version : ' stable'
95+
96+ - name : Install go-coverage-report CLI tool
97+ run : go install github.com/fgrosse/go-coverage-report/cmd/go-coverage-report@latest
98+
99+ - name : Get changed files
100+ uses : tj-actions/changed-files@aa08304bd477b800d468db44fe10f6c61f7f7b11
101+ id : changed-files
102+ with :
103+ write_output_files : true
104+ json : true
105+ files : " **.go"
106+ files_ignore : " vendor/**"
107+ output_dir : .github/outputs
108+
109+ - name : Generate Coverage Report with Fixed PR Number
110+ run : |
111+ # Download current coverage
112+ gh run download "${{ github.event.workflow_run.id }}" --name=consolidated-code-coverage --dir=/tmp/current-coverage
113+ mv /tmp/current-coverage/coverage.txt .github/outputs/new-coverage.txt
114+
115+ # Download baseline coverage from main
116+ LAST_SUCCESSFUL_RUN=$(gh run list --status=success --branch=main --workflow=lint-test.yml --event=push --json=databaseId --limit=1 -q '.[] | .databaseId')
117+
118+ if [[ -n "$LAST_SUCCESSFUL_RUN" ]]; then
119+ gh run download "$LAST_SUCCESSFUL_RUN" --name=consolidated-code-coverage --dir=/tmp/baseline-coverage 2>/dev/null || true
120+ if [[ -f /tmp/baseline-coverage/coverage.txt ]]; then
121+ mv /tmp/baseline-coverage/coverage.txt .github/outputs/old-coverage.txt
122+ fi
123+ fi
124+
125+ # Generate the report using fgrosse's CLI tool (same format!)
126+ go-coverage-report -root=github.com/NVIDIA/nvsentinel \
127+ .github/outputs/old-coverage.txt \
128+ .github/outputs/new-coverage.txt \
129+ .github/outputs/all_modified_files.json > coverage-report.md 2>&1 || true
130+
131+ # Post comment using our correct PR number (this is the only fix needed!)
132+ if [[ -n "${{ steps.pr-number.outputs.pr_number }}" && -f coverage-report.md ]]; then
133+ # Check for existing coverage comment
134+ EXISTING_COMMENT=$(gh api "repos/${{ github.repository }}/issues/${{ steps.pr-number.outputs.pr_number }}/comments" \
135+ --jq '.[] | select(.user.login=="github-actions[bot]" and (.body | test("Coverage Report|Coverage Δ"))) | .id' \
136+ | head -1)
137+
138+ COVERAGE_BODY=$(cat coverage-report.md)
139+
140+ if [[ -n "$EXISTING_COMMENT" ]]; then
141+ echo "Updating existing comment..."
142+ gh api "repos/${{ github.repository }}/issues/${{ steps.pr-number.outputs.pr_number }}/comments/$EXISTING_COMMENT" \
143+ --method PATCH --field body="$COVERAGE_BODY"
144+ else
145+ echo "Creating new comment..."
146+ gh api "repos/${{ github.repository }}/issues/${{ steps.pr-number.outputs.pr_number }}/comments" \
147+ --method POST --field body="$COVERAGE_BODY"
148+ fi
149+ fi
150+ env :
151+ GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
152+ continue-on-error : true # Don't fail if baseline coverage doesn't exist yet
153+
154+ coverage-baseline :
155+ # Only run on successful completion of lint-test workflow for main branch
156+ if : github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'main' && github.event.workflow_run.event == 'push'
157+ runs-on : linux-amd64-cpu4
158+ timeout-minutes : 15
159+ steps :
160+ - uses : actions/checkout@v4
161+ with :
162+ ref : ${{ github.event.workflow_run.head_sha }}
163+
164+ - name : Setup Go
165+ uses : actions/setup-go@v5
166+ with :
167+ go-version : ' stable'
168+
169+ - name : Download all coverage artifacts from completed workflow
170+ uses : actions/download-artifact@v4
171+ with :
172+ pattern : " *-results"
173+ path : coverage-artifacts
174+ merge-multiple : true
175+ run-id : ${{ github.event.workflow_run.id }}
176+
177+ - name : Consolidate coverage files
178+ run : |
179+ echo "Consolidating coverage files from all components for baseline..."
180+ mkdir -p consolidated-coverage
181+
182+ # Find all coverage.txt files and merge them
183+ find coverage-artifacts -name "coverage.txt" -type f | while read -r file; do
184+ echo "Processing: $file"
185+ # Extract the mode line (first line) if it's the first file
186+ if [ ! -f consolidated-coverage/coverage.txt ]; then
187+ head -n 1 "$file" > consolidated-coverage/coverage.txt
188+ fi
189+ # Append coverage data (skip mode line)
190+ tail -n +2 "$file" >> consolidated-coverage/coverage.txt
191+ done
192+
193+ echo "Baseline coverage file created:"
194+ ls -la consolidated-coverage/
195+ echo "Total coverage lines: $(wc -l < consolidated-coverage/coverage.txt)"
196+
197+ - name : Upload consolidated coverage baseline
198+ uses : actions/upload-artifact@v4
199+ with :
200+ name : consolidated-code-coverage
201+ path : consolidated-coverage/coverage.txt
202+ retention-days : 90 # Keep baseline longer
0 commit comments