-
Notifications
You must be signed in to change notification settings - Fork 1
246 lines (232 loc) · 9.18 KB
/
Copy pathci.yml
File metadata and controls
246 lines (232 loc) · 9.18 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
name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
inputs:
nightly:
description: Run nightly checks
default: false
type: boolean
permissions:
actions: read
contents: read
# A push to main keeps its run: cancelling it whenever the next merge lands is what left main without a
# verdict and without a cache write for every job that had not finished yet.
concurrency:
group: ci-${{ github.event_name == 'push' && github.sha || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
# A pull request that touches only the site, Markdown, or the Read the Docs and Renovate manifests
# cannot change a compiled artifact, so the Rust jobs stand down for it. The exception is a document
# a crate embeds with `include_str!`; `just _embedded-docs-contract` keeps that list current. Every
# push and dispatch still runs everything.
changes:
runs-on: ubuntu-24.04
timeout-minutes: 5
outputs:
rust: ${{ steps.filter.outputs.code == 'true' || steps.filter.outputs.embedded == 'true' }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3
id: filter
with:
predicate-quantifier: some-with-excludes
filters: |
code:
- '**'
- '!site/**'
- '!**/*.md'
- '!.readthedocs.yaml'
- '!renovate.json'
- '!LICENSE'
embedded:
- 'site/content/ecosystems/oci/reference/policy.md'
- 'site/static/icon.svg'
- 'site/static/mark.svg'
source:
runs-on: ubuntu-24.04
timeout-minutes: 45
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: $/.github/actions/setup
with:
tools: just aqua:EmbarkStudios/cargo-deny
- run: just lint-source
- run: just lint-deps
automation:
runs-on: ubuntu-24.04
timeout-minutes: 20
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: $/.github/actions/setup
with:
tools: just node prek
- run: just lint-automation
contracts:
needs: changes
if: github.event_name != 'pull_request' || needs.changes.outputs.rust == 'true'
runs-on: ubuntu-24.04
# A cold `just snapshots` measured 5m19s: 2m36s to build peryx-ecosystem-pypi with every feature
# and 112s to run its 2814 tests.
timeout-minutes: 15
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- uses: $/.github/actions/setup
with:
tools: >-
just jq uv aqua:axodotdev/cargo-dist aqua:mitsuhiko/insta github:nextest-rs/nextest
- run: just snapshots
- run: just release-plan
platform:
name: platform (${{ matrix.os }})
needs: changes
if: github.event_name != 'pull_request' || needs.changes.outputs.rust == 'true'
strategy:
fail-fast: false
matrix:
os: [macos-26, windows-2025]
runs-on: ${{ matrix.os }}
timeout-minutes: 60
env:
HOMEBREW_NO_REQUIRE_TAP_TRUST: "1"
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: $/.github/actions/setup
with:
tools: just github:nextest-rs/nextest
- run: just platform-test
coverage:
needs: changes
if: github.event_name != 'pull_request' || needs.changes.outputs.rust == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 120
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: $/.github/actions/setup
with:
tools: >-
just uv aqua:taiki-e/cargo-llvm-cov github:nextest-rs/nextest
github:Shopify/toxiproxy
- run: just coverage-native
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: coverage-native
path: |
.tox/coverage/native.lcov
.tox/coverage/native-gaps.json
if-no-files-found: error
# A body reached only from the browser runs in the target `frontend` measures, so the two halves are
# unioned here rather than each gating alone. Both artifacts are small, so this waits on them both
# and adds a minute rather than serialising the two long jobs.
coverage-lines:
needs: [coverage, frontend]
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: $/.github/actions/setup
with:
tools: just
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: coverage-native
path: .tox/coverage
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: coverage-frontend
path: .tox/coverage
- run: just coverage-lines
frontend:
needs: changes
if: github.event_name != 'pull_request' || needs.changes.outputs.rust == 'true'
runs-on: ubuntu-24.04
timeout-minutes: 60
env:
# `coverage-frontend` builds under `$CARGO_TARGET_DIR/frontend`; rooting that inside the workspace
# target directory is what lets rust-cache carry its dependencies between runs.
CARGO_TARGET_DIR: ${{ github.workspace }}/target
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: $/.github/actions/setup
with:
components: llvm-tools-preview
targets: wasm32-unknown-unknown
tools: >-
just jq node aqua:taiki-e/cargo-llvm-cov github:nextest-rs/nextest github:leptos-rs/cargo-leptos
- run: just frontend-deps
- name: Install LLVM 22
run: |
curl --fail --location --output "$RUNNER_TEMP/llvm.asc" https://apt.llvm.org/llvm-snapshot.gpg.key
fingerprint=$(gpg --show-keys --with-colons "$RUNNER_TEMP/llvm.asc" | awk -F: '$1 == "fpr" { print $10; exit }')
test "$fingerprint" = 6084F3CF814B57C1CF12EFD515CF4D18AF4F7421
sudo install -m 644 "$RUNNER_TEMP/llvm.asc" /etc/apt/keyrings/llvm.asc
repository='https://apt.llvm.org/noble/ llvm-toolchain-noble-22 main'
echo "deb [signed-by=/etc/apt/keyrings/llvm.asc] $repository" | sudo tee /etc/apt/sources.list.d/llvm.list
# Refresh only the list this step just wrote. A plain `apt-get update` reads every list on
# the runner image, so a third party serving a corrupt index fails the whole command: on
# 2026-09-09 Google's Chrome repository returned a Packages.gz whose hash did not match its
# Release file, exit 100, and clang was never installed even though apt.llvm.org was healthy.
sudo apt-get update \
-o Dir::Etc::sourcelist=sources.list.d/llvm.list \
-o Dir::Etc::sourceparts=- \
-o APT::Get::List-Cleanup=0
sudo apt-get install --yes clang-22 lcov
echo "CLANG=clang-22" >> "$GITHUB_ENV"
- run: just coverage-frontend
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: always()
with:
name: coverage-frontend
path: .tox/coverage/frontend-*.lcov
if-no-files-found: error
docs:
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: $/.github/actions/setup
with:
tools: jq just node prek zola
- run: just lint-docs
- run: just docs
nightly:
if: github.event_name == 'workflow_dispatch' && inputs.nightly
uses: $/.github/workflows/nightly.yml
ci-gate:
if: always()
needs: [automation, changes, contracts, coverage, coverage-lines, docs, frontend, platform, source]
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
# A job the `changes` filter stood down reports `skipped`; anything else short of success fails.
- if: >-
needs.automation.result != 'success' || needs.changes.result != 'success' ||
needs.docs.result != 'success' || needs.source.result != 'success' ||
!contains(fromJSON('["success", "skipped"]'), needs.contracts.result) ||
!contains(fromJSON('["success", "skipped"]'), needs.coverage.result) ||
!contains(fromJSON('["success", "skipped"]'), needs['coverage-lines'].result) ||
!contains(fromJSON('["success", "skipped"]'), needs.frontend.result) ||
!contains(fromJSON('["success", "skipped"]'), needs.platform.result)
run: exit 1