Repository navigation
248 lines (228 loc) · 9.57 KB
/
Copy pathci.yml
File metadata and controls
248 lines (228 loc) · 9.57 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
# builds and tests every push and pull request, on gcc and clang.
# the sanitizers are the point. a build that only passes -O2 is not verified.
name: ci
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
name: build and test
runs-on: ubuntu-24.04
# Pinned rather than floating. ubuntu-latest migrates without warning --
# it is scheduled to become 26.04 -- and a new runner image means new
# preinstalled compilers, which is how a green build goes red with no
# code changing. Bump deliberately, after watching a full run go green
# on the new image.
strategy:
matrix:
compiler: [gcc, clang]
env:
# The clang-tidy major version CI installs. Must be >= 19 for the
# KeepEmptyLines block in .clang-format, and must currently exist in
# apt.llvm.org for the runner's codename. See the install step.
LLVM_MAJOR: '24'
steps:
- uses: actions/checkout@v5
# v4 targets Node 20, which the runners now shim with a deprecation
# notice on every job. v5 targets the current runtime.
- name: set compiler
run: |
echo "CC=${{ matrix.compiler }}" >> $GITHUB_ENV
# flint compiles in a fraction of a second, so ccache buys almost nothing
# here. kept because the matrix runs the same build several times over.
- name: configure ccache
run: |
sudo apt-get update && sudo apt-get install -y ccache
ccache --max-size=50M
ccache -z
- name: release build
run: make clean && make release
- name: language tests
run: make test
- name: unit tests
run: make unit
- name: debug build and disassembler
run: make clean && make debug
# gc on every allocation plus asan and ubsan. slow, catches everything.
- name: gc stress and sanitizers
run: make clean && make stress
# The computed-goto interpreter. It is a separate binary and a separate
# build script, so nothing else in this workflow exercises it, and a
# transformation bug in scripts/to_computed_goto.py shows up as a crash at
# run time rather than as a compile error.
- name: computed-goto interpreter
run: |
make flint-goto
sh tests/run_tests.sh ./flint-goto
# clang-tidy, which reports include-hygiene problems the compiler does not.
#
# The LLVM apt packages are the point. The runner's preinstalled
# clang-format/tidy are whatever Ubuntu shipped, and .clang-format uses
# KeepEmptyLines as a nested block, which only exists in clang 19+. On the
# runner's version clang-tidy aborted before checking a single line, so
# this step had never actually run -- it just exited 2 and was marked
# continue-on-error.
#
# Pinning the toolchain is what makes it run. The --depth=1 packages are
# from the LLVM apt repo and always current.
- name: install llvm
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y wget apt-transport-https gpg
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key \
| sudo gpg --dearmor -o /usr/share/keyrings/llvm.gpg
codename=$(lsb_release -cs)
echo "deb [signed-by=/usr/share/keyrings/llvm.gpg]" \
"http://apt.llvm.org/${codename}/ llvm-toolchain-${codename} main" \
| sudo tee /etc/apt/sources.list.d/llvm.list
sudo apt-get update
# The major version is pinned rather than left to float.
#
# Asking for bare `clang-tidy` makes apt resolve to clang-tidy-<N> for
# whatever N it judges newest, and the snapshot repo carries one major
# per distro release. When that resolution picks a version the repo
# does not have, apt fails with "not installable" and the step dies
# before linting anything -- the same silent failure as before, only
# louder.
#
# The apt.llvm.org llvm-toolchain repo carries exactly one major
# version per distro release, so the only safe pin is one that is
# currently published. Verified against the noble package index:
# clang-tidy and clang-tidy-24, and nothing else. Pinning to 20 --
# which is what this was first written as -- fails the same way the
# unpinned version did, with 'clang-tidy-20 is not installable'.
#
# Bump it when a new major lands, and check the index first.
sudo apt-get install -y "clang-tidy-${LLVM_MAJOR}"
# clang-format comes from the same major, so fmt-check and the
# developer's `make fmt` agree. An unpinned clang-format is how
# one version's output becomes another version's violation.
sudo apt-get install -y "clang-format-${LLVM_MAJOR}"
# clang-format runs first, on its own. clang-tidy loads .clang-format for
# every file it processes, and an unrecognised key there aborts the whole
# run before it checks anything -- silently, with exit 2, which reads
# exactly like a clean run. Splitting this into its own step means the
# failure is attributable.
#
# It is expected to fail on older toolchains, which is why it is
# continue-on-error. Its job here is to make a mismatch visible, not to
# gate the build.
- name: clang-format config check
run: make fmt-check CLANG_FORMAT=clang-format-$LLVM_MAJOR
continue-on-error: true
- name: clang-tidy
run: make lint
# Advisory by design: the target says so, and a lint policy change
# should not be able to block a push. The annotations it produces are
# the report, not a gate.
continue-on-error: true
# A file with no trailing newline is a compile error under clang
# (-Wnewline-eof) and accepted by gcc. That asymmetry cost a CI run before
# it was noticed, and it is trivially checkable.
- name: files end with a newline
run: |
bad=0
for f in $(git ls-files '*.c' '*.h' '*.fl' '*.md' '*.py' '*.sh'); do
if [ -s "$f" ] && [ -n "$(tail -c 1 "$f")" ]; then
echo "no newline at end of file: $f"
bad=1
fi
done
if [ "$bad" -ne 0 ]; then
echo
echo "gcc accepts these; clang rejects them under -Werror."
echo "the usual cause is a whole-file rewrite that did not append"
echo "a trailing newline: printf '\n' >> the file fixes it."
fi
exit $bad
- name: ccache stats
run: ccache -s
# The Rust workspace: the safe `flint` embedding crate over `flint-sys`,
# built against the real C runtime this same checkout compiles. The
# crate's build script runs `make libflint.a` itself, so the runner
# needs the same C toolchain as the build job plus a Rust toolchain.
rust:
name: Rust workspace (fmt, clippy, test, examples)
runs-on: ubuntu-24.04
defaults:
run:
working-directory: rust
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- name: formatting
run: cargo fmt --check
- name: lints
run: cargo clippy --workspace --all-targets -- -D warnings
- name: tests
run: cargo test --workspace
# The cdylib guest-module example has no third-party dependencies,
# so it builds offline; it proves the workspace still links the way
# `flint native` loads it. tui-native is excluded: it needs the
# registry for ratatui.
- name: guest-module example
run: cargo build --release --offline
working-directory: rust/examples/rust-native
# Portability probes: signal, not gate. Neither job blocks a push --
# both are continue-on-error -- because neither platform is claimed as
# supported until its probe goes green and stays green. Their job is to
# show exactly where the POSIX assumptions break, in CI, instead of in
# a user's terminal.
macos-probe:
name: macOS probe (clang, release + suites)
runs-on: macos-15
continue-on-error: true
steps:
- uses: actions/checkout@v5
- name: release build
run: make clean && make release
- name: language tests
run: make test
- name: unit tests
run: make unit
# macOS is POSIX throughout (dlopen, fork, git, sh), so the suites
# that need them run here exactly as on Linux.
- name: formatter tests
run: make fmt-test
- name: package-manager tests
run: make pkg-test
- name: runner self-test
run: make runner-test
- name: native ABI tests
run: make native-test
windows-probe:
name: Windows probe (mingw64, build + suites)
runs-on: windows-latest
continue-on-error: true
defaults:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@v5
- uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: >-
base-devel
mingw-w64-x86_64-gcc
mingw-w64-x86_64-make
# MINGW64, not MSYS: the msys shell emulates fork and would prove
# nothing about Windows. CC names the mingw compiler explicitly so a
# PATH change cannot silently switch back to the emulated one.
- name: release build
run: make clean && make release CC=x86_64-w64-mingw32-gcc
# The binary is flint.exe; the msys shell resolves ./flint to it, so
# the suite drivers run unmodified. Suites that need fork (pkg git
# fixtures) or POSIX processes cannot pass here and do not run:
# process execution and git dependencies report "needs a POSIX
# system" on Windows by design.
- name: language tests
run: make test CC=x86_64-w64-mingw32-gcc
- name: unit tests
run: make unit CC=x86_64-w64-mingw32-gcc