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
name: CI
on:
push:
branches:
# Gate pull requests too — notably release-plz's own release PR, which must go
# green before it is merged (release-plz.yml's release job keys off a CI run
# concluding `success`, and its `workflow_run` filter matches `name:` above
# exactly, so this workflow's name must stay `CI`).
#
# THIS WORKFLOW IS LINUX, AND THAT IS THE WHOLE OF THE RELEASE GATE (bl-0158).
# macOS lives in `macos.yml` under its own name, and it is deliberately not
# here: a `workflow_run` verdict is the run's, not a job's, so one red job in
# this file stops every publish. macOS has never been green — 14 tests, two
# root causes, bl-1015 — and while nobody is fixing it, keeping it in this
# file would mean yog could never ship again. It still runs on every push and
# every pull request and still reports; it just is not what the publish waits
# on. Putting a platform back under this name is a decision to let it block a
# release, which is exactly what the name should mean.
pull_request:
workflow_dispatch:
# CI reads the tree and writes nothing back. Every action here is pinned to a
# full commit SHA with its tag in the trailing comment: a tag can be repointed
# at new code by its owner between two runs, a commit SHA cannot (bl-5ae6).
permissions:
contents: read
jobs:
linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
# Nothing here pushes, so leave no credential in .git/config.
persist-credentials: false
- uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable branch @ 2026-08-05
with:
# The SHA pin erases the ref name this action reads the toolchain
# from, so name it; rust-toolchain.toml still pins the build version.
toolchain: stable
components: rustfmt, clippy
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
- name: Cache cargo-tarpaulin 0.35.2
id: tarpaulin-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/.cargo/bin/cargo-tarpaulin
key: cargo-tarpaulin-0.35.2-${{ runner.os }}
- name: Install cargo-tarpaulin 0.35.2
if: steps.tarpaulin-cache.outputs.cache-hit != 'true'
run: cargo install cargo-tarpaulin --version 0.35.2 --locked
- name: Cache cargo-deny 0.20.2
id: deny-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/.cargo/bin/cargo-deny
key: cargo-deny-0.20.2-${{ runner.os }}
- name: Install cargo-deny 0.20.2
if: steps.deny-cache.outputs.cache-hit != 'true'
run: cargo install cargo-deny --version 0.20.2 --locked
# ast-grep 0.44.1 (pinned — sgconfig.yml). `make ci` -> `make lint` runs
# `make rules-audit` (ast-grep scan src + the rules/fixtures negative
# check), so ast-grep must be on PATH before `make ci`.
- name: Cache ast-grep 0.44.1
id: astgrep-cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ~/.cargo/bin/ast-grep
key: ast-grep-0.44.1-${{ runner.os }}
- name: Install ast-grep 0.44.1
if: steps.astgrep-cache.outputs.cache-hit != 'true'
run: cargo install ast-grep --version 0.44.1 --locked
# `make ci` == `make check`: fmt-check + lint (clippy + rules-audit +
# cargo deny check) + coverage. The lint target folds in the supply-chain
# and ast-grep audits, so there is no separate CI-only step to drift.
- run: make ci
- name: Doctests
run: cargo test --doc --workspace