Repository navigation
Conversation
Refactor test/test_runner.py so the cloud path (run_tests) spawns all test runs at once via a ThreadPoolExecutor and collects results as they complete (concurrent.futures.as_completed), instead of running scripts sequentially. The same concurrent driver is applied to the --local path. Test submission is a blocking subprocess call (uv run / flyte run) with no async client, so a thread pool is the right primitive: threads let all runs wait on their cloud/local executions in parallel. A --concurrency flag (default 8, also settable via TestConfig) caps in-flight runs so the backend isn't overwhelmed; --concurrency 1 restores sequential behavior. Contract preserved: same CLI/entrypoint the Makefile + test-examples.yml workflow invoke, same per-test timeout, same pass/fail rules (including the Flyte-failure-in-output override), same result model, log files (logs/<script>.log, _local suffix), reports, and exit-code semantics. Cleanup: - run_single_test / run_single_test_local are now pure workers (run and return a TestResult); all console + log output is done by the driver on completion, so concurrent runs don't interleave output. - Drop the os.environ["FLYTECTL_CONFIG"] global mutation (unsafe under threads) — the config path is passed explicitly via each subprocess env. - Fix a latent bug: isolated local venvs were named by script stem, so two scripts sharing a filename (e.g. multiple main.py) collided; now named by full relative path — required for safe concurrent local runs. - Parse the Flyte config once per run instead of once per test. - Replace the FakeResult hack with a plain returncode override; remove the unused tempfile import; deterministic (sorted) result ordering. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Makes
test/test_runner.pyrun example scripts concurrently instead of sequentially, for both the cloud path (run_tests) and the local path (run_tests_local). Addresses DOC-1098 ("make the test runner async so it spawns all test runs at once and receives results as they complete; clean up the runner generally").How
concurrent.futures.ThreadPoolExecutorand collects results withas_completed, so results are handled the moment each run lands.uv run <script>for cloud,flyte run --localfor local) — there is no async client to await. A thread pool lets all runs wait on their cloud/local executions in parallel (subprocess I/O releases the GIL).--concurrency Nflag (default 8, also settable viaTestConfig.concurrency/ config JSON) caps in-flight runs so the cloud backend isn't overwhelmed.--concurrency 1restores the old sequential behavior.Contract preserved (no behavior change to what the CI workflow sees)
Confirmed against
.github/workflows/test-examples.yml→make {test,test-local,test-preview}→python test/test_runner.py [--local] [--preview] [--file|--filter] [--verbose]:--concurrencyadded).TestResultmodel.test/reports/logs/<script>.log,_localsuffix for local) and sametest_report.json/historical_results.json/index.htmlreports.sys.exit(1)on any failure/timeout).Cleanup included
run_single_test/run_single_test_localare now pure workers (run → returnTestResult); all console + log output happens in the single-threaded completion loop, so concurrent runs don't interleave output. Non-passing tests print their captured stdout/stderr so failures stay diagnosable in the Actions log.os.environ["FLYTECTL_CONFIG"]global mutation (unsafe under threads) — the config path is passed explicitly via each subprocessenv.main.py) collided on the same venv dir — a race under concurrency. Now named by full relative path.FakeResulthack with a plain returncode override; removed the unusedtempfileimport; deterministic (sorted) result ordering.Verification
Done without a live Flyte backend:
python -m py_compileclean;--helpshows all original args +--concurrency;--preview --filter hellodiscovers and lists scripts correctly.--concurrency 1; per-test result attribution correct (no cross-wiring); log files written with correct names/content; deterministic ordering; sequential fallback works.Needs a live backend to confirm (QA)
make test) against the Flyte backend — verify real concurrent submissions, correct per-run result attribution, execution-URL extraction, and that the default concurrency (8) respects backend quotas/rate limits (tune the default if needed).make test-local) — verify paralleluvvenv provisioning +flyte run --localbehaves under load.🤖 Generated with Claude Code