-
Notifications
You must be signed in to change notification settings - Fork 0
208 lines (179 loc) · 6.44 KB
/
ci.yml
File metadata and controls
208 lines (179 loc) · 6.44 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
name: ci
on:
push:
branches: ['**']
paths:
- "Cargo.*"
- "**/*.rs"
- "crates/*/testdata/**"
- ".github/workflows/ci.yml"
pull_request:
branches: [main]
paths:
- "Cargo.*"
- "crates/*/src/**"
jobs:
msrv:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.msrv.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Get the minimum supported rust version (MSRV)
id: msrv
run: |
version=$(sed -rn '/^rust-version\s*=/ s/^.*=\s*"([0-9](\.[0-9]+)+)(.*)/\1/p' Cargo.toml)
if [[ -n ${version} ]]; then
echo "version=${version}" >> $GITHUB_OUTPUT
else
exit 1
fi
test:
needs: msrv
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- os: ubuntu-latest
rust-version: ${{ needs.msrv.outputs.version }}
rust: msrv
- os: ubuntu-latest
rust-version: stable
rust: stable
- os: macos-latest
rust-version: stable
rust: stable
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Set up rust toolchain
uses: dtolnay/rust-toolchain@master
id: rust
with:
toolchain: ${{ matrix.rust-version }}
components: llvm-tools-preview
- name: Install tools on macOS
if: runner.os == 'macOS'
run: |
# install the latest bash release -- macos defaults to an ancient version due to licensing
brew install bash
- name: Restore cache
uses: actions/cache/restore@v4
id: restore-cache
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
target
key: ${{ github.workflow }}-${{ github.job }}-${{ runner.os }}-rust-${{ matrix.rust }}-${{ steps.rust.outputs.cachekey }}-cargo-${{ hashFiles('Cargo.lock') }}
- name: Remove old caches
if: ${{ github.ref_name == 'main' && steps.restore-cache.outputs.cache-hit != 'true' }}
continue-on-error: true
shell: bash
run: |
gh extension install actions/gh-actions-cache
REPO=${{ github.repository }}
BRANCH=${{ github.ref }}
KEY=${{ github.workflow }}-${{ github.job }}-${{ runner.os }}-rust-${{ matrix.rust }}-
# find matching caches
mapfile -t cache_keys < <( gh actions-cache list -R $REPO -B $BRANCH --key $KEY --sort created-at --order desc | cut -f 1 )
# remove all matching caches
for key in ${cache_keys[@]}
do
gh actions-cache delete $key -R $REPO -B $BRANCH --confirm
done
exit 0
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build tests
run: |
# only collect coverage for the latest rust release on linux
if [[ ${{ matrix.rust }} == 'stable' && ${{ runner.os }} == 'Linux' ]]; then
export RUSTFLAGS="-C instrument-coverage"
export CFLAGS="-Wl,--build-id"
export LLVM_PROFILE_FILE="${PWD}/target/%b-%4m.profraw"
fi
# build tests
cargo build --features test --workspace --tests
# remove unnecessary profile data
if [[ ${{ matrix.rust }} == 'stable' && ${{ runner.os }} == 'Linux' ]]; then
find . -name \*.profraw -delete
fi
- name: Save cache
if: ${{ github.ref_name == 'main' && steps.restore-cache.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v4
with:
path: |
~/.cargo/registry/index
~/.cargo/registry/cache
~/.cargo/git/db
target
key: ${{ steps.restore-cache.outputs.cache-primary-key }}
- name: Install grcov
if: ${{ matrix.rust == 'stable' && runner.os == 'Linux' }}
uses: taiki-e/install-action@grcov
- name: Install cargo-nextest
uses: taiki-e/install-action@nextest
- name: Run tests
id: test
run: |
# set environment variables needed for coverage
if [[ ${{ matrix.rust }} == 'stable' && ${{ runner.os }} == 'Linux' ]]; then
export RUSTFLAGS="-C instrument-coverage"
export CFLAGS="-Wl,--build-id"
export LLVM_PROFILE_FILE="${PWD}/target/%b-%4m.profraw"
fi
# run tests
cargo nextest run --features test --workspace --tests
# default to not uploading coverage
COVERAGE=false
# only collect coverage for the latest rust release on linux
if [[ ${{ matrix.rust }} == 'stable' && ${{ runner.os }} == 'Linux' ]]; then
# move all profile data respecting $LLVM_PROFILE_FILE to the expected location
mkdir -p target/coverage
mv target/*.profraw target/coverage
# process coverage information
mkdir coverage
grcov target/coverage \
--source-dir . --binary-path target/debug --llvm --branch \
--keep-only "crates/*/src/*" -t html,lcov -o coverage \
--excl-line "unreachable!(.*)|grcov-excl-line" \
--excl-start grcov-excl-start \
--excl-stop grcov-excl-stop
# Manually check if coverage processing failed since grcov doesn't return a
# failure status on error.
#
# See the upstream issue at https://github.com/mozilla/grcov/issues/1160.
if [[ $(grep -c . coverage/lcov) -le 1 ]]; then
echo "::warning:: Skipping code coverage, grcov failed processing data"
else
COVERAGE=true
fi
# error out if $LLVM_PROFILE_FILE isn't being respected by any tests
rm -rf target/coverage
profraw_files=$(find . -name \*.profraw)
if [[ -n "${profraw_files}" ]]; then
echo "Unknown profraw files: ${profraw_files}"
exit 1
fi
fi
# set output to disable uploading code coverage on grcov failure
echo "coverage=${COVERAGE}" >> $GITHUB_OUTPUT
- name: Upload coverage artifacts
if: ${{ steps.test.outputs.coverage == 'true' }}
uses: actions/upload-artifact@v6
with:
name: coverage
path: coverage
if-no-files-found: error
retention-days: 1
- name: Upload coverage to Codecov
if: ${{ steps.test.outputs.coverage == 'true' }}
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage/lcov
disable_search: true
fail_ci_if_error: false