Skip to content

fix(Bun.SQL) fix SSLRequest - #22378

Merged
Jarred-Sumner merged 21 commits into
mainfrom
ciro/wip-mysql-tls
Sep 4, 2025
Merged

Jarred-Sumner merged 21 commits into
mainfrom
ciro/wip-mysql-tls

Conversation

@cirospaciari

@cirospaciari cirospaciari commented Sep 3, 2025 •

Copy link
Copy Markdown
Member

What does this PR do?

Fixes #22312
Fixes #22313

The correct flow for TLS handshaking is:

Server sending Protocol::Handshake
Client replying with Protocol::SSLRequest:
The usual SSL exchange leading to establishing SSL connection
Client sends Protocol::HandshakeResponse:

Screenshot 2025-09-03 at 15 02 25

Source: https://dev.mysql.com/doc/dev/mysql-server/8.4.5/page_protocol_connection_phase.html

How did you verify your code works?

Tests

@robobun

robobun commented Sep 3, 2025 •

Copy link
Copy Markdown
Collaborator
Updated 5:14 PM PT - Sep 3rd, 2025

❌ @autofix-ci[bot], your commit adc1540 has 2 failures in Build #24945:


🧪   To try this PR locally:

bunx bun-pr 22378

That installs a local version of the PR into your bun-22378 executable, so you can run:

bun-22378 --bun

@cirospaciari
cirospaciari marked this pull request as ready for review September 3, 2025 21:40
@cirospaciari
cirospaciari marked this pull request as draft September 3, 2025 21:41
@coderabbitai

coderabbitai Bot commented Sep 3, 2025 •

Copy link
Copy Markdown
Contributor

Walkthrough

Implements MySQL TLS negotiation and mid-handshake upgrade (CLIENT_SSL/SSLRequest, upgradeToTLS), integrates TLS sequencing (sequence_id), updates TLS status variants, adjusts password send over TLS, adds TLS test infrastructure and tests, changes event-loop log visibility, and reformats a CMake source list.

Changes

Cohort / File(s) Summary
MySQL TLS negotiation & connection
src/sql/mysql/MySQLConnection.zig, src/sql/mysql/TLSStatus.zig
Adds CLIENT_SSL/SSLRequest flow, upgradeToTLS() public API, TLS handshake handling, sets tls_status to ssl_failed on failures, changes message_sent to payloadless variant, adjusts handshake sequencing and password send over TLS, and adds TLS-related logging.
MySQL protocol types
src/sql/mysql/protocol/SSLRequest.zig, src/sql/mysql/protocol/HandshakeResponse41.zig
New SSLRequest packet implementation; HandshakeResponse41 gains sequence_id field and uses it when writing and logging.
Tests: TLS server and test harness
test/js/sql/mysql-tls/Dockerfile, test/js/sql/mysql-tls/conf.d/ssl.cnf, test/js/sql/mysql-tls/ssl/*, test/js/sql/sql-mysql.test.ts, test/harness.ts, test/js/sql/sql.test.ts
Adds TLS-enabled MySQL Docker image and certs, adds Docker-gated TLS test harness and extensive TLS test cases, exposes isDockerEnabled() in harness and uses it from tests.
Miscellaneous
src/bun.js/event_loop.zig, cmake/sources/ZigSources.txt, src/sql/postgres/PostgresSQLConnection.zig
Changes event-loop log scope from visible to hidden, reformats ZigSources.txt, and consolidates SSL-mode handling in Postgres handshake path.

Assessment against linked issues

Objective Addressed Explanation
Fix TLS connection/auth for MySQL with caching_sha2_password, avoiding “Access denied” when TLS is required (#22312) ✅
Implement CLIENT_SSL negotiation (SSLRequest) and mid-handshake upgrade to TLS (#22312) ✅
Correct handshake sequencing (sequence_id) across TLS upgrade (#22312) ✅
Transmit password over TLS with proper auth flow (#22312) ✅

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Event-loop log scope change (src/bun.js/event_loop.zig) Logging visibility change unrelated to MySQL TLS handshake/auth objectives.
ZigSources.txt reformat (cmake/sources/ZigSources.txt) Build source-list formatting does not affect TLS handshake/auth or tests.
Postgres SSL mode switch consolidation (src/sql/postgres/PostgresSQLConnection.zig) Adjusts Postgres handshake control flow; not part of MySQL TLS objectives.
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ciro/wip-mysql-tls

🪧 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.
    • 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.
  • 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

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

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit 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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

@cirospaciari
cirospaciari marked this pull request as ready for review September 3, 2025 21:48
@cirospaciari
cirospaciari requested review from a team and markovejnovic and removed request for a team September 3, 2025 21:48

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/sql/mysql/MySQLConnection.zig (3)

914-925: Incorrect error message says “postgresql”; should be “mysql”.

This leaks a wrong product name on Unix socket connection failures.

Apply:

-                    return globalObject.throwError(err, "failed to connect to postgresql");
+                    return globalObject.throwError(err, "failed to connect to mysql");

1011-1037: Hostname verification error path uses ssl_error even when it’s zero.

On hostname mismatch, ssl_error may be 0; returning it produces a misleading “no error”. Emit a clear failure.

Apply:

-                    if (BoringSSL.c.SSL_get_servername(ssl_ptr, 0)) |servername| {
+                    if (BoringSSL.c.SSL_get_servername(ssl_ptr, 0)) |servername| {
                         const hostname = servername[0..bun.len(servername)];
                         if (!BoringSSL.checkServerIdentity(ssl_ptr, hostname)) {
-                            this.tls_status = .ssl_failed;
-                            return this.failWithJSValue(ssl_error.toJS(this.globalObject));
+                            this.tls_status = .ssl_failed;
+                            return this.failFmt(error.AuthenticationFailed, "TLS hostname verification failed for {s}", .{hostname});
                         }
                     }

782-829: Default SNI/server_name should derive from hostname when not provided.

Without SNI, verify_full may silently skip hostname checks. Set server_name to the connection hostname if unset.

Apply:

-    if (ssl_mode != .disable) {
+    if (ssl_mode != .disable) {
         tls_config = if (tls_object.isBoolean() and tls_object.toBoolean())
             .{}
         else if (tls_object.isObject())
             (jsc.API.ServerConfig.SSLConfig.fromJS(vm, globalObject, tls_object) catch return .zero) orelse .{}
         else {
             return globalObject.throwInvalidArguments("tls must be a boolean or an object", .{});
         };
@@
-        uws.NewSocketHandler(true).configure(tls_ctx.?, true, *@This(), SocketHandler(true));
+        uws.NewSocketHandler(true).configure(tls_ctx.?, true, *@This(), SocketHandler(true));
     }
@@
-        const hostname = hostname_str.toUTF8(bun.default_allocator);
+        const hostname = hostname_str.toUTF8(bun.default_allocator);
         defer hostname.deinit();
+        if (ssl_mode != .disable and tls_config.server_name.len == 0) {
+            // Use SNI for hostname verification if caller didn't provide one.
+            tls_config.server_name = hostname.slice();
+        }

Also applies to: 903-939

🧹 Nitpick comments (8)
test/js/sql/mysql-tls/ssl/ca.srl (1)

1-1: Prevent repo-dirty test runs: ensure ca.srl isn’t mutated on host

If OpenSSL signs using -CAcreateserial/-CAserial against this path at test time, it will bump the serial and dirty the working tree. Please confirm signing happens only inside the Docker image or a temp dir, or copy this file into an ephemeral location before use.

test/js/sql/mysql-tls/ssl/server-ext.cnf (1)

1-4: SANs look good for mysql/localhost/127.0.0.1; consider adding IPv6 loopback

Optional hardening for environments where “localhost” resolves to ::1.

Apply this diff:

-subjectAltName = DNS:mysql, DNS:localhost, IP:127.0.0.1
+subjectAltName = DNS:mysql, DNS:localhost, IP:127.0.0.1, IP:::1
cmake/sources/ZigSources.txt (1)

1-1: Normalize cmake/sources/ZigSources.txt to LF line endings
Converted all CRLF to LF to resolve the “LF will be replaced by CRLF” CI warning. Optionally enforce LF via .gitattributes:

+.gitattributes
+cmake/sources/ZigSources.txt text eol=lf
test/js/sql/mysql-tls/Dockerfile (1)

22-22: Add missing newline at end of file.

The Dockerfile should end with a newline for consistency and best practices.

 EXPOSE 3306
+
src/sql/mysql/protocol/SSLRequest.zig (1)

35-35: Consider consistent log scope naming.

The debug log uses .MySQLConnection scope, which might be confusing since this is in the SSLRequest module. Consider using a more specific scope like .MySQLSSLRequest or keep it consistent with the connection scope if that's the intended behavior.

-const debug = bun.Output.scoped(.MySQLConnection, .hidden);
+const debug = bun.Output.scoped(.MySQLSSLRequest, .hidden);
test/js/sql/sql-mysql.test.ts (2)

189-209: Remove explicit per-test timeout.

Guidelines: do not set explicit test timeouts; rely on Bun’s built-in timeouts.

Apply:

-        }, 10_000);
+        });

275-286: Avoid global table name collisions; prefer TEMPORARY or randomized names.

Multiple tests create/drop a table named "test". Under parallel execution this races. Use TEMPORARY or a unique name per test.

If TEMPORARY isn’t viable, do:

-          await sql`create table test(id int)`;
-          await sql`drop table test`;
+          const tn = sql("t_" + randomUUIDv7("hex").replaceAll("-", ""));
+          await sql`create table ${tn}(id int)`;
+          await sql`drop table ${tn}`;

Also applies to: 280-286

src/sql/mysql/MySQLConnection.zig (1)

826-828: Nit: reduce noisy TLS logs in non-debug runs.

Consider .visible only when a verbose flag is enabled.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0759da2 and d691583.

⛔ Files ignored due to path filters (4)
  • test/js/sql/mysql-tls/ssl/ca-key.pem is excluded by !**/*.pem
  • test/js/sql/mysql-tls/ssl/ca.pem is excluded by !**/*.pem
  • test/js/sql/mysql-tls/ssl/server-cert.pem is excluded by !**/*.pem
  • test/js/sql/mysql-tls/ssl/server-key.pem is excluded by !**/*.pem
📒 Files selected for processing (12)
  • cmake/sources/ZigSources.txt (1 hunks)
  • src/bun.js/event_loop.zig (1 hunks)
  • src/sql/mysql/MySQLConnection.zig (11 hunks)
  • src/sql/mysql/TLSStatus.zig (1 hunks)
  • src/sql/mysql/protocol/HandshakeResponse41.zig (2 hunks)
  • src/sql/mysql/protocol/SSLRequest.zig (1 hunks)
  • test/js/sql/mysql-tls/Dockerfile (1 hunks)
  • test/js/sql/mysql-tls/conf.d/ssl.cnf (1 hunks)
  • test/js/sql/mysql-tls/ssl/ca.srl (1 hunks)
  • test/js/sql/mysql-tls/ssl/server-ext.cnf (1 hunks)
  • test/js/sql/mysql-tls/ssl/server.csr (1 hunks)
  • test/js/sql/sql-mysql.test.ts (2 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
src/**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/building-bun.mdc)

Implement debug logs in Zig using const log = bun.Output.scoped(.${SCOPE}, false); and invoking log("...", .{})

In Zig code, manage memory carefully: use appropriate allocators and defer for cleanup

Files:

  • src/sql/mysql/TLSStatus.zig
  • src/sql/mysql/protocol/HandshakeResponse41.zig
  • src/bun.js/event_loop.zig
  • src/sql/mysql/protocol/SSLRequest.zig
  • src/sql/mysql/MySQLConnection.zig
**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/javascriptcore-class.mdc)

**/*.zig: Declare the extern C symbol in Zig and export a Zig-friendly alias for use
Wrap the Bun____toJS extern in a Zig method that takes a JSGlobalObject and returns JSC.JSValue

Run zig-format to format Zig files (bun run zig-format)

Files:

  • src/sql/mysql/TLSStatus.zig
  • src/sql/mysql/protocol/HandshakeResponse41.zig
  • src/bun.js/event_loop.zig
  • src/sql/mysql/protocol/SSLRequest.zig
  • src/sql/mysql/MySQLConnection.zig
test/**

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

Place all tests under the test/ directory

Files:

  • test/js/sql/mysql-tls/ssl/server.csr
  • test/js/sql/mysql-tls/Dockerfile
  • test/js/sql/mysql-tls/ssl/server-ext.cnf
  • test/js/sql/mysql-tls/conf.d/ssl.cnf
  • test/js/sql/mysql-tls/ssl/ca.srl
  • test/js/sql/sql-mysql.test.ts
test/js/**

📄 CodeRabbit inference engine (test/CLAUDE.md)

Organize unit tests for specific features under test/js/ by module

Files:

  • test/js/sql/mysql-tls/ssl/server.csr
  • test/js/sql/mysql-tls/Dockerfile
  • test/js/sql/mysql-tls/ssl/server-ext.cnf
  • test/js/sql/mysql-tls/conf.d/ssl.cnf
  • test/js/sql/mysql-tls/ssl/ca.srl
  • test/js/sql/sql-mysql.test.ts
src/bun.js/**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/zig-javascriptcore-classes.mdc)

src/bun.js/**/*.zig: In Zig binding structs, expose generated bindings via pub const js = JSC.Codegen.JS and re-export toJS/fromJS/fromJSDirect
Constructors and prototype methods should return bun.JSError!JSC.JSValue to integrate Zig error handling with JS exceptions
Use parameter name globalObject (not ctx) and accept (*JSC.JSGlobalObject, *JSC.CallFrame) in binding methods/constructors
Implement getters as get(this, globalObject) returning JSC.JSValue and matching the .classes.ts interface
Provide deinit() for resource cleanup and finalize() that calls deinit(); use bun.destroy(this) or appropriate destroy pattern
Access JS call data via CallFrame (argument(i), argumentCount(), thisValue()) and throw errors with globalObject.throw(...)
For properties marked cache: true, use the generated Zig accessors (NameSetCached/GetCached) to work with GC-owned values
In finalize() for objects holding JS references, release them using .deref() before destroy

Files:

  • src/bun.js/event_loop.zig
test/js/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

Place JavaScript and TypeScript tests under test/js/

Files:

  • test/js/sql/sql-mysql.test.ts
test/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

test/**/*.{js,ts}: Write tests in JavaScript or TypeScript using Bun’s Jest-style APIs (test, describe, expect) and run with bun test
Prefer data-driven tests (e.g., test.each) to reduce boilerplate
Use shared utilities from test/harness.ts where applicable

Files:

  • test/js/sql/sql-mysql.test.ts
test/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.test.{ts,tsx}: Tests must be named with the suffix .test.ts or .test.tsx and live under the test/ directory
In tests, always use port: 0 and never hardcode ports or use custom random-port utilities
Prefer snapshot tests using normalizeBunSnapshot(...) over direct string equality on stdout/stderr
Do not write tests that assert absence of 'panic', 'uncaught exception', or similar strings in output
Avoid shelling out to tools like find or grep in tests; use Bun.Glob and built-in utilities

Files:

  • test/js/sql/sql-mysql.test.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

Run Prettier to format JS/TS files (bun run prettier)

Files:

  • test/js/sql/sql-mysql.test.ts
test/**/*.test.ts

📄 CodeRabbit inference engine (test/CLAUDE.md)

test/**/*.test.ts: Name test files *.test.ts and use bun:test
Do not write flaky tests: never wait for arbitrary time; wait for conditions instead
Never hardcode port numbers in tests; use port: 0 to get a random port
When spawning Bun in tests, use bunExe() and bunEnv from harness
Prefer async/await in tests; for a single callback, use Promise.withResolvers()
Do not set explicit test timeouts; rely on Bun’s built-in timeouts
Use tempDir/tempDirWithFiles from harness for temporary files and directories in tests
For large/repetitive strings in tests, prefer Buffer.alloc(count, fill).toString() over "A".repeat(count)
Import common test utilities from harness (e.g., bunExe, bunEnv, tempDirWithFiles, tmpdirSync, platform checks, GC helpers)
In error tests, assert non-zero exit codes for failing processes and use toThrow for synchronous errors
Use describe blocks for grouping, describe.each for parameterized tests, snapshots with toMatchSnapshot, and lifecycle hooks (beforeAll, beforeEach, afterEach); track resources for cleanup in afterEach
Use using/await using with Bun resources (e.g., Bun.listen/connect/spawn/serve) to ensure cleanup in tests

Files:

  • test/js/sql/sql-mysql.test.ts
🧠 Learnings (18)
📚 Learning: 2025-08-30T00:07:54.573Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/building-bun.mdc:0-0
Timestamp: 2025-08-30T00:07:54.573Z
Learning: Applies to src/**/*.zig : Implement debug logs in Zig using `const log = bun.Output.scoped(.${SCOPE}, false);` and invoking `log("...", .{})`

Applied to files:

  • src/bun.js/event_loop.zig
📚 Learning: 2025-09-03T17:10:13.460Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.460Z
Learning: Applies to test/**/*.test.ts : When spawning Bun in tests, use `bunExe()` and `bunEnv` from `harness`

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-08-30T00:12:56.803Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/writing-tests.mdc:0-0
Timestamp: 2025-08-30T00:12:56.803Z
Learning: Applies to test/cli/**/*.{js,ts} : When testing Bun as a CLI, use spawn with bunExe() and bunEnv from harness, and capture stdout/stderr via pipes

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T17:10:13.460Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.460Z
Learning: Applies to test/**/*.test.ts : Import common test utilities from `harness` (e.g., `bunExe`, `bunEnv`, `tempDirWithFiles`, `tmpdirSync`, platform checks, GC helpers)

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-08-30T00:12:56.803Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/writing-tests.mdc:0-0
Timestamp: 2025-08-30T00:12:56.803Z
Learning: Applies to test/**/*.{js,ts} : Write tests in JavaScript or TypeScript using Bun’s Jest-style APIs (test, describe, expect) and run with bun test

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T17:09:28.100Z
Learnt from: CR
PR: oven-sh/bun#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-03T17:09:28.100Z
Learning: Applies to test/js/bun/** : Place Bun-specific API tests (http, crypto, ffi, shell, etc.) under test/js/bun/

Applied to files:

  • test/js/sql/sql-mysql.test.ts
  • cmake/sources/ZigSources.txt
📚 Learning: 2025-08-30T00:09:39.100Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/dev-server-tests.mdc:0-0
Timestamp: 2025-08-30T00:09:39.100Z
Learning: Applies to test/bake/bake-harness.ts : Provide and maintain shared test utilities: devTest, prodTest, devAndProductionTest, Dev, Client, and helpers in the harness

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T17:10:13.460Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.460Z
Learning: Applies to test/**/*.test.ts : Use `tempDir`/`tempDirWithFiles` from `harness` for temporary files and directories in tests

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T17:10:13.460Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.460Z
Learning: Applies to test/**/*.test.ts : Use `using`/`await using` with Bun resources (e.g., Bun.listen/connect/spawn/serve) to ensure cleanup in tests

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-08-30T00:09:39.100Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/dev-server-tests.mdc:0-0
Timestamp: 2025-08-30T00:09:39.100Z
Learning: Applies to test/bake/{dev/*.test.ts,dev-and-prod.ts} : Import testing utilities (devTest, prodTest, devAndProductionTest, Dev, Client) from test/bake/bake-harness.ts

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-08-30T00:13:36.815Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/zig-javascriptcore-classes.mdc:0-0
Timestamp: 2025-08-30T00:13:36.815Z
Learning: Applies to src/bun.js/**/*.zig : In Zig binding structs, expose generated bindings via pub const js = JSC.Codegen.JS<ClassName> and re-export toJS/fromJS/fromJSDirect

Applied to files:

  • cmake/sources/ZigSources.txt
📚 Learning: 2025-08-30T00:13:36.815Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/zig-javascriptcore-classes.mdc:0-0
Timestamp: 2025-08-30T00:13:36.815Z
Learning: Applies to src/bun.js/**/*.zig : Constructors and prototype methods should return bun.JSError!JSC.JSValue to integrate Zig error handling with JS exceptions

Applied to files:

  • cmake/sources/ZigSources.txt
📚 Learning: 2025-08-30T00:13:36.815Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/zig-javascriptcore-classes.mdc:0-0
Timestamp: 2025-08-30T00:13:36.815Z
Learning: Applies to src/bun.js/**/*.zig : For properties marked cache: true, use the generated Zig accessors (<Prop>NameSetCached/GetCached) to work with GC-owned values

Applied to files:

  • cmake/sources/ZigSources.txt
📚 Learning: 2025-08-30T00:11:57.076Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/registering-bun-modules.mdc:0-0
Timestamp: 2025-08-30T00:11:57.076Z
Learning: Applies to src/{**/js_*.zig,bun.js/api/**/*.zig} : Use bun.JSError!JSValue for proper error propagation in JS-exposed Zig functions

Applied to files:

  • cmake/sources/ZigSources.txt
📚 Learning: 2025-08-30T00:13:36.815Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/zig-javascriptcore-classes.mdc:0-0
Timestamp: 2025-08-30T00:13:36.815Z
Learning: Applies to src/bun.js/bindings/generated_classes_list.zig : Update src/bun.js/bindings/generated_classes_list.zig to include new classes

Applied to files:

  • cmake/sources/ZigSources.txt
📚 Learning: 2025-09-03T17:09:28.101Z
Learnt from: CR
PR: oven-sh/bun#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-03T17:09:28.101Z
Learning: Applies to src/bun.js/bindings/**/*.cpp : Cache class structures in ZigGlobalObject for bindings

Applied to files:

  • cmake/sources/ZigSources.txt
📚 Learning: 2025-08-30T00:11:57.076Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/registering-bun-modules.mdc:0-0
Timestamp: 2025-08-30T00:11:57.076Z
Learning: Applies to src/**/js_*.zig : Implement JavaScript bindings in a Zig file named with a js_ prefix (e.g., js_smtp.zig, js_your_feature.zig)

Applied to files:

  • cmake/sources/ZigSources.txt
📚 Learning: 2025-08-30T00:13:36.815Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/zig-javascriptcore-classes.mdc:0-0
Timestamp: 2025-08-30T00:13:36.815Z
Learning: Applies to src/bun.js/**/*.zig : Provide deinit() for resource cleanup and finalize() that calls deinit(); use bun.destroy(this) or appropriate destroy pattern

Applied to files:

  • cmake/sources/ZigSources.txt
🧬 Code graph analysis (1)
test/js/sql/sql-mysql.test.ts (1)
test/harness.ts (2)
  • dockerExe (855-857)
  • describeWithContainer (887-967)
🪛 GitHub Actions: autofix.ci
cmake/sources/ZigSources.txt

[warning] 1-1: LF will be replaced by CRLF the next time Git touches it.

🔇 Additional comments (19)
cmake/sources/ZigSources.txt (1)

919-938: New MySQL TLS sources are listed

SSLRequest.zig and TLSStatus.zig entries are present here, so builds should pick them up.

test/js/sql/mysql-tls/ssl/server.csr (1)

1-26: CSR fixture is fine to commit

Contains only public data; aligns with SANs provided via ext file. No action needed.

src/bun.js/event_loop.zig (1)

100-103: Quieter default logging for EventLoop

Switching the scope to hidden reduces noise (even in debug). Looks intentional given the volume of EventLoop logs.

src/sql/mysql/TLSStatus.zig (2)

7-7: LGTM! Simplified status variant aligns with state management.

The removal of the payload from message_sent makes sense as the status itself indicates completion without needing to track partial progress.


10-10: LGTM! New ssl_failed variant improves error handling.

Adding ssl_failed provides better granularity for TLS negotiation outcomes, allowing the connection to differentiate between SSL unavailability and SSL failure scenarios.

test/js/sql/mysql-tls/conf.d/ssl.cnf (1)

1-7: LGTM! Comprehensive TLS configuration for test environment.

The MySQL configuration properly enforces TLS with appropriate certificate paths and TLS versions. The skip_name_resolve=ON setting is a good practice for test environments to avoid DNS resolution issues.

src/sql/mysql/protocol/HandshakeResponse41.zig (3)

11-11: LGTM! Adding sequence_id field for proper MySQL protocol sequencing.

The sequence_id field is necessary for MySQL protocol compliance, especially during TLS handshake sequences where packet ordering matters.


28-28: LGTM! Using dynamic sequence_id instead of hardcoded value.

Replacing the hardcoded 1 with this.sequence_id allows proper packet sequencing during the MySQL handshake, which is critical for TLS upgrade scenarios.


35-35: LGTM! Enhanced debug logging includes sequence_id.

Adding sequence_id to the debug output will help with debugging TLS handshake sequences and packet ordering issues.

test/js/sql/mysql-tls/Dockerfile (1)

16-19: LGTM! Proper security-focused permission setup.

The permission settings are correct for MySQL TLS:

  • chmod 600 on the private key restricts access to owner only (required by MySQL)
  • chmod 640 on PEM files allows MySQL to read certificates
  • Setting ownership to mysql:mysql ensures the MySQL daemon can access the files
src/sql/mysql/protocol/SSLRequest.zig (2)

9-9: LGTM! Empty deinit is appropriate for this struct.

Since SSLRequest doesn't allocate any dynamic memory or resources, an empty deinit function is correct.


11-31: LGTM! SSLRequest implementation follows MySQL protocol correctly.

The implementation properly follows the MySQL SSL request packet format:

  • Correct packet structure with capabilities, max packet size, character set, and padding
  • Proper conditional setting of CLIENT_CONNECT_ATTRS based on has_connection_attributes
  • Appropriate debug logging for troubleshooting
  • Fixed sequence ID of 1 is correct for SSL request packets

The 23 bytes of padding aligns with the MySQL protocol specification.

test/js/sql/sql-mysql.test.ts (2)

57-68: LGTM: CRUD + affectedRows/lastInsertRowid and long-results flow.

Good coverage and use of reserve() with idleTimeout; exercises pipeline and backpressure paths.

Also applies to: 189-201


868-892: LGTM: data-driven timeout key mapping.

Nice use of test.each and local inert server; this validates alias keys consistently.

src/sql/mysql/MySQLConnection.zig (5)

258-265: LGTM: upgrade to TLS right after SSLRequest flush if no backpressure.

This sequencing avoids interleaving plaintext after the SSLRequest and aligns with the protocol.


982-996: LGTM: socket upgrade preserves connection state.

Clean swap from TCP to TLS; onOpen guard below prevents status thrash.


1487-1541: LGTM: HandshakeResponse41 sequencing and capability handling.

Including sequence_id and deferring attrs mirrors mysql2 behavior; write/flush order looks correct.


1381-1387: LGTM: send plaintext password over TLS for caching_sha2_password continue_auth.

Correct per protocol; .writeZ ensures NUL-terminated payload.


323-343: LGTM: flushData backpressure handling.

Accurate wrote/consume semantics and monitor hook; no busy loop risk.

Comment thread src/sql/mysql/MySQLConnection.zig
Comment thread test/js/sql/sql-mysql.test.ts Outdated
Comment thread test/js/sql/sql-mysql.test.ts
Comment thread test/js/sql/sql-mysql.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/sql/mysql/MySQLConnection.zig (1)

915-929: Wrong service name in error message (user-facing)

On Unix socket failure, message says “postgresql”. Should be “mysql”.

Apply:

-                    return globalObject.throwError(err, "failed to connect to postgresql");
+                    return globalObject.throwError(err, "failed to connect to mysql");
🧹 Nitpick comments (4)
src/sql/mysql/MySQLConnection.zig (4)

826-826: Add context to TLS init log (nit)

Include server_name/mode to ease triage.

Apply:

- debug("configured TLS context", .{});
+ debug("configured TLS context (server_name: {s}, mode: {s})", .{ this.tls_config.server_name, @tagName(this.ssl_mode) });

982-997: upgradeToTLS: assert TLS context presence (nit)
Add a debug assert to catch unexpected null tls_ctx.

Apply:

 pub fn upgradeToTLS(this: *MySQLConnection) void {
+    bun.assert(this.tls_ctx != null);
     if (this.socket == .SocketTCP) {

1012-1049: TLS handshake success path — add hostname fallback for verify_full (optional)

If SSL_get_servername is null (no SNI), .verify_full currently skips hostname verification. Consider falling back to this.tls_config.server_name to enforce host checks.

Apply:

-                    if (BoringSSL.c.SSL_get_servername(ssl_ptr, 0)) |servername| {
-                        const hostname = servername[0..bun.len(servername)];
-                        if (!BoringSSL.checkServerIdentity(ssl_ptr, hostname)) {
+                    if (BoringSSL.c.SSL_get_servername(ssl_ptr, 0)) |servername| {
+                        const hostname = servername[0..bun.len(servername)];
+                        if (!BoringSSL.checkServerIdentity(ssl_ptr, hostname)) {
+                            this.tls_status = .ssl_failed;
+                            return this.failWithJSValue(ssl_error.toJS(this.globalObject));
+                        }
+                    } else if (this.tls_config.server_name.len > 0) {
+                        const hostname = this.tls_config.server_name;
+                        if (!BoringSSL.checkServerIdentity(ssl_ptr, hostname)) {
                             this.tls_status = .ssl_failed;
                             return this.failWithJSValue(ssl_error.toJS(this.globalObject));
                         }
                     }

Note: Keep .require same as .prefer per project intent. I used the shared learning from this PR thread when reviewing this choice.


1491-1491: Include sequence id in debug (nit)

Apply:

-    debug("sendHandshakeResponse", .{});
+    debug("sendHandshakeResponse (seq={d})", .{ this.sequence_id });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between d691583 and 89bb9ef.

📒 Files selected for processing (2)
  • src/sql/mysql/MySQLConnection.zig (11 hunks)
  • src/sql/postgres/PostgresSQLConnection.zig (1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/building-bun.mdc)

Implement debug logs in Zig using const log = bun.Output.scoped(.${SCOPE}, false); and invoking log("...", .{})

In Zig code, manage memory carefully: use appropriate allocators and defer for cleanup

Files:

  • src/sql/postgres/PostgresSQLConnection.zig
  • src/sql/mysql/MySQLConnection.zig
**/*.zig

📄 CodeRabbit inference engine (.cursor/rules/javascriptcore-class.mdc)

**/*.zig: Declare the extern C symbol in Zig and export a Zig-friendly alias for use
Wrap the Bun____toJS extern in a Zig method that takes a JSGlobalObject and returns JSC.JSValue

Run zig-format to format Zig files (bun run zig-format)

Files:

  • src/sql/postgres/PostgresSQLConnection.zig
  • src/sql/mysql/MySQLConnection.zig
🧠 Learnings (1)
📚 Learning: 2025-09-03T22:12:26.851Z
Learnt from: cirospaciari
PR: oven-sh/bun#22378
File: src/sql/mysql/MySQLConnection.zig:0-0
Timestamp: 2025-09-03T22:12:26.851Z
Learning: In Bun's MySQL SSL implementation, the .require SSL mode is designed to behave the same as .prefer for postgres.js compatibility, allowing graceful fallback to non-SSL connections when the server doesn't support SSL. Only .verify_ca and .verify_full modes will fail when SSL is not available.

Applied to files:

  • src/sql/postgres/PostgresSQLConnection.zig
  • src/sql/mysql/MySQLConnection.zig
🔇 Additional comments (7)
src/sql/postgres/PostgresSQLConnection.zig (1)

446-448: Treating .require like .prefer — acknowledged and aligned with intent

Matches the stated compatibility goal (postgres.js). No further action.

src/sql/mysql/MySQLConnection.zig (6)

256-265: TLS upgrade gating in drain path looks correct

Upgrading only when tls_status == .message_sent and no backpressure prevents interleaving pre-TLS traffic. Good sequencing.


999-1007: Avoids resetting state on post-upgrade onOpen — good

Setting .handshaking only for TCP prevents clobbering state when uWS re-enters on TLS. LGTM.


1220-1249: SSLRequest → TLS upgrade sequencing looks correct

  • Send SSLRequest
  • mark tls_status = .message_sent
  • flush; upgrade if no backpressure
  • gracefully handle servers without CLIENT_SSL, only failing in .verify_ca/.verify_full (intended “require==prefer” behavior).

LGTM.


1524-1524: Sequencing after TLS — good

Using this.sequence_id aligns with SSLRequest(seq=1) → HandshakeResponse(seq=2) ordering.


2004-2004: New import wired

Importing SSLRequest here matches the new handshake flow. LGTM.


1386-1391: writeZ exists on NewWriter—ignore suggested fallback
this.writer() returns a NewWriter which defines pub fn writeZ(...), so the build will succeed and no manual null-terminator fallback is needed.

Likely an incorrect or invalid review comment.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
test/js/sql/sql.test.ts (4)

22-32: Avoid custom random-port helper; let Docker pick a free port

Tests must not use custom random-port utilities. Map a random host port with -p 0:5432 and then read it via docker port.

-async function findRandomPort() {
-  return new Promise<number>((resolve, reject) => {
-    const server = net.createServer();
-    server.listen(0, () => {
-      const port = (server.address() as import("node:net").AddressInfo).port;
-      server.close(() => resolve(port));
-    });
-    server.on("error", reject);
-  });
-}
+// no-op: rely on Docker's -p 0:5432 and inspect mapped port

And in startContainer():

-    const port = await findRandomPort();
-    const containerName = `postgres-test-${port}`;
+    const containerName = `postgres-test-${Date.now()}`;
...
-    await execAsync(`${dockerCLI} run -d --name ${containerName} -p ${port}:5432 custom-postgres`);
+    await execAsync(`${dockerCLI} run -d --name ${containerName} -p 0:5432 custom-postgres`);
+    const { stdout: portMap } = await execAsync(`${dockerCLI} port ${containerName} 5432/tcp`);
+    const port = Number(portMap.trim().split(":").pop());

85-88: Don’t call process.exit(1) in tests

Exiting the process masks failures and kills the runner. Throw the error so the test fails normally.

-  } catch (error) {
-    console.error("Error:", error);
-    process.exit(1);
-  }
+  } catch (error) {
+    console.error("PostgreSQL container startup failed:", error);
+    throw error;
+  }

151-154: Use explicit host and container port in proxy, not login object

login.host is undefined and login is declared later. Use localhost and container.port directly.

-    const containerSocket = net.createConnection({
-      host: login.host,
-      port: login.port,
-    });
+    const containerSocket = net.createConnection({
+      host: "127.0.0.1",
+      port: container.port,
+    });

718-718: Typo causes runtime failure: savepoit → savepoint

This test will throw because savepoit doesn’t exist.

-            await sql.savepoit("watpoint", async sql => {
+            await sql.savepoint("watpoint", async sql => {
♻️ Duplicate comments (3)
test/js/sql/sql-mysql.test.ts (3)

13-38: Fix: move/guard Docker build; remove top-level await/expect to avoid crashing test discovery

Top-level async work and assertions (expect(await dockerProcess.exited).toBe(0)) can break test discovery and make the entire file fail to load. Build the TLS image synchronously and gate TLS tests without asserting at module scope. Keep non‑TLS MySQL tests runnable even if TLS build fails.

Apply:

-const docker = isDockerEnabled() ? dockerExe() : null;
-if (docker) {
-  const dockerfilePath = path.join(import.meta.dir, "mysql-tls", ".");
-  console.log("Building Docker image...");
-  const dockerProcess = Bun.spawn([docker, "build", "-t", "mysql-tls", dockerfilePath], {
-    cwd: path.join(import.meta.dir, "mysql-tls"),
-  });
-  expect(await dockerProcess.exited).toBe(0);
-  console.log("Docker image built");
-  const images = [
-    {
-      name: "MySQL with TLS",
-      image: "mysql-tls",
-      env: {
-        MYSQL_ROOT_PASSWORD: "bun",
-      },
-    },
-    {
-      name: "MySQL",
-      image: "mysql:8",
-      env: {
-        MYSQL_ROOT_PASSWORD: "bun",
-      },
-    },
-  ];
+const docker = dockerExe();
+const images: {
+  name: string;
+  image: string;
+  env: Record<string, string>;
+}[] = [
+  {
+    name: "MySQL",
+    image: "mysql:8",
+    env: { MYSQL_ROOT_PASSWORD: "bun" },
+  },
+];
+if (isDockerEnabled() && docker) {
+  const dockerfilePath = path.join(import.meta.dir, "mysql-tls");
+  const { exitCode } = Bun.spawnSync({
+    cmd: [docker, "build", "-t", "mysql-tls", dockerfilePath],
+    cwd: dockerfilePath,
+    stdout: "inherit",
+    stderr: "inherit",
+  });
+  if (exitCode === 0) {
+    images.push({
+      name: "MySQL with TLS",
+      image: "mysql-tls",
+      env: { MYSQL_ROOT_PASSWORD: "bun" },
+    });
+  } else {
+    console.warn(`Skipping TLS tests: docker build failed (exit: ${exitCode})`);
+  }
 }

91-112: Replace external dependency in timeout test with a local inert server

Relying on example.com is flaky and slow; use a local TCP server that never speaks MySQL to trigger connection timeout deterministically.

Apply:

-        await using sql = new SQL({
-          ...options,
-          hostname: "example.com",
-          connection_timeout: 4,
-          onconnect,
-          onclose,
-          max: 1,
-        });
+        const server = net.createServer().listen();
+        const port2 = (server.address() as import("node:net").AddressInfo).port;
+        await using sql = new SQL({
+          adapter: "mysql",
+          host: "127.0.0.1",
+          port: port2,
+          connection_timeout: 4,
+          onconnect,
+          onclose,
+          max: 1,
+        });
         let error: any;
         try {
           await sql`select SLEEP(8)`;
         } catch (e) {
           error = e;
         }
         expect(error.code).toBe(`ERR_MYSQL_CONNECTION_TIMEOUT`);
-        expect(error.message).toContain("Connection timeout after 4s");
+        expect(error.message).toMatch(/after 4s/);
         expect(onconnect).not.toHaveBeenCalled();
         expect(onclose).toHaveBeenCalledTimes(1);
+        server.close();

893-896: Fix test to assert instead of returning a tuple

Returning a tuple performs no assertion and can pass spuriously.

Apply:

-        test("Array returns rows as arrays of columns", async () => {
-          await using sql = new SQL(options);
-          return [(await sql`select CAST(1 AS SIGNED) as x`.values())[0][0], 1];
-        });
+        test("Array returns rows as arrays of columns", async () => {
+          await using sql = new SQL(options);
+          expect((await sql`select CAST(1 AS SIGNED) as x`.values())[0][0]).toBe(1);
+        });
🧹 Nitpick comments (5)
test/harness.ts (1)

16-16: Use execFileSync and consolidate child_process imports

Avoid shell parsing/quoting issues and keep built-in imports consistent with node: specifier.

-import { execSync } from "child_process";
+import { execFileSync } from "node:child_process";

Also consider merging the existing import on Line 11 into the same node:child_process import for consistency.

test/js/sql/sql.test.ts (3)

3-3: Use harness.dockerExe() and drop ad-hoc Docker detection

Since you already import harness helpers, prefer dockerExe() over Bun.which(). It centralizes platform quirks (e.g., docker.exe on Windows).

-import { bunEnv, bunExe, isCI, isDockerEnabled, tempDirWithFiles } from "harness";
+import { bunEnv, bunExe, isCI, isDockerEnabled, dockerExe, tempDirWithFiles } from "harness";

And later:

-const dockerCLI = Bun.which("docker") as string;
+const dockerCLI = dockerExe();

133-137: Avoid mixed ESM/CommonJS and duplicate imports

You already import path and net at top. Import fs and os once at top and remove these requires to prevent shadowing.

-  const net = require("node:net");
-  const fs = require("node:fs");
-  const path = require("node:path");
-  const os = require("node:os");
+  // reuse top-level imports; add once at top of file:
+  // import fs from "node:fs";
+  // import os from "node:os";

7-7: Optional: keep child_process usage minimal

exec is fine here, but consider using $ from Bun for consistency, or keep execAsync only where needed (Docker CLI).

test/js/sql/sql-mysql.test.ts (1)

189-210: Remove explicit per-test timeout; follow test guidelines

Avoid setting numeric timeouts; rely on Bun’s built-in timeouts and wait for conditions instead.

Apply:

-        }, 10_000);
+        });
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 89bb9ef and 47c6002.

📒 Files selected for processing (4)
  • cmake/sources/ZigSources.txt (1 hunks)
  • test/harness.ts (2 hunks)
  • test/js/sql/sql-mysql.test.ts (2 hunks)
  • test/js/sql/sql.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmake/sources/ZigSources.txt
🧰 Additional context used
📓 Path-based instructions (7)
test/**

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

Place all tests under the test/ directory

Files:

  • test/js/sql/sql.test.ts
  • test/harness.ts
  • test/js/sql/sql-mysql.test.ts
test/js/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

Place JavaScript and TypeScript tests under test/js/

Files:

  • test/js/sql/sql.test.ts
  • test/js/sql/sql-mysql.test.ts
test/**/*.{js,ts}

📄 CodeRabbit inference engine (.cursor/rules/writing-tests.mdc)

test/**/*.{js,ts}: Write tests in JavaScript or TypeScript using Bun’s Jest-style APIs (test, describe, expect) and run with bun test
Prefer data-driven tests (e.g., test.each) to reduce boilerplate
Use shared utilities from test/harness.ts where applicable

Files:

  • test/js/sql/sql.test.ts
  • test/harness.ts
  • test/js/sql/sql-mysql.test.ts
test/**/*.test.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

test/**/*.test.{ts,tsx}: Tests must be named with the suffix .test.ts or .test.tsx and live under the test/ directory
In tests, always use port: 0 and never hardcode ports or use custom random-port utilities
Prefer snapshot tests using normalizeBunSnapshot(...) over direct string equality on stdout/stderr
Do not write tests that assert absence of 'panic', 'uncaught exception', or similar strings in output
Avoid shelling out to tools like find or grep in tests; use Bun.Glob and built-in utilities

Files:

  • test/js/sql/sql.test.ts
  • test/js/sql/sql-mysql.test.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (CLAUDE.md)

Run Prettier to format JS/TS files (bun run prettier)

Files:

  • test/js/sql/sql.test.ts
  • test/harness.ts
  • test/js/sql/sql-mysql.test.ts
test/**/*.test.ts

📄 CodeRabbit inference engine (test/CLAUDE.md)

test/**/*.test.ts: Name test files *.test.ts and use bun:test
Do not write flaky tests: never wait for arbitrary time; wait for conditions instead
Never hardcode port numbers in tests; use port: 0 to get a random port
When spawning Bun in tests, use bunExe() and bunEnv from harness
Prefer async/await in tests; for a single callback, use Promise.withResolvers()
Do not set explicit test timeouts; rely on Bun’s built-in timeouts
Use tempDir/tempDirWithFiles from harness for temporary files and directories in tests
For large/repetitive strings in tests, prefer Buffer.alloc(count, fill).toString() over "A".repeat(count)
Import common test utilities from harness (e.g., bunExe, bunEnv, tempDirWithFiles, tmpdirSync, platform checks, GC helpers)
In error tests, assert non-zero exit codes for failing processes and use toThrow for synchronous errors
Use describe blocks for grouping, describe.each for parameterized tests, snapshots with toMatchSnapshot, and lifecycle hooks (beforeAll, beforeEach, afterEach); track resources for cleanup in afterEach
Use using/await using with Bun resources (e.g., Bun.listen/connect/spawn/serve) to ensure cleanup in tests

Files:

  • test/js/sql/sql.test.ts
  • test/js/sql/sql-mysql.test.ts
test/js/**

📄 CodeRabbit inference engine (test/CLAUDE.md)

Organize unit tests for specific features under test/js/ by module

Files:

  • test/js/sql/sql.test.ts
  • test/js/sql/sql-mysql.test.ts
🧠 Learnings (17)
📚 Learning: 2025-08-30T00:12:56.803Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/writing-tests.mdc:0-0
Timestamp: 2025-08-30T00:12:56.803Z
Learning: Applies to test/**/*.{js,ts} : Use shared utilities from test/harness.ts where applicable

Applied to files:

  • test/js/sql/sql.test.ts
  • test/harness.ts
  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T17:10:13.460Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.460Z
Learning: Applies to test/**/*.test.ts : Import common test utilities from `harness` (e.g., `bunExe`, `bunEnv`, `tempDirWithFiles`, `tmpdirSync`, platform checks, GC helpers)

Applied to files:

  • test/js/sql/sql.test.ts
  • test/harness.ts
  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T17:10:13.460Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.460Z
Learning: Applies to test/**/*.test.ts : When spawning Bun in tests, use `bunExe()` and `bunEnv` from `harness`

Applied to files:

  • test/js/sql/sql.test.ts
  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-08-30T00:12:56.803Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/writing-tests.mdc:0-0
Timestamp: 2025-08-30T00:12:56.803Z
Learning: Applies to test/cli/**/*.{js,ts} : When testing Bun as a CLI, use spawn with bunExe() and bunEnv from harness, and capture stdout/stderr via pipes

Applied to files:

  • test/js/sql/sql.test.ts
  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T17:09:28.100Z
Learnt from: CR
PR: oven-sh/bun#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-03T17:09:28.100Z
Learning: Applies to test/js/bun/** : Place Bun-specific API tests (http, crypto, ffi, shell, etc.) under test/js/bun/

Applied to files:

  • test/js/sql/sql.test.ts
  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-08-30T00:12:56.803Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/writing-tests.mdc:0-0
Timestamp: 2025-08-30T00:12:56.803Z
Learning: Applies to test/**/*.{js,ts} : Write tests in JavaScript or TypeScript using Bun’s Jest-style APIs (test, describe, expect) and run with bun test

Applied to files:

  • test/js/sql/sql.test.ts
  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-08-30T00:09:39.100Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/dev-server-tests.mdc:0-0
Timestamp: 2025-08-30T00:09:39.100Z
Learning: Applies to test/bake/bake-harness.ts : Provide and maintain shared test utilities: devTest, prodTest, devAndProductionTest, Dev, Client, and helpers in the harness

Applied to files:

  • test/js/sql/sql.test.ts
  • test/harness.ts
  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T17:10:13.460Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.460Z
Learning: Applies to test/**/*.test.ts : Use `using`/`await using` with Bun resources (e.g., Bun.listen/connect/spawn/serve) to ensure cleanup in tests

Applied to files:

  • test/js/sql/sql.test.ts
  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-08-30T00:09:39.100Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/dev-server-tests.mdc:0-0
Timestamp: 2025-08-30T00:09:39.100Z
Learning: Applies to test/bake/{dev/*.test.ts,dev-and-prod.ts} : Import testing utilities (devTest, prodTest, devAndProductionTest, Dev, Client) from test/bake/bake-harness.ts

Applied to files:

  • test/js/sql/sql.test.ts
  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-08-30T00:12:56.803Z
Learnt from: CR
PR: oven-sh/bun#0
File: .cursor/rules/writing-tests.mdc:0-0
Timestamp: 2025-08-30T00:12:56.803Z
Learning: Applies to test/js/bun/**/*.{js,ts} : Place Bun API tests under test/js/bun/, separated by category (e.g., test/js/bun/glob/)

Applied to files:

  • test/js/sql/sql.test.ts
📚 Learning: 2025-09-03T17:09:28.100Z
Learnt from: CR
PR: oven-sh/bun#0
File: CLAUDE.md:0-0
Timestamp: 2025-09-03T17:09:28.100Z
Learning: Applies to test/**/*.test.{ts,tsx} : Avoid shelling out to tools like find or grep in tests; use Bun.Glob and built-in utilities

Applied to files:

  • test/js/sql/sql.test.ts
📚 Learning: 2025-09-03T17:10:13.460Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.460Z
Learning: Applies to test/**/*.test.ts : Do not write flaky tests: never wait for arbitrary time; wait for conditions instead

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T17:10:13.460Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.460Z
Learning: Applies to test/**/*.test.ts : Never hardcode port numbers in tests; use `port: 0` to get a random port

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T01:30:57.965Z
Learnt from: markovejnovic
PR: oven-sh/bun#21728
File: test/js/valkey/valkey.test.ts:264-271
Timestamp: 2025-09-03T01:30:57.965Z
Learning: For test/js/valkey/valkey.test.ts PUB/SUB tests, avoid arbitrary sleeps and async-forEach. Instead, resolve a Promise from the subscriber callback when the expected number of messages is observed and await it with a bounded timeout (e.g., withTimeout + Promise.withResolvers) to account for Redis server→subscriber propagation.

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T17:10:13.460Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.460Z
Learning: Applies to test/**/*.test.ts : Prefer `async/await` in tests; for a single callback, use `Promise.withResolvers()`

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T17:10:13.460Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.460Z
Learning: Applies to test/**/*.test.ts : In error tests, assert non-zero exit codes for failing processes and use `toThrow` for synchronous errors

Applied to files:

  • test/js/sql/sql-mysql.test.ts
📚 Learning: 2025-09-03T17:10:13.460Z
Learnt from: CR
PR: oven-sh/bun#0
File: test/CLAUDE.md:0-0
Timestamp: 2025-09-03T17:10:13.460Z
Learning: Applies to test/**/*.test.ts : Use `tempDir`/`tempDirWithFiles` from `harness` for temporary files and directories in tests

Applied to files:

  • test/js/sql/sql-mysql.test.ts
🧬 Code graph analysis (2)
test/harness.ts (1)
scripts/utils.mjs (4)
  • isLinux (24-24)
  • isLinux (24-24)
  • isMacOS (23-23)
  • isMacOS (23-23)
test/js/sql/sql-mysql.test.ts (1)
test/harness.ts (3)
  • isDockerEnabled (860-877)
  • dockerExe (856-858)
  • describeWithContainer (906-986)
⏰ 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: Format

Comment thread test/harness.ts
Comment thread test/js/sql/sql-mysql.test.ts
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.

Bun SQL with AWS RDS MySQL not connecting MySql Access Denied - failed to connect via TLS Caching SHA2 password

3 participants