From 92ee9f87ddc4dbd093fe2b9642405f47466dc634 Mon Sep 17 00:00:00 2001 From: diegosouzapw Date: Tue, 26 May 2026 06:50:13 -0300 Subject: [PATCH] fix(ci): green up remaining red checks (coverage artifacts, integration regex, e2e routing) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Coverage gate (`Coverage` job) The shard step wrote with `--output-dir=coverage-shard --reporter=json`, which emits the final `coverage-final.json` report but leaves the raw v8 temp files in `coverage/tmp`. The upload then picked up an empty `coverage-shard/` ("No files were found"), so the merge job downstream blew up with `ENOENT scandir 'coverage-shards'`. Switch to `--temp-directory=coverage-shard` so the raw v8 coverage files land in the artifact path the merge step expects. Integration Tests (1/2) — `chat-pipeline.test.ts` The `Gemini CLI fingerprint` assertion still pinned `google-api-nodejs-client/9.15.1`. PR #2676 bumped the constant to 10.3.0; derive the version from `GEMINI_CLI_GOOGLE_API_NODE_CLIENT_VERSION` the same way the unit tests do. E2E Tests (5/6) - `proxy-registry.smoke.spec.ts`: the registry heading now lives under the "Proxy Pool" sub-tab of /dashboard/system/proxy. The default tab is "Global Config", so the heading was off-screen. Navigate directly with `?tab=proxy-pool` so the smoke flow finds the heading again. - `providers-bailian-coding-plan.spec.ts`: switch the two `waitForLoadState` calls from `networkidle` to `domcontentloaded`. The bailian provider page keeps a long-poll alive (quota refresh), so `networkidle` never settled and the 300 s default timeout kicked in. `domcontentloaded` is enough to assert the dashboard rendered. --- .github/workflows/ci.yml | 8 +++++++- tests/e2e/providers-bailian-coding-plan.spec.ts | 4 ++-- tests/e2e/proxy-registry.smoke.spec.ts | 4 +++- tests/integration/chat-pipeline.test.ts | 5 +++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 375a946574..74bf958031 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -284,9 +284,15 @@ jobs: - run: npm run check:node-runtime - name: Run c8 over shard ${{ matrix.shard }}/4 run: | + # `--temp-directory` (writable via NODE_V8_COVERAGE) is what the merge + # job reads with `c8 report --temp-directory ...`. Using `--output-dir` + # only produces the final json *report* and leaves the raw v8 files in + # `coverage/tmp`, so uploading `coverage-shard/` was empty. Pin the temp + # dir so the raw coverage files live there and the artifact upload picks + # them up regardless of `--test-force-exit` timing. npx c8 \ --reporter=json \ - --output-dir=coverage-shard \ + --temp-directory=coverage-shard \ --exclude=tests/** \ --exclude=**/*.test.* \ node --import tsx --test --test-force-exit --test-concurrency=4 \ diff --git a/tests/e2e/providers-bailian-coding-plan.spec.ts b/tests/e2e/providers-bailian-coding-plan.spec.ts index 1abe178c17..1dd3704806 100644 --- a/tests/e2e/providers-bailian-coding-plan.spec.ts +++ b/tests/e2e/providers-bailian-coding-plan.spec.ts @@ -59,7 +59,7 @@ test.describe("Bailian Coding Plan Provider", () => { }); await gotoDashboardRoute(page, "/dashboard/providers/bailian-coding-plan"); - await page.waitForLoadState("networkidle"); + await page.waitForLoadState("domcontentloaded"); // Dismiss any pre-existing dialog/overlay that may appear on page load const preExistingDialog = page.getByRole("dialog").first(); @@ -170,7 +170,7 @@ test.describe("Bailian Coding Plan Provider", () => { }); await gotoDashboardRoute(page, "/dashboard/providers/bailian-coding-plan"); - await page.waitForLoadState("networkidle"); + await page.waitForLoadState("domcontentloaded"); // Dismiss any pre-existing dialog/overlay that may appear on page load const preExistingDialog = page.getByRole("dialog").first(); diff --git a/tests/e2e/proxy-registry.smoke.spec.ts b/tests/e2e/proxy-registry.smoke.spec.ts index f7f45c8218..7c2b087d01 100644 --- a/tests/e2e/proxy-registry.smoke.spec.ts +++ b/tests/e2e/proxy-registry.smoke.spec.ts @@ -172,7 +172,9 @@ test.describe("Proxy Registry smoke flow", () => { }); }); - await gotoDashboardRoute(page, "/dashboard/system/proxy"); + // The proxy registry now lives under the "Proxy Pool" sub-tab of the proxy + // settings page; navigate directly to it so the heading renders. + await gotoDashboardRoute(page, "/dashboard/system/proxy?tab=proxy-pool"); await expect(page.getByRole("heading", { name: "Proxy Registry" })).toBeVisible(); diff --git a/tests/integration/chat-pipeline.test.ts b/tests/integration/chat-pipeline.test.ts index c324b318f9..f5fd2289a8 100644 --- a/tests/integration/chat-pipeline.test.ts +++ b/tests/integration/chat-pipeline.test.ts @@ -24,7 +24,8 @@ const { initTranslators } = await import("../../open-sse/translator/index.ts"); const { clearInflight } = await import("../../open-sse/services/requestDedup.ts"); const { setCliCompatProviders } = await import("../../open-sse/config/cliFingerprints.ts"); const { BaseExecutor } = await import("../../open-sse/executors/base.ts"); -const { GEMINI_CLI_VERSION } = await import("../../open-sse/services/geminiCliHeaders.ts"); +const { GEMINI_CLI_VERSION, GEMINI_CLI_GOOGLE_API_NODE_CLIENT_VERSION } = + await import("../../open-sse/services/geminiCliHeaders.ts"); const { getCircuitBreaker, resetAllCircuitBreakers } = await import("../../src/shared/utils/circuitBreaker.ts"); const { clearProviderFailure } = await import("../../open-sse/services/accountFallback.ts"); @@ -938,7 +939,7 @@ test("chat pipeline sends Gemini CLI OAuth requests with native Cloud Code trans assert.match( generateCall.headers["User-Agent"], new RegExp( - `^GeminiCLI/${GEMINI_CLI_VERSION.replaceAll(".", "\\.")}/gemini-3-flash-preview .* google-api-nodejs-client/9\\.15\\.1$` + `^GeminiCLI/${GEMINI_CLI_VERSION.replaceAll(".", "\\.")}/gemini-3-flash-preview .* google-api-nodejs-client/${GEMINI_CLI_GOOGLE_API_NODE_CLIENT_VERSION.replaceAll(".", "\\.")}$` ) ); assert.match(generateCall.headers["X-Goog-Api-Client"], /^gl-node\/\d+\.\d+\.\d+$/);