Skip to content

refactor(container): share the PyNvVideoCodec install guard - #15595

Merged
dmitry-tokarev-nv merged 4 commits into
ai-dynamo:mainfrom
ericcurtin:ericcurtin/share-pynvvideocodec-guard
Oct 7, 2026
Merged

dmitry-tokarev-nv merged 4 commits into
ai-dynamo:mainfrom
ericcurtin:ericcurtin/share-pynvvideocodec-guard

Conversation

@ericcurtin

@ericcurtin ericcurtin commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Overview:

Share the PyNvVideoCodec install guard across the vllm, sglang and trtllm images.

Details:

  • One script replaces two identical heredocs and the trtllm shell checks.
  • Its deny list comes from codec_policy.yaml.
  • Validation: new unit tests pass. The template RUN steps pass in a container build on the real 2.2.3 wheel, and each negative control (second dist, second tarball, denied lib, empty package) still fails. No full image build.

Where should the reviewer start?

container/compliance/check_pynvvideocodec.py

Related Issues

🔗 This PR is linked to an issue:

Summary by CodeRabbit

  • New Features
    • Runtime image builds now check that the installed PyNvVideoCodec matches version 2.2.3 and includes the expected FFmpeg components.
    • Builds fail when the package is missing, duplicated, has an unexpected version, or contains components disallowed by the codec policy.
    • The check is applied consistently across the SGLang, TensorRT-LLM, and vLLM runtime images.

One script reads its deny list from codec_policy.yaml.

Signed-off-by: Eric Curtin <eric.curtin@docker.com>
@ericcurtin
ericcurtin requested review from a team as code owners October 3, 2026 11:01
@copy-pr-bot

copy-pr-bot Bot commented Oct 3, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@ericcurtin
ericcurtin deployed to external_collaborator October 3, 2026 11:01 — with GitHub Actions Active
@ericcurtin
ericcurtin deployed to external_collaborator October 3, 2026 11:01 — with GitHub Actions Active
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

👋 Hi ericcurtin! Thank you for contributing to ai-dynamo/dynamo.

Just a reminder: The NVIDIA Test Github Validation CI runs an essential subset of the testing framework to quickly catch errors.Your PR reviewers may elect to test the changes comprehensively before approving your changes.

🚀

@github-actions github-actions Bot added refactor external-contribution Pull request is from an external contributor backend::trtllm Relates to the trtllm backend container labels Oct 3, 2026
Signed-off-by: Eric Curtin <eric.curtin@docker.com>
@ericcurtin
ericcurtin deployed to external_collaborator October 3, 2026 11:01 — with GitHub Actions Active
@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

🧰 Additional context used
📚 Code guidelines (1)
.ai/python-guidelines.md — configured

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: ai-dynamo/dynamo/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Enterprise
  • Run ID: f3274c3c-7259-49a9-b8ab-6d96e4c9772c
📥 Commits

Reviewing files that changed from the base of the PR and between 88750c1 and 73a310d.

📒 Files selected for processing (7)
  • container/compliance/check_pynvvideocodec.py
  • container/compliance/scan_codecs.py
  • container/compliance/tests/test_check_pynvvideocodec.py
  • container/templates/sglang_runtime.Dockerfile
  • container/templates/trtllm_runtime.Dockerfile
  • container/templates/vllm_runtime.Dockerfile
  • tests/dependencies/test_pynvvideocodec_spec.py

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.


Walkthrough

The pull request adds a shared PyNvVideoCodec install guard that reads the codec policy. Three runtime templates invoke it with pin 2.2.3. Tests cover guard validation and check that staged templates include the invocation.

Changes

PyNvVideoCodec install validation

Layer / File(s) Summary
Policy-driven install guard
container/compliance/check_pynvvideocodec.py, container/compliance/scan_codecs.py, container/compliance/tests/test_check_pynvvideocodec.py
The guard requires one distribution at the pinned version, the required bundled libraries, no policy-denied libraries, and exactly one recorded FFmpeg source tarball. Tests cover these checks and CLI results.
Runtime template integration
container/templates/sglang_runtime.Dockerfile, container/templates/trtllm_runtime.Dockerfile, container/templates/vllm_runtime.Dockerfile, tests/dependencies/test_pynvvideocodec_spec.py
The runtime templates invoke the shared guard with pin 2.2.3. The TRT-LLM template retains FFmpeg library enumeration and decoder checks. Dependency tests check for the guard invocation in staged templates.

Priority: ⬇️ Low

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

Merge Risk: ⚪ Minimal · up to 73a31

This change moves the PyNvVideoCodec install checks into one shared guard used by the three runtime templates. No concrete problems were found, and the existing failure cases remain covered by tests.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 39.13% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 23 functions across 4 files. (3 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: sharing the PyNvVideoCodec install guard across container templates.
Description check ✅ Passed The description includes the required Overview, Details, reviewer starting point, and Related Issues sections. It describes the change, reports validation and its limits, and links issue #15582.
Linked Issues check ✅ Passed Issue #15582 requires one PyNvVideoCodec guard under container/compliance/, calls from all three runtime templates, deny rules from codec_policy.yaml, and failure checks for invalid installs. `che…
Out of Scope Changes check ✅ Passed The CodecPolicy.violates helper supports policy-based decisions in the shared guard. The new tests and template changes implement or verify issue #15582. The reviewed diff shows no unrelated changes…
Full details: Docstring Coverage

Explanation

Docstring coverage is 39.13% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 23 functions across 4 files. (3 skipped: 3 unsupported.)

  • Fix all pre-merge checks with AI
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

Comment thread container/compliance/tests/test_check_pynvvideocodec.py
Signed-off-by: Eric Curtin <eric.curtin@docker.com>
@ericcurtin
ericcurtin deployed to external_collaborator October 3, 2026 11:25 — with GitHub Actions Active
@ericcurtin

Copy link
Copy Markdown
Contributor Author

@dmitry-tokarev-nv @dagil-nvidia PTAL when you get a chance. Thank you!

@dmitry-tokarev-nv dmitry-tokarev-nv 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.

Not approving yet. The P2 below makes the shared guard weaker than the two heredocs it replaces, so it needs a fix first. Read at 6e99032266.

[P2] Build-suffixed codec libraries pass the new guard. Inline at check_pynvvideocodec.py:75, confirmed end to end on the CI images in that thread.

[P3] Restore the empty-package test case. Reply on the existing thread at test_check_pynvvideocodec.py:128.

CI on this head: the guard step ran on amd64 and arm64 in the vLLM, SGLang and TensorRT-LLM image builds, and all seven required checks pass.

What I verified, with controls.
  • The new guard exits 0 on the real 2.2.3 install in the vLLM, SGLang and TensorRT-LLM CI images from #14925 (06c2ff404e) and from this head. With --pinned 2.2.2 it exits 1 in each. The old heredoc exits 0 on the same installs.
  • In 48 BuildKit builds on this head's images, the cases in the description each fail the new guard: second distribution, second source tarball, denied library, and empty package. A wrong version fails too. The clean install passes.
  • Each template's interpreter imports yaml and the guard in the current base images: vLLM v0.30.0-ubuntu2404, SGLang v0.5.19-cu130-runtime, and TensorRT-LLM 1.3.0rc29.
  • test_pynvvideocodec_spec.py passes 14 tests. A wrong pin or a removed guard call in the vLLM template fails 2 of them each.
  • Rendering the three CUDA runtime Dockerfiles changes only the guard sections.
  • test_check_pynvvideocodec.py (22) and test_scan_codecs.py (23) pass locally and in the CI unit lane.
  • This head's runtime-test images pass the dependency, multimodal and NVDEC test files: 872 tests, 0 failures, with the NVDEC GPU decode tests run in each image.

Comment thread container/compliance/check_pynvvideocodec.py Outdated
@dmitry-tokarev-nv

Copy link
Copy Markdown
Contributor

/ok to test 6e99032

@dynamo-review-agent dynamo-review-agent Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Previously reported defects still present:

  • Original discussion: Still present at the reviewed head: check_pynvvideocodec.py delegates denied-library detection to policy.violates(...), so build-suffixed denied codec libraries such as libavcodec_nvc.so.* remain outside the deny globs described in the existing thread.
  • Original discussion: Still present at the reviewed head: test_a_partial_package_fails parameterizes only the one-library cases and does not restore the empty package case discussed in the thread.
  • Original discussion: The shared guard still only calls policy.violates(...), so codec-family libraries with build suffixes such as libavcodec_nvc.so.63 do not match the policy's plain/hash/dynamo deny globs and pass where the replaced prefix-based guards failed. Restore family-prefix detection before applying policy waivers.
  • Original discussion: Verified still present at the reviewed head: check_pynvvideocodec.py now relies on policy.violates(...), whose deny globs cover plain, hash-renamed, and _dynamo codec library names but not other build-suffixed names such as libavcodec_nvc.so.63, libswscale_nvc.so.10, or libx264_nvc.so.164. The vLLM and SGLang runtime guard can therefore accept PyNvVideoCodec installs that the replaced prefix-based heredocs rejected. Restore family-prefix rejection before applying the policy waivers, and add a suffixed-library regression case.
  • Original discussion: Verified still present: test_a_partial_package_fails still lacks the empty-package parameter, so a guard that skips required-library validation when no bundled libraries are found would not be caught by this test.
  • Original discussion: Verified still present: the guard still delegates denial to policy globs that do not match build-suffixed third-party names such as libavcodec_nvc.so.63, libswscale_nvc.so.10, or libx264_nvc.so.164, so those bundled codec libraries can pass the shared guard.
  • Original discussion: Verified still present: the shared guard relies on codec_policy.yaml deny globs via policy.violates(), and those globs reject plain, hash-renamed, and _dynamo library names but do not reject other build-suffixed denied families such as libavcodec_nvc.so.63, libswscale_nvc.so.10, or libx264_nvc.so.164. The removed vLLM/SGLang heredocs used basename prefix matching for denied families, so those suffixed libraries would have failed before and now pass the guard.

Comment thread tests/dependencies/test_pynvvideocodec_spec.py Outdated
@devin-ai-integration

devin-ai-integration Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

✅ Dynamo PR CI passed — run 37480550987 (attempt 1) on 1d27fb141e

Gate checks: ✅ backend-status-check · ✅ deploy-status-check · ✅ dynamo-status-check

Posted automatically by Devin for run 37480550987. Updated on every full-CI run of this PR.

@dmitry-tokarev-nv dmitry-tokarev-nv 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.

Tested suggestions for the two open items, at 6e99032266. Please apply all three with "Add suggestion to batch", so that the fix and its tests land in one commit. When they land, I will re-run my probes on the new head and approve.

[P2] The fix is a suggestion on the check_pynvvideocodec.py:75 thread, and its test is at test_check_pynvvideocodec.py:120.

[P3] The suggestion is at test_check_pynvvideocodec.py:128.

Comment thread container/compliance/tests/test_check_pynvvideocodec.py
Comment thread container/compliance/tests/test_check_pynvvideocodec.py Outdated
Signed-off-by: Eric Curtin <eric.curtin@docker.com>
@ericcurtin
ericcurtin deployed to external_collaborator October 6, 2026 01:15 — with GitHub Actions Active
@ericcurtin

Copy link
Copy Markdown
Contributor Author

@dmitry-tokarev-nv Applied all three suggestions in 1d27fb1. PTAL when you get a chance. Thank you!

@dmitry-tokarev-nv

Copy link
Copy Markdown
Contributor

/ok to test 1d27fb1

@dmitry-tokarev-nv dmitry-tokarev-nv 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.

I approve 1d27fb141e. My P2 and P3 are fixed, and I resolved my three threads with the evidence. The fix and its tests are my suggestions, applied as written, so this approval partly reviews my own code.

[P3] No test protects the policy.violates(...) branch at check_pynvvideocodec.py:86. Without the branch, all 25 tests still pass. This gap is in the fix that I suggested. No push is needed for this approval, and a follow-up PR is fine.

Open: the two bot threads, at test line 130 and on the spec-test docstring, are yours to resolve, because main requires resolved threads.

Not run in CI: the SGLang image build on the v0.5.21 base with this guard. I tested that base in an image built from main.

What I measured at 1d27fb141e, with controls.
  • The guard file and its test file at this head are byte-identical to the files at 6e99032266 with my three suggestion blocks applied. The only other change removes a test docstring, after a bot comment.
  • On fake installs, a build-suffixed library from each of the nine old DENIED families now fails, as with the old heredoc. The table is on the check_pynvvideocodec.py:75 thread.
  • In the vLLM, SGLang and TensorRT-LLM runtime-test images for 6e99032266, the guard exits 0 on the real 2.2.3 install. It exits 1 with --pinned 2.2.2, and 1 with a planted suffixed library.
  • The 62 tests in the three test files of this PR pass in all three images.
  • Mutants: against a guard that skips the required-library check on an empty package, only the restored () case fails. Against a guard without the fix, only the two new suffixed cases fail.
  • A merge with main at 7d82c10d9ea050de5147d94894b99d664d60d37c is clean in git merge-tree. The 62 tests pass on the merged tree in the vLLM image, and in the SGLang image for main at c746b5de1b. main then moved to c5d615ea59193aa7805da7979ce22567289fa26a. The merge with it is clean too, and its two new commits change only files under components/src/dynamo/.
  • Behavior change: a suffixed libavformat or libavutil now fails too. The waivers cover only libavformat.so* and libavutil.so* directly in the package folder, and the real wheel bundles only those names.
  • CI on this head: PR run 37480550987 succeeded. The guard step ran on amd64 and arm64 in the vLLM, SGLang and TensorRT-LLM image builds. The dynamo-runtime / test / sequential cuda13.0, amd64 job passed all 25 guard tests. PR-XPU 37480550144 succeeded with its XPU lanes skipped. Pre Merge 37398246272 succeeded, and its PyNvVideoCodec spec hook passed.
The SGLang v0.5.21 base, which no CI run used with this guard.
  • main moved the SGLang base from v0.5.19 to v0.5.21 in 5c8b22b3d9, after the merge base of this branch. The guard imports yaml through scan_codecs.py, and the old heredoc did not.
  • Before the guard step, the template installs pip packages only with --no-deps, apart from gpu_memory_service (which needs msgspec and uvloop) and google-crc32c. So yaml must come from the base image.
  • In the SGLang runtime-test image for main at c746b5de1b, /opt/sglang/bin/python3 imports PyYAML 6.0.1. The PyYAML dist-info folder is dated 2026-10-01, like sglang-0.5.21 from the base. PyNvVideoCodec, which the template installs, is dated 2026-10-06. The guard step uses this interpreter: in the CI build of this head, the guard found the install under /opt/sglang.
  • In that image, the guard from the merged tree exits 0 on the real install, and 1 with a planted libavcodec_nvc.so.63.
The P3, with a tested change to one test.

At 6e99032266, policy.violates(...) was the only way to deny a library, so every denied-library test needed it. The fix adds a prefix match, which also catches every current test case. So a guard without the policy.violates(...) branch still passes all 25 tests.

The branch still matters. It is the only path for a name that matches a wildcard deny glob but no derived family. Without the branch, libavfoo_dynamo.so.1 and libswfoo_dynamo.so.2 pass the guard, and a new glob such as **/libfoo*.so* does not reach it.

This change to the first lines of the test at test_check_pynvvideocodec.py:143 covers the branch. The rest of the test stays the same.

@pytest.mark.parametrize("glob", ["**/libfoo.so*", "**/libfoo*.so*"])
def test_a_family_added_to_the_policy_reaches_the_guard(tmp_path, glob):
    site = _install(tmp_path, libs=(*GOOD_LIBS, "libfoo.so.1"))
    _check(site)
    doc = yaml.safe_load(DEFAULT_POLICY.read_text(encoding="utf-8"))
    doc["deny_globs"].append(glob)

With this change, the file passes 26 of 26 at this head. Without the branch, only test_a_family_added_to_the_policy_reaches_the_guard[**/libfoo*.so*] fails. black 23.1.0, isort 5.12.0, flake8 7.3.0 and ruff 0.5.2 pass on the changed file.

@furionw furionw 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.

Thank you

@dmitry-tokarev-nv
dmitry-tokarev-nv merged commit 50b1ce6 into ai-dynamo:main Oct 7, 2026
112 checks passed

This branch was successfully deployed

1 active deployment
external_collaborator — 1d27fb14 Deployed Oct 6, 2026 by ericcurtin via ok-to-test #26696
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend::trtllm Relates to the trtllm backend container external-contribution Pull request is from an external contributor refactor size/XL

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE]: Share the PyNvVideoCodec install guard and read its deny list from the codec policy

4 participants