Skip to content

Commit

Permalink
build: Run MySQL and PostgreSQL locally on the runner (#3095)
Browse files Browse the repository at this point in the history
- Use two new actions to setup / run PostgreSQL and MySQL without Docker. Container-based services only work on Linux runners
- Add new sqltest/local package
- Refactor TestValidSchema to use the local package
- Mark some tests as having invalid schemas. We've never verified the MySQL schemas before this PR
- Mark a few tests as failing on Windows
  • Loading branch information
kyleconroy committed Jan 3, 2024
1 parent 1f24e10 commit 874bfc2
Show file tree
Hide file tree
Showing 68 changed files with 457 additions and 176 deletions.
14 changes: 13 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ on:
jobs:
test:
strategy:
max-parallel: 2
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
cgo: ['1', '0']
Expand Down Expand Up @@ -49,12 +48,25 @@ jobs:
env:
CGO_ENABLED: ${{ matrix.cgo }}

# Start a PostgreSQL server
- uses: sqlc-dev/action-setup-postgres@master
with:
postgres-version: "16"
id: postgres

# Start a MySQL server
- uses: shogo82148/actions-setup-mysql@v1
with:
mysql-version: "8.1"

- name: test ./...
run: gotestsum --junitfile junit.xml -- --tags=examples -timeout 20m ./...
env:
CI_SQLC_PROJECT_ID: ${{ secrets.CI_SQLC_PROJECT_ID }}
CI_SQLC_AUTH_TOKEN: ${{ secrets.CI_SQLC_AUTH_TOKEN }}
SQLC_AUTH_TOKEN: ${{ secrets.CI_SQLC_AUTH_TOKEN }}
MYSQL_SERVER_URI: root:@tcp(localhost:3306)/mysql?multiStatements=true&parseTime=true
POSTGRESQL_SERVER_URI: ${{ steps.postgres.outputs.connection-uri }}?sslmode=disable
CGO_ENABLED: ${{ matrix.cgo }}

vuln_check:
Expand Down
4 changes: 2 additions & 2 deletions examples/authors/postgresql/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import (
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"

"github.com/sqlc-dev/sqlc/internal/sqltest/hosted"
"github.com/sqlc-dev/sqlc/internal/sqltest/local"
)

func TestAuthors(t *testing.T) {
ctx := context.Background()
uri := hosted.PostgreSQL(t, []string{"schema.sql"})
uri := local.PostgreSQL(t, []string{"schema.sql"})
db, err := pgx.Connect(ctx, uri)
if err != nil {
t.Fatal(err)
Expand Down
5 changes: 3 additions & 2 deletions examples/batch/postgresql/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ import (

"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
"github.com/sqlc-dev/sqlc/internal/sqltest/hosted"

"github.com/sqlc-dev/sqlc/internal/sqltest/local"
)

func TestBatchBooks(t *testing.T) {
uri := hosted.PostgreSQL(t, []string{"schema.sql"})
uri := local.PostgreSQL(t, []string{"schema.sql"})

ctx := context.Background()

Expand Down
4 changes: 2 additions & 2 deletions examples/booktest/postgresql/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import (
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"

"github.com/sqlc-dev/sqlc/internal/sqltest/hosted"
"github.com/sqlc-dev/sqlc/internal/sqltest/local"
)

func TestBooks(t *testing.T) {
ctx := context.Background()
uri := hosted.PostgreSQL(t, []string{"schema.sql"})
uri := local.PostgreSQL(t, []string{"schema.sql"})
db, err := pgx.Connect(ctx, uri)
if err != nil {
t.Fatal(err)
Expand Down
10 changes: 5 additions & 5 deletions examples/ondeck/mysql/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
_ "github.com/go-sql-driver/mysql"
"github.com/google/go-cmp/cmp"

"github.com/sqlc-dev/sqlc/internal/sqltest/hosted"
"github.com/sqlc-dev/sqlc/internal/sqltest/local"
)

func join(vals ...string) sql.NullString {
Expand Down Expand Up @@ -144,10 +144,10 @@ func runOnDeckQueries(t *testing.T, q *Queries) {
func TestPrepared(t *testing.T) {
t.Parallel()

uri := hosted.MySQL(t, []string{"schema"})
uri := local.MySQL(t, []string{"schema"})
db, err := sql.Open("mysql", uri)
if err != nil {
t.Fatal(err)
t.Fatalf("%s: %s", uri, err)
}
defer db.Close()

Expand All @@ -162,10 +162,10 @@ func TestPrepared(t *testing.T) {
func TestQueries(t *testing.T) {
t.Parallel()

uri := hosted.MySQL(t, []string{"schema"})
uri := local.MySQL(t, []string{"schema"})
db, err := sql.Open("mysql", uri)
if err != nil {
t.Fatal(err)
t.Fatalf("%s: %s", uri, err)
}
defer db.Close()

Expand Down
2 changes: 1 addition & 1 deletion examples/ondeck/mysql/schema/0001_city.sql
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CREATE TABLE city (
slug varchar(255) PRIMARY KEY,
name text NOT NULL
)
);
10 changes: 5 additions & 5 deletions examples/ondeck/postgresql/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/google/go-cmp/cmp"
_ "github.com/lib/pq"

"github.com/sqlc-dev/sqlc/internal/sqltest/hosted"
"github.com/sqlc-dev/sqlc/internal/sqltest/local"
)

func runOnDeckQueries(t *testing.T, q *Queries) {
Expand Down Expand Up @@ -126,10 +126,10 @@ func runOnDeckQueries(t *testing.T, q *Queries) {
func TestPrepared(t *testing.T) {
t.Parallel()

uri := hosted.PostgreSQL(t, []string{"schema"})
uri := local.PostgreSQL(t, []string{"schema"})
db, err := sql.Open("postgres", uri)
if err != nil {
t.Fatal(err)
t.Fatalf("%s: %s", uri, err)
}
defer db.Close()

Expand All @@ -144,10 +144,10 @@ func TestPrepared(t *testing.T) {
func TestQueries(t *testing.T) {
t.Parallel()

uri := hosted.PostgreSQL(t, []string{"schema"})
uri := local.PostgreSQL(t, []string{"schema"})
db, err := sql.Open("postgres", uri)
if err != nil {
t.Fatal(err)
t.Fatalf("%s: %s", uri, err)
}
defer db.Close()

Expand Down
8 changes: 7 additions & 1 deletion internal/codegen/golang/result.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package golang

import (
"bufio"
"fmt"
"sort"
"strings"
Expand Down Expand Up @@ -205,9 +206,14 @@ func buildQueries(req *plugin.GenerateRequest, options *opts.Options, structs []
comments = append(comments, query.Name)
}
comments = append(comments, " ")
for _, line := range strings.Split(query.Text, "\n") {
scanner := bufio.NewScanner(strings.NewReader(query.Text))
for scanner.Scan() {
line := scanner.Text()
comments = append(comments, " "+line)
}
if err := scanner.Err(); err != nil {
return nil, err
}
}

gq := Query{
Expand Down
9 changes: 7 additions & 2 deletions internal/endtoend/case_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@ type Testcase struct {
Exec *Exec
}

type ExecMeta struct {
InvalidSchema bool `json:"invalid_schema"`
}

type Exec struct {
Command string `json:"command"`
Contexts []string `json:"contexts"`
Process string `json:"process"`
OS []string `json:"os"`
Env map[string]string `json:"env"`
Meta ExecMeta `json:"meta"`
}

func parseStderr(t *testing.T, dir, testctx string) []byte {
Expand Down Expand Up @@ -52,10 +57,10 @@ func parseExec(t *testing.T, dir string) *Exec {
var e Exec
blob, err := os.ReadFile(path)
if err != nil {
t.Fatal(err)
t.Fatalf("%s: %s", path, err)
}
if err := json.Unmarshal(blob, &e); err != nil {
t.Fatal(err)
t.Fatalf("%s: %s", path, err)
}
if e.Command == "" {
e.Command = "generate"
Expand Down
90 changes: 14 additions & 76 deletions internal/endtoend/ddl_test.go
Original file line number Diff line number Diff line change
@@ -1,51 +1,21 @@
package main

import (
"context"
"fmt"
"os"
"path/filepath"
"runtime"
"slices"
"strings"
"testing"

"github.com/jackc/pgx/v5"

"github.com/sqlc-dev/sqlc/internal/config"
"github.com/sqlc-dev/sqlc/internal/migrations"
"github.com/sqlc-dev/sqlc/internal/quickdb"
pb "github.com/sqlc-dev/sqlc/internal/quickdb/v1"
"github.com/sqlc-dev/sqlc/internal/sql/sqlpath"
"github.com/sqlc-dev/sqlc/internal/sqltest/local"
)

func TestValidSchema(t *testing.T) {
if os.Getenv("CI") != "" && runtime.GOOS != "linux" {
t.Skipf("only run these tests in CI on linux: %s %s", os.Getenv("CI"), runtime.GOOS)
}

ctx := context.Background()

projectID := os.Getenv("CI_SQLC_PROJECT_ID")
authToken := os.Getenv("CI_SQLC_AUTH_TOKEN")
if projectID == "" || authToken == "" {
t.Skip("missing project id or auth token")
}

client, err := quickdb.NewClient(projectID, authToken)
if err != nil {
t.Fatal(err)
}

for _, replay := range FindTests(t, "testdata", "managed-db") {
for _, replay := range FindTests(t, "testdata", "base") {
replay := replay // https://golang.org/doc/faq#closures_and_goroutines

if len(replay.Stderr) > 0 {
continue
}

if replay.Exec != nil {
if !slices.Contains(replay.Exec.Contexts, "managed-db") {
if replay.Exec.Meta.InvalidSchema {
continue
}
}
Expand All @@ -63,60 +33,28 @@ func TestValidSchema(t *testing.T) {

for j, pkg := range conf.SQL {
j, pkg := j, pkg
if pkg.Engine != config.EnginePostgreSQL {
switch pkg.Engine {
case config.EnginePostgreSQL:
// pass
case config.EngineMySQL:
// pass
default:
continue
}
t.Run(fmt.Sprintf("endtoend-%s-%d", file, j), func(t *testing.T) {
t.Parallel()

if strings.Contains(file, "pg_dump") {
t.Skip("loading pg_dump not supported")
}

var schema []string
for _, path := range pkg.Schema {
schema = append(schema, filepath.Join(filepath.Dir(file), path))
}

files, err := sqlpath.Glob(schema)
if err != nil {
t.Fatal(err)
}

var sqls []string
for _, f := range files {
contents, err := os.ReadFile(f)
if err != nil {
t.Fatalf("%s: %s", f, err)
}
// Support loading pg_dump SQL files
before := strings.ReplaceAll(string(contents), "CREATE SCHEMA public;", "CREATE SCHEMA IF NOT EXISTS public;")
sqls = append(sqls, migrations.RemoveRollbackStatements(before))
}

resp, err := client.CreateEphemeralDatabase(ctx, &pb.CreateEphemeralDatabaseRequest{
Engine: "postgresql",
Region: quickdb.GetClosestRegion(),
Migrations: sqls,
})
if err != nil {
t.Fatalf("region %s: %s", quickdb.GetClosestRegion(), err)
}

t.Cleanup(func() {
_, err = client.DropEphemeralDatabase(ctx, &pb.DropEphemeralDatabaseRequest{
DatabaseId: resp.DatabaseId,
})
if err != nil {
t.Fatal(err)
}
})

conn, err := pgx.Connect(ctx, resp.Uri)
if err != nil {
t.Fatalf("connect %s: %s", resp.Uri, err)
switch pkg.Engine {
case config.EnginePostgreSQL:
local.PostgreSQL(t, schema)
case config.EngineMySQL:
local.MySQL(t, schema)
}
defer conn.Close(ctx)
})
}
}
Expand Down

0 comments on commit 874bfc2

Please sign in to comment.