fix: stabilize Windows CI integration tests - #10940
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces several test stability improvements, including Windows-specific process teardown using taskkill, increased timeouts, parallelized test execution, and skipping MOTD fetching in CI environments. Feedback on these changes highlights a potential race condition on Windows where the process teardown promise is resolved too early, implicit any type violations on the this parameter in test suites, and a redundant process.env.CI check before calling fetchMOTD().
| }); | ||
|
|
||
| describe("apps:list", () => { | ||
| describe("apps:list", function (this) { |
There was a problem hiding this comment.
In TypeScript, the special this parameter must have an explicit type annotation (e.g., this: Mocha.Suite). Leaving it as function (this) results in an implicit any type, which violates the repository style guide's rule against using any as an escape hatch.
describe("apps:list", function (this: Mocha.Suite) {References
- Never use
anyorunknownas an escape hatch. Define proper interfaces/types or use type guards. (link)
There was a problem hiding this comment.
Done! Added explicit type annotation.
| }); | ||
|
|
||
| describe("apps:sdkconfig", () => { | ||
| describe("apps:sdkconfig", function (this) { |
There was a problem hiding this comment.
In TypeScript, the special this parameter must have an explicit type annotation (e.g., this: Mocha.Suite). Leaving it as function (this) results in an implicit any type, which violates the repository style guide's rule against using any as an escape hatch.
describe("apps:sdkconfig", function (this: Mocha.Suite) {References
- Never use
anyorunknownas an escape hatch. Define proper interfaces/types or use type guards. (link)
There was a problem hiding this comment.
Done! Added explicit type annotation.
| if (!process.env.CI) { | ||
| fetchMOTD(); | ||
| } |
|
/joe-review |
…l, and fix debug log step
…emulator/triggers tests
…ean-install cleanup
…r in pnpm fixture
…--no-audit to npm ci
…ock during npm ci
| p.once("exit", () => resolve()); | ||
| }); | ||
|
|
||
| const timeoutPromise = new Promise<void>((resolve) => setTimeout(resolve, 2000)); |
There was a problem hiding this comment.
🟡 Nit: Uncleared timeout
Rationale: The setTimeout is not cleared if the process exits before the 2-second timeout, which can keep the event loop active.
Suggested Fix:
let timeoutId: NodeJS.Timeout;
const timeoutPromise = new Promise<void>((resolve) => {
timeoutId = setTimeout(resolve, 2000);
});
try {
execSync(`taskkill /pid ${p.pid} /T /F`);
} catch {
// ignore if process already exited
}
return Promise.race([exitPromise, timeoutPromise]).then(() => {
clearTimeout(timeoutId);
this.process = undefined;
});…, and port filtering
… prevent cross-OS test collision
Description
Stabilizes Windows CI integration tests, addresses review feedback, and improves runner reliability.
Key Changes
src/unzip.ts,src/unzip.spec.ts):parentWithSeptrailing separator check inisChildDirto prevent prefix-matching sibling directories (e.g./tmp/appvs/tmp/app-secret) from bypassing directory traversal protection.win32to prevent casing discrepancies betweenprocess.cwd()and archive entries from triggering false-positive Zip Slip errors.isChildDir.scripts/integration-helpers/cli.ts):CLIProcess.stop()on Windows, executetaskkill /pid ${p.pid} /T /Fand await the processexitevent with a 2-second timeout race fallback.clearTimeoutwhen process exit resolves first.scripts/hosting-tests/run.sh,scripts/triggers-end-to-end-tests/run.sh):LISTENINGstate (lsof -sTCP:LISTENon POSIX and$2 ~ port"$" && $4 == "LISTENING"on Windows) to prevent killing client test runner processes with active connections to emulator ports.${GITHUB_RUN_NUMBER}-${RUNNER_OS}-${RANDOM}) to prevent cross-OS test collisions in matrix CI runs.src/fetchMOTD.ts):fetchMOTD()early whenprocess.env.CIis set to avoid unnecessary network calls and potential timeouts during CI test execution.scripts/hosting-tests/run.sh,scripts/storage-deploy-tests/run.sh):firebase target:apply <service> <target-name> <resource> --project <project>commands instead of writing.firebasercdirectly..github/workflows/node-test.yml):Set-MpPreference -ExclusionPath @("${{ github.workspace }}", "$env:LocalAppData\npm-cache", "$env:AppData\npm")) with explanatory documentation.npm@9.5downgrade step on Node 24 Windows runners to eliminate Arborist deadlock duringnpm ci.--prefer-offline --no-auditacross fixture dependency installations in test runners.scripts/client-integration-tests/tests.ts,run.sh):this: Mocha.Suiteannotations.this.timeout(15 * 1000)andthis.retries(2)toapps:listandapps:sdkconfigsuites.apps.listvariants in parallel usingPromise.all..firebasercdeletion indeployHostingafter hook with try/catch.scripts/client-integration-tests/run.sh.CI Validation Runs
All 6 Windows integration test suites (
client-integration,emulator,hosting,triggers-end-to-end:inspect,functions-discover,storage-deploy) and all 12 Linux suites have been validated with 100% GREEN (53/53 passing checks):b667bc42dclient-integration(2m43s),emulator(4m29s),hosting(7m11s),triggers:inspect(8m26s),functions-discover(6m45s),storage-deploy(6m38s)fa6cdcd78client-integration(3m50s),emulator(4m26s),hosting(7m9s),triggers:inspect(8m6s),functions-discover(8m21s),storage-deploy(11m54s)b10a8181dclient-integration(2m39s),emulator(4m41s),hosting(6m55s),triggers:inspect(9m8s),functions-discover(7m24s),storage-deploy(6m53s)