Skip to content

Conversation

@matthiasmatt
Copy link
Contributor

This pull request introduces a new GitHub Actions workflow for building and publishing the Passkey Bundler Docker image, updates the Docker base image for improved compatibility, enhances environment variable parsing, and adds new configuration-related tests. The changes improve the CI/CD pipeline, increase Docker image compatibility, and strengthen configuration validation.

CI/CD and Docker workflow improvements:

  • Added a new workflow .github/workflows/passkey-bundler-docker.yml to build, push, and publish multi-architecture Docker images for Passkey Bundler, including logic to detect relevant changes and handle release tags.
  • Updated .github/workflows/release.yml to ignore passkey-bundler/v* tags, preventing duplicate releases for Docker-specific tags.

Docker image compatibility:

  • Changed the base image in passkey-bundler/Dockerfile from node:20-alpine to node:20-bookworm-slim for both build and runtime stages, improving compatibility with native dependencies.

Configuration handling and testing:

  • Improved boolean environment variable parsing in passkey-bundler/src/config.ts to support more values (e.g., "y", "on", "n", "off") and handle whitespace/empty strings robustly.
  • Added helpers and new tests in passkey-bundler/test/basic.test.ts to verify configuration loading, especially for testnet mode and authentication requirements. [1] [2]

@matthiasmatt matthiasmatt requested a review from a team as a code owner December 19, 2025 17:42
Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new GitHub Actions workflow for publishing the Passkey Bundler, improves Docker image compatibility, and enhances configuration handling. The changes are well-structured and clearly described. My review includes a minor simplification for the boolean environment variable parsing and suggestions to improve test hygiene by using temporary directories for database files in the new tests, ensuring they are isolated and leave no artifacts.

Comment on lines +218 to +236
test("testnet mode defaults authRequired=true and requires API keys", () => {
const entryPoint = "0x" + "11".repeat(20)
const privateKey = "0x" + "22".repeat(32)

withBundlerEnv(
{
BUNDLER_MODE: "testnet",
ENTRY_POINT: entryPoint,
BUNDLER_PRIVATE_KEY: privateKey,
DB_URL: "sqlite:./data/bundler.sqlite",
},
() => {
assert.throws(
() => loadConfig(),
/Testnet mode requires API keys \(set BUNDLER_API_KEYS\) or disable authRequired/,
)
},
)
})

Choose a reason for hiding this comment

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

high

This test writes to a hardcoded database path (sqlite:./data/bundler.sqlite), which can cause side effects and leave artifacts after test runs. To ensure test isolation and cleanliness, it's best practice to use a temporary directory for such files and clean it up afterwards, similar to how other tests in this file are structured.

test("testnet mode defaults authRequired=true and requires API keys", () => {
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), "passkey-bundler-"))
  try {
    const entryPoint = "0x" + "11".repeat(20)
    const privateKey = "0x" + "22".repeat(32)

    withBundlerEnv(
      {
        BUNDLER_MODE: "testnet",
        ENTRY_POINT: entryPoint,
        BUNDLER_PRIVATE_KEY: privateKey,
        DB_URL: `sqlite:${path.join(dir, "bundler.sqlite")}`,
      },
      () => {
        assert.throws(
          () => loadConfig(),
          /Testnet mode requires API keys \(set BUNDLER_API_KEYS\) or disable authRequired/,
        )
      },
    )
  } finally {
    fs.rmSync(dir, { recursive: true, force: true })
  }
})

Comment on lines +238 to +254
test("testnet mode respects BUNDLER_REQUIRE_AUTH=false", () => {
const entryPoint = "0x" + "11".repeat(20)
const privateKey = "0x" + "22".repeat(32)

const config = withBundlerEnv(
{
BUNDLER_MODE: "testnet",
ENTRY_POINT: entryPoint,
BUNDLER_PRIVATE_KEY: privateKey,
DB_URL: "sqlite:./data/bundler.sqlite",
BUNDLER_REQUIRE_AUTH: "false",
},
() => loadConfig(),
)

assert.equal(config.authRequired, false)
})

Choose a reason for hiding this comment

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

high

Similar to the previous test, this test writes to a hardcoded database path. This should be updated to use a temporary directory to ensure test isolation and prevent leaving artifacts.

test("testnet mode respects BUNDLER_REQUIRE_AUTH=false", () => {
  const dir = fs.mkdtempSync(path.join(os.tmpdir(), "passkey-bundler-"))
  try {
    const entryPoint = "0x" + "11".repeat(20)
    const privateKey = "0x" + "22".repeat(32)

    const config = withBundlerEnv(
      {
        BUNDLER_MODE: "testnet",
        ENTRY_POINT: entryPoint,
        BUNDLER_PRIVATE_KEY: privateKey,
        DB_URL: `sqlite:${path.join(dir, "bundler.sqlite")}`,
        BUNDLER_REQUIRE_AUTH: "false",
      },
      () => loadConfig(),
    )

    assert.equal(config.authRequired, false)
  } finally {
    fs.rmSync(dir, { recursive: true, force: true })
  }
})

const toBool = (value?: string) => {
if (value === undefined) return undefined
const normalized = value.trim().toLowerCase()
if (!normalized) return undefined

Choose a reason for hiding this comment

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

medium

This check for an empty normalized string is redundant. If normalized is an empty string, it won't be found in either of the subsequent includes() checks, and the function will correctly return undefined at the end. Removing this line makes the function more concise without changing its behavior.

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.

2 participants