Skip to content

Commit 3a9ff7d

Browse files
committed
[WIP] test codeql and code coverage
Signed-off-by: Davanum Srinivas <[email protected]>
1 parent 0478308 commit 3a9ff7d

File tree

5 files changed

+657
-11
lines changed

5 files changed

+657
-11
lines changed

.github/workflows/code-scanning.yml

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ jobs:
3232
prepare-environment:
3333
uses: ./.github/workflows/prepare-environment.yml
3434

35-
analyze:
36-
name: Analyze Go code with CodeQL
35+
codeql-pr-analysis:
36+
if: startsWith(github.ref, 'refs/heads/pull-request/')
37+
name: CodeQL PR Analysis
3738
runs-on: linux-amd64-cpu4
3839
timeout-minutes: 360
3940
needs: prepare-environment
@@ -57,16 +58,60 @@ jobs:
5758
shellcheck-version: ${{ needs.prepare-environment.outputs.shellcheck_version }}
5859

5960
- name: Initialize CodeQL
60-
uses: github/codeql-action/init@v3
61+
uses: github/codeql-action/init@v4
6162
with:
6263
languages: go
6364
build-mode: manual
6465
env:
6566
CODEQL_EXTRACTOR_GO_BUILD_TRACING: on
66-
- shell: bash
67+
68+
- name: Build with CodeQL
6769
run: |
6870
make build-all
71+
72+
- name: Perform CodeQL Analysis
73+
uses: github/codeql-action/analyze@v4
74+
with:
75+
category: "/language:go"
76+
77+
codeql-baseline-analysis:
78+
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
79+
name: CodeQL Baseline Analysis
80+
runs-on: linux-amd64-cpu4
81+
timeout-minutes: 360
82+
needs: prepare-environment
83+
permissions:
84+
security-events: write
85+
packages: read
86+
steps:
87+
- name: Checkout repository
88+
uses: actions/checkout@v4
89+
90+
- name: Setup build environment
91+
uses: ./.github/actions/setup-build-env
92+
with:
93+
go-version: ${{ needs.prepare-environment.outputs.go_version }}
94+
python-version: ${{ needs.prepare-environment.outputs.python_version }}
95+
poetry-version: ${{ needs.prepare-environment.outputs.poetry_version }}
96+
golangci-lint-version: ${{ needs.prepare-environment.outputs.golangci_lint_version }}
97+
protobuf-version: ${{ needs.prepare-environment.outputs.protobuf_version }}
98+
protoc-gen-go-version: ${{ needs.prepare-environment.outputs.protoc_gen_go_version }}
99+
protoc-gen-go-grpc-version: ${{ needs.prepare-environment.outputs.protoc_gen_go_grpc_version }}
100+
shellcheck-version: ${{ needs.prepare-environment.outputs.shellcheck_version }}
101+
102+
- name: Initialize CodeQL
103+
uses: github/codeql-action/init@v4
104+
with:
105+
languages: go
106+
build-mode: manual
107+
env:
108+
CODEQL_EXTRACTOR_GO_BUILD_TRACING: on
109+
110+
- name: Build with CodeQL
111+
run: |
112+
make build-all
113+
69114
- name: Perform CodeQL Analysis
70-
uses: github/codeql-action/analyze@v3
115+
uses: github/codeql-action/analyze@v4
71116
with:
72117
category: "/language:go"
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
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/[email protected]
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

.github/workflows/lint-test.yml

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ 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:
@@ -212,13 +217,71 @@ jobs:
212217
path: consolidated-coverage/coverage.txt
213218
retention-days: 30
214219

215-
- name: Generate Go Coverage Report
216-
uses: fgrosse/go-coverage-report@8c1d1a09864211d258937b1b1a5b849f7e4f2682 # v1.2.0
220+
- name: Extract PR number from branch name
221+
id: pr-number
222+
run: |
223+
if [[ "${{ github.ref }}" =~ pull-request/([0-9]+) ]]; then
224+
echo "pr_number=${BASH_REMATCH[1]}" >> $GITHUB_OUTPUT
225+
else
226+
echo "pr_number=" >> $GITHUB_OUTPUT
227+
fi
228+
229+
- name: Install go-coverage-report CLI tool
230+
run: go install github.com/fgrosse/go-coverage-report/cmd/[email protected]
231+
232+
- name: Get changed files
233+
uses: tj-actions/changed-files@aa08304bd477b800d468db44fe10f6c61f7f7b11
234+
id: changed-files
217235
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
236+
write_output_files: true
237+
json: true
238+
files: "**.go"
239+
files_ignore: "vendor/**"
240+
output_dir: .github/outputs
241+
242+
- name: Generate Coverage Report with Fixed PR Number
243+
run: |
244+
# Current coverage is already uploaded in this workflow
245+
gh run download "${{ github.run_id }}" --name=consolidated-code-coverage --dir=/tmp/current-coverage
246+
mv /tmp/current-coverage/coverage.txt .github/outputs/new-coverage.txt
247+
248+
# Download baseline coverage from main
249+
LAST_SUCCESSFUL_RUN=$(gh run list --status=success --branch=main --workflow=lint-test.yml --event=push --json=databaseId --limit=1 -q '.[] | .databaseId')
250+
251+
if [[ -n "$LAST_SUCCESSFUL_RUN" ]]; then
252+
gh run download "$LAST_SUCCESSFUL_RUN" --name=consolidated-code-coverage --dir=/tmp/baseline-coverage 2>/dev/null || true
253+
if [[ -f /tmp/baseline-coverage/coverage.txt ]]; then
254+
mv /tmp/baseline-coverage/coverage.txt .github/outputs/old-coverage.txt
255+
fi
256+
fi
257+
258+
# Generate the report using fgrosse's CLI tool (same format!)
259+
go-coverage-report -root=github.com/NVIDIA/nvsentinel \
260+
.github/outputs/old-coverage.txt \
261+
.github/outputs/new-coverage.txt \
262+
.github/outputs/all_modified_files.json > coverage-report.md 2>&1 || true
263+
264+
# Post comment using our correct PR number (this is the only fix needed!)
265+
if [[ -n "${{ steps.pr-number.outputs.pr_number }}" && -f coverage-report.md ]]; then
266+
# Check for existing coverage comment
267+
EXISTING_COMMENT=$(gh api "repos/${{ github.repository }}/issues/${{ steps.pr-number.outputs.pr_number }}/comments" \
268+
--jq '.[] | select(.user.login=="github-actions[bot]" and (.body | test("Coverage Report|Coverage Δ"))) | .id' \
269+
| head -1)
270+
271+
COVERAGE_BODY=$(cat coverage-report.md)
272+
273+
if [[ -n "$EXISTING_COMMENT" ]]; then
274+
echo "Updating existing comment..."
275+
gh api "repos/${{ github.repository }}/issues/${{ steps.pr-number.outputs.pr_number }}/comments/$EXISTING_COMMENT" \
276+
--method PATCH --field body="$COVERAGE_BODY"
277+
else
278+
echo "Creating new comment..."
279+
gh api "repos/${{ github.repository }}/issues/${{ steps.pr-number.outputs.pr_number }}/comments" \
280+
--method POST --field body="$COVERAGE_BODY"
281+
fi
282+
fi
283+
env:
284+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
222285
continue-on-error: true # Don't fail if baseline coverage doesn't exist yet
223286

224287
consolidated-coverage-baseline:

0 commit comments

Comments
 (0)