Skip to content

Commit 60cec40

Browse files
committed
[CI] Add nightly ELD code coverage workflow with regression detection
Add nightly-eld-code-coverage.yml which runs daily after the nightly build. The workflow: - Builds ELD with source-based coverage instrumentation (ELD_COVERAGE=ON) - Runs the full check-eld test suite under LLVM_PROFILE_FILE to collect per-process .profraw files - Merges profiles with llvm-profdata and generates an HTML report with llvm-cov show - Extracts Line/Function/Region/Branch percentages from the TOTAL row of llvm-cov report - Compares each metric against a coverage-baseline.txt stored on the code-coverage branch; fails the workflow if any metric regresses - On first run (no baseline present) records the baseline without failing - Force-pushes the HTML report and updated baseline to the code-coverage orphan branch on every successful run Signed-off-by: bsaharsh <bsaharsh@qti.qualcomm.com>
1 parent 77e70fc commit 60cec40

1 file changed

Lines changed: 206 additions & 0 deletions

File tree

Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
name: Nightly ELD code coverage
2+
3+
on:
4+
schedule:
5+
- cron: '0 9 * * *'
6+
workflow_dispatch: {}
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
coverage:
13+
if: github.repository == 'qualcomm/eld'
14+
runs-on: self-hosted
15+
concurrency:
16+
group: ${{ github.workflow }}
17+
cancel-in-progress: true
18+
permissions:
19+
contents: write
20+
21+
env:
22+
CCACHE_DIR: /local/mnt/workspace/ccache/coverage
23+
CCACHE_BASEDIR: ${{ github.workspace }}
24+
CCACHE_COMPILERCHECK: content
25+
CCACHE_NOHASHDIR: true
26+
27+
steps:
28+
- name: Checkout llvm-project
29+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
30+
with:
31+
repository: llvm/llvm-project
32+
path: llvm-project
33+
34+
- name: Checkout eld
35+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
36+
with:
37+
repository: ${{ github.repository }}
38+
ref: ${{ github.ref_name }}
39+
path: llvm-project/llvm/tools/eld
40+
41+
- name: Setup musl environment
42+
run: echo "/opt/musl/bin" >> $GITHUB_PATH
43+
44+
- uses: ./llvm-project/llvm/tools/eld/.github/workflows/FetchNightlyToolset
45+
46+
- name: Run CMake
47+
run: |
48+
mkdir -p "$CCACHE_DIR"
49+
ccache --zero-stats
50+
ccache --set-config "max_size=0"
51+
52+
rm -rf obj
53+
mkdir -p obj
54+
cd obj
55+
cmake -G Ninja \
56+
../llvm-project/llvm/tools/eld \
57+
-DELD_USE_EXTERNAL_LLVM=ON \
58+
-DLLVM_DIR=$(llvm-config --cmakedir) \
59+
-DCMAKE_BUILD_TYPE=Debug \
60+
-DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON \
61+
-DLLVM_ENABLE_ASSERTIONS:BOOL=ON \
62+
-DCMAKE_C_COMPILER="$(which clang)" \
63+
-DCMAKE_CXX_COMPILER="$(which clang++)" \
64+
-DCMAKE_CXX_FLAGS="-stdlib=libc++" \
65+
-DELD_TARGETS_TO_BUILD="ARM;AArch64;RISCV;Hexagon;X86;Template" \
66+
-DLLVM_CCACHE_BUILD:BOOL=ON \
67+
-DLLVM_CCACHE_DIR:STRING="$CCACHE_DIR" \
68+
-DELD_ENABLE_SYMBOL_VERSIONING=ON \
69+
-DELD_ENABLE_RUN_TESTS:BOOL=ON \
70+
-DELD_LLVM_COV=ON
71+
72+
- name: Build
73+
working-directory: obj
74+
run: ninja
75+
76+
- name: Run tests with coverage profiling
77+
working-directory: obj
78+
run: |
79+
export PATH="$PATH:/opt/qemu/bin"
80+
export PATH="$PATH:/local/mnt/workspace/arm-unknown-linux-gnueabi/bin"
81+
export PATH="$PATH:/local/mnt/workspace/aarch64-unknown-linux-gnu/bin"
82+
export PATH="$PATH:/local/mnt/workspace/riscv32-unknown-linux-gnu/bin"
83+
export PATH="$PATH:/local/mnt/workspace/riscv64-unknown-linux-gnu/bin"
84+
export PATH="$PATH:/local/mnt/workspace/x86_64-unknown-linux-gnu/bin"
85+
86+
export ELD_ARM_C_COMPILER=arm-unknown-linux-gnueabi-cc
87+
export ELD_ARM_CXX_COMPILER=arm-unknown-linux-gnueabi-c++
88+
export ELD_ARM_SYSROOT=/local/mnt/workspace/arm-unknown-linux-gnueabi/arm-unknown-linux-gnueabi/sysroot
89+
export ELD_AARCH64_C_COMPILER=aarch64-unknown-linux-gnu-cc
90+
export ELD_AARCH64_CXX_COMPILER=aarch64-unknown-linux-gnu-c++
91+
export ELD_AARCH64_SYSROOT=/local/mnt/workspace/aarch64-unknown-linux-gnu/aarch64-unknown-linux-gnu/sysroot
92+
export ELD_RISCV32_C_COMPILER=riscv32-unknown-linux-gnu-cc
93+
export ELD_RISCV32_CXX_COMPILER=riscv32-unknown-linux-gnu-c++
94+
export ELD_RISCV32_SYSROOT=/local/mnt/workspace/riscv32-unknown-linux-gnu/riscv32-unknown-linux-gnu/sysroot
95+
export ELD_RISCV64_C_COMPILER=riscv64-unknown-linux-gnu-cc
96+
export ELD_RISCV64_CXX_COMPILER=riscv64-unknown-linux-gnu-c++
97+
export ELD_RISCV64_SYSROOT=/local/mnt/workspace/riscv64-unknown-linux-gnu/riscv64-unknown-linux-gnu/sysroot
98+
export ELD_X86_64_C_COMPILER=x86_64-unknown-linux-gnu-cc
99+
export ELD_X86_64_CXX_COMPILER=x86_64-unknown-linux-gnu-c++
100+
export ELD_X86_64_SYSROOT=/local/mnt/workspace/x86_64-unknown-linux-gnu/x86_64-unknown-linux-gnu/sysroot
101+
102+
LLVM_PROFILE_FILE="$PWD/eld-%p.profraw" ninja check-eld
103+
104+
- name: Summarize test results
105+
working-directory: obj
106+
run: ninja check-eld-summary
107+
108+
- name: Merge profile data
109+
working-directory: obj
110+
run: llvm-profdata merge -sparse eld-*.profraw -o eld.profdata
111+
112+
- name: Generate HTML coverage report
113+
working-directory: obj
114+
run: |
115+
llvm-cov show \
116+
--format=html \
117+
--instr-profile=eld.profdata \
118+
--object lib/libLW.so \
119+
--show-branches=count \
120+
--show-expansions \
121+
--show-instantiations \
122+
--include-filename-regex='/eld/' \
123+
-o coverage-report
124+
125+
- name: Extract coverage and check for regression
126+
working-directory: obj
127+
run: |
128+
COV_SUMMARY=$(llvm-cov report \
129+
--instr-profile=eld.profdata \
130+
--object lib/libLW.so \
131+
--include-filename-regex='/eld/')
132+
133+
TOTAL_LINE=$(echo "$COV_SUMMARY" | grep '^TOTAL')
134+
135+
REGION_COV=$(echo "$TOTAL_LINE" | awk '{print $4}')
136+
FUNC_COV=$(echo "$TOTAL_LINE" | awk '{print $7}')
137+
LINE_COV=$(echo "$TOTAL_LINE" | awk '{print $10}')
138+
BRANCH_COV=$(echo "$TOTAL_LINE" | awk '{print $13}')
139+
140+
# Export for the deploy step
141+
echo "LINE_COV=$LINE_COV" >> "$GITHUB_ENV"
142+
echo "FUNC_COV=$FUNC_COV" >> "$GITHUB_ENV"
143+
echo "REGION_COV=$REGION_COV" >> "$GITHUB_ENV"
144+
echo "BRANCH_COV=$BRANCH_COV" >> "$GITHUB_ENV"
145+
146+
# Fetch baseline from the code-coverage-reports branch (if it exists)
147+
BASELINE=$(git -C "${{ github.workspace }}/llvm-project/llvm/tools/eld" \
148+
show origin/code-coverage-reports:coverage-baseline.txt 2>/dev/null || true)
149+
150+
if [ -z "$BASELINE" ]; then
151+
echo "No baseline found — first run, will record baseline."
152+
exit 0
153+
fi
154+
155+
echo "Baseline:"
156+
echo "$BASELINE"
157+
158+
PREV_LINE=$(echo "$BASELINE" | grep '^LINE=' | cut -d= -f2)
159+
PREV_FUNC=$(echo "$BASELINE" | grep '^FUNCTION=' | cut -d= -f2)
160+
PREV_REGION=$(echo "$BASELINE" | grep '^REGION=' | cut -d= -f2)
161+
PREV_BRANCH=$(echo "$BASELINE" | grep '^BRANCH=' | cut -d= -f2)
162+
163+
# awk_lt a b — exits 0 (true) when a < b (strips trailing %)
164+
awk_lt() {
165+
awk -v a="${1%%%}" -v b="${2%%%}" 'BEGIN { exit !(a+0 < b+0) }'
166+
}
167+
168+
REGRESSIONS=""
169+
awk_lt "$LINE_COV" "$PREV_LINE" && REGRESSIONS="${REGRESSIONS} LINE: $LINE_COV < $PREV_LINE (baseline)\n"
170+
awk_lt "$FUNC_COV" "$PREV_FUNC" && REGRESSIONS="${REGRESSIONS} FUNCTION: $FUNC_COV < $PREV_FUNC (baseline)\n"
171+
awk_lt "$REGION_COV" "$PREV_REGION" && REGRESSIONS="${REGRESSIONS} REGION: $REGION_COV < $PREV_REGION (baseline)\n"
172+
awk_lt "$BRANCH_COV" "$PREV_BRANCH" && REGRESSIONS="${REGRESSIONS} BRANCH: $BRANCH_COV < $PREV_BRANCH (baseline)\n"
173+
174+
if [ -n "$REGRESSIONS" ]; then
175+
echo "Coverage regression detected:"
176+
printf "%b" "$REGRESSIONS"
177+
exit 1
178+
fi
179+
180+
echo "No regression detected."
181+
182+
- name: Deploy coverage report to code-coverage-reports branch
183+
run: |
184+
REPORT_SRC="${{ github.workspace }}/obj/coverage-report"
185+
186+
cd llvm-project/llvm/tools/eld
187+
git config user.name 'github-actions'
188+
git config user.email 'github-actions@github.com'
189+
190+
git checkout --orphan code-coverage-reports
191+
git rm -rf .
192+
193+
cp -r "${REPORT_SRC}/." .
194+
195+
printf 'LINE=%s\nFUNCTION=%s\nREGION=%s\nBRANCH=%s\n' \
196+
"${LINE_COV}" "${FUNC_COV}" "${REGION_COV}" "${BRANCH_COV}" \
197+
> coverage-baseline.txt
198+
199+
touch .nojekyll
200+
git add .
201+
git commit -m "Update ELD coverage report ($(date -u '+%Y-%m-%d'))"
202+
git push -f origin HEAD:refs/heads/code-coverage-reports
203+
204+
- name: Prune ccache after build
205+
if: always()
206+
run: ccache --evict-older-than 7200s --dir=$CCACHE_DIR

0 commit comments

Comments
 (0)