-
Notifications
You must be signed in to change notification settings - Fork 208
282 lines (262 loc) · 10.8 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
# Complete CI workflow
# Run by bors, 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/cancel-action@0.2
# 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:
# Environment variables used by toolchain
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
# Local variables
# Note: using variables is limited at the moment, see https://github.com/actions/runner/issues/480
GDRUST_FEATURES: "gdnative/async,gdnative/serde"
on:
push:
branches:
- staging
- trying
defaults:
run:
shell: bash
jobs:
rustfmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- 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@v2
- 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;
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.51', postfix: ' (msrv 1.51)' }
testflags: '-- --skip ui_tests'
runs-on: ${{ matrix.os.id }}
steps:
- uses: actions/checkout@v2
- name: "Install Rust"
uses: ./.github/composite/rust
with:
rust: ${{ matrix.rust.toolchain }}
- 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@v2
- 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@v2
- 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/0.4.62/cargo-dinghy-macos-0.4.62.tgz -o cargo-dinghy-macos.tar.gz;
tar -zxvf cargo-dinghy-macos.tar.gz;
mkdir -p $HOME/.cargo/bin;
cp cargo-dinghy-0.4.62/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@v2
- name: "Install Rust"
uses: ./.github/composite/rust
#with:
# rust: ${{ matrix.rust.toolchain }}
- name: "Install Java + NDK"
run: |
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64;
export ANDROID_SDK_ROOT=/opt/ndk/android-ndk-r21d;
# 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 openjdk-8-jdk;
sudo apt-get install llvm-dev libclang-dev clang g++-multilib gcc-multilib libc6-dev libc6-dev-arm64-cross;
# Downloading NDK. This file is huge (1Gb) maybe extract only what's needed and repackage.;
# See https://developer.android.com/ndk/downloads for updates.;
# The Android SDK which comes with Android Studio is not required. Only Java + NDK are.;
mkdir /opt/ndk
install -d /opt/ndk;
cd /opt/ndk && wget -nc -nv https://dl.google.com/android/repository/android-ndk-r21d-linux-x86_64.zip && cd $GITHUB_WORKSPACE;
echo "bcf4023eb8cb6976a4c7cff0a8a8f145f162bf4d /opt/ndk/android-ndk-r21d-linux-x86_64.zip" >> /opt/ndk/SHA1SUM.txt;
sha1sum --check /opt/ndk/SHA1SUM.txt;
cd /opt/ndk && unzip -q android-ndk-r21d-linux-x86_64.zip && cd $GITHUB_WORKSPACE;
# Using clang linker from NDK when building Android programs.;
install -d $HOME/.cargo;
echo >> $HOME/.cargo/config;
echo "[target.aarch64-linux-android]" >> $HOME/.cargo/config;
find /opt/ndk -name aarch64-linux-android21-clang++ -printf 'linker = "%p"\n' >> $HOME/.cargo/config;
echo >> $HOME/.cargo/config;
echo "[target.armv7-linux-androideabi]" >> $HOME/.cargo/config;
find /opt/ndk -name armv7a-linux-androideabi21-clang++ -printf 'linker = "%p"\n' >> $HOME/.cargo/config;
echo >> $HOME/.cargo/config;
- name: "Build Rust for targets: aarch64-linux-android, armv7-linux-androideabi"
run: |
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.4.1"
postfix: ''
- rust: nightly
godot: "3.4.1"
postfix: ' (nightly)'
- rust: '1.51'
godot: "3.4.1"
postfix: ' (msrv 1.51)'
# Test with oldest supported engine version
- rust: stable
godot: "3.2"
postfix: ''
build_args: '--features custom-godot'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: "Run Godot integration test"
uses: ./.github/composite/godot
with:
rust_toolchain: ${{ matrix.rust }}
rust_extra_args: ${{ matrix.build_args }}
godot_ver: ${{ matrix.godot }}
# This job doesn't actually test anything, but is used to tell bors that the build completed,
# as there is no practical way to detect when a workflow is successful, listening to webhooks only.
# The ID (not name) of this job is the one referenced in bors.toml.
#
# ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
full-ci:
if: github.event_name == 'push' && success()
needs:
#- rustfmt
- clippy
- test
- integration-test-godot
- build-release
- build-ios
- build-android
runs-on: ubuntu-latest
steps:
- name: "Mark the job as a success"
run: exit 0