-
Notifications
You must be signed in to change notification settings - Fork 211
349 lines (323 loc) · 13.6 KB
/
full-ci.yml
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
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# Complete CI workflow
# Run by GitHub merge queues, and enforced before any PR is merged
# Includes unit and integration tests for all platforms, as well as optional nightly jobs
# See also: https://matklad.github.io/2021/09/04/fast-rust-builds.html
# Note: if workflow-wide fail-fast is needed, this step can be added at the end of *each* job.
# It will immediately cancel all outstanding jobs. This can be useful to free them up for other runs.
# - name: If job failed, cancel workflow...
# if: failure()
# uses: andymckay/[email protected]
# Note: important points about Rust caching (Swatinem/rust-cache action), which contributes majorly to speedup:
# 1. It caches only dependencies. The own crates are always fully recompiled, and incremental compilation is disabled.
# 2. It takes the current job ID as a key, which means it CANNOT cache between jobs.
# Running a prior job to reuse build artifacts is thus pointless with this action.
# 3. The dependencies in Cargo.toml are hashed into the key, thus it cannot happen that removing a dependency will still work
# due to the dependency being cached. On the other hand, it means dependency changes come with full recompile.
# 4. As the effectivity of the cache depends on previous runs and available runners, workflow execution times
# can easily vary by 30%.
# Note: if CI becomes more complex, we might look into code-generation of the action and workflow files at some point.
# 300+ LOC for a few platform tests is still OK, but there's a lot of repetition, and quite some limitations that could be addressed.
name: Full CI
env:
# Local variables
# Note: using variables is limited at the moment, see https://github.com/actions/runner/issues/480
GDRUST_FEATURES: "gdnative/async,gdnative/serde,gdnative_bindings_generator/debug"
CARGO_DENY_VERSION: "0.14.20"
CARGO_DINGHY_VERSION: "0.6.8"
CARGO_MACHETE_VERSION: "0.6.2"
on:
merge_group:
defaults:
run:
shell: bash
jobs:
rustfmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: "Install Rust"
uses: ./.github/composite/rust
with:
components: rustfmt
- name: "Check rustfmt"
run: cargo fmt --all -- --check
clippy:
name: clippy${{ matrix.rust.postfix }}
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.rust.toolchain == 'nightly' }}
needs: rustfmt
strategy:
matrix:
rust:
- toolchain: stable
postfix: ''
- toolchain: nightly
postfix: ' (nightly)'
steps:
- uses: actions/checkout@v4
- name: "Install Rust"
uses: ./.github/composite/rust
with:
rust: ${{ matrix.rust.toolchain }}
components: clippy
- name: "Check clippy"
run: cargo clippy --workspace --features ${GDRUST_FEATURES} -- -D clippy::style -D clippy::complexity -D clippy::perf -D clippy::dbg_macro -D clippy::todo -D clippy::unimplemented -D warnings
cargo-deny-machete:
runs-on: ubuntu-latest
needs: rustfmt
steps:
- uses: actions/checkout@v4
# Deny
# Note: manually downloading is ~30s faster than https://github.com/EmbarkStudios/cargo-deny-action
- name: "Install cargo-deny"
run: |
wget --no-verbose https://github.com/EmbarkStudios/cargo-deny/releases/download/$CARGO_DENY_VERSION/cargo-deny-$CARGO_DENY_VERSION-x86_64-unknown-linux-musl.tar.gz -O cargo-deny.tar.gz
tar -zxvf cargo-deny.tar.gz
mkdir -p $HOME/.cargo/bin
mv cargo-deny-$CARGO_DENY_VERSION-x86_64-unknown-linux-musl/cargo-deny $HOME/.cargo/bin
- name: "Deny non-conforming dependencies"
run: cargo deny check --config tools/deny.toml
# Machete
- name: "Install cargo-machete"
uses: baptiste0928/cargo-install@v1
with:
crate: cargo-machete
version: ${{ env.CARGO_MACHETE_VERSION }}
- name: "Use machete to cut down dependencies"
run: cargo machete
test:
name: test-${{ matrix.os.name }}${{ matrix.rust.postfix }}
needs: rustfmt
continue-on-error: ${{ matrix.rust.toolchain == 'nightly' }}
strategy:
fail-fast: true # cancel all jobs as soon as one fails?
matrix:
# Order this way because MacOS typically has longest duration, followed by Windows, so it benefits total workflow execution time.
# Additionally, the 'linux (msrv *)' special case will then be listed next to the other 'linux' jobs.
# Note: Windows uses '--target x86_64-pc-windows-msvc' by default as Cargo argument.
os:
- id: macos-latest
name: macos
- id: windows-latest
name: windows
- id: ubuntu-latest
name: linux
rust:
- toolchain: stable
postfix: ''
- toolchain: nightly
postfix: ' (nightly)'
# All non-stable versions skip UI tests, as it's usually impossible to have them satisfy all possible compiler versions simultaneously
include:
- rust: { toolchain: 'nightly' }
testflags: '-- --skip ui_tests'
- os: { id: ubuntu-latest, name: linux }
rust: { toolchain: '1.70', postfix: ' (msrv 1.70)' }
testflags: '-- --skip ui_tests'
- os: { id: ubuntu-latest, name: linux }
rust: { toolchain: 'stable', postfix: ' (minimal-deps)', special: 'minimal-deps' }
testflags: '-- --skip ui_tests'
runs-on: ${{ matrix.os.id }}
steps:
- uses: actions/checkout@v4
- name: "Install nightly Rust (minimal-deps only)"
if: ${{ matrix.rust.special == 'minimal-deps' }}
run: rustup toolchain install nightly --profile minimal --component cargo
- name: "Install minimal dependency versions from Cargo"
run: cargo +nightly update -Z minimal-versions
if: ${{ matrix.rust.special == 'minimal-deps' }}
- name: "Install Rust"
uses: ./.github/composite/rust
with:
rust: ${{ matrix.rust.toolchain }}
cache-key: ${{ matrix.rust.special }} # 'minimal-deps' or empty/not defined
- name: "Install LLVM"
uses: ./.github/composite/llvm
if: ${{ matrix.os.id == 'windows-latest' }}
- name: "Compile tests"
run: cargo test --workspace --features ${GDRUST_FEATURES} --no-run
- name: "Test"
run: cargo test --workspace --features ${GDRUST_FEATURES} ${{ matrix.testflags }}
build-release:
name: build-release-${{ matrix.os.name }}
needs: rustfmt
strategy:
fail-fast: true # cancel all jobs as soon as one fails?
matrix:
os:
- id: macos-latest
name: macos
- id: windows-latest
name: windows
- id: ubuntu-latest
name: linux
runs-on: ${{ matrix.os.id }}
steps:
- uses: actions/checkout@v4
- name: "Install Rust"
uses: ./.github/composite/rust
with:
rust: stable
- name: "Install LLVM"
uses: ./.github/composite/llvm
if: ${{ matrix.os.id == 'windows-latest' }}
- name: "Release build (check only)"
run: cargo check --release
build-ios:
needs: rustfmt
#continue-on-error: ${{ matrix.rust == 'nightly' }}
#strategy:
# matrix:
# rust: [stable]
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: "Install Rust"
uses: ./.github/composite/rust
#with:
# rust: ${{ matrix.rust.toolchain }}
- name: "Install cargo-dinghy"
run: |
rustup target add x86_64-apple-ios
curl -L https://github.com/sonos/dinghy/releases/download/$CARGO_DINGHY_VERSION/cargo-dinghy-macos-$CARGO_DINGHY_VERSION.tgz -o cargo-dinghy-macos.tar.gz
tar -zxvf cargo-dinghy-macos.tar.gz
mkdir -p $HOME/.cargo/bin
cp cargo-dinghy-$CARGO_DINGHY_VERSION/cargo-dinghy $HOME/.cargo/bin
- name: "Cross-compile to iOS"
run: |
RUNTIME_ID=$(xcrun simctl list runtimes | grep iOS | cut -d ' ' -f 7 | tail -1)
export SIM_ID=$(xcrun simctl create My-iphone11 com.apple.CoreSimulator.SimDeviceType.iPhone-11 $RUNTIME_ID)
xcrun simctl boot $SIM_ID
cd gdnative-core
cargo dinghy --platform auto-ios-x86_64 test
cd ..
cd gdnative-sys
cargo dinghy --platform auto-ios-x86_64 test
build-android:
# Note: even though Android builds for another architecture than Linux, it can reuse downloaded crates (source code, maybe 'cargo check').
needs: rustfmt
#continue-on-error: ${{ matrix.rust == 'nightly' }}
#strategy:
# matrix:
# rust: [stable]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: "Install Rust"
uses: ./.github/composite/rust
#with:
# rust: ${{ matrix.rust.toolchain }}
- name: "Install Java + NDK"
run: |
# aarch64 and armv7 cover most Android phones & tablets.
rustup target add aarch64-linux-android armv7-linux-androideabi
sudo apt-get update
sudo apt-get install llvm-dev libclang-dev clang g++-multilib gcc-multilib libc6-dev libc6-dev-arm64-cross
# Relies on ls listing alphabetically, NDK versions having fixed
# digits, and the folder not containing any other files
- name: "Find highest Android NDK version"
run: |
highestNdk=$(ls $ANDROID_SDK_ROOT/ndk | tail -n1)
echo "Highest Android NDK: $highestNdk"
echo "ANDROID_NDK_VERSION=$highestNdk" >> $GITHUB_ENV
# See https://github.com/godot-rust/godot-rust/pull/920
- name: "Found version ${{ env.ANDROID_NDK_VERSION }}. Workaround Rust bug..."
run: >
find -L $ANDROID_SDK_ROOT/ndk/$ANDROID_NDK_VERSION -name libunwind.a
-execdir sh -c 'echo "INPUT(-lunwind)" > libgcc.a' \;
- name: "Build Rust for targets: aarch64-linux-android, armv7-linux-androideabi"
run: |
export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER=$ANDROID_SDK_ROOT/ndk/$ANDROID_NDK_VERSION/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang++
export CARGO_TARGET_ARMV7_LINUX_ANDROIDEABI_LINKER=$ANDROID_SDK_ROOT/ndk/$ANDROID_NDK_VERSION/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi21-clang++
cargo build --target aarch64-linux-android --release
cargo build --target armv7-linux-androideabi --release
integration-test-godot:
name: itest-godot-${{ matrix.godot }}${{ matrix.postfix }}
needs: rustfmt
continue-on-error: ${{ matrix.rust.toolchain == 'nightly' }}
strategy:
fail-fast: false # cancel all jobs as soon as one fails?
matrix:
include:
# Latest Godot with different Rust versions
- rust: stable
godot: "3.5.1-stable"
postfix: ''
- rust: stable
godot: "3.5.1-stable"
postfix: ' (ptrcall)'
build_args: '--features ptrcall'
- rust: stable
godot: "3.5.1-stable"
postfix: ' (inventory)'
build_args: '--features inventory'
- rust: stable
godot: "3.5.1-stable"
postfix: ' (inventory)'
# Limiting no-manual-register tests to stable as to not slow down CI too far -- if inventory is
# working across all 3 Rust versions, this is likely to be as well.
build_args: '--features inventory,no-manual-register'
- rust: nightly
godot: "3.5.1-stable"
postfix: ' (nightly)'
- rust: nightly
godot: "3.5.1-stable"
postfix: ' (nightly, ptrcall)'
build_args: '--features ptrcall'
- rust: nightly
godot: "3.5.1-stable"
postfix: ' (nightly, inventory)'
build_args: '--features inventory'
- rust: '1.70'
godot: "3.5.1-stable"
postfix: ' (msrv 1.70)'
- rust: '1.70'
godot: "3.5.1-stable"
postfix: ' (msrv 1.70, ptrcall)'
build_args: '--features ptrcall'
- rust: '1.70'
godot: "3.5.1-stable"
postfix: ' (msrv 1.70, inventory)'
build_args: '--features inventory'
# Test with oldest supported engine version
- rust: stable
godot: "3.2-stable"
postfix: ''
build_args: '--features custom-godot'
- rust: stable
godot: "3.2-stable"
postfix: ' (ptrcall)'
build_args: '--features custom-godot,ptrcall'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: "Run Godot integration test"
uses: ./.github/composite/godot
with:
rust_toolchain: ${{ matrix.rust }}
rust_extra_args: ${{ matrix.build_args }}
godot_ver: ${{ matrix.godot }}
# Job to notify merge queue about success/failure. Named the same as the one in minimal-ci.
# It is always run, even on failure, to not wait until timeouts happen.
#
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
ci-status:
# Check for 'merge_group' not strictly necessary, but helpful when adding add-hoc `push:` trigger to `on:` for testing branch.
if: always() && github.event_name == 'merge_group'
needs:
- rustfmt
- clippy
- cargo-deny-machete
- test
- build-release
- build-ios
- build-android
- integration-test-godot
runs-on: ubuntu-latest
steps:
- name: "Success"
if: ${{ !(contains(needs.*.result, 'failure')) }}
run: exit 0
- name: "Failure"
if: ${{ contains(needs.*.result, 'failure') }}
run: exit 1