Skip to content

feat(download): add EBI-internal FIRE S3 protocol (--protocol fire) - #118

Merged
ypriverol merged 6 commits into
devfrom
feat/fire-s3-protocol
Jul 29, 2026
Merged

feat(download): add EBI-internal FIRE S3 protocol (--protocol fire)#118
ypriverol merged 6 commits into
devfrom
feat/fire-s3-protocol

Conversation

@ypriverol

@ypriverol ypriverol commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Some datasets fail to download over FTP / HTTPS / Globus. This adds a fire protocol that fetches over the EBI-internal FIRE S3 endpoint (hl.fire.sdo.ebi.ac.uk) — reachable only inside EBI infrastructure (compute/login nodes), where it is markedly faster and more reliable than the public paths.

It reuses the existing S3 mechanism already used by the s3 protocol (unsigned/anonymous, bucket pride-public, object key = the archive-relative path YYYY/MM/ACCESSION/filename), differing only in the endpoint host: s3 → public hh.fire, fire → internal hl.fire.

Equivalent to the manual command:

aws --no-sign-request --endpoint-url https://hl.fire.sdo.ebi.ac.uk \
    s3 cp s3://pride-public/2015/08/PXD002137/<file> .

Changes

  • download/pride.py
    • FIRE_S3_URL constant (hl.fire.sdo.ebi.ac.uk), overridable via the PRIDEPY_FIRE_ENDPOINT env var.
    • download_files_from_s3() gains an endpoint_url parameter and now derives the FTP URL robustly via _get_download_url(record, "ftp") instead of positional publicFileLocations indexing.
    • fire routed in _batch_download_by_protocol (internal endpoint) alongside s3 (public endpoint); added to _get_download_url and the supported-protocol list.
    • Requested-only fallback: _protocol_sequence("fire") == ["fire", "aspera", "s3", "ftp", "globus"], and fire is never folded into another protocol's fallback chain — it is unreachable outside EBI, so it would only waste retries there. A run started outside EBI still completes via the public protocols.
  • pridepy.pyfire added to PROTOCOL_CHOICES (so every subcommand, incl. download-files-by-list, accepts it) and help text.
  • tests — internal-endpoint selection + S3 object-key derivation (2015/08/PXD002137/a.raw), and the requested-only fallback ordering.

Usage

pridepy download-files-by-list -a PXD002137 -F files.txt -o . --protocol fire

Validation

  • pytest pridepy/tests/ — 152 passed, 4 skipped (network).
  • Live EBI-cluster test of --protocol fire against a real dataset to follow in a comment.

Notes

  • The fire endpoint is internal to EBI; outside EBI it will fail fast and fall back to the public protocols, so the flag is safe to pass anywhere.

Summary by CodeRabbit

  • New Features

    • Added fire as a supported download protocol.
    • FIRE downloads use a dedicated internal S3 endpoint when explicitly selected.
    • Added fallback behavior from FIRE to standard public download protocols.
  • Documentation

    • Updated command-line help text to describe the new FIRE protocol and its fallback behavior.

ypriverol added 5 commits May 29, 2026 16:00
Major development to include MassIVE; iPROX and PRoteomeXchange
CPTAC download implementation
Enable to download entire CPTAC dataset
Minor changes for existing folders projects.
FTP/HTTPS/Globus fetches fail for some datasets. Add a `fire` protocol that
downloads over the EBI-internal FIRE S3 endpoint (hl.fire.sdo.ebi.ac.uk),
which is reachable only inside EBI infrastructure but is far more reliable
there. It reuses the existing S3 mechanism (unsigned, bucket pride-public,
object key = archive-relative path YYYY/MM/ACCESSION/filename) against the
internal endpoint instead of the public hh.fire endpoint used by `s3`.

- pride.py: FIRE_S3_URL constant (env-overridable via PRIDEPY_FIRE_ENDPOINT);
  download_files_from_s3() gains an endpoint_url arg and derives the FTP URL
  robustly via _get_download_url(); fire routed in _batch_download_by_protocol.
- `fire` is requested-only: tried first then falls back to the public
  protocols, and is never folded into another protocol's fallback (unreachable
  outside EBI, so no wasted retries there).
- CLI: `fire` added to --protocol choices across subcommands + help text.
- tests: internal-endpoint selection + S3 key derivation, requested-only order.

Equivalent to:
  aws --no-sign-request --endpoint-url https://hl.fire.sdo.ebi.ac.uk \
      s3 cp s3://pride-public/2015/08/PXD002137/<file> .
@qodo-code-review

Copy link
Copy Markdown
Contributor

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 831750bd-b023-4351-b720-5b26c8649081

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

PrideProvider adds an explicit fire protocol using an environment-configurable internal FIRE S3 endpoint, derives archive-relative S3 keys from FTP paths, updates CLI support and validation, and adds tests for endpoint routing and fallback ordering.

Changes

FIRE download support

Layer / File(s) Summary
Protocol and endpoint contracts
pridepy/download/pride.py
Adds FIRE_S3_URL, treats explicit fire requests as fire-first fallback sequences, and shares S3/fire archive-path resolution.
S3 routing, CLI exposure, and validation
pridepy/download/pride.py, pridepy/pridepy.py, pridepy/tests/test_review_fixes.py
Adds configurable S3 endpoint handling and archive-relative object keys, routes s3 and fire, exposes fire in CLI choices and help text, updates validation, and tests the new behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: shen-yufei

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant PrideProvider
  participant FIRE_S3
  CLI->>PrideProvider: request fire download
  PrideProvider->>PrideProvider: derive archive-relative object key
  PrideProvider->>FIRE_S3: request object from FIRE endpoint
  FIRE_S3-->>PrideProvider: return file content
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding the EBI-internal FIRE S3 download protocol via --protocol fire.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/fire-s3-protocol

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.

)
# boto3.resource was created against the internal hl.fire endpoint.
assert mock_boto.call_args.kwargs["endpoint_url"] == PrideProvider.FIRE_S3_URL
assert "hl.fire.sdo.ebi.ac.uk" in PrideProvider.FIRE_S3_URL

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pridepy/tests/test_review_fixes.py`:
- Line 168: Update the assertion for PrideProvider.FIRE_S3_URL in
test_review_fixes.py to avoid hard-coding the default endpoint; validate it
against the configured PRIDEPY_FIRE_ENDPOINT or the expected override-aware
value, while preserving the existing routing assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bab2c31c-f823-48d2-944f-731c19fc38f0

📥 Commits

Reviewing files that changed from the base of the PR and between 8546049 and 539f02e.

📒 Files selected for processing (3)
  • pridepy/download/pride.py
  • pridepy/pridepy.py
  • pridepy/tests/test_review_fixes.py

)
# boto3.resource was created against the internal hl.fire endpoint.
assert mock_boto.call_args.kwargs["endpoint_url"] == PrideProvider.FIRE_S3_URL
assert "hl.fire.sdo.ebi.ac.uk" in PrideProvider.FIRE_S3_URL

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not hard-code the default endpoint in an override-aware test.

PRIDEPY_FIRE_ENDPOINT can legitimately change FIRE_S3_URL; this assertion then fails despite line 167 confirming that routing used the configured endpoint.

Proposed fix
-        assert "hl.fire.sdo.ebi.ac.uk" in PrideProvider.FIRE_S3_URL
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
assert "hl.fire.sdo.ebi.ac.uk" in PrideProvider.FIRE_S3_URL
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pridepy/tests/test_review_fixes.py` at line 168, Update the assertion for
PrideProvider.FIRE_S3_URL in test_review_fixes.py to avoid hard-coding the
default endpoint; validate it against the configured PRIDEPY_FIRE_ENDPOINT or
the expected override-aware value, while preserving the existing routing
assertion.

@ypriverol

Copy link
Copy Markdown
Contributor Author

Live EBI-cluster test — passed ✅

Tested on the EBI Codon login node (inside EBI infrastructure), branch installed into an isolated venv so the shared env was untouched.

1. Endpoint + key derivationhead_object against the internal endpoint resolves the archive-relative key:

endpoint: https://hl.fire.sdo.ebi.ac.uk
key:      2015/08/PXD002137/20120119_EXQ6_JRW_SA_CAN10_T_06.raw
content-length: 3,075,244,480 bytes  (3.0 GB)  → OK

2. End-to-end CLIpridepy download-files-by-list -a PXD002137 -F manifest -o out --protocol fire:

INFO - Downloading 1 file(s) via fire (batch)
INFO - Downloading 1 file(s) from FIRE S3 endpoint https://hl.fire.sdo.ebi.ac.uk (bucket pride-public)
search.zip: 100%|██████████| 108M/108M [00:03<00:00, 27.7MB/s]
INFO - Successfully downloaded out/search.zip

Landed file size 108,278,658 bytes — exact match to the object. ~28 MB/s over the internal network.

This is the same PXD002137 dataset whose FTP/HTTPS fetches were failing; fire pulls it cleanly. Confirms the endpoint selection, S3 object-key derivation, and CLI wiring all work inside EBI.

@ypriverol
ypriverol changed the base branch from master to dev July 29, 2026 15:26
A FIRE failure is endpoint-level (the EBI-internal host is unreachable), so it
fails identically for every file; boto3 already retries each file 5x within the
Phase-1 batch. Retrying fire per-file in Phase-2 just burned retries on
connections that cannot succeed. Exclude fire from the per-file fallback so
those files go straight to the public protocols. Addresses CodeRabbit review.
@ypriverol

Copy link
Copy Markdown
Contributor Author

Review pass — security + CodeRabbit

Security review (SSRF / path-traversal / injection focus): clean. The endpoint is set only from a trusted env var / CLI click.Choice; a malicious API response can influence only the S3 object key (path-only, anonymous read of the public bucket), and the local-write path reuses the unchanged basename-only get_output_file_name — no traversal. No verify=False, no subprocess/eval/pickle/credentials added.

CodeRabbit — 1 actionable finding on this PR, fixed in d78a130:

After a FIRE (endpoint-level) failure, the Phase-2 per-file fallback re-attempted fire before the public protocols — wasted retries when the internal host is unreachable.

Fixed: fire is now excluded from the per-file Phase-2 fallback (fallback_sequence = [p for p in protocol_sequence if p != "fire"]). Rationale — a FIRE failure is endpoint-level (fails identically for every file), and boto3 already retries each file 5× within the Phase-1 batch, so per-file fire retries in Phase-2 can't succeed where Phase-1 didn't. Failed files now go straight to aspera → s3 → ftp → globus. Added test_fire_not_retried_in_phase2_fallback.

(CodeRabbit's other two findings were on .github/instructions/codacy.instructions.md, an untracked local tooling file that is not part of this PR.)

Tests: 13 passed in test_review_fixes.py (fire suite), full suite green.

@ypriverol
ypriverol merged commit 3399adb into dev Jul 29, 2026
6 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