Fix CI: don't require uninstalled Ensembl release 115 - #399
Merged
Conversation
CI (and any env without release 115) was failing three tests because they depend on Ensembl 115, which the openvax/ensembl-data mirror doesn't publish (it tops out at GRCh38.95): * test_frameshift_cterminus_regression.py hardcodes cached_release(115) for the ATM p.F61fs regression from #396. Guard it: skip cleanly at module level when release 115 isn't installed. The same bug CLASS is covered on release 81 by test_annotator_divergence_scenarios.py and test_protein_diff_parity.py, so CI coverage of #396/#397 is unaffected. * test_timings.py used random_variants(), whose genome_name='GRCh38' default resolves via genome_for_reference_name to pyensembl's LATEST release (now 115) rather than an installed one. Add a backward-compatible ensembl= param to random_variants and pin the timing test to cached_release(81). This unbreaks main, which went red at dead346 (#396 merge) — the failures were masked locally on machines that happen to have release 115 cached. Claude-Session: https://claude.ai/code/session_01VNtZRyKZ7u9jiMGPQEbx4c
Pinning test_timings to release 81 surfaced a latent bug: random_variants draws from all of ensembl.transcript_ids(), which on release 81 includes transcripts on alternate/patch scaffolds (e.g. CHR_HSCHR19LRC_COX1_CTG3_1) that Variant() rejects as non-standard for GRCh38, raising ValueError and failing the whole generator. It was flaky rather than deterministic because the timing test's warmup draw is unseeded. Wrap the per-draw body in try/except ValueError and skip to the next transcript, so an unlucky pick no longer fails generation. The count*100 iteration budget and the terminal 'Unable to generate' error still catch a systematically-broken genome. Verified: 40 seeds x 50 variants on release 81 now all succeed. Claude-Session: https://claude.ai/code/session_01VNtZRyKZ7u9jiMGPQEbx4c
The previous commit wrapped Variant construction in try/except, but the 'Invalid contig name' ValueError is raised LAZILY -- from the .transcripts / .genes properties via _check_that_genome_has_contig, not from __init__ -- so construction succeeded and the error only surfaced later in .effects(). That made the earlier fix (and its stress test, which never called .effects()) ineffective; CI kept failing on a different alt scaffold (CHR_HSCHR11_2_CTG1). Filter transcripts up front to those whose contig is in set(ensembl.contigs()) -- the exact validity set _check_that_genome_has_contig uses -- so every returned variant is annotatable. Variant preserves the scaffold contig name (verified), so the filter aligns exactly with the validator. Note contigs() differs by environment (locally it includes alt scaffolds, CI excludes them); because filter and validator both call contigs(), they stay consistent either way. Verified under a simulated-CI contigs() (272 scaffolds excluded): 25 seeds x 30 variants generate + annotate with zero failures and no leaked contigs. Claude-Session: https://claude.ai/code/session_01VNtZRyKZ7u9jiMGPQEbx4c
Third time's the charm. The prior filter used set(ensembl.contigs()), but the lazy validator (_check_that_genome_has_contig) checks self.genome.contigs(), and self.genome = infer_genome(ensembl) is NOT guaranteed to be the same object as the passed ensembl -- in CI their contig sets differed, so the filter excluded nothing and CI kept failing on CHR_HSCHR11_2_CTG1. Validate each built variant against variant.genome.contigs() -- the exact same object and call the validator uses -- so the check is consistent with effect prediction by construction, regardless of how infer_genome resolves ensembl or how contigs() varies across environments. valid_contigs is computed once from the first successfully-built variant (all share a genome). Verified by patching the resolved genome's contigs() to exclude its 272 alt scaffolds (simulating CI): 25 seeds x 30 variants now generate AND annotate with zero failures and no leaked contigs. Claude-Session: https://claude.ai/code/session_01VNtZRyKZ7u9jiMGPQEbx4c
… path) My prior two attempts compared the variant's contig against a locally computed contig set (ensembl.contigs(), then variant.genome.contigs()). Both were inconsistent with the validator, because Variant._check_that_genome_has_contig reads a PROCESS-WIDE cache (_reference_name_to_valid_contig_names, keyed by reference name) that an earlier test populates with a scaffold-free set. So my set could include scaffolds the cached validator set excluded, and CI kept failing on a different alt scaffold each unseeded run. Skip via the exact path the caller uses: after constructing the variant, access variant.transcripts (which runs _check_that_genome_has_contig against the shared cache) inside the try/except. A scaffold variant raises there and is skipped; what survives is guaranteed annotatable by the same cache .effects() will read. Also drop variants that overlap no transcript. Verified by seeding _reference_name_to_valid_contig_names['GRCh38'] with a scaffold-free set (as CI's earlier tests do) and generating + annotating across 20 seeded and 10 unseeded draws: zero failures, no leaked scaffolds. Claude-Session: https://claude.ai/code/session_01VNtZRyKZ7u9jiMGPQEbx4c
iskandr
added a commit
that referenced
this pull request
Jul 9, 2026
test_collection_filtering.py calls variants.effects() at module import using the db_snp_variants fixtures from tests/data.py. Those Variants defaulted to reference_name "GRCh38", which pyensembl resolves to its LATEST known release (currently 115) rather than an installed one. The CI mirror (openvax/ensembl-data) tops out at GRCh38.95, so collection intermittently died with "GTF database needs to be created" whenever the latest-release GTF wasn't present -- a pre-existing flake on main's default run, not something the annotator switch introduced. Pin the three snps to cached_release(81) -- the installed release the downstream transcript-id assertions (ENST00000371321, ...371763, ...464755, ...613244) were written against. Same class of fix as #399.
iskandr
added a commit
that referenced
this pull request
Jul 9, 2026
test_collection_filtering.py calls variants.effects() at module import using the db_snp_variants fixtures from tests/data.py. Those Variants defaulted to reference_name "GRCh38", which pyensembl resolves to its LATEST known release (currently 115) rather than an installed one. The CI mirror (openvax/ensembl-data) tops out at GRCh38.95, so collection intermittently died with "GTF database needs to be created" whenever the latest-release GTF wasn't present -- a pre-existing flake on main's default run, not something the annotator switch introduced. Pin the three snps to cached_release(81) -- the installed release the downstream transcript-id assertions (ENST00000371321, ...371763, ...464755, ...613244) were written against. Same class of fix as #399.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
mainis red (sincedead346, the #396 merge). Three tests depend on Ensembl release 115, which theopenvax/ensembl-datamirror doesn't publish — it tops out at GRCh38.95 — so CI can't install it. The failures were masked on developer machines that happen to have release 115 cached locally.Fixes
test_frameshift_cterminus_regression.pyhardcodescached_release(115)for the ATM p.F61fs regression from PR: Fix protein_diff frameshift C-terminus truncation on a coincidental shared suffix #396. Now it skips cleanly at module level when release 115 isn't installed. The same bug class is covered on an installed release (81) bytest_annotator_divergence_scenarios.pyandtest_protein_diff_parity.py, so coverage of PR: Fix protein_diff frameshift C-terminus truncation on a coincidental shared suffix #396/protein_diff drops novel C-terminal residues on frameshift/stop-loss with a coincidental shared suffix #397 doesn't depend on 115.test_timings.pyusedrandom_variants(), whosegenome_name="GRCh38"default resolves (viagenome_for_reference_name) to pyensembl's latest release — now 115 — rather than an installed one. Added a backward-compatibleensembl=parameter torandom_variantsand pinned the timing test tocached_release(81), matching the rest of the suite.Verification
ValueError: GTF database needs to be createdCI hit when a release is absent.ruffclean.Note
Root cause is pyensembl-release drift:
genome_for_reference_name("GRCh38")now points at 115. Worth a durable follow-up — e.g. pin the default release used byrandom_variants, or pin thepyensemblversion inrequirements.txt— so a future "latest" bump doesn't silently break CI again.https://claude.ai/code/session_01VNtZRyKZ7u9jiMGPQEbx4c