-
Notifications
You must be signed in to change notification settings - Fork 11
425 lines (414 loc) · 18.6 KB
/
Copy pathci.yml
File metadata and controls
425 lines (414 loc) · 18.6 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
name: CI
on:
push:
branches: [ main ]
pull_request:
jobs:
macos-smoke:
name: macOS smoke
runs-on: macos-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
toolchain: stable
- name: Build and exercise reference-pack CLI
run: |
cargo build --locked --bin rosalind
target/debug/rosalind reference build \
--fasta examples/data/illumina_toy/reference.fa \
--output "$RUNNER_TEMP/reference.rref"
target/debug/rosalind reference inspect \
--reference-pack "$RUNNER_TEMP/reference.rref" --json
advisory-audit:
name: Rust advisory audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
toolchain: stable
- name: Install pinned cargo-audit
run: cargo install cargo-audit --version 0.22.1 --locked
- name: Check RustSec advisories
run: cargo audit
rust:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Cache cargo artifacts
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
toolchain: stable
- name: Cargo fmt
run: cargo fmt --all -- --check
- name: Cargo test
run: cargo test --workspace
- name: Synthetic chr20 GIAB smoke
run: |
benchmarks/giab/smoke.sh
python3 -m unittest discover -s benchmarks/giab -p 'test_*.py'
- name: Build examples
run: cargo build --examples
- name: Build docs
run: cargo doc --workspace --no-deps
- name: Compile receipt parser fuzz targets
run: cargo check --manifest-path fuzz/Cargo.toml --bins
- name: Package publishable crates and embedded assets
run: |
cargo package -p rosalind-build-info --allow-dirty
cargo package -p rosalind-receipt --allow-dirty
cargo package -p rosalind-bio --allow-dirty \
--config 'patch.crates-io.rosalind-receipt.path="crates/receipt"' \
--config 'patch.crates-io.rosalind-build-info.path="crates/build-info"'
cargo package -p rosalind-bio --allow-dirty --list \
--config 'patch.crates-io.rosalind-receipt.path="crates/receipt"' \
--config 'patch.crates-io.rosalind-build-info.path="crates/build-info"' > package-files.txt
grep -q '^web/verify/pkg/rosalind_verify_bg.wasm$' package-files.txt
grep -q '^assets/demo/reference.fa$' package-files.txt
grep -q '^assets/scaffold/Cargo.toml.template$' package-files.txt
python:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Cache cargo artifacts
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Cache pip
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('.github/workflows/ci.yml') }}
restore-keys: |
${{ runner.os }}-pip-
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
toolchain: stable
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.11'
- name: Install Python feature dependencies
run: pip install numpy pyarrow
- name: Build the rosalind binary
run: cargo build --release --bin rosalind
- name: Exercise the Python boundary (bit-reproducible feature substrate)
# Builds a toy reference pack + BAM, extracts native Arrow twice, and
# proves the streams are byte-identical with matching BLAKE3 receipts.
run: python3 examples/reproducible_features_demo.py target/release/rosalind
cli-e2e:
runs-on: ubuntu-latest
env:
PYO3_PYTHON: python3
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Cache cargo artifacts
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Cache pip
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('.github/workflows/ci.yml') }}
restore-keys: |
${{ runner.os }}-pip-
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.11'
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
toolchain: stable
- name: Verify the committed toy reference is intact (pinned hash)
# A real anti-corruption gate, not the old self-referential check: pin the
# COMMITTED reference.fa (the one the release bundle + every other job
# ships) to a known hash. The previous step regenerated reference.fa at
# 1 Mbp without --length, overwriting the committed 4 kbp fixture and
# checking freshly-generated files against freshly-generated sums (a
# tautology that also tested a different reference than ships).
run: |
echo "ce8a6df801e836f4eda0b7661a68dcd7b7a9ab247c66d4582a89dbc207554efa examples/data/illumina_toy/reference.fa" \
| sha256sum --check
- name: Generate reads from the committed toy reference
# --reference simulates reads FROM the committed reference (does not invent
# or overwrite one), so cli-e2e exercises exactly the fixture that ships.
run: python3 scripts/generate_toy_data.py examples/data/illumina_toy --reference examples/data/illumina_toy/reference.fa
- name: Align to SAM
run: |
cargo run --release -- align \
--reference examples/data/illumina_toy/reference.fa \
--reads examples/data/illumina_toy/reads_R1.fastq \
--format sam \
--output examples/data/illumina_toy/alignments.sam
- name: Align to BAM
run: |
cargo run --release -- align \
--reference examples/data/illumina_toy/reference.fa \
--reads examples/data/illumina_toy/reads_R1.fastq \
--format bam \
--force \
--output examples/data/illumina_toy/alignments.bam
- name: Call variants
run: |
cargo run --release -- variants \
--reference examples/data/illumina_toy/reference.fa \
--alignments examples/data/illumina_toy/alignments.sam \
--mapq-threshold 5 \
--output examples/data/illumina_toy/variants.vcf
- name: Sanity-check outputs
run: |
test -s examples/data/illumina_toy/alignments.sam
test -s examples/data/illumina_toy/alignments.bam
grep -q '^#CHROM' examples/data/illumina_toy/variants.vcf
grep -q -v '^#' examples/data/illumina_toy/variants.vcf || echo \"warning: no variant lines emitted\"
- name: Build index for the bounded contract path
run: |
cargo run --release -- index \
--reference examples/data/illumina_toy/reference.fa \
--output examples/data/illumina_toy/reference.idx
- name: Sort the BAM for the contract path
run: |
cargo run --release -- sort \
--input examples/data/illumina_toy/alignments.bam \
--output examples/data/illumina_toy/sorted.bam
- name: Contract gate — fits / verify / refuse (bounded --index path)
run: |
set -e
# (1) Generous budget fits -> exit 0 + "contract: OK".
cargo run --release -- variants --index examples/data/illumina_toy/reference.idx \
--alignments examples/data/illumina_toy/sorted.bam \
--memory-budget-mb 4096 --enforce \
-o examples/data/illumina_toy/contract.vcf 2> ok.log
grep -q "contract: OK" ok.log
# (2) Verify the receipt without re-running -> exit 0.
cargo run --release -- verify \
--manifest examples/data/illumina_toy/contract.vcf.manifest.json | grep -q "verify: OK"
# (3) 1 MiB budget refuses up front -> exit 3, and writes no VCF.
rm -f examples/data/illumina_toy/refused.vcf
set +e
cargo run --release -- variants --index examples/data/illumina_toy/reference.idx \
--alignments examples/data/illumina_toy/sorted.bam \
--memory-budget-mb 1 --enforce \
-o examples/data/illumina_toy/refused.vcf 2> refuse.log
code=$?
set -e
test "$code" -eq 3
grep -q "REFUSE" refuse.log
test ! -f examples/data/illumina_toy/refused.vcf
- name: Reproduce fence — a stranger re-derives the result on this runner
# The contract.vcf + its receipt were produced above; reproduce re-derives it
# byte-for-byte from content-located inputs on THIS runner (a different machine
# than the author's), writes a chainable certificate, and a byte-changed input
# is correctly reported INCONCLUSIVE (exit 7) — never a false DIVERGED.
run: |
set -e
D=examples/data/illumina_toy
cargo run --release -- reproduce \
--manifest $D/contract.vcf.manifest.json \
--inputs $D/ | tee reproduce.log
grep -q "REPRODUCED" reproduce.log
test -f $D/contract.vcf.manifest.json.repro.json
# Negative: a byte-changed input can no longer be content-located -> exit 7.
mkdir -p tamper && cp $D/reference.idx tamper/ && cp $D/sorted.bam tamper/
printf 'x' >> tamper/sorted.bam
set +e
cargo run --release -- reproduce \
--manifest $D/contract.vcf.manifest.json --inputs tamper/ > /dev/null 2>&1
code=$?
set -e
test "$code" -eq 7
- name: Emit a self-hosted reproducibility badge
run: |
D=examples/data/illumina_toy
cargo run --release -- badge \
--manifest $D/contract.vcf.manifest.json \
--repro $D/contract.vcf.manifest.json.repro.json \
-o badge.json
cat badge.json
- name: Upload the reproducibility badge
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: rosalind-reproducibility-badge
path: badge.json
if-no-files-found: ignore
- name: Exercise the rosalind-budget Action (local, from-source binary)
uses: ./
with:
index: examples/data/illumina_toy/reference.idx
alignments: examples/data/illumina_toy/sorted.bam
budget-mb: 4096
binary-path: target/release/rosalind
output: examples/data/illumina_toy/action.vcf
- name: Build the preferred analysis reference for Action compatibility
run: |
target/release/rosalind reference build \
--fasta examples/data/illumina_toy/reference.fa \
--output examples/data/illumina_toy/action.rref
- name: Exercise reference-pack and Arrow Action inputs
uses: ./
with:
reference-pack: examples/data/illumina_toy/action.rref
alignments: examples/data/illumina_toy/sorted.bam
analyzer: features
format: arrow-ipc
budget-mb: 4096
binary-path: target/release/rosalind
output: examples/data/illumina_toy/action.arrow
artifact-name: rosalind-reference-pack-arrow
msrv:
name: MSRV (1.83)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Cache cargo artifacts
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-msrv-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-msrv-
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
toolchain: 1.83.0
- name: cargo check on the declared MSRV
run: cargo check --all-targets
clippy:
name: Clippy (-D warnings)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Cache cargo artifacts
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-clippy-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-clippy-
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
toolchain: stable
components: clippy
- name: Clippy as a gate
run: cargo clippy --all-targets -- -D warnings
benchmarks:
name: Claims harness
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- name: Cache cargo artifacts
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
toolchain: stable
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.11'
- name: Run the claims harness (a standing regression gate on the contract + reproducibility)
run: bash benchmarks/run.sh
studio-assets:
name: Receipt Studio generated assets
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
with:
toolchain: 1.83.0
targets: wasm32-unknown-unknown
- uses: taiki-e/install-action@c7eb1735f09259a5035e8e5d44b1406b1cddc0fb # v2
with:
tool: wasm-pack@0.14.0
- name: Rebuild committed client-only WASM
env:
RUSTUP_TOOLCHAIN: 1.83.0
run: scripts/build-wasm-verifier.sh
- name: Generated assets are reproducible
run: git diff --exit-code -- web/verify/pkg crates/receipt-wasm/Cargo.lock
- name: Upload generated assets on mismatch
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: receipt-studio-generated-${{ github.run_id }}
path: web/verify/pkg
if-no-files-found: error
- name: WASM unit tests
run: cargo test --manifest-path crates/receipt-wasm/Cargo.toml
release-automation:
name: Maintainer automation dry run
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
- name: Install pinned workflow linters
run: |
curl -fsSLO https://github.com/rhysd/actionlint/releases/download/v1.7.12/actionlint_1.7.12_linux_amd64.tar.gz
echo '8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8 actionlint_1.7.12_linux_amd64.tar.gz' | sha256sum --check
tar -xzf actionlint_1.7.12_linux_amd64.tar.gz actionlint
sudo install actionlint /usr/local/bin/actionlint
curl -fsSLO https://github.com/koalaman/shellcheck/releases/download/v0.10.0/shellcheck-v0.10.0.linux.x86_64.tar.xz
echo '6c881ab0698e4e6ea235245f22832860544f17ba386442fe7e9d629f8cbedf87 shellcheck-v0.10.0.linux.x86_64.tar.xz' | sha256sum --check
tar -xJf shellcheck-v0.10.0.linux.x86_64.tar.xz
sudo install shellcheck-v0.10.0/shellcheck /usr/local/bin/shellcheck
python3 -m pip install 'jsonschema==4.23.0'
- name: Maintainer CLI fake-remote integration suite
run: cargo test -p xtask --locked
- name: Validate schemas, workflows, and shell entry points
run: |
set +e
cargo xtask doctor --json > maintainer-report.json
doctor_code=$?
set -e
if [ "$doctor_code" -ne 0 ] && [ "$doctor_code" -ne 3 ]; then exit "$doctor_code"; fi
cargo xtask partners init --persona analyzer-builder --output partner-packet
python3 - <<'PY'
import json
from pathlib import Path
from jsonschema import Draft202012Validator, validate
for path in Path("release/schemas").glob("*.json"):
Draft202012Validator.check_schema(json.load(open(path)))
validate(json.load(open("maintainer-report.json")), json.load(open("release/schemas/maintainer-report-v1.schema.json")))
validate(json.load(open("partner-packet/feedback.json")), json.load(open("release/schemas/design-partner-v1.schema.json")))
PY
scripts/verify-release-automation.py
actionlint
shellcheck scripts/release-publish.sh scripts/post-publish-smoke.sh \
scripts/stage-release.sh benchmarks/giab/prepare.sh benchmarks/giab/run.sh \
benchmarks/giab/happy/run.sh assets/scaffold/scripts/contract-check.sh
bash -n scripts/release-publish.sh scripts/post-publish-smoke.sh \
scripts/stage-release.sh benchmarks/giab/prepare.sh benchmarks/giab/run.sh \
benchmarks/giab/happy/run.sh assets/scaffold/scripts/contract-check.sh