Commit 135141a
authored
Add OpenFold3 SageMaker DLC (build + tests, incl. precomputed-MSA under network isolation) (#6285)
* Add OpenFold3 SageMaker DLC (build + basic tests)
OpenFold3 protein-structure prediction image for SageMaker async inference,
private release to JumpStart.
- docker/openfold3/Dockerfile: 2-stage build on devel-cu130-amzn2023, conda-lock
env, OpenFold3 pinned to tag 0.4.1, baked checkpoint of3-p2-155k.pt
- scripts/docker/openfold3/: Flask+gunicorn serve, SageMaker handler (GPU pool,
per-GPU warmup), entrypoint
- .github/config/image/openfold3/sagemaker.yml: release:false, public_registry:
false (private-only); tag 0.4-cu130-amzn2023
- .github/workflows/openfold3.{pipeline,pr-amzn2023,autorelease-sagemaker-amzn2023}.yml:
minimal pipeline (build + sanity + security + release)
- release-schedule.yml: register autorelease cron
Model tests and SageMaker endpoint tests intentionally omitted (added later
once test artifacts are uploaded to S3).
* Apply dockerfmt formatting to openfold3 Dockerfile
* Enable pull_request trigger for openfold3 PR workflow
* Fix and allowlist openfold3 ECR scan CVEs
ECR enhanced scan flagged 43 CRITICAL/HIGH CVEs. Remediation:
Fixed (14, in Dockerfile): upgrade pure-Python utility libs not in the
model dependency graph — GitPython>=3.1.50, urllib3>=2.7.0, pillow>=12.2.0,
dulwich>=1.2.5, msgpack>=1.2.1.
Allowlisted (29, test/security/data/ecr_scan_allowlist/openfold3/):
- openssl (21) + curl (3): conda-vendored native libs pinned by OpenFold3
0.4.1 upstream lock; upgrading risks breaking the locked env.
- torch 2.5.1 (3): official upstream pin (cuda12.4); CVE-2025-32434 torch.load
RCE not reachable (baked checkpoint, no untrusted load).
- quinn-proto (1): inside the uv build-tool binary, not runtime.
- jaraco.context (1): vendored in setuptools.
All allowlist entries carry review_by 2026-09-30.
* Fully remediate openfold3 Python CVEs in both envs + purge conda cache
The first remediation pass left 14 CVEs because:
- conda's extracted package cache (/opt/conda/pkgs/<pkg>-<oldver>) kept old
METADATA the scanner reads, even after the active env was upgraded
- awscli (installed for the checkpoint download) pinned urllib3<2.7, downgrading
the patched urllib3
- msgpack was only upgraded in the openfold3 env, not the base env
Fix: upgrade the libs in BOTH base and openfold3 envs, run remediation last
(after awscli is removed), and purge the conda pkg cache + conda clean.
* Fetch checkpoint via curl instead of awscli
awscli pulled in botocore, which pins urllib3<2.7 and conflicted with the CVE
remediation (capping urllib3 at 2.6.3). The checkpoint is a public, anonymously
readable S3 object, so fetch it over HTTPS with curl like the other DLCs do —
removing the awscli/botocore dependency entirely (no install/uninstall dance).
* Add OpenFold3 SageMaker async-inference tests
Deploys one 4-GPU ml.g6.12xlarge async endpoint (reused across cases) and
exercises it via S3 in/out. Three cases:
- small protein, 1 request (smoke)
- large protein, 1 request (baseline timing)
- large protein, 4 concurrent: asserts the GPU pool keeps wall-time under 2x
the single-request time (vs ~4x if serialized)
Validation is smoke-level (valid non-empty CIF). Wires a sagemaker-tests job
into the pipeline (gated on customer_type==sagemaker) + PR change detection.
* Inline SageMaker test fixtures, drop conftest.py
Match the repo convention: vllm/sglang/ray/vllm-omni all keep their SageMaker
endpoint fixtures in the test file rather than a per-suite conftest.py. Shared
fixtures (image_uri, region, aws_session) still come from the root
test/conftest.py.
* Align openfold3 SageMaker test with pytorch pattern (env vars, no conftest)
Follow test/pytorch/integration/sagemaker convention (per kwanggg/reenable-pytorch-pr):
- config via env vars TEST_IMAGE_URI / SM_ROLE_ARN / AWS_REGION instead of the
--image-uri pytest arg + aws_session fixture
- workflow builds SM_ROLE_ARN from CI_AWS_ACCOUNT_ID + SageMakerRole, single
sagemaker-test job with check-image-exists graceful skip
- requirements pin sagemaker>=3.0.0 (SDK v3) like pytorch
The endpoint deploy/teardown stays a module-scoped fixture in the test file
(persistent endpoint needs cleanup, unlike pytorch's fire-and-forget training
jobs) — but no separate conftest.py.
* Harden OpenFold3 SageMaker async test (fix CI hang + orphan leak)
Root cause of the 2-hour CI hang: the SageMaker execution role
(AmazonSageMakerFullAccess) can read but NOT write s3://dlc-cicd-models — that
managed policy only grants S3 write to buckets named *sagemaker*. The endpoint
ran the prediction but could not write the async OUTPUT object, so the test's
3600s poll waited a full hour with no result and no failure object, then the
2h merge-conditions cap canceled the job (skipping fixture teardown -> orphaned
ml.g6.12xlarge endpoints).
Fixes:
- async input + output now use the account default sagemaker-<region>-<account>
bucket (writable by the role); queries are staged there from dlc-cicd-models
(read-only is permitted). QUERY_SRC_BUCKET/PREFIX are env-overridable.
- read FailureLocation + POLL_TIMEOUT=900s + 5s interval: a dropped/failed
request now fails fast and legibly instead of a 1h hang.
- first-request retry + 30s settle after InService: SageMaker async can silently
drop the first request submitted immediately after InService (the discrepancy
vs the POC, where a human waits after warmup).
- cleanup-first _sweep_stale() in the fixture so a canceled run never strands or
blocks the next one.
Validated end-to-end on the real DLC image (ml.g6.12xlarge, account
897880167187): all 3 tests pass. Timings: small 80s, large 206s, 4-concurrent
268s vs 206s single (ratio 1.30 < 2.0 -> GPU pool parallelizes). Endpoint
auto-deleted, no orphan.
* Simplify SageMaker async test: single bucket, preflight, no retry
- Query inputs + async output both use the account default sagemaker bucket
(queries submitted directly, no cross-bucket staging from dlc-cicd-models).
- Add _preflight_s3() to fail fast (before the ~10-min deploy) if queries are
missing or the output bucket is not writable.
- Drop the first-request retry; keep the 30s post-InService settle.
- Validated end-to-end on the DLC image (account 897880167187): all 3 pass.
* Expand SageMaker test module header to document env vars, GPU model, and S3 bucket rationale
* Restructure sagemaker-test workflow into preflight + endpoint-test (vllm/sglang pattern), drop skip notice
* TEMP(gamma-validation): release openfold3 to gamma (028) from PR pipeline
One-off gamma pre-prod validation push. force_release bypasses the active
us-west-2 change-control window (2026-06-23..27). Release-gate temporarily
relaxed to allow the .pr caller / non-main ref. REVERT all three files after
the gamma run completes.
- sagemaker.yml: release/force_release=true, environment=gamma
- openfold3.pipeline.yml: drop main-ref + autorelease/dispatch gate conditions
- openfold3.pr-amzn2023.yml: release=true
* Revert "TEMP(gamma-validation): release openfold3 to gamma (028) from PR pipeline"
This reverts commit df8a7d2.
* Enable network isolation in SageMaker async test
Validates the production no-outbound-network posture: weights are baked into
the image and inputs arrive via S3, so the default single-sequence inference
path needs no internet. MSA is off by default.
* Support customer precomputed MSA + add isolated MSA test
Handler: a chain may carry an optional precomputed_msa list of {name, content}
a3m/sto alignments. Names are validated against OF3 0.4.1's recognized keys
(unrecognized names are silently ignored by OF3 → single-sequence), then staged
to a per-request temp dir with main_msa_file_paths set. No network needed, so it
works under network isolation. Subprocess engine only; optional and backward
compatible.
Test: test_large_precomputed_msa reads the uploaded a3m fixture, derives the
query sequence from its first record, and submits both inline to the isolated
endpoint — validating the bring-your-own-MSA path end-to-end.
* Submit prebuilt large_msa.json instead of assembling MSA request at runtime
Mirrors small.json/large.json: the MSA request (622-res protein + inline
colabfold_main.a3m) is a committed fixture uploaded to the sagemaker bucket,
submitted directly. Drops the runtime read/parse/stage helpers.
* Reject use_msa_server under network isolation with an actionable error
The endpoint runs network-isolated, so the MSA server has no outbound internet
and a use_msa_server=true request hangs until the predict timeout (~55min,
holds a GPU) — confirmed by a manual repro. Reject it up front (before leasing
a GPU) with a clear error that points to the precomputed_msa format + supported
names. Env-overridable via OPENFOLD3_ALLOW_MSA_SERVER=1 for a non-isolated
deploy. Adds test_msa_server_rejected_under_isolation asserting fast rejection.
* Use committed small_msa_server.json fixture for the MSA-server rejection test
Replaces the inline _submit_inline helper: the negative test now submits a
committed query (small protein, use_msa_server=true) via the standard _invoke
path, matching small/large/large_msa. Uploaded by upload_openfold3_test_queries.sh.
* Enable openfold3 release now that CDK ECR repo + ReleaseLogic tag are deployed
Both companion CRs are deployed: the openfold3 ECR repo exists in the release
account and the openfold3 framework/tag entry is live in the release-logic S3
dist. Flip release:true so the scheduled autorelease (and dispatch) publishes
to the private registry. PR runs still never release (release-gate requires
main-ref + an autorelease/dispatch caller).
* Address review: guard release job on !failure/!cancelled; move all Dockerfile ARGs to config
(1) release job had a custom if: that overrides the default 'skip on failed
needs', so a failed/cancelled build or release-gate could still let release run.
Add !failure() && !cancelled() (matches PR #6307 fix).
(2) Add base_image + miniforge_version to the build: block so every Dockerfile
ARG is declared in the config (config = source of truth, Dockerfile ARG = fallback
default). All 6 ARGs (BASE_IMAGE, MINIFORGE_VERSION, OPENFOLD3_REF, CHECKPOINT,
DLC_MAJOR/MINOR_VERSION) are now config-driven.
* nit: order release if: as !failure && !cancelled && should-release for consistency1 parent 12a9acd commit 135141a
13 files changed
Lines changed: 1689 additions & 0 deletions
File tree
- .github
- config/image/openfold3
- workflows
- docker/openfold3
- scripts/docker/openfold3
- test
- openfold3/sagemaker
- security/data/ecr_scan_allowlist/openfold3
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
73 | 73 | | |
74 | 74 | | |
75 | 75 | | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
Lines changed: 38 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 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 | + | |
0 commit comments