Skip to content

build(ci): rebuild the committed asset tables from pinned downloads in Rust - #403

Merged
GeiserX merged 10 commits into
GeiserX:mainfrom
geiresx:pgp/rust-z2b
Nov 13, 2026
Merged

GeiserX merged 10 commits into
GeiserX:mainfrom
geiresx:pgp/rust-z2b

Conversation

@geiresx

@geiresx geiresx commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

Three committed tables are rebuilt in CI from pinned public downloads: the interval rows of bin/cn_loci.tsv, assets/callability_genes.tsv and assets/sv_rule_regions.tsv. Each builder was Python: scripts/ci/build-cn-intervals.py and a heredoc inside scripts/ci/build-callability.sh and scripts/ci/build-sv-rule-regions.sh. They had three download routines with two different retry rules. The SV rule builder kept the last GENCODE record of a gene, while the callability builder kept the first and skipped the _PAR_Y copies. build-cn-intervals.py --check said "0 line(s) differ" for a catalog with an added line. The SV builder held 217 MB to write a 250 KB table.

Fix

Three new verbs in the og binary, in rust/crates/og-dev/src/build/:

Verb Replaces
og dev build cn-intervals scripts/ci/build-cn-intervals.py (deleted)
og dev build callability the Python heredoc of build-callability.sh
og dev build sv-rule-regions the Python heredoc of build-sv-rule-regions.sh

og never downloads. The shell scripts fetch the pinned files with curl through one shared function, scripts/ci/lib/fetch-pinned.sh, then hand og the folder. build-cn-intervals.py is now build-cn-intervals.sh, with the same --list, --cache and --check.

The GTF is read as bytes, with a small scanner for its key "value" pairs, only on the lines a builder keeps. The cut sets of the cn builder are merged once per chromosome and searched by binary search. Coverage uses og-intervals sets.

What changes on purpose

  • One download rule. A cached file with the right sha256 is read in place, not copied. A 403 or 404 fails at once on every attempt. Other failures, stalled transfers included, get at most six retries, 30 s apart, within a five-minute retry window. The Python cn builder tried three times.
  • The marker line of bin/cn_loci.tsv names scripts/ci/build-cn-intervals.sh. No row changes. A marker naming another builder is still found.
  • build-cn-intervals.sh --check counts the lines only in the file and the lines only in the rebuild, and says when only the order differs.
  • The SV rule builder keeps the first GENCODE record per HGNC id and skips _PAR_Y copies, as the callability builder does. No pseudogene of the pinned files is in a PAR, so the table does not change.
  • Each table is written to a temporary file and renamed.

Pipeline output names, formats, options and config keys stay unchanged. All table data rows stay byte for byte the same. The cn catalog marker names the new shell builder.

Measurements (MacMini-2, warm cache, the full script)

Builder Python og
callability (85 MB of downloads, 3.2 GB GTF text) 5.5 s, 39 MB 2.5 s, 27 MB
SV rule regions (145 MB of downloads) 10.5 s, 217 MB 4.9 s, 30 MB
cn intervals (150 KB of downloads) 0.14 s, 31 MB 0.07 s, 5 MB

Files needed for the port

The approved scope includes these 26 paths. Each supports the implementation, caller switch or deletion.

Path Reason
rust/crates/og-dev/src/build/callability.rs Build the callability table in Rust.
rust/crates/og-dev/src/build/cn_intervals.rs Build the CN interval rows in Rust.
rust/crates/og-dev/src/build/gtf.rs Share the streaming GTF reader.
rust/crates/og-dev/src/build/mod.rs Dispatch the builders and test the shared HTTP fetch policy.
rust/crates/og-dev/src/build/sv_rules.rs Build the SV rule regions in Rust.
rust/crates/og-dev/src/lib.rs Expose the build verbs.
rust/crates/og-dev/Cargo.toml Reuse og-intervals.
rust/Cargo.lock Record the og-dev dependency on og-intervals.
rust/og/src/main.rs List the build verbs in usage.
scripts/ci/build-callability.sh Fetch pinned inputs and call og.
scripts/ci/build-cn-intervals.py Delete the replaced Python builder.
scripts/ci/build-cn-intervals.sh Keep the shell entry point and flags.
scripts/ci/build-sv-rule-regions.sh Fetch pinned inputs and call og.
scripts/ci/lib/fetch-pinned.sh Share pin checking and bounded retries.
scripts/ci/e2e-run.sh Use the new CN builder for catalog cache fills.
scripts/ci/e2e-case-paths.tsv Map the three catalog cases to the new implementation.
tests/e2e/cn-intervals-1-catalog.sh Run the shell replacement.
tests/test_copy_number.py Run og instead of importing the deleted builder.
tests/test_e2e_data_cache.sh Read download pins from the shell replacement.
bin/cn_loci.tsv Name the new builder in the marker.
bin/copy_number.py Update the builder comment.
versions.env Update the builder comment.
docs/cn-loci.md Document the replacement command.
docs/testing.md Document the catalog checks with og.
docs/rust.md Document the three new verbs.
CHANGELOG.md Name the port and deliberate behavior changes.

How it was checked

  • Retry fix head 0948aae258d8b6c383ccb2a49133d8e1bc119480: red-before-fix request sequences and green local results. The four HTTP tests use Rust and a local HTTP server. They verify immediate stops after 403/404, retry exhaustion, recovery, pin failures, cache hits and cleanup.

  • Final-head fast checks are queued or running: Guard, Rust, Lint, Nextflow, Docs, Container Test, Personal data.

  • On MacMini-2 with the pinned downloads, the callability and SV builders reproduce their committed tables byte for byte (cmp). The cn builder reproduces its committed interval rows, with the documented marker change. The --list output of the cn script is the same as the Python's, so the e2e data cache key does not move.

  • Three e2e cases pass when run one by one on MacMini-2: cn-intervals-1-catalog (4 checks), callability-1-catalog (4 checks) and followups-ci-3-sv-rule-regions (9 checks, including cache reuse). All three ran on 0948aae2 with fresh downloads. The SV case uses pcre2grep for its existing PCRE assertion because BSD grep lacks -P.

  • cargo test -p og-dev (27 builder tests on small synthetic GTF, BED and HGNC inputs, plus four HTTP fetch tests), clippy with -D warnings, rustfmt and cargo doc are clean. tests/test_copy_number.py passes with and without OG. tests/test_e2e_data_cache.sh, tests/test_e2e_shards.sh, scripts/ci/e2e-scope.sh check, shellcheck and the personal-data scan pass.

  • Red first: 1f2b7fca planted three wrong rules. Callability keeps the _PAR_Y copies. The SV builder keeps the last record per HGNC id. Each cn piece ends one base short. Guard's rust job failed at cargo test. Its red run shows five failed builder tests. Reverted in 1b8998f, whose tree is the same as before the plant. Its run was cancelled when the next fix superseded it. The current-head CI run will verify the restored code. On MacMini-2 the planted og failed the cn check on 89 rows, while the two PAR plants left both real tables unchanged. On today's pins the PAR rule changes nothing. The unit tests guard it.

  • The e2e cases' red controls passed on this head: The cn check exits 1 when one target moves by 1 kb. The callability rebuild differs from a hand-edited catalog. The SV check exits 1 and shows the MHC row when its end moves by 1.

  • fetch-pinned.sh and the scripts: a 404 fails in 0.3 s, a wrong sha256 fails and leaves no file, a download and a cache hit both pass.

  • Review: the upstream CodeRabbit limit was reached, so the review ran on the fork's mirror PR, build(ci): rebuild the committed asset tables from pinned downloads in Rust geiresx/OwnGenome#138. It found all four planted lines, removed by the revert. Commit cebf6b94 fixes its two other findings. Each fetch writes its own temporary file. Every attempt stops stalled transfers (30 s to connect, 1 KB/s for 60 s).

  • ORACLE_RUNNER=local scripts/ci/oracle-diff.sh --self-test passes all 15 checks. The comparator self-test passes all 44 cases. The Linux shadow self-test skips on macOS and remains CI's check.

The latest repository CodeRabbit review was submitted at 11:59 UTC on PR #400. The shared 55-minute queue prevents another request at this handoff. The previous fork review has six resolved threads. The independent review findings are fixed.

Bead: pgp-bs9u.35

og dev build cn-intervals, callability and sv-rule-regions read the
pinned downloads from a folder and write bin/cn_loci.tsv's interval rows,
assets/callability_genes.tsv and assets/sv_rule_regions.tsv, byte for
byte as the Python builders did. The GTF is read as bytes with a hand
scanner of its attributes, the cut sets are merged once per chromosome
and searched by binary search, and og never downloads.

The SV rule builder now keeps the first GENCODE record per HGNC id and
skips _PAR_Y copies, as the callability builder does; the committed
table does not change.

Bead: pgp-bs9u.35
build-callability.sh and build-sv-rule-regions.sh keep their downloads
and hand the folder to og dev build; their Python heredocs are gone.
build-cn-intervals.py becomes build-cn-intervals.sh with the same --list,
--cache and --check. The three share scripts/ci/lib/fetch-pinned.sh: a
cached file with the right sha256 is read in place, a 403 or 404 fails
at once, anything else is retried for about five minutes.

The marker line of bin/cn_loci.tsv names the new script; no row changes.
The cn-intervals case, the e2e data fill and the converter checks of
tests/test_copy_number.py call the new script and og.

Bead: pgp-bs9u.35
Red-first control, reverted in the next commit: callability keeps the
_PAR_Y copies, the SV rule builder keeps the last record per HGNC id,
and each cn-intervals piece ends one base short.

Bead: pgp-bs9u.35
@geiresx
geiresx requested a review from GeiserX as a code owner November 13, 2026 11:30
@coderabbitai

coderabbitai Bot commented Nov 13, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 44 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration

Commits

Reviewing files that changed from the base of the PR and between 2c5532a and 533ccfb.

Files ignored due to path filters: 3

  • bin/cn_loci.tsv is excluded by !**/*.tsv
  • rust/Cargo.lock is excluded by !**/*.lock
  • scripts/ci/e2e-case-paths.tsv is excluded by !**/*.tsv
Files selected for processing: 23

  • CHANGELOG.md
  • bin/copy_number.py
  • docs/cn-loci.md
  • docs/rust.md
  • docs/testing.md
  • rust/crates/og-dev/Cargo.toml
  • rust/crates/og-dev/src/build/callability.rs
  • rust/crates/og-dev/src/build/cn_intervals.rs
  • rust/crates/og-dev/src/build/gtf.rs
  • rust/crates/og-dev/src/build/mod.rs
  • rust/crates/og-dev/src/build/sv_rules.rs
  • rust/crates/og-dev/src/lib.rs
  • rust/og/src/main.rs
  • scripts/ci/build-callability.sh
  • scripts/ci/build-cn-intervals.py
  • scripts/ci/build-cn-intervals.sh
  • scripts/ci/build-sv-rule-regions.sh
  • scripts/ci/e2e-run.sh
  • scripts/ci/lib/fetch-pinned.sh
  • tests/e2e/cn-intervals-1-catalog.sh
  • tests/test_copy_number.py
  • tests/test_e2e_data_cache.sh
  • versions.env
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

…go red"

The plant turned five builder tests red in Guard's rust job (run
43417543846); back to the right rules.

Bead: pgp-bs9u.35
… failed

fetch_pinned downloads to a mktemp file beside the target, so two runs
on one cache never write the same partial file, and gives curl a 30 s
connect timeout and a 1 KB/s for 60 s floor, so a stalled server reaches
the retry or the error instead of holding the build.

Bead: pgp-bs9u.35
@geiresx

geiresx commented Nov 13, 2026

Copy link
Copy Markdown
Collaborator Author

The review findings are addressed in 0948aae.

The approved scope now covers all 26 changed paths. The PR body lists each path and its role in the port.

The shared fetch loop checks every HTTP response. A 403 or 404 stops immediately. Other errors get at most six retries within the existing five-minute window. Connection and stall limits, checksum verification, cache hits and temporary-file cleanup remain covered.

Red first: the new Rust tests ran against the previous fetch implementation at cebf6b9, using real HTTP responses on loopback:

http_403_stops_after_any_attempt: FAILED
  got [503, 403, 200], expected [503, 403]
http_404_stops_after_any_attempt: FAILED
  got [503, 404, 200], expected [503, 404]
other_failures_retry_but_stop_at_the_bound: FAILED
  got [503, 503, 503, 503, 503, 503, 503, 200], expected seven requests

After the fix, all four fetch tests pass. Rust 1.93 runs 52 og-dev unit tests and nine repository tests successfully. Clippy with warnings denied, rustfmt and cargo doc also pass. The cache shell suite passes 30 checks.

# Conflicts:
#	CHANGELOG.md
#	rust/crates/og-dev/src/lib.rs
#	rust/og/src/main.rs
…list zram0

Some runner images list /dev/zram0 as a disk of 0 bytes with no file
system. The spare-disk step took it for the blank disk, and mkfs.ext4
stopped the leg before any case ran. The step now skips zram, ram and
loop devices and any disk of 0 bytes.
@GeiserX
GeiserX merged commit b184d58 into GeiserX:main Nov 13, 2026
43 of 52 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants