From 25eb88743033273dfb75cd2d6755f624025ae2fd Mon Sep 17 00:00:00 2001 From: Benjamin Van Dam Date: Fri, 3 Jul 2026 14:37:28 +0200 Subject: [PATCH 1/2] feat(ci): retry transient platform errors, run firms in parallel, warn on firm drift Production revealed three problems with the parallel liquid-test run: 1. Transient platform errors counted as test failures. The platform sometimes returns internal_error ('Internal error. Try to run the test again...') or no response at all; the workflow reported those as FAILED with no second chance. Each template now gets up to MAX_TEST_ATTEMPTS (default 3) when its failure reason is transient (internal error, no response, run never completed, timeout). Genuine test failures - the CLI names the failing unit tests - are never retried. 2. A CLI crash failed every template in the batch. A template whose verdict is missing (the CLI died or dropped it) is now retried instead of immediately failing, and only reported as failed when retries are exhausted. A crashed bucket runner is also detected per template. 3. Firms waited on each other. Each | bucket now runs as its own background job (capped at MAX_PARALLEL_FIRMS, default 3), so a slow firm only delays its own bucket. Bucket output is flushed as one log group per bucket when it finishes, with a heartbeat line while waiting. Also: warn once when templates fall back to 'first firm id in config.json' - that choice silently changes when config.json is regenerated (this moved a whole PR's tests to a firm without test data and failed them all), and add timeout-minutes to the job now that retries can extend it. --- .github/workflows/run_tests.yml | 253 +++++++++++++++++++++++--------- 1 file changed, 183 insertions(+), 70 deletions(-) diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index f062585..c7f256d 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -78,16 +78,25 @@ jobs: test-templates: runs-on: ubuntu-latest + # A single platform test run can take up to ~33 minutes (the CLI's own polling limit), + # and transient errors are retried, so give the job room without letting it hang forever. + timeout-minutes: 120 env: SF_API_CLIENT_ID: "${{ secrets.SF_API_CLIENT_ID }}" SF_API_SECRET: "${{ secrets.SF_API_SECRET }}" SF_TEST_FIRM_ID: "${{ vars.SF_TEST_FIRM_ID }}" CHANGED_TEMPLATES: "${{ needs.check-changed-templates.outputs.changed_templates }}" - # Maximum number of liquid tests run in parallel against the live platform per batch. - # A single `run-test --status` call fires all of its handles concurrently (Promise.all) - # with no client-side rate limiting, so we cap the batch size and run batches - # sequentially to keep the global number of in-flight tests bounded. + # Concurrency and retry knobs. One `run-test --status` call runs all of its templates + # concurrently (Promise.all) with no client-side rate limiting, so the global number of + # in-flight tests is bounded by MAX_PARALLEL_TESTS (per call) x MAX_PARALLEL_FIRMS + # (buckets running at the same time). MAX_PARALLEL_TESTS: 10 + # How many firm|type buckets run at the same time. Different firms no longer wait for + # each other; a slow firm only delays its own bucket. + MAX_PARALLEL_FIRMS: 3 + # Attempts per template for TRANSIENT platform errors (internal error, no response, + # run never completed). Genuine test failures are never retried. + MAX_TEST_ATTEMPTS: 3 if: ${{ needs.check-changed-templates.outputs.changed_templates != '[]' }} needs: [check-auth, check-changed-templates] steps: @@ -112,13 +121,16 @@ jobs: - name: Run liquid tests for updated templates (grouped per firm, run in parallel) run: | MAX_PARALLEL="${MAX_PARALLEL_TESTS:-10}" - # Testable templates grouped by "|