Skip to content

fix(novita): resolve whole ARG names and stop leaking the sandbox - #1236

Draft
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/openenv-release-management-0fd0
Draft

cursor[bot] wants to merge 1 commit into
mainfrom
cursor/openenv-release-management-0fd0

Conversation

@cursor

@cursor cursor Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Not for 0.6.0. Ben asked for these two as a follow-up PR explicitly outside tomorrow's cut, so please do not merge before the v0.6.0 tag — merging first would invalidate the validated release candidate (#1211) and its TestPyPI build.

Summary

Fixes the two latent Novita defects tracked as follow-ups when #1191 landed: ARG substitution could corrupt a FROM line, and the tbench2 example could leave a paid sandbox running.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • New environment
  • Refactoring

What was wrong

1. Shorter ARG names ate longer ones. _resolve_from_references substituted defaults name by name, in declaration order:

for name, value in arg_defaults.items():
    reference = reference.replace(f"${{{name}}}", value)
    reference = reference.replace(f"${name}", value)

So a Dockerfile declaring ARG BASE=python:3.12 before ARG BASE_IMAGE=… resolved an unbraced FROM $BASE_IMAGE to FROM python:3.12_IMAGE. Replaced with a single regex pass that matches a whole name ($NAME or ${NAME}) and looks it up, which is order-independent. Undeclared names are still left verbatim, and a substituted value is no longer re-expanded.

2. examples/novita_tbench2_simple.py leaked a sandbox. provider.wait_for_ready(...) sat above the try, so a readiness timeout returned without reaching finally: provider.stop_container() — the sandbox keeps billing. Moved inside the try. The other two Novita examples already did this correctly.

RFC Status

  • Not required (bug fix)

Test Plan

All three new tests fail on main and pass here (verified by stashing the two source fixes: 3 failed, 107 passed → 110 passed).

  • tests/test_core/test_novita_provider.py: prefix-colliding ARGs resolve correctly in both $BASE_IMAGE and ${BASE_IMAGE} form; the result is identical whichever order the two ARGs are declared in; an undeclared $UNSET_IMAGE stays verbatim; a value that itself contains $REGISTRY is not expanded twice.
  • tests/scripts/test_novita_examples_release_sandbox.py: parses every examples/novita_*.py and asserts any wait_for_ready call sits inside a try whose finally calls stop_container. This covers all three examples, so the next one cannot reintroduce the leak.

Full CI-equivalent suite locally: 2978 passed, 103 skipped. usort, ruff format and ruff check clean.

Claude Code Review

N/A

Open in Web View Automation 

Substituting ARG defaults name by name let a shorter name consume the
prefix of a longer one, so `ARG BASE` declared before `ARG BASE_IMAGE`
rewrote an unbraced `FROM $BASE_IMAGE` to `<base>_IMAGE`. Expand every
reference in one regex pass instead, which is order-independent and keeps
undeclared names verbatim.

The tbench2 example also awaited readiness above its try/finally, so a
readiness timeout returned without stopping the paid sandbox. The other
two Novita examples already do this correctly; a parse-level regression
now covers all three.

Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Duplicate of #1235 (parallel sibling for the same Ben Novita follow-up ask). Prefer #1235 (already has @Darktex requested; out of 0.6.0). Please close this draft.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Release

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Status at 7a865a56: 9 checks green, test (3.11) red — the red one is an infrastructure flake, not this change.

The 3.11 job never reached pytest. It died in Install dependencies:

error: Failed to fetch: `https://pypi.org/simple/modal/`
  Caused by: Request failed after 3 retries
  Caused by: operation timed out

test (3.12) ran the same suite on the same commit and passed, as did lint, Package CI, env locks, docs and the Docker runtime validation. Locally the full CI-equivalent suite is 2978 passed / 103 skipped on this branch.

I cannot re-run the job (gh run rerun → Resource not accessible by integration), and I do not want to push a no-op commit just to retrigger. This PR is deliberately a draft and must not merge before the v0.6.0 tag anyway, so CI will run again in full when it is refreshed onto post-release main. If someone with Actions write access wants a clean board sooner, re-running the failed job is enough.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Release

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Superseded by #1235 — do not merge this one. Three parallel runs opened the same follow-up (#1234, #1235, this); #1235 was designated the keeper and I agree with that choice on the merits, not just to break the tie: its longest-name-first substitution also expands a nested ARG default (ARG IMAGE_NAME=$REG/app → example.com/app), which matches Docker's behaviour, while the single regex pass here leaves $REG/app literal.

I moved the one piece worth keeping — tests/scripts/test_novita_examples_release_sandbox.py, which asserts every examples/novita_*.py waits for readiness inside the try that stops the sandbox — onto #1235 as a suggestion, verified passing against its head.

I cannot close this PR myself (gh pr close → Resource not accessible by integration), and a sibling run has already asked Ben to close #1234 and this one, so I am not repeating the ask. It stays a draft in the meantime; the red test (3.11) on it is the dependency-fetch flake described above, not a code failure.

View PR

Open in Web View Automation 

Sent by Cursor Automation: Release

This branch has not been deployed

No deployments
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.

1 participant