Repository navigation
Stop cloud backtests when the requested push fails - #718
Conversation
`lean cloud backtest --push`, `lean cloud optimize --push` and `lean cloud live deploy --push` logged a push failure as a warning and then ran the previous cloud files, exiting 0. PushManager.push_projects now reports whether every project was pushed, and CloudProjectManager raises a PushFailedError when a requested push fails, so the command exits nonzero before compiling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
Approving. This fixes #717 as the issue asks, and nothing outside it changed.
What I checked
- Every caller of
get_cloud_project: onlycloud backtest,cloud optimizeandcloud live deploypasspush=True. The others passFalseand behave as before.lean cloud pushignores the new return value, so it behaves as before too. - Both push paths in
get_cloud_project(by local name, and by cloud name/id with a local copy) now stop beforeprojects.getand compile.PushFailedErrorisn't aRuntimeError, socloud backtestno longer turns a failed push into "No project ... found".main.pyprints it asError: ...and exits 1. - Mocked
push_projectsin the existing tests returns a truthyMock, so those tests are unaffected. - With the
lean/componentschanges reverted, the 4 new tests fail and the 2False-return checks still pass, which matches the description. With the fix, the full suite passes, excepttests/ui/test_app.py::test_command_process_runs_the_cli_as_a_child_process. That test fails the same way without the fix, because my environment has an installed CLI version that differs from the dev one. - CI is green on every platform and Python version.
- I also ran it end to end myself with a project that already had a cloud ID and a local file over the upload size limit.
lean cloud backtest <name> --pushandlean cloud backtest <cloud id> --pushboth printed the push warning, thenError: Cannot push ... aborting so the cloud does not run outdated files, didn't compile and exited 1. After I removed the file, the same command pushed and backtested as before, exit 0.
Your question about lean cloud push: making it exit nonzero changes a different command's behavior, which scripts may depend on. Leaving it out of this PR is right. Whether to change it is for a QuantConnect member to decide, in its own issue.
Other repositories: none need an update. The change is internal to the CLI, and the docs don't describe this exit status.
Risk: I set risk:low. The change is small and easy to revert. It only stops a run that would otherwise use stale cloud files after a push the user asked for already failed, so paths that work today are unchanged. The evidence covers it: tests that fail without the fix, green CI and an end-to-end run.
There was a problem hiding this comment.
Approved at caf182d. No blocking findings.
The change addresses #717 without changing successful pushes, push=False callers, or standalone lean cloud push. Both resolver paths stop after a failed requested upload. The dedicated exception also preserves the push-failure message instead of triggering backtest's project-not-found rewrite.
Verification
- CI: 54 successful checks, 6 skipped.
- Clean Python 3.11 environment,
python -m pytest -q: 2807 passed, 81 skipped on the full rerun. The first run had one unrelated random-name collision (2806 passed, 81 skipped, 1 failed); tracked separately in #722, with a deterministic reproduction. - Affected push-manager, resolver, backtest, optimization and live-command tests: 154 passed, 3 skipped.
python static_analysis.py: BUILD PASSED, with five existing unused-import warnings.- Replacing the two changed component methods with their base-branch versions made four new tests fail, including the command exiting 0 after a rejected upload. The failure-return assertion alone also accepts the old
None, but the resolver and command tests detect the original bug. - Additional local probes verified mixed-success batches, associated-library failure, empty batches, and a successful retry after failure.
- Tested end to end with an existing cloud ID and an upload rejected with HTTP 413: backtest by local name and cloud ID, optimization, and live deployment each exited 1 before compilation. No live deployment was started. After removing the oversized source file, push, compilation and backtesting succeeded with exit 0.
Separate existing issues
I reproduced these on both the base branch and this commit, so they do not block this fix:
- #719: referenced libraries are not uploaded by cloud commands'
--pushpath. - #720: an ID-based
--pushskips a locally renamed project. - #721: a push-induced directory rename leaves the resolver reading the old configuration path.
No other repositories need an update for this change. Keeping standalone lean cloud push exit-status changes out of this PR preserves its scope.
Risk: risk:low retained. This is a small, reversible fix that stops execution after an upload the user requested has already failed. Successful paths remain unchanged, and regression tests, green CI and end-to-end checks support that behavior.
Closes #717
What changed and why
With
--push,lean cloud backtest,lean cloud optimizeandlean cloud live deploypush the local project first. When that push failed (for example a write-permission error or files over the size limit),PushManager.push_projectsonly logged a warning, andCloudProjectManager.get_cloud_projectreturned the existing cloud project because it already had a cloud ID. The command then compiled and ran the previous cloud files and exited 0.PushManager.push_projectsnow returnsTruewhen every project and library was pushed andFalseotherwise. It still logs the same warnings and keeps pushing the remaining projects, solean cloud pushbehaves as before.CloudProjectManager.get_cloud_project(..., push=True)raises a newPushFailedErrorwhen the push fails, on both paths: project given by local name and project given by cloud name/id with a local copy. The command stops before compiling and exits 1 with:Error: Cannot push '<project>' to the cloud, aborting so the cloud does not run outdated filesPushFailedErroris its own type (notRuntimeError) becauselean cloud backtestrewrites anyRuntimeErrorfromget_cloud_projectinto a "No project ... found" message, which would hide the real cause.Commands that call
get_cloud_projectwithpush=Falseare unchanged.Tests
New tests:
test_push_manager.py:push_projectsreturnsTrueon success andFalsewhen a project that already has a cloud ID fails to upload.test_cloud_project_manager.py:get_cloud_projectraisesPushFailedErrorand does not look up the cloud project when the push fails, for a local project name and for a cloud id.test_backtest.py:lean cloud backtest "Python Project" --pushwith an existing cloud ID and a failed upload (write-permission error) exits nonzero and never compiles or runs a backtest.The new tests except the
Falsereturn test fail without the fix.python -m pytest -s -rs(Python 3.11):2807 passed, 81 skippedpython static_analysis.py:BUILD PASSEDscripts/readme.py: README unchangedTested end to end against a cloud API, with a project that already had a cloud ID and a local file too large to upload (the update request returns 413):
Cannot push ... status code 413, thenStarted compiling, ran the backtest on the old files, exit 0.Error: Cannot push 'E2EPush717' to the cloud, aborting so the cloud does not run outdated files, no compile, exit 1.Question
lean cloud pushitself still exits 0 when a project cannot be pushed (it only logs the warning), which I left as is because the issue is about the commands that run code afterwards. Should it also exit nonzero? That would be a separate change.