Skip to content

feat: Add container pooling for 60-80% faster test execution#549

Merged
jleni merged 6 commits intomainfrom
feat/pooling
Jul 20, 2025
Merged

feat: Add container pooling for 60-80% faster test execution#549
jleni merged 6 commits intomainfrom
feat/pooling

Conversation

@jleni
Copy link
Copy Markdown
Member

@jleni jleni commented Jul 20, 2025

Summary

This PR introduces a transparent container pooling system for Zemu that dramatically improves test execution performance by reusing Docker containers instead of creating new ones for each test.

Key Benefits

  • 🚀 60-80% faster test execution by eliminating container startup overhead (3-5 seconds per test)
  • 100% backwards compatible - all existing code works without changes
  • 🔧 Opt-in by default with multiple ways to disable if needed

What's Changed

New Features

  • Added ContainerPool class for managing pre-warmed containers
  • Implemented container reuse with proper cleanup and reset
  • Added port range pre-allocation to avoid conflicts
  • Lazy pool initialization (only when first needed)

Integration

  • Transparently integrated into Zemu.start() method
  • Automatic fallback to traditional containers if pool unavailable
  • Graceful error handling and recovery

Usage

The pool is enabled by default. No code changes needed:

// Your existing code works exactly the same, just faster\!
const sim = new Zemu(elfPath)
await sim.start(options)  // Automatically uses pool if available

Opt-Out Options

If you need to disable the pool for any reason:

  1. Environment variable: ZEMU_DISABLE_POOL=true
  2. Per-test: await sim.start({ ...options, disablePool: true })
  3. Globally: Zemu.disablePool()

Technical Details

Container Lifecycle

  • Containers are pre-created and kept warm
  • When acquired, containers are reset to clean state
  • Released containers return to pool for reuse
  • Automatic cleanup on process exit

Port Management

  • Pre-allocated port ranges per device type
  • Prevents port conflicts in parallel execution
  • Ranges: nanos (10000+), nanox (10100+), etc.

Performance Impact

  • Container creation: ~3-5 seconds → near instant
  • Full test suite: significant time savings
  • CI/CD pipelines: reduced build times

Testing

  • All existing tests pass without modification
  • Pool disable functionality verified
  • Graceful fallback tested
  • Container cleanup verified

Breaking Changes

None. This is a performance enhancement that maintains full backwards compatibility.

Summary by CodeRabbit

  • New Features

    • Introduced emulator container pooling for improved performance and resource management.
    • Added project tooling configuration files for Node.js version management and task automation.
    • Added recommended VS Code extensions and workspace settings for consistent formatting and spell checking.
    • Introduced a new linting and formatting toolchain using Biome.
    • Added new continuous integration workflows and enhanced dependency update automation.
    • Added detailed developer documentation.
    • Added Vitest testing framework configuration for streamlined test execution.
  • Bug Fixes

    • Modernized and improved code style, consistency, and formatting across the codebase.
  • Chores

    • Upgraded dependencies and migrated build/test scripts to pnpm and Vitest.
    • Updated author and engine requirements in project metadata.
    • Cleaned up obsolete configuration files (Jest, ESLint, Yarn, Prettier).
  • Documentation

    • Added comprehensive documentation for development, testing, and release processes.

jleni added 3 commits July 19, 2025 19:02
* modernize

* refactor: migrate to biome and standardize code style across project

* chore: update biome lint command and add fix script alias

* style: standardize quotes to single quotes and fix formatting

* refactor: replace forEach loops with for...of and remove unnecessary async keywords

* refactor: replace forEach loops with for...of and remove unnecessary async declarations

* ci: update workflow commands and disable coverage in ci-ts pipeline

* temporarily disable docker
* activate testing in ci

* ci: remove frozen lockfile in CI workflow
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jul 20, 2025

Walkthrough

This update introduces a container pooling system for emulator management in the Zemu framework, adds new configuration files for Biome, Vitest, and project tooling, and migrates CI/CD workflows to use reusable GitHub Actions. It replaces Yarn and Jest with pnpm and Vitest, updates dependencies, and applies consistent code style changes throughout the codebase.

Changes

Files/Groups Change Summary
.eslintrc.json, .prettierignore, .prettierrc, .yarnrc.yml, jest.config.js Removed ESLint, Prettier, Yarn, and Jest configuration files.
.github/workflows/main.yml Removed legacy main CI workflow with static-check and build-test jobs.
.github/workflows/ci-ts.yaml, .github/workflows/publish.yml Added new CI workflow for TypeScript and refactored publish workflow to use external reusable workflows, with concurrency and improved triggers.
.github/dependabot.yml Updated Dependabot config: target branch to main, grouped PRs, ignored major updates, improved commit message settings.
.gitignore Added tests/snapshots-tmp/ to ignored paths.
.mise.toml, .nvmrc, .vscode/extensions.json, .vscode/settings.json, biome.json, vitest.config.ts Added new configuration files for tooling, VSCode, Biome, and Vitest.
CLAUDE.md Added documentation for project structure, development, and testing practices.
package.json Migrated scripts from yarn/jest to pnpm/vitest/biome, updated dependencies, enforced Node.js and pnpm engine versions, changed author.
tsconfig.json Updated TypeScript target to ES2022.
src/Zemu.ts Added container pooling support: static pool management methods, refactored start and close methods to use pool or fallback, new private helper methods, added pooled container tracking.
src/containerPool.ts New singleton ContainerPool class managing emulator container pools per device model with port assignment, async lifecycle, reset/load logic, error handling, and status reporting.
src/types.ts Changed enums to explicit numeric assignments, switched to single quotes, stylistic interface changes.
src/emulator.ts, src/grpc/index.ts, src/index.ts, src/actions.ts, src/buttons.ts, src/buttons_flex.ts, src/buttons_stax.ts, src/constants.ts, src/zondax.ts, tests/basic.s.test.ts, tests/basic.x.test.ts, tests/globalsetup.ts, tests/minapp/index.ts, tests/pullImageKillOld.ts Applied consistent code style: single quotes, removed trailing semicolons, formatting, minor modernizations.

Sequence Diagram(s)

Emulator Startup with Container Pooling

sequenceDiagram
    participant User
    participant Zemu
    participant ContainerPool
    participant EmuContainer

    User->>Zemu: start(options)
    alt Pooling enabled & not disabled in options
        Zemu->>ContainerPool: initializePool(config) (if needed)
        Zemu->>ContainerPool: acquire(model, elfPath, libElfs)
        alt Container available
            ContainerPool-->>Zemu: pooledContainer
            Zemu->>EmuContainer: connect()
            Zemu->>Zemu: finalizeStart()
        else No container available or error
            Zemu->>Zemu: startWithNewContainer()
        end
    else Pooling disabled
        Zemu->>Zemu: startWithNewContainer()
    end
    Zemu-->>User: (startup complete)
Loading

Emulator Close with Container Pooling

sequenceDiagram
    participant User
    participant Zemu
    participant ContainerPool
    participant EmuContainer

    User->>Zemu: close()
    alt Using pooled container
        Zemu->>ContainerPool: release(container)
        alt Release fails
            Zemu->>EmuContainer: stop()
        end
    else Not using pool
        Zemu->>EmuContainer: stop()
    end
    Zemu-->>User: (close complete)
Loading

Container Pool Initialization

sequenceDiagram
    participant Zemu
    participant ContainerPool
    participant EmuContainer

    Zemu->>ContainerPool: initialize(config)
    loop For each model in config
        loop For N containers
            ContainerPool->>EmuContainer: create(elf, ports)
            EmuContainer-->>ContainerPool: ready
        end
    end
    ContainerPool-->>Zemu: (pool ready)
Loading

📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge Base: Disabled due to Reviews > Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between d129b10 and cbacbce.

📒 Files selected for processing (3)
  • .github/dependabot.yml (1 hunks)
  • .vscode/settings.json (1 hunks)
  • tests/pullImageKillOld.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • tests/pullImageKillOld.ts
  • .github/dependabot.yml
  • .vscode/settings.json
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test-with-docker
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/pooling

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 21

🧹 Nitpick comments (9)
src/constants.ts (1)

39-51: Consider explicit default for new pool toggle
IStartOptions now contains optional disablePool?: boolean, but DEFAULT_START_OPTIONS omits it.
Adding disablePool: false clarifies the intent and avoids downstream undefined checks.

   approveAction: ButtonKind.ApproveHoldButton,
   approveKeyword: '',
   rejectKeyword: '',
+  disablePool: false,
 }
src/actions.ts (1)

20-26: Dummy button is hard-coded to nanos; consider making it model-agnostic

Hard-coding the fallback button to 'nanos' may yield incorrect coordinates/timing when the click schedule ultimately drives a different device model. Not a blocker, but worth keeping in mind if you later introduce model-specific behaviour or visual tests that rely on accurate coordinates.

src/grpc/index.ts (1)

31-35: const self = this can be replaced with arrow callback

Using an arrow function keeps lexical this intact and avoids the self alias boilerplate.

-    // eslint-disable-next-line @typescript-eslint/no-this-alias
-    const self = this
-    // @ts-expect-error types are missing
-    // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
-    this.server.addService(rpcDefinition.ledger_go.ZemuCommand.service, {
-      Exchange(call: any, callback: any, ctx = self) {
+    this.server.addService(rpcDefinition.ledger_go.ZemuCommand.service, {
+      Exchange: (call: any, callback: any) => {
+        const ctx = this
         ...
       },
     })
src/buttons.ts (1)

52-54: Remove stray console output from library code

console.log in a shared helper risks polluting stdout for downstream consumers (e.g., test output, CI logs). Prefer throwing, returning undefined, or using a proper logger with verbosity control.

-  console.log(`Unsupported ButtonKind: ${model}, ${buttonKind}`)
+  // Consider throwing or using a debug logger instead of console.log
CLAUDE.md (2)

14-17: pnpm copy-files script is undocumented in package.json

The docs advertise an extra build step, but there is no matching script in package.json.
Either add the script or drop the reference to avoid confusion.


94-99: Consider warning about Docker Desktop resource limits

Parallel, pre-warmed containers can quickly exhaust the default 2 CPU / 2 GB limits of Docker Desktop on macOS/Windows.
A short note here (or a link to the “Important Notes” section) would help newcomers avoid opaque “container out-of-memory” failures.

vitest.config.ts (1)

11-15: Path alias should be resolved to an absolute path

Vitest (and Vite) recommend using resolve(__dirname, 'src') (or fileURLToPath) to avoid win/posix edge-cases and ensure TS path mapping stays in sync.

-import { defineConfig } from 'vitest/config'
+import { defineConfig } from 'vitest/config'
+import { resolve } from 'node:path'

 ...
   resolve: {
     alias: {
-      '@': './src',
+      '@': resolve(__dirname, 'src'),
     },
   },
tests/basic.s.test.ts (1)

34-38: Vitest’s test.concurrent API is still experimental

Vitest v1 marks test.concurrent as experimental; failures are rare but possible.
If stability issues arise, consider plain test() with the --run-in-band flag or allowOnly filters.

src/containerPool.ts (1)

135-136: Consider validating the dummy ELF path.

The hardcoded dummy ELF path might not exist in all environments. Consider adding validation or making it configurable.

Consider adding a check for the dummy ELF path existence or make it a configurable constant:

-    // Use a dummy ELF path for pool containers - will be replaced when acquired
-    // For now, we need a valid ELF file path to create the container
-    const dummyElfPath = 'bin/demoAppS.elf'
+    // Use a dummy ELF path for pool containers - will be replaced when acquired
+    const dummyElfPath = process.env.ZEMU_POOL_DUMMY_ELF || 'bin/demoAppS.elf'
+    if (!fs.existsSync(dummyElfPath)) {
+      throw new Error(`Dummy ELF path does not exist: ${dummyElfPath}`)
+    }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Knowledge Base: Disabled due to Reviews > Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 26d8035 and 2cc01b9.

⛔ Files ignored due to path filters (2)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (36)
  • .eslintrc.json (0 hunks)
  • .github/dependabot.yml (1 hunks)
  • .github/workflows/ci-ts.yaml (1 hunks)
  • .github/workflows/main.yml (0 hunks)
  • .github/workflows/publish.yml (1 hunks)
  • .gitignore (1 hunks)
  • .mise.toml (1 hunks)
  • .nvmrc (1 hunks)
  • .prettierignore (0 hunks)
  • .prettierrc (0 hunks)
  • .vscode/extensions.json (1 hunks)
  • .vscode/settings.json (1 hunks)
  • .yarnrc.yml (0 hunks)
  • CLAUDE.md (1 hunks)
  • biome.json (1 hunks)
  • jest.config.js (0 hunks)
  • package.json (2 hunks)
  • src/Zemu.ts (9 hunks)
  • src/actions.ts (1 hunks)
  • src/buttons.ts (1 hunks)
  • src/buttons_flex.ts (3 hunks)
  • src/buttons_stax.ts (3 hunks)
  • src/constants.ts (1 hunks)
  • src/containerPool.ts (1 hunks)
  • src/emulator.ts (1 hunks)
  • src/grpc/index.ts (2 hunks)
  • src/index.ts (1 hunks)
  • src/types.ts (1 hunks)
  • src/zondax.ts (3 hunks)
  • tests/basic.s.test.ts (2 hunks)
  • tests/basic.x.test.ts (2 hunks)
  • tests/globalsetup.ts (1 hunks)
  • tests/minapp/index.ts (2 hunks)
  • tests/pullImageKillOld.ts (1 hunks)
  • tsconfig.json (1 hunks)
  • vitest.config.ts (1 hunks)
💤 Files with no reviewable changes (6)
  • .prettierignore
  • .yarnrc.yml
  • jest.config.js
  • .eslintrc.json
  • .github/workflows/main.yml
  • .prettierrc
🧰 Additional context used
🧬 Code Graph Analysis (5)
src/buttons_flex.ts (2)
src/buttons_stax.ts (17)
  • quitAppButton (27-32)
  • swipeContinueButton (34-39)
  • navRightButton (41-46)
  • navLeftButton (48-53)
  • settingsNavRightButton (56-56)
  • settingsNavnavLeftButton (58-63)
  • settingsQuitButton (65-70)
  • rejectButton (72-77)
  • toggleOption1 (80-85)
  • approveTapButton (87-92)
  • prevPageButton (94-99)
  • approveHoldButton (101-106)
  • toggleOption2 (109-114)
  • confirmYesButton (123-128)
  • confirmNoButton (130-135)
  • showQRButton (137-142)
  • closeQRButton (144-149)
src/types.ts (1)
  • IButton (73-78)
src/constants.ts (2)
src/index.ts (3)
  • DEFAULT_START_OPTIONS (20-20)
  • IStartOptions (21-21)
  • ButtonKind (21-21)
src/types.ts (2)
  • IStartOptions (44-65)
  • IDeviceWindow (16-21)
src/buttons_stax.ts (2)
src/buttons_flex.ts (17)
  • quitAppButton (27-32)
  • swipeContinueButton (34-39)
  • navRightButton (41-46)
  • navLeftButton (48-53)
  • settingsNavRightButton (56-56)
  • settingsNavnavLeftButton (58-63)
  • settingsQuitButton (65-70)
  • rejectButton (72-77)
  • toggleOption1 (80-85)
  • approveTapButton (87-92)
  • prevPageButton (94-99)
  • approveHoldButton (101-106)
  • toggleOption2 (109-114)
  • confirmYesButton (116-121)
  • confirmNoButton (123-128)
  • showQRButton (130-135)
  • closeQRButton (137-142)
src/types.ts (1)
  • IButton (73-78)
src/buttons.ts (1)
src/types.ts (2)
  • IButton (73-78)
  • TModel (42-42)
tests/globalsetup.ts (1)
src/Zemu.ts (1)
  • Zemu (68-1049)
🪛 YAMLlint (1.37.1)
.github/dependabot.yml

[error] 18-18: trailing spaces

(trailing-spaces)


[error] 25-25: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/publish.yml

[error] 24-24: no new line character at the end of file

(new-line-at-end-of-file)

.github/workflows/ci-ts.yaml

[error] 30-30: trailing spaces

(trailing-spaces)


[error] 34-34: trailing spaces

(trailing-spaces)


[error] 39-39: trailing spaces

(trailing-spaces)


[error] 45-45: trailing spaces

(trailing-spaces)


[error] 48-48: trailing spaces

(trailing-spaces)


[error] 52-52: no new line character at the end of file

(new-line-at-end-of-file)

🪛 Gitleaks (8.27.2)
src/emulator.ts

21-21: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.

(generic-api-key)

🪛 GitHub Actions: CI-ts
src/containerPool.ts

[error] 48-48: Biome lint/correctness/noUnusedPrivateClassMembers: This private class member 'maxWaitTime' is defined but never used. Unsafe fix suggested: Remove unused declaration.


[error] 166-166: Biome lint/correctness/noUnusedFunctionParameters: The parameter 'transportPort' is unused. Unsafe fix suggested: prepend parameter with an underscore.


[error] 176-176: Biome lint/correctness/noUnusedVariables: The variable 'error' is unused. Unsafe fix suggested: prepend variable with an underscore.


[error] 324-324: Biome lint/correctness/noUnusedVariables: The variable 'model' is unused. Unsafe fix suggested: prepend variable with an underscore.


[error] 17-17: Biome assist/source/organizeImports: The imports and exports are not sorted. Safe fix suggested: Organize Imports.

src/Zemu.ts

[error] 17-17: Biome assist/source/organizeImports: The imports and exports are not sorted. Safe fix suggested: Organize Imports.


[error] 92-92: Biome lint/style/noInferrableTypes: This type annotation is trivially inferred from its initialization. Safe fix suggested: Remove the type annotation.


[error] 94-94: Biome lint/style/noInferrableTypes: This type annotation is trivially inferred from its initialization. Safe fix suggested: Remove the type annotation.


[error] 148-410: Biome format: Formatter would have printed changes to multiple lines including import organization, trailing commas, arrow function parentheses, and whitespace fixes.

🔇 Additional comments (37)
.gitignore (1)

176-177: Addition looks good & aligns with new snapshot workflow
Ignoring tests/snapshots-tmp/ prevents committing ephemeral snapshot artefacts generated by Vitest. No concerns.

src/index.ts (1)

16-22: Pure style change – OK
Import/​export quote-style switch is in line with the new Biome config; nothing functional altered.

src/buttons_stax.ts (1)

151-160: Map entry will break after rename
Once the symbol is fixed (see previous comment) adjust the map accordingly:

-  [ButtonKind.SettingsNavLeftButton, stax.settingsNavnavLeftButton],
+  [ButtonKind.SettingsNavLeftButton, stax.settingsNavLeftButton],
src/buttons_flex.ts (1)

144-153: Update map after symbol rename

-  [ButtonKind.SettingsNavLeftButton, flex.settingsNavnavLeftButton],
+  [ButtonKind.SettingsNavLeftButton, flex.settingsNavLeftButton],
src/actions.ts (1)

16-17: Purely stylistic diff – no functional impact

Imports were switched to single quotes and kept type-safe. No action needed.

src/zondax.ts (1)

34-36: Defaults and fall-backs look correct

The newly formatted default click arrays and touch sequences remain intact and unambiguous. No behaviour change detected.

tests/minapp/index.ts (1)

25-33: Object.hasOwn requires Node 20; verify runtime compatibility

Object.hasOwn() landed in Node 20. If your minimum supported runtime is < 20, fall back to Object.prototype.hasOwnProperty.call(obj, key).

CLAUDE.md (1)

104-107: Node 22 is not LTS – highlight the implication

Requiring a non-LTS runtime may surprise CI users locked to the LTS channel.
Add a sentence explaining why 22+ is needed (e.g. StructuredClone / top-level await) and how to use ZEMU_NODE_VERSION_OVERRIDE if they must stay on 20.

.nvmrc (1)

1-1: Pinning to 22 may break contributors on LTS

Node 22 is in current status until Oct 2025. Consider:

-22
+20
+# or use:
+# lts/*

and rely on engines/CI to enforce 22 only where strictly needed.

.vscode/extensions.json (1)

1-3: 👍 Editor tooling recommendation looks good

.vscode/settings.json (2)

4-7: Biome “quick-fix” keys likely incorrect

VS Code expects either source.fixAll.biome or source.organizeImports.biome, not quickfix.biome.
Please double-check the Biome extension docs – these keys may be silently ignored.

-    "quickfix.biome": "explicit",
+    "source.fixAll.biome": "explicit",

1-15: Config looks good overall

Consistent formatter + on-save actions will help avoid style drift.
No further issues spotted.

vitest.config.ts (1)

4-10: Sane default test settings

60 s timeout, Node env and globals make sense for this repo. 👍

.mise.toml (2)

21-24: Ensure pnpm check script exists

tasks.check calls pnpm check, but no native pnpm check command exists unless you defined a script named check in package.json.
Please verify; otherwise the task will fail.


1-31: Nice use of mise tasks

Clear, self-documenting tasks aligned with CI pipeline.

tests/basic.s.test.ts (1)

1-168: Styling-only diff acknowledged

Switch to single quotes & reordered imports only—logic untouched. Looks good.

.github/dependabot.yml (1)

1-25: Dependabot config otherwise looks solid

Daily updates, grouped minor/patch bumps & CI actions separation are sensible.

tests/basic.x.test.ts (4)

3-3: LGTM - Modern Node.js import syntax

The change to use 'node:path' import is a good practice for explicitly indicating Node.js built-in modules.


19-19: LGTM - Import statement formatting

Stylistic change to single quotes aligns with the project's code style standardization.


21-30: LGTM - Consistent variable declarations and formatting

The changes maintain functionality while improving code style consistency with single quotes and proper formatting.


32-89: LGTM - Test logic preserved with improved formatting

All test cases maintain their original logic while adopting the new code style. The migration to Vitest with test.concurrent syntax is appropriate and the test assertions remain intact.

tests/globalsetup.ts (2)

1-1: LGTM - Import statement formatting

Stylistic change to single quotes aligns with project standards.


3-8: LGTM - Correctly removed async from synchronous function

The removal of async from catchExit is correct since Zemu.stopAllEmuContainers() is a synchronous method according to the implementation in src/Zemu.ts.

package.json (4)

3-3: LGTM - Author organization update

The change from "Zondax GmbH" to "Zondax AG" appears to be a legitimate organizational update.


21-24: LGTM - Modern engine requirements

The engine requirements for Node.js >=22.0.0 and pnpm >=8.0.0 are appropriate for a modern project and align with the infrastructure modernization.


25-37: LGTM - Comprehensive tooling modernization

The script updates reflect a well-planned migration:

  • Yarn → pnpm for package management
  • Jest → Vitest for testing
  • ESLint/Prettier → Biome for linting/formatting

This modernization should improve performance and developer experience.


41-68: LGTM - Updated dependencies align with modernization

The dependency updates are consistent with the infrastructure modernization and include security updates for packages like axios.

src/emulator.ts (4)

17-19: LGTM - Modern Node.js import syntax

The change to explicit Node.js built-in module imports (node:path, node:stream) is a best practice.


62-67: LGTM - Improved iteration pattern

The change from forEach to for...of loop is more readable and potentially more performant.


144-148: LGTM - Consistent iteration pattern

Another good improvement from forEach to for...of loop for better readability.


229-230: LGTM - Explicit undefined assignment

Setting this.currentContainer = undefined is clearer and more explicit than using delete, which is a good practice.

src/types.ts (4)

16-27: LGTM - Consistent interface formatting

The removal of semicolons and consistent formatting improves readability while maintaining the same interface definitions.


42-42: LGTM - Consistent string literal formatting

Standardizing to single quotes aligns with the project's code style.


63-63: LGTM - New container pooling option

The addition of disablePool?: boolean supports the new container pooling feature mentioned in the PR objectives.


85-132: LGTM - Explicit enum values improve maintainability

Adding explicit numeric values to enums prevents issues with accidental reordering and makes the values clear and predictable. This is especially important for enums that might be serialized or used in external interfaces.

biome.json (1)

1-104: LGTM! Comprehensive Biome configuration.

The configuration properly sets up linting, formatting, and code assistance rules. The migration from ESLint/Prettier to Biome is well-executed with appropriate rule mappings and settings.

src/Zemu.ts (1)

143-166: Well-implemented pool initialization with good error handling.

The pool initialization method properly handles configuration, provides sensible defaults, and includes appropriate error recovery by disabling the pool on failure.

Comment thread .github/dependabot.yml Outdated
Comment thread .github/dependabot.yml Outdated
Comment thread .github/workflows/ci-ts.yaml Outdated
Comment thread .github/workflows/ci-ts.yaml Outdated
Comment thread .github/workflows/publish.yml
Comment thread src/Zemu.ts
Comment thread tests/globalsetup.ts
Comment thread tests/minapp/index.ts
Comment thread tests/pullImageKillOld.ts Outdated
Comment thread tsconfig.json
Comment on lines +3 to 5
"target": "es2022",
"module": "commonjs",
"moduleResolution": "node",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

target: "es2022" with module: "commonjs" blocks top-level await

ES2022 features such as top-level await only work under an ESModule loader.
If the codebase intends to rely on them (e.g. pool warm-up at module scope), switch to:

-  "module": "commonjs",
+  "module": "es2022",

or to "module": "nodenext" for seamless CJS/ESM interop.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"target": "es2022",
"module": "commonjs",
"moduleResolution": "node",
"target": "es2022",
- "module": "commonjs",
+ "module": "es2022",
"moduleResolution": "node",
🤖 Prompt for AI Agents
In tsconfig.json around lines 3 to 5, the current setting "target": "es2022"
combined with "module": "commonjs" prevents using top-level await. To fix this,
change the "module" option to "es2022" or "nodenext" to enable ESModule loading
and support top-level await. Update the "module" field accordingly to allow
ES2022 features to work properly.

jleni added 3 commits July 20, 2025 12:25
- Fix YAML linting issues in GitHub workflow files
  - Remove trailing spaces in ci-ts.yaml
  - Add missing newlines at end of YAML files
- Fix typo: settingsNavnavLeftButton → settingsNavLeftButton
- Organize imports in containerPool.ts (external packages first)
- Remove unused model variable in cleanup() method
- Apply automated code formatting improvements
- Fix missing parentheses in tests/minapp/index.ts toString() call
- Add error handling to gRPC exchange promise chain
- Remove async modifier from globalsetup.ts (no await needed)
- Add race condition protection for pool initialization
- Document DEV_CERT_PRIVATE_KEY as development-only test key
- Fix trailing spaces in .github/dependabot.yml
- Add missing await to async operations in tests/pullImageKillOld.ts
- Wrap async calls in IIFE to prevent CI hanging on cleanup

This should resolve the hanging CI build and address the remaining
CodeRabbit linting issues.
@jleni jleni merged commit a20fc25 into main Jul 20, 2025
6 checks passed
@jleni jleni deleted the feat/pooling branch July 20, 2025 13:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant