Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,38 @@ jobs:
with:
files: ./coverage.txt
token: ${{ secrets.CODECOV_TOKEN }}

test-mariadb:
name: MySQL suite on MariaDB
runs-on: ubuntu-latest
timeout-minutes: 10

services:
mariadb:
image: mariadb:11.4
env:
MARIADB_ROOT_PASSWORD: root
options: >-
--health-cmd "healthcheck.sh --connect --innodb_initialized"
--health-interval 5s
--health-timeout 5s
--health-retries 12
ports:
- 3306:3306

steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1

- name: Set up Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e
with:
go-version: '1.27'
cache: true

# The mysql package and the adapters' MySQL tests, against MariaDB on
# the default MySQL address. The Postgres-backed tests are the other
# job's business.
- name: Run the MySQL-backed tests against MariaDB
run: |
go test -race -count=1 ./mysql/...
go test -race -count=1 -run 'TestMySQL' ./migrate/goose/... ./migrate/golangmigrate/...
20 changes: 20 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ POSTGRES_DB := testdb
MYSQL_SERVICE := test-mysql
MYSQL_USER := root
MYSQL_PASSWORD := root
MARIADB_SERVICE := test-mariadb

.PHONY: check_pgcli
check_pgcli:
Expand Down Expand Up @@ -103,13 +104,31 @@ define wait_for_mysql
echo "✅ MySQL is ready!"
endef

# The MariaDB image ships the mariadb client, not mysql.
define wait_for_mariadb
@echo "Waiting for MariaDB to be ready..."
@attempts=0; \
while ! docker compose -f $(1) exec -T $(2) mariadb -u$(3) -p$(4) -e 'SELECT 1' >/dev/null 2>&1; do \
attempts=$$((attempts+1)); \
if [ $$attempts -gt 60 ]; then \
echo "❌ MariaDB failed to become ready after 60 seconds"; \
echo "Try 'make $(5)' for a fresh start"; \
exit 1; \
fi; \
echo "⏳ Waiting... ($$attempts/60)"; \
sleep 1; \
done; \
echo "✅ MariaDB is ready (port 3307; set TEST_MYSQL_URL to use it)"
endef

## test/db/start: Start PostgreSQL test database
.PHONY: test/db/start
test/db/start:
@echo 'Starting test database...'
docker compose -f $(POSTGRES_COMPOSE_FILE) up -d
$(call wait_for_postgres,$(POSTGRES_COMPOSE_FILE),$(POSTGRES_SERVICE),$(POSTGRES_USER),$(POSTGRES_DB),test/db/restart)
$(call wait_for_mysql,$(POSTGRES_COMPOSE_FILE),$(MYSQL_SERVICE),$(MYSQL_USER),$(MYSQL_PASSWORD),test/db/restart)
$(call wait_for_mariadb,$(POSTGRES_COMPOSE_FILE),$(MARIADB_SERVICE),$(MYSQL_USER),$(MYSQL_PASSWORD),test/db/restart)

## test/db/stop: Stop PostgreSQL test database
.PHONY: test/db/stop
Expand Down Expand Up @@ -141,6 +160,7 @@ test/db/restart: test/db/clean
docker compose -f $(POSTGRES_COMPOSE_FILE) up -d
$(call wait_for_postgres,$(POSTGRES_COMPOSE_FILE),$(POSTGRES_SERVICE),$(POSTGRES_USER),$(POSTGRES_DB),test/db/restart)
$(call wait_for_mysql,$(POSTGRES_COMPOSE_FILE),$(MYSQL_SERVICE),$(MYSQL_USER),$(MYSQL_PASSWORD),test/db/restart)
$(call wait_for_mariadb,$(POSTGRES_COMPOSE_FILE),$(MARIADB_SERVICE),$(MYSQL_USER),$(MYSQL_PASSWORD),test/db/restart)

## test/db/psql: Connect to Postgres database
.PHONY: test/db/psql
Expand Down
19 changes: 19 additions & 0 deletions docker-compose.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,22 @@ services:
- "--skip-log-bin"
- "--innodb-doublewrite=0"
- "--innodb-flush-method=O_DIRECT_NO_FSYNC"

# MariaDB on 3307: point TEST_MYSQL_URL at it to run the MySQL suite
# against MariaDB, as CI does.
test-mariadb:
image: mariadb:11.4
environment:
MARIADB_ROOT_PASSWORD: root
ports:
- "3307:3306"
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 5s
timeout: 3s
retries: 12
command:
- "--innodb-flush-log-at-trx-commit=0"
- "--skip-log-bin"
- "--innodb-doublewrite=0"
- "--innodb-flush-method=O_DIRECT_NO_FSYNC"
7 changes: 6 additions & 1 deletion mysql/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,9 +553,14 @@ func lockName(template string) string {
return "testdb:template:" + hex.EncodeToString(sum[:12])
}

// buildLockTimeout bounds GET_LOCK when ctx has no deadline. MySQL treats a
// negative timeout as "forever" but MariaDB returns NULL for it, so a long
// finite wait is used on both; ctx still cancels the statement earlier.
const buildLockTimeout = 24 * time.Hour

// lockBuild takes the template's build lock, waiting as long as ctx allows.
func lockBuild(ctx context.Context, conn *sql.Conn, template string) error {
timeout := -1 // forever, as far as MySQL is concerned; ctx still applies
timeout := int(buildLockTimeout.Seconds())
if deadline, ok := ctx.Deadline(); ok {
timeout = max(int(time.Until(deadline).Seconds()), 1)
}
Expand Down
Loading