Skip to content

fix: harden hail_init credentials check and DuckDB index metadata#97

Merged
ameynert merged 1 commit into
mainfrom
fix/infra-credentials-and-index-guards
Jun 3, 2026
Merged

fix: harden hail_init credentials check and DuckDB index metadata#97
ameynert merged 1 commit into
mainfrom
fix/infra-credentials-and-index-guards

Conversation

@ameynert

@ameynert ameynert commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Small infrastructure-hardening fixes across hail.py and the DuckDB index builders.

Changes

#76 — fail fast on a missing credentials file. In GCS mode, hail_init previously set GOOGLE_APPLICATION_CREDENTIALS only if path.exists(), so a provided-but-missing file was silently ignored and surfaced later as an opaque GCS auth error. It now raises FileNotFoundError with a clear remediation message. Extracted into _export_gcs_credentials (also keeps hail_init under the complexity limit).

#87 — DuckDB index guards.

  • write_metadata_tables writes its five metadata tables in a single transaction, so an interrupted init leaves no partially populated index (which a later append/finalize would read as corrupt metadata).
  • read_and_validate_pops_legends rejects an empty table_pairs list with a clear ValueError instead of a raw IndexError.
  • finalize_duckdb_index logs a warning when the sequences table is empty, rather than silently producing a zero-row index.

Tests

  • test_hail.pyhail_init raises FileNotFoundError for a missing credentials file and ValueError when none is provided (no Hail context needed).
  • test_read_and_validate_pops_legends_empty_raises — empty list → ValueError.
  • test_finalize_warns_on_empty_sequences — empty sequences table → warning (pure DuckDB).

Verification

  • uv run --directory divref poe fix-and-check-all — 184 passed; ruff (check + format) and mypy clean.

Note on overlap with the upcoming style PR

This PR touches only hail.py's body + docstring. The hail_init keyword-only (*) change stays in the house-rule PR (#82) together with its call-site updates — a different hunk, so the two merge cleanly in sequence.

Closes #76
Closes #87

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@ameynert, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 1 minute and 41 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e61e044e-1618-48b4-9cf6-d9a4cfb0a66c

📥 Commits

Reviewing files that changed from the base of the PR and between 1736c06 and 53f59f9.

📒 Files selected for processing (6)
  • divref/divref/duckdb_index.py
  • divref/divref/hail.py
  • divref/divref/tools/finalize_duckdb_index.py
  • divref/tests/test_hail.py
  • divref/tests/tools/test_finalize_duckdb_index.py
  • divref/tests/tools/test_init_duckdb_index.py

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Base automatically changed from am_review to main June 3, 2026 21:26
- hail_init now raises FileNotFoundError when the GCS credentials path is
  provided but does not exist, instead of silently skipping it and failing later
  with an opaque GCS auth error; extracted into _export_gcs_credentials (#76).
- write_metadata_tables writes its five metadata tables in one transaction so an
  interrupted init leaves no partially populated index that a later
  append/finalize would read as corrupt metadata (#87).
- read_and_validate_pops_legends rejects an empty table-pair list with a clear
  ValueError instead of a raw IndexError (#87).
- finalize_duckdb_index logs a warning when the sequences table is empty (#87).

Closes #76
Closes #87

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ameynert
ameynert force-pushed the fix/infra-credentials-and-index-guards branch from 5d55ad9 to 53f59f9 Compare June 3, 2026 22:23
@ameynert
ameynert temporarily deployed to github-actions-snakemake-linting June 3, 2026 22:23 — with GitHub Actions Inactive
@ameynert

ameynert commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ameynert
ameynert merged commit ae8c764 into main Jun 3, 2026
4 checks passed
@ameynert
ameynert deleted the fix/infra-credentials-and-index-guards branch June 3, 2026 23:44
ameynert added a commit that referenced this pull request Jun 3, 2026
## Summary
Pure style/convention cleanup (#82) — no behavior change. Kept separate
from the functional infra PR (#97) per the "never mix formatting and
functional" rule.

## Changes
- **Keyword-only `hail_init`** — added the leading `*` and updated its
four call sites (`extract_gnomad_afs`, `extract_gnomad_single_afs`,
`extract_sample_metadata`, `gnomad_hail_table_test_data`) to pass
`gcs_credentials_path` by keyword.
- **`Raises:` blocks** added to `extract_gnomad_afs` and
`extract_gnomad_single_afs` (the two extract tools that actually raise
`ValueError`).
- **Builtin generics in `main.py`** — `list[...]` and
`collections.abc.Callable` instead of `typing.List` / `typing.Callable`.

## Scope notes (the original nit was slightly off)
- `gnomad_hail_table_test_data` **already** led with `*`, so only its
call site changed.
- `extract_sample_metadata` raises nothing, so it gets no `Raises:`
block (only its call site changed).

## Conflict-free with #97
This PR touches only `hail_init`'s **signature line** (the `*`); PR #97
touched `hail.py`'s **body + docstring**. Different hunks, so they merge
cleanly in sequence regardless of order.

## Verification
- `uv run --directory divref poe fix-and-check-all` — 180 passed; ruff
(check + format) and mypy clean.

Closes #82

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant