-
Notifications
You must be signed in to change notification settings - Fork 19
600 lines (577 loc) · 25.1 KB
/
Copy pathci.yml
File metadata and controls
600 lines (577 loc) · 25.1 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
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
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
# Cancel superseded runs on the same ref (e.g. rapid pushes to a PR).
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Least-privilege default token.
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
# Fail the build on any warning across the whole workspace.
RUSTFLAGS: "-D warnings"
RUSTDOCFLAGS: "-D warnings"
jobs:
fmt:
name: rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install toolchain (rustfmt)
run: rustup component add rustfmt
- name: Check formatting
run: cargo fmt --all --check
clippy:
name: clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install toolchain (clippy)
run: rustup component add clippy
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- uses: Swatinem/rust-cache@v2
- name: Lint
run: cargo clippy --workspace --all-targets --all-features
test:
name: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- uses: Swatinem/rust-cache@v2
- name: Build
run: cargo build --workspace --all-targets --all-features --locked
- name: Test
run: cargo test --workspace --all-features --locked
fuse-mount:
name: fuse mount e2e
runs-on: ubuntu-latest
# The read-path unit/integration tests never touch the kernel (they use mock
# TCP servers). This job mounts a real TalonFuse on /dev/fuse and reads a
# file back through the kernel, asserting byte-exactness end to end — the one
# layer only a real mount can cover. GitHub's Linux runners provide an
# accessible /dev/fuse; macOS and restricted sandboxes do not, which is why
# the test is #[ignore]d and gated behind the `mount` feature by default.
env:
# Turn a missing/unusable /dev/fuse into a hard failure here, so this job
# can never pass without actually exercising the kernel mount path.
TALON_REQUIRE_FUSE: "1"
steps:
- uses: actions/checkout@v4
- name: Capture the FUSE environment
# /dev/fuse existing is necessary but not sufficient (#405). Capture
# everything that can make an unprivileged mount fail, so a failing run
# is diagnosable from its own log rather than from a second run.
run: |
if [ ! -e /dev/fuse ]; then
echo "::error::/dev/fuse is missing on this runner; the FUSE mount test cannot run"
exit 1
fi
echo "--- identity (root would bypass fusermount3 entirely) ---"
id
echo "--- /dev/fuse ---"
ls -l /dev/fuse
echo "--- fusermount3 on PATH, and every copy of it ---"
ls -l "$(command -v fusermount3)" 2>/dev/null || echo "(none on PATH)"
ls -l /usr/bin/fusermount3 /usr/local/bin/fusermount3 2>/dev/null || true
echo "--- /etc/fuse.conf ---"
cat /etc/fuse.conf 2>/dev/null || echo "(absent)"
echo "--- apparmor ---"
aa-status --enabled 2>/dev/null && echo "apparmor enabled" || echo "apparmor not enabled or unavailable"
- name: Ensure an unprivileged FUSE mount is possible
# Some runner images carry a second fusermount3 in /usr/local/bin, owned
# by the runner user and without the setuid bit, which shadows the
# system helper on PATH. An unprivileged process invoking it cannot
# mount, which is #405: every mount test then fails with EPERM in the
# same second while /dev/fuse looks perfectly healthy.
#
# Captured from a failing runner:
# -rwxrwxrwx 1 runner runner /usr/local/bin/fusermount3
# against a passing one:
# -rwsr-xr-x 1 root root /usr/bin/fusermount3
#
# Remove the shadow rather than chmod-ing it. Adding setuid to a
# runner-writable binary would be worse than the bug, and removing it
# keeps the job exercising the real system helper -- which is the only
# reason this test is worth running.
run: |
shadow=/usr/local/bin/fusermount3
if [ -e "$shadow" ] && [ ! -u "$shadow" ]; then
echo "removing non-setuid $shadow which shadows the system helper (#405)"
sudo rm -f "$shadow"
hash -r 2>/dev/null || true
fi
helper="$(command -v fusermount3 || true)"
if [ -z "$helper" ] || [ ! -u "$helper" ]; then
echo "::error::no setuid fusermount3 on PATH (found: ${helper:-none}); unprivileged mounts cannot work"
ls -l "$helper" 2>/dev/null || true
exit 1
fi
ls -l "$helper"
# pjdfstest mounts with allow_other (#419), which needs this enabled.
if ! grep -q '^user_allow_other' /etc/fuse.conf 2>/dev/null; then
echo user_allow_other | sudo tee -a /etc/fuse.conf >/dev/null
fi
grep '^user_allow_other' /etc/fuse.conf
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- uses: Swatinem/rust-cache@v2
- name: Run the real-kernel mount test
run: >-
cargo test -p talon-fuse --features mount --test mount_e2e --locked
-- --ignored --nocapture
docs:
name: doc
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- uses: Swatinem/rust-cache@v2
- name: Build docs
run: cargo doc --workspace --no-deps --all-features
docs-book:
name: mdbook build
runs-on: ubuntu-latest
# Ensures the mdBook documentation site always builds. Deployment to GitHub
# Pages happens separately (docs.yml) only on merge to main.
env:
MDBOOK_VERSION: "0.4.52"
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
- name: Install mdBook
run: cargo install mdbook --version ${MDBOOK_VERSION} --locked
- name: Build the book
run: mdbook build docs/book
config-docs:
name: reference docs drift
runs-on: ubuntu-latest
# The configuration and REST API references are generated from the code /
# OpenAPI spec. Fail if a committed copy is stale so docs cannot drift.
steps:
- uses: actions/checkout@v4
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- uses: Swatinem/rust-cache@v2
- name: Configuration reference drift
run: |
cargo run -q -p talon-coordinator --features etcd,kubernetes \
--bin talon-gen-config-docs > /tmp/config-ref.md
if ! diff -u docs/reference/configuration.md /tmp/config-ref.md; then
echo "::error::docs/reference/configuration.md is stale; run 'just gen-config-docs'"
exit 1
fi
- name: REST API reference drift
run: |
cargo run -q -p talon-coordinator --bin talon-gen-api-docs > /tmp/api-ref.md
if ! diff -u docs/reference/rest-api.md /tmp/api-ref.md; then
echo "::error::docs/reference/rest-api.md is stale; run 'just gen-api-docs'"
exit 1
fi
docs-quality:
name: docs quality
runs-on: ubuntu-latest
# Documentation hygiene: spelling (typos) and links (lychee). Config lives
# in typos.toml and lychee.toml; run the same checks locally via
# `just spell` and `just linkcheck`.
steps:
- uses: actions/checkout@v4
- name: Spell check
uses: crate-ci/typos@master
- name: Link check
# Offline: validate internal / relative links only. External URLs are
# not fetched, so a slow or rate-limited third-party site (e.g. a
# timeout to etcd.io) can never turn the gate red on a false negative.
uses: lycheeverse/lychee-action@v2
with:
args: >-
--offline --no-progress
README.md DESIGN.md CONTRIBUTING.md BENCHMARKS.md
'docs/**/*.md' '.github/**/*.md'
fail: true
etcd-contract:
name: etcd backend contract
runs-on: ubuntu-latest
# Exercises the production etcd ClusterStateStore backend against a real
# ephemeral etcd, as required by the state-store contract. etcd is launched
# explicitly rather than as a service container because that image's
# healthcheck is unreliable on GitHub-hosted runners.
env:
ETCD_VERSION: v3.5.16
TALON_ETCD_TEST_ENDPOINT: 127.0.0.1:2379
steps:
- uses: actions/checkout@v4
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- name: Start ephemeral etcd
run: |
curl -fsSL -o /tmp/etcd.tar.gz \
"https://github.com/etcd-io/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz"
tar xzf /tmp/etcd.tar.gz -C /tmp
ETCD_DIR="/tmp/etcd-${ETCD_VERSION}-linux-amd64"
"$ETCD_DIR/etcd" --data-dir /tmp/etcd-data \
--listen-client-urls http://127.0.0.1:2379 \
--advertise-client-urls http://127.0.0.1:2379 &
echo "ETCD_PID=$!" >> "$GITHUB_ENV"
for i in $(seq 1 30); do
if "$ETCD_DIR/etcdctl" --endpoints=127.0.0.1:2379 endpoint health; then
exit 0
fi
sleep 1
done
echo "etcd did not become healthy" >&2
exit 1
- uses: Swatinem/rust-cache@v2
- name: Run etcd backend contract tests
run: >-
cargo test -p talon-coordinator
--features etcd,state-store-testkit
--test etcd_contract --locked
- name: Run etcd metadata-store contract tests
# Same ephemeral etcd, different store. ADR 0003 §7 keeps TMS and
# ClusterStateStore as separate abstractions under separate prefixes,
# and one of these tests asserts the two cannot collide.
run: >-
cargo test -p talon-metadata
--features etcd
--test etcd_backend --locked
docker-build:
name: docker image build
runs-on: ubuntu-latest
# Smoke-build every container image on PRs (no push) so a broken Dockerfile
# fails CI. A merge to main runs the real, publishing build in
# release-images.yml instead — running both would double the most expensive
# job in the repo for no extra signal, so this job is PR-only.
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- name: Validate docker-compose
run: |
docker compose config --quiet
docker compose --profile ha config --quiet
# The latency lab is a standalone stack; validate it parses too.
docker compose -f deploy/testenv/docker-compose.yml config --quiet
docker compose -f deploy/testenv/docker-compose.yml --profile tools config --quiet
# The builds read the main-seeded layer cache (written by
# release-images.yml on every merge) but do not write. This sacrifices
# layer reuse between pushes of one PR (entries written from a PR are
# only readable within that PR) to keep mode=max exports from churning
# the repository's 10GB Actions cache quota, which is already saturated
# by the rust-cache entries every other job depends on.
- name: Build coordinator image
uses: docker/build-push-action@v6
with:
context: .
file: deploy/docker/coordinator.Dockerfile
push: false
cache-from: type=gha,scope=coordinator
- name: Build worker image
uses: docker/build-push-action@v6
with:
context: .
file: deploy/docker/worker.Dockerfile
push: false
cache-from: type=gha,scope=worker
- name: Build fuse image
uses: docker/build-push-action@v6
with:
context: .
file: deploy/docker/fuse.Dockerfile
push: false
cache-from: type=gha,scope=fuse
- name: Build gateway image
uses: docker/build-push-action@v6
with:
context: .
file: deploy/docker/gateway.Dockerfile
push: false
cache-from: type=gha,scope=gateway
helm:
name: helm chart
runs-on: ubuntu-latest
# Lint and render the Talon chart across every state backend so a broken
# template or invalid values fails CI. No cluster is required — helm renders
# locally and we structurally validate the output.
steps:
- uses: actions/checkout@v4
- name: Install Helm
uses: azure/setup-helm@v4
with:
version: v3.16.3
- name: Lint (all backends)
run: |
for be in memory kubernetes etcd; do
rp=3; [ "$be" = memory ] && rp=1
echo "::group::lint $be"
helm lint deploy/helm/talon --strict \
--set coordinator.backend="$be" --set coordinator.replicas="$rp"
echo "::endgroup::"
done
- name: Render (all backends) and validate YAML
run: |
for be in memory kubernetes etcd; do
rp=3; [ "$be" = memory ] && rp=1
echo "::group::template $be"
helm template t deploy/helm/talon \
--set coordinator.backend="$be" --set coordinator.replicas="$rp" \
| python3 -c "import sys,yaml; list(yaml.safe_load_all(sys.stdin))"
echo "::endgroup::"
done
- name: Reject invalid configurations
run: |
if helm template t deploy/helm/talon --set coordinator.backend=redis >/dev/null 2>&1; then
echo "::error::unknown backend should have failed"; exit 1
fi
if helm template t deploy/helm/talon \
--set coordinator.backend=memory --set coordinator.replicas=3 >/dev/null 2>&1; then
echo "::error::memory backend with HA should have failed"; exit 1
fi
s3-e2e:
name: s3 backend and gateway e2e (localstack)
runs-on: ubuntu-latest
# Exercises the real S3Backend (SigV4 signing + path-style endpoint) against
# LocalStack, reading bytes an object actually contains. The test skips when
# TALON_S3_TEST_ENDPOINT is unset; this job sets it after seeding the bucket.
services:
localstack:
image: localstack/localstack:3.8
ports:
- 4566:4566
env:
SERVICES: s3
options: >-
--health-cmd "curl -sf http://localhost:4566/_localstack/health || exit 1"
--health-interval 5s --health-timeout 5s --health-retries 20
env:
AWS_ACCESS_KEY_ID: test
AWS_SECRET_ACCESS_KEY: test
AWS_DEFAULT_REGION: us-east-1
TALON_S3_TEST_ENDPOINT: http://127.0.0.1:4566
TALON_S3_TEST_BUCKET: talon-e2e
TALON_S3_TEST_KEY: e2e/object.bin
TALON_S3_TEST_REGION: us-east-1
TALON_S3_SDK_PYTHON: python
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- name: Install S3 client libraries
run: python -m pip install boto3==1.40.0 minio==7.2.16
- name: Seed the bucket with a deterministic object
run: |
# 4096 bytes where byte i == i % 251 (matches the test's expectation).
python3 - <<'PY'
data = bytes((i % 251) for i in range(4096))
open("/tmp/object.bin", "wb").write(data)
PY
aws --endpoint-url http://127.0.0.1:4566 s3 mb s3://talon-e2e
aws --endpoint-url http://127.0.0.1:4566 s3 cp /tmp/object.bin s3://talon-e2e/e2e/object.bin
- uses: Swatinem/rust-cache@v2
- name: Run the S3 backend e2e test
run: cargo test -p talon-backend --test s3_e2e --locked -- --nocapture
- name: Run the S3 SDK gateway conformance test
run: cargo test -p talon-gateway --test s3_sdk_e2e --locked -- --nocapture
gcs-e2e:
name: gcs backend e2e (fake-gcs)
runs-on: ubuntu-latest
# Exercises the real GcsBackend (bearer auth + endpoint override) against
# fake-gcs-server, reading bytes an object actually contains. The test skips
# when TALON_GCS_TEST_ENDPOINT is unset; this job sets it after seeding.
# fake-gcs is launched explicitly (docker run) rather than as a service
# container so we can pass `-scheme http` for a plaintext endpoint.
env:
TALON_GCS_TEST_ENDPOINT: http://127.0.0.1:4443
TALON_GCS_TEST_BUCKET: talon-e2e
TALON_GCS_TEST_KEY: e2e/object.bin
steps:
- uses: actions/checkout@v4
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- name: Start fake-gcs-server and seed a deterministic object
run: |
docker run -d --name fake-gcs -p 4443:4443 \
fsouza/fake-gcs-server:1.49 \
-scheme http -port 4443 -public-host 127.0.0.1:4443
# Wait for it to answer.
for i in $(seq 1 30); do
if curl -sf http://127.0.0.1:4443/storage/v1/b >/dev/null 2>&1; then break; fi
sleep 1
done
# 4096 bytes where byte i == i % 251 (matches the test's expectation).
python3 -c "open('/tmp/object.bin','wb').write(bytes(i%251 for i in range(4096)))"
curl -sf -X POST "http://127.0.0.1:4443/storage/v1/b?project=talon" \
-H 'Content-Type: application/json' -d '{"name":"talon-e2e"}' || true
curl -sf -X POST \
"http://127.0.0.1:4443/upload/storage/v1/b/talon-e2e/o?uploadType=media&name=e2e/object.bin" \
-H 'Content-Type: application/octet-stream' \
--data-binary @/tmp/object.bin
- uses: Swatinem/rust-cache@v2
- name: Run the GCS e2e test
run: cargo test -p talon-backend --test gcs_e2e --locked -- --nocapture
azure-e2e:
name: azure backend and gateway e2e (azurite)
runs-on: ubuntu-latest
# Exercises the real AzureBackend (Shared Key signing + path-style endpoint)
# against Azurite, reading bytes an object actually contains. The test skips
# when TALON_AZURE_TEST_ENDPOINT is unset; this job sets it after seeding.
# Azurite is launched explicitly (docker run) so we can pass
# --skipApiVersionCheck: the runner's az CLI sends a newer API version than
# the pinned Azurite supports, which is only relevant to seeding.
env:
TALON_AZURE_TEST_ENDPOINT: http://127.0.0.1:10000
TALON_AZURE_TEST_CONTAINER: talon-e2e
TALON_AZURE_TEST_KEY: e2e/object.bin
TALON_AZURE_SDK_PYTHON: python
# Azurite's well-known dev connection string (public emulator values).
AZURE_STORAGE_CONNECTION_STRING: "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1;"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- name: Install the official Azure Storage SDK
run: python -m pip install azure-storage-blob==12.26.0
- name: Start Azurite and seed a deterministic object
run: |
docker run -d --name azurite -p 10000:10000 \
mcr.microsoft.com/azure-storage/azurite:3.33.0 \
azurite-blob --blobHost 0.0.0.0 --blobPort 10000 --skipApiVersionCheck
# Wait for the blob endpoint to answer.
for i in $(seq 1 30); do
if curl -sf http://127.0.0.1:10000/devstoreaccount1 >/dev/null 2>&1; then break; fi
sleep 1
done
# 4096 bytes where byte i == i % 251 (matches the test's expectation).
python3 -c "open('/tmp/object.bin','wb').write(bytes(i%251 for i in range(4096)))"
az storage container create --name talon-e2e
az storage blob upload --container-name talon-e2e \
--name e2e/object.bin --file /tmp/object.bin --overwrite
- uses: Swatinem/rust-cache@v2
- name: Run the Azure backend e2e test
run: cargo test -p talon-backend --test azure_e2e --locked -- --nocapture
- name: Run the Azure SDK gateway conformance test
run: cargo test -p talon-gateway --test azure_sdk_e2e --locked -- --nocapture
python-client:
name: python client
runs-on: ubuntu-latest
# Builds the wheel and drives it against a real coordinator, worker, and
# blob origin. Mocks would only assert that the mocks behave as written; the
# value of the binding is that it exercises the real protocol path.
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
- uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install build and test tooling
run: |
# protoc compiles talon-worker's WAL record schema and the etcd
# client's generated code; both binaries below need it.
sudo apt-get update && sudo apt-get install -y protobuf-compiler
python -m pip install --upgrade maturin pytest
- name: Build the release binaries the tests drive
run: |
cargo build --release --locked \
-p talon-worker --bin talon-worker \
-p talon-coordinator --bin talon-coordinator
- name: Build and install the wheel
run: |
maturin build --release --manifest-path clients/python/Cargo.toml --out dist
python -m pip install --force-reinstall dist/*.whl
- name: Run the client tests
run: python -m pytest clients/python/tests/ -v
java-client:
name: java client
runs-on: ubuntu-latest
# Two suites: conformance vectors, which guard the hand-written codec
# against drift from the Rust implementation, and an end-to-end read against
# a live cluster. The first is what makes a second protocol implementation
# maintainable; the second proves it actually reads bytes.
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
- uses: actions/setup-java@v4
with:
distribution: temurin
# Matches the pom's maven.compiler.release, so a source-level feature
# newer than the declared minimum fails here rather than at a user.
java-version: "17"
- name: Install protoc
# java_client_e2e.sh builds talon-worker, whose build script compiles
# the WAL record schema.
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- name: Run conformance vectors and the end-to-end suite
run: scripts/java_client_e2e.sh
bench:
name: bench (informational)
runs-on: ubuntu-latest
# Never blocks a merge: shared runners are too noisy for absolute-time
# gating. This posts the baseline diff for visibility only.
continue-on-error: true
steps:
- uses: actions/checkout@v4
- uses: Swatinem/rust-cache@v2
- name: Benchmark check vs committed baseline
id: bench
run: |
python3 scripts/bench.py check main --soft | tee bench-report.md
- name: Publish report to job summary
if: always()
run: cat bench-report.md >> "$GITHUB_STEP_SUMMARY"
coverage:
name: coverage (informational)
runs-on: ubuntu-latest
# Informational. The workspace sits around 81% line coverage; the value of
# this job is making the *per-file* numbers visible so gaps get noticed
# (a new module landing at 0%, a rewrite dropping a file to half), not
# gating on a single aggregate. A threshold can follow once there is a
# baseline to argue from.
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Install protoc
run: sudo apt-get update && sudo apt-get install -y protobuf-compiler
- name: Install toolchain (llvm-tools)
run: rustup component add llvm-tools-preview
- uses: Swatinem/rust-cache@v2
- uses: taiki-e/install-action@cargo-llvm-cov
- name: Measure coverage
run: cargo llvm-cov --workspace --all-features --summary-only | tee coverage.txt
- name: Publish report to job summary
if: always()
run: |
{
echo '### Coverage'
echo '```'
cat coverage.txt
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
audit:
name: dependency advisories
runs-on: ubuntu-latest
# Blocking, unlike coverage: this has a crisp pass/fail. A crate in the tree
# either carries an unacknowledged RUSTSEC advisory or it does not. Known
# ones are acknowledged with a written justification in deny.toml.
#
# A nightly run lives in audit-schedule.yml: an advisory can be published
# against an already-merged crate, so the check needs a heartbeat that does
# not depend on someone opening a PR.
steps:
- uses: actions/checkout@v4
- uses: taiki-e/install-action@cargo-deny
- name: Check advisories, bans, and sources
run: cargo deny check advisories bans sources