From c82a15f9f349e247afce4ecd8abe270e0111059c Mon Sep 17 00:00:00 2001 From: Minh Cung Date: Sun, 29 Mar 2026 21:17:50 +1100 Subject: [PATCH 1/2] . --- .github/workflows/ci.yml | 35 ++++++++++++++++ .../2026-03-29-mysql-integration-ci-design.md | 41 +++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 docs/adr/2026-03-29-mysql-integration-ci-design.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93700f8..ac0caa9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -76,3 +76,38 @@ jobs: env: RAIN_POSTGRES_DSN: postgres://rain:rain@127.0.0.1:5432/rain_test?sslmode=disable run: go test -race ./pkg/rain -run '^TestPostgresIntegration' + + mysql-integration: + name: MySQL Integration Tests + runs-on: ubuntu-latest + needs: [precommit] + timeout-minutes: 10 + services: + mysql: + image: mysql:8.4 + env: + MYSQL_DATABASE: rain_test + MYSQL_USER: rain + MYSQL_PASSWORD: rain + MYSQL_ROOT_PASSWORD: root + ports: + - 3306:3306 + options: >- + --health-cmd="mysqladmin ping -h 127.0.0.1 -urain -prain" + --health-interval=10s + --health-timeout=5s + --health-retries=10 + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: "1.26" + + - name: Run MySQL integration tests + env: + RAIN_MYSQL_DSN: rain:rain@tcp(127.0.0.1:3306)/rain_test?parseTime=true + run: go test -race ./pkg/rain -run '^TestMySQLIntegration' diff --git a/docs/adr/2026-03-29-mysql-integration-ci-design.md b/docs/adr/2026-03-29-mysql-integration-ci-design.md new file mode 100644 index 0000000..132bd0f --- /dev/null +++ b/docs/adr/2026-03-29-mysql-integration-ci-design.md @@ -0,0 +1,41 @@ +# ADR: MySQL integration coverage in CI + +## Status +Accepted on 2026-03-29. + +## Context +The repository already contains MySQL-backed integration coverage in `pkg/rain/mysql_integration_test.go`, and CI already runs separate SQLite and Postgres integration jobs. + +That leaves one gap in cross-dialect runtime verification: MySQL behavior is exercised locally when contributors provide a DSN, but it is not enforced as a distinct signal in GitHub Actions. + +The workflow already uses separate jobs per backend, so adding MySQL should preserve that structure rather than introducing a larger matrix refactor. + +## Decision +Add a dedicated `mysql-integration` job to the existing GitHub Actions workflow. + +The new job: + +- uses `ubuntu-latest` +- provisions a `mysql:8.4` service container +- creates a fixed `rain_test` database with a `rain` user +- passes `RAIN_MYSQL_DSN` to the test process +- runs `go test -race ./pkg/rain -run '^TestMySQLIntegration'` + +Keep the existing SQLite and Postgres jobs unchanged. + +## Consequences +### Positive +- CI now exposes MySQL runtime compatibility as an independent signal. +- Backend-specific failures remain isolated because each database keeps its own job. +- The workflow change is incremental and consistent with the current CI layout. + +### Negative +- CI runtime increases because another service-backed job must start and execute. +- The workflow now contains some duplicated setup across database jobs. + +## Testing approach +- Keep running the existing local validation flow: + - `make fmt` + - `make lint` + - `make test` +- In GitHub Actions, run `go test -race ./pkg/rain -run '^TestMySQLIntegration'` in the dedicated MySQL job. From 988ae3d052d66d17bf2c0ca65b5d800efbc36ffd Mon Sep 17 00:00:00 2001 From: Minh Cung Date: Sun, 29 Mar 2026 21:59:19 +1100 Subject: [PATCH 2/2] . --- pkg/rain/mysql_integration_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/rain/mysql_integration_test.go b/pkg/rain/mysql_integration_test.go index b225348..dc3025a 100644 --- a/pkg/rain/mysql_integration_test.go +++ b/pkg/rain/mysql_integration_test.go @@ -177,9 +177,9 @@ func defineMySQLTables(suffix string) (*mysqlUsersTable, *mysqlPostsTable) { users := schema.Define("users_"+suffix, func(t *mysqlUsersTable) { t.ID = t.BigSerial("id").PrimaryKey() t.Email = t.VarChar("email", 255).NotNull() - t.Name = t.Text("name").NotNull().Default("guest") + t.Name = t.VarChar("name", 255).NotNull().Default("guest") t.Active = t.Boolean("active").NotNull().Default(true) - t.Nickname = t.Text("nickname").Nullable().Default("buddy") + t.Nickname = t.VarChar("nickname", 255).Nullable().Default("buddy") t.CreatedAt = t.TimestampTZ("created_at").NotNull().DefaultNow() })