forked from ChelseaKR/tods-validate
-
Notifications
You must be signed in to change notification settings - Fork 0
241 lines (226 loc) · 9.7 KB
/
Copy pathci.yml
File metadata and controls
241 lines (226 loc) · 9.7 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
name: CI
on:
push:
branches: [main]
pull_request:
# Cancel superseded runs of the same ref (CICD §11c): a new push to a PR
# obsoletes the in-flight run, so spending the remaining minutes is waste.
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: "3.12"
# CQ-09 drift half of the gate; see the note in the Makefile's `lockfile`
# target for why `uv sync --frozen` alone cannot fail on a stale lock.
- run: uv lock --check
- run: uv sync --frozen --extra dev
- run: echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
- run: make lint
- run: make format
- run: make typecheck
docs-drift:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: "3.12"
- run: python -m pip install .
- name: Check that docs/rules.md matches the rule registry
run: make docs-check
# Compares docs/v1-contract-candidate.json against the implementation on every
# pull request. It is a `make verify` gate, but until now it reached CI only
# through the release workflows, which are `on: release` -- so the public
# contract was first verified after a release tag was cut, and a change to a
# rule's declared category (which docs-check and the conformance corpus are
# both blind to) could land on main with fully green CI.
contract:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: "3.12"
- run: python -m pip install .
- name: Check the public contract matches the implementation
run: make contract-check
i18n:
# Enforce the i18n N/A declaration (INTERNATIONALIZATION-STANDARD §1): fail
# if docs/I18N.md is missing its status marker or its Reason line.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
with:
python-version: "3.12"
- name: Check the i18n N/A declaration is present
run: python scripts/check_i18n.py
# Validates CITATION.cff against the CFF 1.2.0 schema (DOC-08). Catches
# malformed citation metadata (the release checklist only eyeballs that
# version/date-released match the tag; this checks the file parses at all).
citation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
- run: make citation
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.12", "3.13"]
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: ${{ matrix.python-version }}
# CQ-09 drift half of the gate; see the note in the Makefile's `lockfile`
# target for why `uv sync --frozen` alone cannot fail on a stale lock.
- run: uv lock --check
- run: uv sync --frozen --extra dev
- run: echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
- run: make test
# Perf budget (QM-02): validation throughput must stay within
# perf/baseline.json's regression factor. scripts/benchmark.py could always
# measure this; nothing compared the measurement to anything, so a regression
# was only visible to whoever ran it and remembered the old number.
#
# The baseline is recorded from this job, on this machine class, because a
# number measured anywhere else is not comparable to what this job measures.
# The check fails rather than passes while the baseline is unrecorded.
perf:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: "3.12"
# CQ-09 drift half of the gate; see the note in the Makefile's `lockfile`
# target for why `uv sync --frozen` alone cannot fail on a stale lock.
- run: uv lock --check
- run: uv sync --frozen
- run: echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
- run: make perf-check
# WCAG 2.1 AA automation, and nothing else. `make a11y` used to begin with
# `npm audit --audit-level=high`, so an unfixable advisory in the npm
# toolchain aborted the recipe before pa11y-ci started: this job went red for
# a dependency reason and performed no accessibility check at all. The Node
# dependency audit now runs as its own gate in the `audit` job below, which
# is a required status check; this job answers one question and reports one
# result.
accessibility:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: "3.12"
# CQ-09 drift half of the gate; see the note in the Makefile's `lockfile`
# target for why `uv sync --frozen` alone cannot fail on a stale lock.
- run: uv lock --check
- run: uv sync --frozen
- run: echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "24"
cache: npm
cache-dependency-path: package-lock.json
- run: npm ci --ignore-scripts
- name: Select the hosted Chrome binary
run: |
a11y_chrome="$(command -v google-chrome)"
test -x "$a11y_chrome"
echo "PUPPETEER_EXECUTABLE_PATH=$a11y_chrome" >> "$GITHUB_ENV"
- run: make a11y
# Dependency vulnerability audit (CQ-11 / SEC-11), Python and Node. Blocking;
# no mute pattern. Both audits run on every commit even when the other one
# fails: `if: ${{ !cancelled() }}` lets the later step start regardless of the
# earlier step's result, and a failed step still fails this job, so neither
# audit can hide behind the other's result.
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
python-version: "3.12"
- uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "24"
cache: npm
cache-dependency-path: package-lock.json
# CQ-09 drift half of the gate; see the note in the Makefile's `lockfile`
# target for why `uv sync --frozen` alone cannot fail on a stale lock.
- run: uv lock --check
- run: uv sync --frozen --extra dev
- run: echo "$PWD/.venv/bin" >> "$GITHUB_PATH"
- name: Python dependency audit (pip-audit over uv.lock)
run: make audit
# npm audit reads the committed lockfile, so no npm ci is needed here.
- name: Node dependency audit (npm audit, adjudicated against waivers.yml)
if: ${{ !cancelled() }}
run: make npm-audit
# Secret scan over the PR/push diff and full history (SEC-17/18). Installs
# the gitleaks CLI directly (checksum-verified) rather than the third-party
# `gitleaks/gitleaks-action`, which is license-gated for organizations.
secrets:
runs-on: ubuntu-latest
env:
GITLEAKS_VERSION: "8.30.1"
GITLEAKS_SHA256: "551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb"
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
fetch-depth: 0 # full history: gitleaks scans commits, not just the tree
- name: Install gitleaks (checksum-verified)
run: |
set -eu
curl -sSL -o gitleaks.tar.gz \
"https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
echo "${GITLEAKS_SHA256} gitleaks.tar.gz" | sha256sum -c -
tar -xzf gitleaks.tar.gz gitleaks
sudo install -m 0755 gitleaks /usr/local/bin/gitleaks
- run: make secrets
action-self-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
persist-credentials: false
- name: Run the action against the valid fixture feed
uses: ./
with:
path: tests/fixtures/valid/tods
gtfs: tests/fixtures/valid/gtfs
# merge-handoff moved to .github/workflows/merge-handoff.yml (weekly schedule
# + workflow_dispatch): it is advisory (continue-on-error) and CICD §11d says
# a job that cannot block the merge does not spend minutes on every commit.