Skip to content

feat(customizer): build RL training image to support DPO+GRPO - #901

Merged
anubhutivyas merged 1 commit into
mainfrom
aalgo-414-rl-image/anubhutiv
Jul 30, 2026
Merged

feat(customizer): build RL training image to support DPO+GRPO#901
anubhutivyas merged 1 commit into
mainfrom
aalgo-414-rl-image/anubhutiv

Conversation

@anubhutivyas

@anubhutivyas anubhutivyas commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features
    • Added redesigned NeMo-RL GPU base and training images with configurable base selection/version pinning.
    • Added a dedicated transformer-engine wheel build and packaging target.
    • Added a NeMo-RL training smoke-test build target and a default training command in the training image.
  • Documentation
    • Updated NeMo-RL Docker build/runtime documentation, including Ray venv behavior and shared cache guidance.
  • Tests
    • Strengthened GPU smoke tests to validate per-actor venv availability and imports via venv-scoped checks.

Testing:

Built the image and can run the DPO job fine with image chnages in this PR and DPO restoration in this PR - #943

========================= Step 2/2 =========================
▶ Taking a training step...
▶ Starting validation at step 2 for `default` set..
/opt/nemo-rl/nemo_rl/data/llm_message_utils.py:573: UserWarning: add_bos_token is True but the tokenizer does not have a BOS token. Skipping BOS token addition.
  warnings.warn(

📊 Validation Results for `default` set:
    • Validation loss: 0.6645
    • Validation sft_loss: 0.0000
    • Validation preference_loss: 0.6645
    • Validation accuracy: 1.0000
    • Validation rewards_chosen_mean: 0.7755
    • Validation rewards_rejected_mean: -0.3986
    • Validation num_valid_samples: 16.0000
    • Validation global_valid_seqs: 32.0000
    • Validation global_valid_toks: 496.0000

  ⏱️  Validation Timing for `default` set:
    • Total validation time: 3.16s
Saving checkpoint for step 2...
(DTensorPolicyWorker[rank=0] pid=16213) Saving tokenizer (or processor) to /var/run/scratch/job/training/checkpoints/tmp_step_2/policy/tokenizer

📊 Training Results:
  • loss: 0.6931
  • sft_loss: 0.0000
  • preference_loss: 0.6931
  • accuracy: 0.0000
  • rewards_chosen_mean: 0.0000
  • rewards_rejected_mean: 0.0000
  • num_valid_samples: 32.0000
  • global_valid_seqs: 64.0000
  • global_valid_toks: 992.0000
  • Training FLOPS: 1.07 TFLOPS (1.07 TFLOPS per rank)

⏱️  Timing:
  • Total step time: 19.36s
  • checkpointing: 9.95s (51.4%)
  • policy_training: 5.80s (30.0%)
  • policy_training/submit_training_futures: 0.00s (0.0%)
  • policy_training/sharding_data: 0.00s (0.0%)
Max number of steps has been reached, stopping training early
2026-07-30 06:30:55,618 - nmp.rl.tasks.training.backends.nemo_rl.ray_bootstrap - INFO - Driver completed with exit code: 0
2026-07-30 06:30:55,618 - nmp.rl.tasks.training.backends.nemo_rl.ray_bootstrap - INFO - [INFO] Cleaning up Ray cluster from RANK 0
[ray_bootstrap] Driver completed with exit code: 0
2026-07-30 06:30:55,618 - nmp.rl.tasks.training.backends.nemo_rl.ray_bootstrap - INFO - Creating termination signal: /tmp/logs/ENDED.platform-job-attempt-DxuNbv2JYdB16FkFVXK28e
2026-07-30 06:30:55,618 - nmp.rl.tasks.training.backends.nemo_rl.ray_bootstrap - INFO - Stopping Ray with 20s grace period
2026-07-30 06:31:15,640 - nmp.rl.tasks.training.backends.nemo_rl.ray_bootstrap - WARNING - ray stop did not complete within 20s
2026-07-30 06:31:25,618 - nmp.rl.tasks.training.backends.nemo_rl.ray_bootstrap - WARNING - [WARN] Cleanup timed out. Forcing termination.
2026-07-30 06:31:25,619 - nmp.rl.tasks.training.backends.nemo_rl.backend - INFO - Training completed successfully
2026-07-30 06:31:25,640 - nmp.rl.tasks.training.backends.nemo_rl.ray_bootstrap - INFO - [INFO] Cleanup complete.
2026-07-30 06:31:25,791 - httpx - INFO - HTTP Request: PUT http://nemo-platform-api:8080/apis/jobs/v2/workspaces/default/jobs/rl-f9c107ce2d15/steps/dpo-training/tasks/task-62494ac1-447f-439b-a3ab-1d4ee5b12cc0 "HTTP/1.1 200 OK"
2026-07-30 06:31:25,792 - nmp.rl.tasks.training.backends.nemo_rl.backend - INFO - Processing created checkpoint
Using dcp_ckpt_path of Dtensor V1: /var/run/scratch/job/training/checkpoints/step_2/policy/weights
Loading weights: 100%|██████████| 311/311 [00:00<00:00, 3381.07it/s]
Writing model shards: 100%|██████████| 1/1 [00:00<00:00,  2.39it/s]
2026-07-30 06:31:35,699 - nmp.rl.tasks.training.backends.nemo_rl.checkpoints - INFO - Saved HF checkpoint successfully
2026-07-30 06:31:35,746 - nmp.rl.tasks.training.chat_templates - INFO - Applied chat template to output checkpoint
2026-07-30 06:31:35,947 - httpx - INFO - HTTP Request: PUT http://nemo-platform-api:8080/apis/jobs/v2/workspaces/default/jobs/rl-f9c107ce2d15/steps/dpo-training/tasks/task-62494ac1-447f-439b-a3ab-1d4ee5b12cc0 "HTTP/1.1 200 OK"
2026-07-30 06:31:35,948 - nmp.rl.tasks.training.runner - INFO - Result written to: /var/run/scratch/job/training/rl_training_result.json
[launcher] 2026/07/30 06:31:37 Process completed successfully.

@github-actions github-actions Bot added the feat label Jul 27, 2026
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 28392/36233 78.4% 62.8%
Integration Tests 16980/34951 48.6% 21.1%

@anubhutivyas
anubhutivyas force-pushed the aalgo-414-rl-image/anubhutiv branch from dc44a1d to 8434602 Compare July 28, 2026 06:40
@anubhutivyas anubhutivyas changed the title feat(customizer): build RL tarining image to support DPO+GRPO feat(customizer): build RL training image to support DPO+GRPO Jul 28, 2026
@anubhutivyas
anubhutivyas force-pushed the aalgo-414-rl-image/anubhutiv branch from 8434602 to 8c0c013 Compare July 28, 2026 16:21
@anubhutivyas
anubhutivyas marked this pull request as ready for review July 28, 2026 16:21
@anubhutivyas
anubhutivyas requested review from a team as code owners July 28, 2026 16:21
@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR relocates NeMo-RL image definitions into docker/rl/, pins the RL source commit, adds configurable base-image selection, builds TransformerEngine wheels, introduces a training smoke-test target, and validates actor-specific environments.

Changes

NeMo-RL image pipeline

Layer / File(s) Summary
RL build inputs and Bake graph
docker-bake.hcl
Adds pinned RL settings, configurable base and wheel contexts, updated RL target wiring, the training smoke-test target, and TransformerEngine wheel target.
Pinned RL base image build
docker/rl/Dockerfile.nmp-rl-base, docker/rl/README.md
Configures NeMo-Gym cache behavior, prefetches sandbox dependencies, validates cache size, generates a container fingerprint, and publishes a non-root base image.
Training runtime and import validation
docker/rl/Dockerfile.nmp-rl-training, tests/smoke_gpu/*, plugins/nemo-rl/README.md
Builds the training and CPU smoke-test stages, registers the marker, validates actor-specific imports and shared-cache links, and updates Dockerfile references.
TransformerEngine wheel build
docker/base/Dockerfile.python-wheels
Builds pinned cp313 TransformerEngine wheels for CUDA architectures 9.0 and 10.0 and publishes them through a scratch wheel image.

Sequence Diagram(s)

sequenceDiagram
  participant DockerBake
  participant RLBase
  participant RLTraining
  participant SmokeTest
  DockerBake->>RLBase: build pinned nmp-rl-base
  RLBase->>RLTraining: provide nmp-rl-base context
  DockerBake->>RLTraining: build training runtime
  DockerBake->>SmokeTest: build smoke-test stage with marker
  SmokeTest->>SmokeTest: validate actor venv imports and cache links
Loading

Suggested reviewers: crookedstorm, albcui, aleckhoury, ngoncharenko, svvarom

🚥 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 accurately summarizes the main change: adding an RL training image for DPO and GRPO support.
✨ 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 aalgo-414-rl-image/anubhutiv

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

@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: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docker/rl/README.md (1)

79-79: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Remove the unmatched code fence.

This opens a fenced block at EOF without a matching opener.

🤖 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 `@docker/rl/README.md` at line 79, Remove the unmatched code fence at the end
of the README so the document does not end with an unterminated fenced block.
🤖 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 `@docker/rl/Dockerfile.nmp-rl-base`:
- Around line 155-157: Pin the OpenSandbox and Tenacity runtime dependencies
installed by the Dockerfile command instead of using lower bounds. Use exact
versions sourced from the RL dependency set or a pinned constraints file, and
update the uv pip install step so repeatable builds no longer resolve different
package versions.
- Around line 179-181: Remove the `|| true` fallback from the RUN step invoking
`cve-cleanup.sh` so cleanup failures fail the image build. Update
`cve-cleanup.sh` to handle expected missing files or packages idempotently while
propagating unexpected command errors.
- Around line 18-42: Update the nemo-rl source stage to consume the advertised
named build context instead of always fetching via remote ADD. Configure the
corresponding Bake target to provide the default Git source for nemo-rl while
preserving the NEMO_RL_REPO and NEMO_RL_REF overrides, or remove the documented
local-context override if it cannot be supported.
- Around line 195-221: After the permission setup in the nmp-rl-base stage,
configure a verified non-root default user for the published image instead of
leaving it as root. Add the user selection after the chmod command so the
existing setup remains root-owned, and ensure it matches the UID 1000 runtime
user expected by the training image.

In `@docker/rl/README.md`:
- Around line 1-8: Add a prerequisites section at the top of the README before
the build graph, documenting the required setup and dependencies. Append a ##
Next Steps section at the end with links to the Bake target, plugin guide, and
smoke test, preserving the existing design-decision content between these
sections.
- Around line 1-5: Update the product-name references in the README heading and
introductory text to use the repository’s configured documentation substitutions
instead of hardcoded names. Preserve the existing meaning and formatting while
applying substitutions consistently to NeMo-RL, NeMo Platform, and NeMo-Gym
references as supported by the Sphinx configuration.

---

Outside diff comments:
In `@docker/rl/README.md`:
- Line 79: Remove the unmatched code fence at the end of the README so the
document does not end with an unterminated fenced block.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: dccaf471-9bdd-46e8-a6d9-efdd24e2d5ee

📥 Commits

Reviewing files that changed from the base of the PR and between 944d77e and 8c0c013.

📒 Files selected for processing (9)
  • docker-bake.hcl
  • docker/Dockerfile.nmp-rl-base
  • docker/Dockerfile.nmp-rl-training
  • docker/rl/Dockerfile.nmp-rl-base
  • docker/rl/Dockerfile.nmp-rl-training
  • docker/rl/README.md
  • plugins/nemo-rl/README.md
  • tests/smoke_gpu/conftest.py
  • tests/smoke_gpu/test_rl_training.py
💤 Files with no reviewable changes (2)
  • docker/Dockerfile.nmp-rl-base
  • docker/Dockerfile.nmp-rl-training

Comment thread docker/rl/Dockerfile.nmp-rl-base Outdated
Comment thread docker/rl/Dockerfile.nmp-rl-base Outdated
Comment thread docker/rl/Dockerfile.nmp-rl-base
Comment thread docker/rl/README.md Outdated
Comment thread docker/rl/README.md Outdated

@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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
docker/rl/Dockerfile.nmp-rl-base (2)

33-34: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Pin NEMO_RL_REF to an immutable commit.

nmp/customizer is a mutable branch, so identical builds can consume different source. Default to a full commit SHA.

🤖 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 `@docker/rl/Dockerfile.nmp-rl-base` around lines 33 - 34, Update the
NEMO_RL_REF build argument in the Dockerfile to default to the full immutable
commit SHA for the intended revision, replacing the mutable nmp/customizer
branch while leaving NEMO_RL_REPO unchanged.

74-94: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Verify toolchain downloads before execution.

The CMake archive and uv installer execute without checksum or signature verification. Pin and validate their SHA-256 digests first.

🤖 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 `@docker/rl/Dockerfile.nmp-rl-base` around lines 74 - 94, Update the CMake
download and uv installation flow to verify SHA-256 digests before extracting or
executing either toolchain artifact. Add build arguments or equivalent pinned
digest values for the CMake archive and uv installer, validate each downloaded
file with the existing checksum tooling, and only continue when verification
succeeds; preserve the current installation paths and version-based URLs.
🤖 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 `@docker/base/Dockerfile.python-wheels`:
- Around line 348-364: Replace the floating TE_REF branch reference with the
full commit SHA 42b840051647eef89761a16dfdff87e82bb253ab in the Dockerfile’s
TransformerEngine checkout, and update the corresponding TransformerEngine
reference in docker-bake.hcl to the same SHA.

In `@docker/rl/Dockerfile.nmp-rl-base`:
- Around line 328-333: Update the Git cleanup RUN command near the .git removal
step to remove the `2>/dev/null || true` fallback, allowing `find` or `rm`
failures to fail the image build while retaining the existing `.git` removal
behavior.
- Around line 221-224: The OpenSandbox and multimedia dependency installs
currently target only /opt/nemo_rl_venv, while actors use /opt/ray_venvs. Update
the actor-prefetch or worker-venv setup near the existing opensandbox and
av/opencv_python_headless/decord2 installation logic so /opt/ray_venvs receives
the same packages and wheel replacements.

In `@docker/rl/README.md`:
- Around line 60-61: Update the sentence in the README to use the possessive
“its” instead of “it's” and change “is” to “are” for subject-verb agreement,
preserving the referenced symbols and meaning.
- Line 40: Update all five fenced code blocks in the README, including the
blocks near the referenced sections, to specify an appropriate language
identifier such as text for the ASCII diagrams. Preserve the diagram contents
and formatting.

---

Outside diff comments:
In `@docker/rl/Dockerfile.nmp-rl-base`:
- Around line 33-34: Update the NEMO_RL_REF build argument in the Dockerfile to
default to the full immutable commit SHA for the intended revision, replacing
the mutable nmp/customizer branch while leaving NEMO_RL_REPO unchanged.
- Around line 74-94: Update the CMake download and uv installation flow to
verify SHA-256 digests before extracting or executing either toolchain artifact.
Add build arguments or equivalent pinned digest values for the CMake archive and
uv installer, validate each downloaded file with the existing checksum tooling,
and only continue when verification succeeds; preserve the current installation
paths and version-based URLs.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a3dfd466-83d7-43a3-befc-62e1ed80bdc0

📥 Commits

Reviewing files that changed from the base of the PR and between 8c0c013 and 97edbf0.

📒 Files selected for processing (5)
  • docker-bake.hcl
  • docker/base/Dockerfile.python-wheels
  • docker/rl/Dockerfile.nmp-rl-base
  • docker/rl/Dockerfile.nmp-rl-training
  • docker/rl/README.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • docker/rl/Dockerfile.nmp-rl-training
  • docker-bake.hcl

Comment thread docker/base/Dockerfile.python-wheels
Comment thread docker/rl/Dockerfile.nmp-rl-base
Comment thread docker/rl/Dockerfile.nmp-rl-base Outdated
Comment thread docker/rl/README.md Outdated
Comment thread docker/rl/README.md Outdated
@anubhutivyas
anubhutivyas force-pushed the aalgo-414-rl-image/anubhutiv branch from 97edbf0 to 51db768 Compare July 29, 2026 21:58
@anubhutivyas anubhutivyas self-assigned this Jul 29, 2026

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

Some option changes and questions. The smoke test and .git delete need properly addressed (either correcting me or fixing) before approval

Comment thread docker/rl/README.md Outdated
Comment thread docker/rl/README.md
Comment thread docker/rl/README.md Outdated
Comment thread docker/rl/Dockerfile.nmp-rl-base Outdated
Comment thread tests/smoke_gpu/test_rl_training.py Outdated
Comment thread docker/rl/Dockerfile.nmp-rl-base
Comment thread docker/rl/Dockerfile.nmp-rl-base

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docker/rl/Dockerfile.nmp-rl-base (1)

401-407: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Exclude .git before copying a local source context.

NO_VCS_VERSION=1 only skips version probing. A documented local nemo-rl context can still copy .git into the layer at line 258, exposing history/remotes. Exclude VCS entries during the source COPY; do not remove them in a later layer. This also makes test_no_git_directories_shipped reliable for local builds.

🤖 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 `@docker/rl/Dockerfile.nmp-rl-base` around lines 401 - 407, Update the local
nemo-rl source COPY instruction near the existing source copy to exclude .git
directories before they enter the image layer, using the Docker build’s
established ignore mechanism. Do not rely on deleting .git in a later layer, and
preserve the NO_VCS_VERSION environment setting separately.
🤖 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 `@tests/smoke_gpu/test_rl_training.py`:
- Around line 37-57: Extend WORKER_VENV_IMPORTS with entries for the async Vllm
worker and SyncRolloutActor venvs, including each venv’s required import
packages. Ensure all five Docker-prefetched actor venvs are represented so smoke
tests validate every prefetch filter case.

---

Outside diff comments:
In `@docker/rl/Dockerfile.nmp-rl-base`:
- Around line 401-407: Update the local nemo-rl source COPY instruction near the
existing source copy to exclude .git directories before they enter the image
layer, using the Docker build’s established ignore mechanism. Do not rely on
deleting .git in a later layer, and preserve the NO_VCS_VERSION environment
setting separately.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: f771cacf-0932-40e3-83fc-1dc64d337262

📥 Commits

Reviewing files that changed from the base of the PR and between 805808d and 03869e4.

📒 Files selected for processing (3)
  • docker/rl/Dockerfile.nmp-rl-base
  • docker/rl/README.md
  • tests/smoke_gpu/test_rl_training.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • docker/rl/README.md

Comment thread tests/smoke_gpu/test_rl_training.py

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

LGTM -- as a fast follow can we document the hardware restriction for mamba DPO and GRPO? I'm not sure how to surface this on our skills. If you have ideas, fold it into the docs change, otherwise let's just create a ticket to refine

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

LGTM

Signed-off-by: anubhutiv <anubhutiv@nvidia.com>
@anubhutivyas
anubhutivyas force-pushed the aalgo-414-rl-image/anubhutiv branch from 08ae0fe to be54770 Compare July 30, 2026 19:09
@anubhutivyas
anubhutivyas added this pull request to the merge queue Jul 30, 2026
Merged via the queue into main with commit 5df24b5 Jul 30, 2026
58 checks passed
@anubhutivyas
anubhutivyas deleted the aalgo-414-rl-image/anubhutiv branch July 30, 2026 19:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants