-
Notifications
You must be signed in to change notification settings - Fork 15
271 lines (242 loc) Β· 10.9 KB
/
coverage.yaml
File metadata and controls
271 lines (242 loc) Β· 10.9 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
271
name: Code coverage
on:
pull_request:
types: [opened, synchronize, reopened, labeled]
concurrency:
group: ${{ github.repository_id }}-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
shell: "bash -ex {0}"
permissions:
contents: read
jobs:
label-check:
if: >-
(github.event.action == 'labeled' && github.event.label.name == 'ci:coverage'
|| github.event.action != 'labeled' && contains(github.event.pull_request.labels.*.name, 'ci:coverage'))
&& !github.event.pull_request.head.repo.fork
runs-on: ubuntu-24.04
steps:
- run: 'true'
cooldown-check:
name: Cargo cooldown check
runs-on: ubuntu-24.04
needs: label-check
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: ./.github/actions/cooldown-check
coverage:
needs: [label-check, cooldown-check]
runs-on: solx-linux-amd64
permissions:
contents: read
pull-requests: write
packages: read
container:
image: ghcr.io/nomicfoundation/solx-ci-runner@sha256:c0866d146261cd0a51dc7d9077444b8ac3dde12c53d2151137834e6be149dbc7
env:
BOOST_PREFIX: ${{ github.workspace }}/solx-solidity/boost/lib
SOLC_PREFIX: ${{ github.workspace }}/solx-solidity/build
PROFDATA_FILE: solx.profdata
LCOV_FILE: codecov.lcov
OUTPUT_HTML_DIR: COVERAGE
COVERAGE_IGNORE_REGEX: '/(solx-llvm|target-llvm|solx-solidity|\.cargo|cargo/registry)/'
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
submodules: true
- name: Checkout submodules
run: |
git config --global --add safe.directory '*'
git submodule update --init --force --depth=1 --recursive --checkout
- name: Build LLVM
uses: ./.github/actions/build-llvm
with:
build-type: 'RelWithDebInfo'
enable-assertions: 'false'
enable-coverage: 'true'
enable-mlir: 'true'
- name: Building solc
uses: ./.github/actions/build-solc
with:
cmake-build-type: RelWithDebInfo
working-dir: 'solx-solidity'
- name: Build solx
id: build-solx
uses: ./.github/actions/build-rust
with:
exec_name: 'solx'
build-type: 'release'
enable-coverage: 'true'
target: 'x86_64-unknown-linux-gnu'
- name: Run integration tests
run: |
TMP="${PROFDATA_FILE}.tmp"
TARGET_DIR="./target/x86_64-unknown-linux-gnu/release"
for TEST_PATH in tests/solidity/simple/default.sol tests/solidity/complex/default; do
WORKDIR=$(basename ${TEST_PATH})
mkdir -p "${GITHUB_WORKSPACE}/${WORKDIR}"
"${TARGET_DIR}/solx-dev" test solx-tester \
--binary "${TARGET_DIR}/solx-tester" \
--solidity-compiler ${{ steps.build-solx.outputs.binary-path }} \
--path ${TEST_PATH} --workflow build --optimizer M3B3
mv *.profraw "${GITHUB_WORKSPACE}/${WORKDIR}/" || true
find "${GITHUB_WORKSPACE}/${WORKDIR}" -type f -name '*.profraw' -print > profiles.lst
if [[ -f "${PROFDATA_FILE}" ]]; then
llvm-profdata merge -sparse -num-threads="$(nproc)" -o "${TMP}" "${PROFDATA_FILE}" @profiles.lst
else
llvm-profdata merge -sparse -num-threads="$(nproc)" -o "${TMP}" @profiles.lst
fi
mv -f "${TMP}" "${PROFDATA_FILE}"
rm -rf "${GITHUB_WORKSPACE}/${WORKDIR}"
done
- name: Preserve instrumented binary
env:
SOLX_BINARY: ${{ steps.build-solx.outputs.binary-path }}
run: |
cp "${SOLX_BINARY}" "${GITHUB_WORKSPACE}/solx-instrumented"
cp "./target/x86_64-unknown-linux-gnu/release/solx-tester" "${GITHUB_WORKSPACE}/solx-tester-instrumented"
cp "./target/x86_64-unknown-linux-gnu/release/solx-dev" "${GITHUB_WORKSPACE}/solx-dev-instrumented"
- name: Run unit tests
env:
RUSTC_BOOTSTRAP: 1
RUSTFLAGS: '-C target-feature=+crt-static -C instrument-coverage -C link-arg=-fuse-ld=lld'
LLVM_PROFILE_FILE: 'unit-tests-%p-%m.profraw'
run: cargo fetch --locked && cargo test --frozen --release --target x86_64-unknown-linux-gnu
# Inkwell feature poisoning: solc path builds inkwell with LLVM linking,
# slang path needs no-llvm-linking. cargo clean cannot reliably clear
# cached llvm-sys build script output. Use a separate target directory
# for complete isolation.
- name: Run slang unit tests
if: contains(github.event.pull_request.labels.*.name, 'ci:slang')
env:
RUSTC_BOOTSTRAP: 1
RUSTFLAGS: '-C instrument-coverage -C link-arg=-fuse-ld=lld'
LLVM_PROFILE_FILE: 'slang-tests-%p-%m.profraw'
CARGO_TARGET_DIR: target-slang
run: cargo test-slang --frozen --release --target x86_64-unknown-linux-gnu
- name: Preserve slang instrumented binary
if: contains(github.event.pull_request.labels.*.name, 'ci:slang')
run: cp "./target-slang/x86_64-unknown-linux-gnu/release/solx" "${GITHUB_WORKSPACE}/solx-slang-instrumented"
- name: Merge slang test profraw
if: contains(github.event.pull_request.labels.*.name, 'ci:slang')
run: |
find . -name 'slang-tests-*.profraw' -print > slang-profiles.lst
if [ -s slang-profiles.lst ]; then
TMP="${PROFDATA_FILE}.tmp"
llvm-profdata merge -sparse -num-threads="$(nproc)" -o "${TMP}" "${PROFDATA_FILE}" @slang-profiles.lst
mv -f "${TMP}" "${PROFDATA_FILE}"
find . -name 'slang-tests-*.profraw' -delete
fi
- name: Merge unit test profraw
run: |
find . -name 'unit-tests-*.profraw' -print > unit-profiles.lst
if [ -s unit-profiles.lst ]; then
TMP="${PROFDATA_FILE}.tmp"
llvm-profdata merge -sparse -num-threads="$(nproc)" -o "${TMP}" "${PROFDATA_FILE}" @unit-profiles.lst
mv -f "${TMP}" "${PROFDATA_FILE}"
find . -name 'unit-tests-*.profraw' -delete
fi
- name: Generate coverage reports
run: |
OBJECTS=(
-object "${GITHUB_WORKSPACE}/solx-instrumented"
-object "${GITHUB_WORKSPACE}/solx-tester-instrumented"
-object "${GITHUB_WORKSPACE}/solx-dev-instrumented"
)
[ -f "${GITHUB_WORKSPACE}/solx-slang-instrumented" ] && OBJECTS+=(-object "${GITHUB_WORKSPACE}/solx-slang-instrumented")
llvm-cov show --show-directory-coverage \
--format=html --output-dir=${OUTPUT_HTML_DIR} \
--ignore-filename-regex="${COVERAGE_IGNORE_REGEX}" \
-instr-profile=${PROFDATA_FILE} "${OBJECTS[@]}"
mkdir -p llvm
llvm-cov export --format=lcov \
--ignore-filename-regex="${COVERAGE_IGNORE_REGEX}" \
-instr-profile=${PROFDATA_FILE} \
"${OBJECTS[@]}" > ./llvm/${LCOV_FILE}
- name: Coverage summary
id: coverage-summary
run: |
OBJECTS=(
-object "${GITHUB_WORKSPACE}/solx-instrumented"
-object "${GITHUB_WORKSPACE}/solx-tester-instrumented"
-object "${GITHUB_WORKSPACE}/solx-dev-instrumented"
)
[ -f "${GITHUB_WORKSPACE}/solx-slang-instrumented" ] && OBJECTS+=(-object "${GITHUB_WORKSPACE}/solx-slang-instrumented")
llvm-cov report -instr-profile=${PROFDATA_FILE} "${OBJECTS[@]}" \
--ignore-filename-regex="${COVERAGE_IGNORE_REGEX}" \
> coverage-report.txt
# Parse llvm-cov report into per-crate markdown table
awk '
/^---/ || /^Filename/ || /^$/ { next }
/^TOTAL/ {
total_lines = $(NF-5); total_missed = $(NF-4)
total_funcs = $(NF-8); total_missed_funcs = $(NF-7)
next
}
NF > 3 {
file = $1
n = split(file, parts, "/")
crate = ""
for (i = 1; i <= n-1; i++) {
if (parts[i] ~ /^solx/ && parts[i+1] == "src") {
crate = parts[i]; break
}
}
if (crate == "") next
lines[crate] += $(NF-5)
missed[crate] += $(NF-4)
funcs[crate] += $(NF-8)
missed_f[crate] += $(NF-7)
}
END {
for (c in lines) {
lp = (lines[c] > 0) ? (lines[c] - missed[c]) / lines[c] * 100 : 0
fp = (funcs[c] > 0) ? (funcs[c] - missed_f[c]) / funcs[c] * 100 : 0
le = (lp >= 80) ? "π’" : (lp >= 50) ? "π‘" : "π΄"
fe = (fp >= 80) ? "π’" : (fp >= 50) ? "π‘" : "π΄"
printf "| %s | %s %.1f%% | %s %.1f%% |\n", c, le, lp, fe, fp
}
lp = (total_lines > 0) ? (total_lines - total_missed) / total_lines * 100 : 0
fp = (total_funcs > 0) ? (total_funcs - total_missed_funcs) / total_funcs * 100 : 0
le = (lp >= 80) ? "π’" : (lp >= 50) ? "π‘" : "π΄"
fe = (fp >= 80) ? "π’" : (fp >= 50) ? "π‘" : "π΄"
printf "ZTOTAL| **Total** | **%s %.1f%%** | **%s %.1f%%** |\n", le, lp, fe, fp
}' coverage-report.txt > coverage-rows.txt
{
echo "| Crate | Line Coverage | Function Coverage |"
echo "|:------|:------------:|:-----------------:|"
grep -v '^ZTOTAL' coverage-rows.txt | sort
sed -n 's/^ZTOTAL//p' coverage-rows.txt
} > coverage-summary.md
cat coverage-summary.md >> "${GITHUB_STEP_SUMMARY}"
{
echo "summary<<COVERAGE_EOF"
cat coverage-summary.md
echo "COVERAGE_EOF"
} >> "${GITHUB_OUTPUT}"
- name: Post PR coverage summary
uses: mshick/add-pr-comment@ffd016c7e151d97d69d21a843022fd4cd5b96fe5 # v3.9.0
with:
message-id: 'coverage-summary'
message: |
### Coverage Summary
${{ steps.coverage-summary.outputs.summary }}
[Codecov Report](https://app.codecov.io/gh/${{ github.repository }}/pull/${{ github.event.pull_request.number }}) | [HTML Report](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}#artifacts) | [Workflow Run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
- name: Upload coverage artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: 'Coverage integration tests HTML'
path: ${{ env.OUTPUT_HTML_DIR }}
- name: Upload coverage to Codecov
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
if: (success() || failure())
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: 'llvm/codecov.lcov'
slug: ${{ github.repository }}
fail_ci_if_error: false