diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 6807694..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: build -permissions: {} # no need any permissions -on: - push: - branches: [main] - pull_request: - branches: [main] - schedule: - - cron: '0 10 * * 1' # run "At 10:00 on Monday" - workflow_call: -jobs: - run: - name: Build - runs-on: ubuntu-latest - timeout-minutes: 5 - strategy: - fail-fast: true - matrix: - go: ['1.20', '1.21'] - steps: - - name: Check out code - uses: actions/checkout@v4 - - name: Install Go - uses: actions/setup-go@v4 - with: - go-version: ${{ matrix.go }} - check-latest: true - - run: go version - - name: Go Format - run: gofmt -s -w . && git diff --exit-code - - name: Go Tidy - run: go mod tidy && git diff --exit-code - - name: Go Vet - run: go vet ./... - - name: Go Download - run: go mod download - - name: Go Mod Verify - run: go mod verify - - uses: sqlc-dev/setup-sqlc@v3 - with: - sqlc-version: '1.20.0' - - name: Install deps - run: | - go install goa.design/goa/v3/cmd/goa@v3 - go install github.com/rjeczalik/interfaces/cmd/interfacer@latest - go install go.uber.org/mock/mockgen@latest - go install github.com/onsi/ginkgo/v2/ginkgo@latest - - name: Generate - run: | - make generate - go mod tidy # Running go mod tidy because goa's dependency will generate undesired changes - git diff --exit-code - - name: Go Build - run: make build - - name: Go Test - run: make test - - name: Upload Coverage - uses: codecov/codecov-action@v3 - continue-on-error: true - with: - token: ${{secrets.CODECOV_TOKEN}} - file: ./cover.profile - fail_ci_if_error: false - - name: Test Summary - uses: test-summary/action@v2 - with: - paths: | - report.xml - if: always() diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..931a45d --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,151 @@ +name: ci +permissions: { } # no need any permissions +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + schedule: + - cron: '0 10 * * 1' # run "At 10:00 on Monday" + workflow_call: +jobs: + test: + name: Test + runs-on: ubuntu-latest + timeout-minutes: 5 + strategy: + fail-fast: true + matrix: + go: [ '1.20', '1.21' ] + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Install Go + uses: actions/setup-go@v4 + with: + go-version: ${{ matrix.go }} + check-latest: true + - run: go version + - name: Go Format + run: gofmt -s -w . && git diff --exit-code + - name: Go Tidy + run: go mod tidy && git diff --exit-code + - name: Go Vet + run: go vet ./... + - name: Go Download + run: go mod download + - name: Go Mod Verify + run: go mod verify + - uses: sqlc-dev/setup-sqlc@v3 + with: + sqlc-version: '1.20.0' + - name: Install deps + run: | + go install goa.design/goa/v3/cmd/goa@v3 + go install github.com/rjeczalik/interfaces/cmd/interfacer@latest + go install go.uber.org/mock/mockgen@latest + go install github.com/onsi/ginkgo/v2/ginkgo@latest + - name: Generate + run: | + make generate + go mod tidy # Running go mod tidy because goa's dependency will generate undesired changes + git diff --exit-code + - name: Go Build + run: make build + - name: Go Test + run: make test + - name: Upload Coverage + uses: codecov/codecov-action@v3 + continue-on-error: true + with: + token: ${{secrets.CODECOV_TOKEN}} + file: ./cover.profile + fail_ci_if_error: false + - name: Test Summary + uses: test-summary/action@v2 + with: + paths: | + report.xml + if: always() + lint: + name: Lint + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Install Go + uses: actions/setup-go@v4 + with: + go-version: 'stable' + check-latest: true + - name: Checkout code + uses: actions/checkout@v4 + - name: Lint + uses: golangci/golangci-lint-action@v3.7.0 + with: + version: latest + args: --timeout 5m + db: + name: Sqlc + runs-on: ubuntu-latest + services: + postgres: + image: "postgres:14" + env: + POSTGRES_USER: rotabot + POSTGRES_PASSWORD: '' + POSTGRES_DB: rotabot + POSTGRES_HOST_AUTH_METHOD: trust + ports: + - 5432:5432 + # needed because the postgres container does not provide a healthcheck + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + timeout-minutes: 5 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: setup-sqlc + uses: sqlc-dev/setup-sqlc@v3 + with: + sqlc-version: '1.20.0' + - name: Run db migrations + run: | + make migrations/up DB_DSN=rotabot:postgres@localhost:5432/rotabot?sslmode=disable + - run: sqlc diff + - run: sqlc vet + migrations: + name: Migrations + runs-on: ubuntu-latest + services: + postgres: + image: "postgres:14" + env: + POSTGRES_USER: rotabot + POSTGRES_PASSWORD: '' + POSTGRES_DB: rotabot + POSTGRES_HOST_AUTH_METHOD: trust + ports: + - 5432:5432 + # needed because the postgres container does not provide a healthcheck + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + timeout-minutes: 5 + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: DB Schema Diff + run: make migrations/test && git diff --exit-code + vuln: + name: Vuln + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Install Go + uses: actions/setup-go@v4 + with: + go-version: 'stable' + check-latest: true + - name: Checkout + uses: actions/checkout@v4 + - name: Install govulncheck + run: go install golang.org/x/vuln/cmd/govulncheck@latest + - name: Run govulncheck + run: govulncheck -test ./... diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 274a712..0000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: lint -permissions: {} # no need any permissions -on: - push: - branches: [main] - pull_request: - branches: [main] - workflow_call: -jobs: - run: - name: Lint - runs-on: ubuntu-latest - timeout-minutes: 5 - steps: - - name: Install Go - uses: actions/setup-go@v4 - with: - go-version: 'stable' - check-latest: true - - name: Checkout code - uses: actions/checkout@v4 - - name: Lint - uses: golangci/golangci-lint-action@v3.7.0 - with: - version: latest - args: --timeout 5m diff --git a/.github/workflows/sqlc.yml b/.github/workflows/sqlc.yml deleted file mode 100644 index 05dc945..0000000 --- a/.github/workflows/sqlc.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: sqlc -permissions: {} # no need any permissions -on: - push: - branches: [main] - pull_request: - branches: [main] - workflow_call: -jobs: - run: - name: Sqlc - runs-on: ubuntu-latest - services: - postgres: - image: "postgres:15" - env: - POSTGRES_DB: postgres - POSTGRES_PASSWORD: postgres - POSTGRES_USER: postgres - ports: - - 5432:5432 - # needed because the postgres container does not provide a healthcheck - options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 - timeout-minutes: 5 - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: setup-sqlc - uses: sqlc-dev/setup-sqlc@v3 - with: - sqlc-version: '1.20.0' - - name: Run db migrations - run: | - make migrations/up DB_DSN=postgres:postgres@localhost:5432/postgres?sslmode=disable - - run: sqlc diff - - run: sqlc vet diff --git a/.github/workflows/vuln.yml b/.github/workflows/vuln.yml deleted file mode 100644 index 4a84699..0000000 --- a/.github/workflows/vuln.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: vuln -permissions: {} # no need any permissions -on: - push: - branches: [main] - pull_request: - branches: [main] - schedule: - - cron: '0 10 * * 1' # run "At 10:00 on Monday" - workflow_call: -jobs: - run: - name: Vuln - runs-on: ubuntu-latest - timeout-minutes: 5 - steps: - - name: Install Go - uses: actions/setup-go@v4 - with: - go-version: 'stable' - check-latest: true - - name: Checkout - uses: actions/checkout@v4 - - name: Install govulncheck - run: go install golang.org/x/vuln/cmd/govulncheck@latest - - name: Run govulncheck - run: govulncheck -test ./... diff --git a/Makefile b/Makefile index 891ff41..d2d29cd 100644 --- a/Makefile +++ b/Makefile @@ -101,3 +101,8 @@ migrations/force: .PHONY: migrations/version migrations/version: go run -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest -path=./assets/migrations -database="postgres://${DB_DSN}" version + +migrations/test: + go run -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest -path=./assets/migrations -database="postgres://rotabot@localhost:5432/rotabot?sslmode=disable" up + # We are using the `tail` command here to remove the header comment from pg_dump which includes the version and OS that ran the command which it will be different depending if is CI or local. + pg_dump --dbname=rotabot --username=rotabot --no-password --port=5432 --host=localhost | tail -n +7 > assets/structure.sql diff --git a/assets/efs.go b/assets/efs.go index 3915191..998c992 100644 --- a/assets/efs.go +++ b/assets/efs.go @@ -5,4 +5,4 @@ import ( ) //go:embed "migrations" -var EmbeddedFiles embed.FS +var Migrations embed.FS diff --git a/assets/structure.sql b/assets/structure.sql new file mode 100644 index 0000000..250a54f --- /dev/null +++ b/assets/structure.sql @@ -0,0 +1,158 @@ + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- Name: pgcrypto; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA public; + + +-- +-- Name: EXTENSION pgcrypto; Type: COMMENT; Schema: -; Owner: +-- + +COMMENT ON EXTENSION pgcrypto IS 'cryptographic functions'; + + +-- +-- Name: generate_uid(integer); Type: FUNCTION; Schema: public; Owner: rotabot +-- + +CREATE FUNCTION public.generate_uid(size integer) RETURNS text + LANGUAGE plpgsql + AS $$ +DECLARE +characters TEXT := 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + bytes +BYTEA := gen_random_bytes(size); + l +INT := length(characters); + i +INT := 0; +output TEXT := ''; +BEGIN + WHILE +i < size + LOOP + output := output || substr(characters, get_byte(bytes, i) % l + 1, 1); + i +:= i + 1; +END LOOP; + RETURN +output; +END; +$$; + + +ALTER FUNCTION public.generate_uid(size integer) OWNER TO rotabot; + +-- +-- Name: trigger_set_timestamp(); Type: FUNCTION; Schema: public; Owner: rotabot +-- + +CREATE FUNCTION public.trigger_set_timestamp() RETURNS trigger + LANGUAGE plpgsql + AS $$ +BEGIN + NEW.UPDATED_AT = NOW(); +RETURN NEW; +END; +$$; + + +ALTER FUNCTION public.trigger_set_timestamp() OWNER TO rotabot; + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- Name: rotas; Type: TABLE; Schema: public; Owner: rotabot +-- + +CREATE TABLE public.rotas ( + id text DEFAULT ('RT'::text || public.generate_uid(14)) NOT NULL, + team_id text NOT NULL, + channel_id text NOT NULL, + name text NOT NULL, + metadata jsonb NOT NULL, + created_at timestamp without time zone DEFAULT now() NOT NULL, + updated_at timestamp without time zone DEFAULT now() NOT NULL +); + + +ALTER TABLE public.rotas OWNER TO rotabot; + +-- +-- Name: schema_migrations; Type: TABLE; Schema: public; Owner: rotabot +-- + +CREATE TABLE public.schema_migrations ( + version bigint NOT NULL, + dirty boolean NOT NULL +); + + +ALTER TABLE public.schema_migrations OWNER TO rotabot; + +-- +-- Data for Name: rotas; Type: TABLE DATA; Schema: public; Owner: rotabot +-- + +COPY public.rotas (id, team_id, channel_id, name, metadata, created_at, updated_at) FROM stdin; +\. + + +-- +-- Data for Name: schema_migrations; Type: TABLE DATA; Schema: public; Owner: rotabot +-- + +COPY public.schema_migrations (version, dirty) FROM stdin; +3 f +\. + + +-- +-- Name: rotas rotas_pkey; Type: CONSTRAINT; Schema: public; Owner: rotabot +-- + +ALTER TABLE ONLY public.rotas + ADD CONSTRAINT rotas_pkey PRIMARY KEY (id); + + +-- +-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: rotabot +-- + +ALTER TABLE ONLY public.schema_migrations + ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version); + + +-- +-- Name: idx_unique_rota_within_team_and_channel; Type: INDEX; Schema: public; Owner: rotabot +-- + +CREATE UNIQUE INDEX idx_unique_rota_within_team_and_channel ON public.rotas USING btree (name, channel_id, team_id); + + +-- +-- Name: rotas rotas_updated_at_trigger; Type: TRIGGER; Schema: public; Owner: rotabot +-- + +CREATE TRIGGER rotas_updated_at_trigger BEFORE UPDATE ON public.rotas FOR EACH ROW EXECUTE FUNCTION public.trigger_set_timestamp(); + + +-- +-- PostgreSQL database dump complete +-- + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..8a4ae62 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,12 @@ +version: '3.4' + +services: + database: + image: 'postgres:14' + ports: + - 5432:5432 + environment: + POSTGRES_USER: rotabot + POSTGRES_PASSWORD: '' + POSTGRES_DB: rotabot + POSTGRES_HOST_AUTH_METHOD: trust \ No newline at end of file diff --git a/go.mod b/go.mod index 5bed05c..8ec0b97 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.20 require ( github.com/KimMachineGun/automemlimit v0.3.0 github.com/ajg/form v1.5.1 + github.com/docker/go-connections v0.4.0 github.com/getsentry/sentry-go v0.24.0 github.com/golang-migrate/migrate/v4 v4.16.2 github.com/google/uuid v1.3.1 @@ -43,7 +44,6 @@ require ( github.com/dimfeld/httptreemux/v5 v5.5.0 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/docker v24.0.6+incompatible // indirect - github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect diff --git a/internal/postgres.go b/internal/postgres.go new file mode 100644 index 0000000..e5c324e --- /dev/null +++ b/internal/postgres.go @@ -0,0 +1,86 @@ +package internal + +import ( + "context" + "fmt" + "net" + "strings" + "time" + + "github.com/docker/go-connections/nat" + "github.com/testcontainers/testcontainers-go" + "github.com/testcontainers/testcontainers-go/wait" +) + +const ( + defaultUser = "rotabot" + defaultPassword = "password" + defaultPostgresImage = "docker.io/postgres:14-alpine" +) + +type PostgresContainer struct { + testcontainers.Container + dbName string + user string + password string +} + +// ConnectionString returns the connection string for the postgres container, using the default 5432 port, and +// obtaining the host and exposed port from the container. It also accepts a variadic list of extra arguments +// which will be appended to the connection string. The format of the extra arguments is the same as the +// connection string format, e.g. "connect_timeout=10" or "application_name=myapp" +func (c *PostgresContainer) ConnectionString(ctx context.Context, args ...string) (string, error) { + containerPort, err := c.Container.MappedPort(ctx, "5432/tcp") + if err != nil { + return "", err + } + + host, err := c.Container.Host(ctx) + if err != nil { + return "", err + } + + extraArgs := strings.Join(args, "&") + connStr := fmt.Sprintf("postgres://%s:%s@%s/%s?%s", c.user, c.password, net.JoinHostPort(host, containerPort.Port()), c.dbName, extraArgs) + return connStr, nil +} + +func (c *PostgresContainer) Terminate(ctx context.Context) error { + return c.Container.Terminate(ctx) +} + +func RunContainer(ctx context.Context, opts ...testcontainers.ContainerCustomizer) (*PostgresContainer, error) { + req := testcontainers.ContainerRequest{ + Image: defaultPostgresImage, + Env: map[string]string{ + "POSTGRES_USER": defaultUser, + "POSTGRES_PASSWORD": defaultPassword, + "POSTGRES_DB": defaultUser, + }, + ExposedPorts: []string{"5432/tcp"}, + Cmd: []string{"postgres", "-c", "fsync=off"}, + WaitingFor: wait.ForSQL("5432/tcp", "postgres", func(host string, port nat.Port) string { + return fmt.Sprintf("postgres://%s:%s@%s/%s?%s", "rotabot", "password", net.JoinHostPort(host, port.Port()), "rotabot", "sslmode=disable") + }).WithStartupTimeout(time.Second * 5), + } + + genericContainerReq := testcontainers.GenericContainerRequest{ + ContainerRequest: req, + Started: true, + } + + for _, opt := range opts { + opt.Customize(&genericContainerReq) + } + + container, err := testcontainers.GenericContainer(ctx, genericContainerReq) + if err != nil { + return nil, err + } + + user := req.Env["POSTGRES_USER"] + password := req.Env["POSTGRES_PASSWORD"] + dbName := req.Env["POSTGRES_DB"] + + return &PostgresContainer{Container: container, dbName: dbName, password: password, user: user}, nil +} diff --git a/lib/db/migration.go b/lib/db/migration.go index ac95aab..f068ec2 100644 --- a/lib/db/migration.go +++ b/lib/db/migration.go @@ -15,7 +15,7 @@ import ( func Migrate(ctx context.Context, dsn string) error { logger := zapctx.Logger(ctx) - iofsDriver, err := iofs.New(assets.EmbeddedFiles, "migrations") + iofsDriver, err := iofs.New(assets.Migrations, "migrations") if err != nil { logger.Error("pulling_db_migrations", zap.Error(err)) return err diff --git a/lib/db/migration_test.go b/lib/db/migration_test.go index 9d4e24a..2a2ca76 100644 --- a/lib/db/migration_test.go +++ b/lib/db/migration_test.go @@ -2,31 +2,24 @@ package db import ( "context" - "time" - - "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/modules/postgres" - "github.com/testcontainers/testcontainers-go/wait" "github.com/jackc/pgx/v5" . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" + "github.com/rotabot-io/rotabot/internal" ) var _ = Describe("Migration", func() { var ctx context.Context var connString string var conn *pgx.Conn - var container *postgres.PostgresContainer + var container *internal.PostgresContainer BeforeEach(func() { var err error ctx = context.Background() - container, err = postgres.RunContainer(ctx, - testcontainers.WithWaitStrategy(wait.ForLog("database system is ready to accept connections").WithOccurrence(2).WithStartupTimeout(5*time.Second)), - ) + container, err = internal.RunContainer(ctx) Expect(err).ToNot(HaveOccurred()) connString, err = container.ConnectionString(ctx, "sslmode=disable") diff --git a/lib/db/repository_test.go b/lib/db/repository_test.go index 6d7fffd..e4f1bab 100644 --- a/lib/db/repository_test.go +++ b/lib/db/repository_test.go @@ -2,40 +2,33 @@ package db import ( "context" - "time" + "path/filepath" "github.com/jackc/pgx/v5" - - "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/modules/postgres" - "github.com/testcontainers/testcontainers-go/wait" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" + "github.com/rotabot-io/rotabot/internal" + "github.com/testcontainers/testcontainers-go/modules/postgres" ) var _ = Describe("Repository", func() { var ctx context.Context var connString string var conn *pgx.Conn - var container *postgres.PostgresContainer + var container *internal.PostgresContainer BeforeEach(func() { var err error ctx = context.Background() - container, err = postgres.RunContainer(ctx, - testcontainers.WithWaitStrategy(wait.ForLog("database system is ready to accept connections").WithOccurrence(2).WithStartupTimeout(5*time.Second)), + container, err = internal.RunContainer(ctx, + postgres.WithInitScripts(filepath.Join("..", "..", "assets", "structure.sql")), ) Expect(err).ToNot(HaveOccurred()) connString, err = container.ConnectionString(ctx, "sslmode=disable") Expect(err).ToNot(HaveOccurred()) - err = Migrate(ctx, connString) - Expect(err).ToNot(HaveOccurred()) - conn, err = pgx.Connect(ctx, connString) Expect(err).ToNot(HaveOccurred()) diff --git a/lib/db/rotas_test.go b/lib/db/rotas_test.go index 7801c22..a92eea0 100644 --- a/lib/db/rotas_test.go +++ b/lib/db/rotas_test.go @@ -3,16 +3,14 @@ package db import ( "context" "errors" - "time" - - "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/modules/postgres" - "github.com/testcontainers/testcontainers-go/wait" + "path/filepath" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgconn" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + "github.com/rotabot-io/rotabot/internal" + "github.com/testcontainers/testcontainers-go/modules/postgres" ) var _ = Describe("Rotas", func() { @@ -22,17 +20,14 @@ var _ = Describe("Rotas", func() { BeforeEach(func() { ctx = context.Background() - container, err := postgres.RunContainer(ctx, - testcontainers.WithWaitStrategy(wait.ForLog("database system is ready to accept connections").WithOccurrence(2).WithStartupTimeout(5*time.Second)), + container, err := internal.RunContainer(ctx, + postgres.WithInitScripts(filepath.Join("..", "..", "assets", "structure.sql")), ) Expect(err).ToNot(HaveOccurred()) dbUrl, err := container.ConnectionString(ctx, "sslmode=disable") Expect(err).ToNot(HaveOccurred()) - err = Migrate(ctx, dbUrl) - Expect(err).ToNot(HaveOccurred()) - conn, err := pgx.Connect(ctx, dbUrl) Expect(err).ToNot(HaveOccurred()) q = New(conn) diff --git a/slack/service_test.go b/slack/service_test.go index 882c65e..342d769 100644 --- a/slack/service_test.go +++ b/slack/service_test.go @@ -2,17 +2,15 @@ package slack import ( "context" - "time" + "path/filepath" + "github.com/rotabot-io/rotabot/internal" "github.com/rotabot-io/rotabot/slack/slackclient" "github.com/jackc/pgx/v5/pgxpool" - "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/modules/postgres" - "github.com/testcontainers/testcontainers-go/wait" - "github.com/slack-go/slack" + "github.com/testcontainers/testcontainers-go/modules/postgres" "github.com/rotabot-io/rotabot/lib/db" @@ -27,30 +25,24 @@ import ( var _ = Describe("Service", func() { var ( - ctx context.Context - sc *mock_slackclient.MockSlackClient - svc gen.Service - connString string - conn *pgxpool.Pool - container *postgres.PostgresContainer + ctx context.Context + sc *mock_slackclient.MockSlackClient + svc gen.Service + conn *pgxpool.Pool ) channelId := "C041Q6Z5FSP" teamId := "T042E16BURW" BeforeEach(func() { - var err error ctx = context.Background() - container, err = postgres.RunContainer(ctx, - testcontainers.WithWaitStrategy(wait.ForLog("database system is ready to accept connections").WithOccurrence(2).WithStartupTimeout(5*time.Second)), + container, err := internal.RunContainer(ctx, + postgres.WithInitScripts(filepath.Join("..", "assets", "structure.sql")), ) Expect(err).ToNot(HaveOccurred()) - connString, err = container.ConnectionString(ctx, "sslmode=disable") - Expect(err).ToNot(HaveOccurred()) - - err = db.Migrate(ctx, connString) + connString, err := container.ConnectionString(ctx, "sslmode=disable") Expect(err).ToNot(HaveOccurred()) conn, err = pgxpool.New(ctx, connString) diff --git a/slack/views/home_test.go b/slack/views/home_test.go index 31317e4..a0e78ef 100644 --- a/slack/views/home_test.go +++ b/slack/views/home_test.go @@ -2,46 +2,38 @@ package views import ( "context" - "time" - - "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/modules/postgres" - "github.com/testcontainers/testcontainers-go/wait" + "path/filepath" "github.com/jackc/pgx/v5" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" gen "github.com/rotabot-io/rotabot/gen/slack" + "github.com/rotabot-io/rotabot/internal" "github.com/rotabot-io/rotabot/lib/db" "github.com/rotabot-io/rotabot/slack/slackclient" "github.com/rotabot-io/rotabot/slack/slackclient/mock_slackclient" "github.com/slack-go/slack" + "github.com/testcontainers/testcontainers-go/modules/postgres" ) var _ = Describe("Home", func() { var ( - ctx context.Context - sc *mock_slackclient.MockSlackClient - home *Home - connString string - tx pgx.Tx - conn *pgx.Conn - container *postgres.PostgresContainer + ctx context.Context + sc *mock_slackclient.MockSlackClient + home *Home + tx pgx.Tx + conn *pgx.Conn ) BeforeEach(func() { - var err error ctx = context.Background() - container, err = postgres.RunContainer(ctx, - testcontainers.WithWaitStrategy(wait.ForLog("database system is ready to accept connections").WithOccurrence(2).WithStartupTimeout(5*time.Second)), + container, err := internal.RunContainer(ctx, + postgres.WithInitScripts(filepath.Join("..", "..", "assets", "structure.sql")), ) Expect(err).ToNot(HaveOccurred()) - connString, err = container.ConnectionString(ctx, "sslmode=disable") - Expect(err).ToNot(HaveOccurred()) - - err = db.Migrate(ctx, connString) + connString, err := container.ConnectionString(ctx, "sslmode=disable") Expect(err).ToNot(HaveOccurred()) conn, err = pgx.Connect(ctx, connString) diff --git a/slack/views/save_rota_test.go b/slack/views/save_rota_test.go index fa7df40..bd840c9 100644 --- a/slack/views/save_rota_test.go +++ b/slack/views/save_rota_test.go @@ -2,13 +2,11 @@ package views import ( "context" - "time" + "path/filepath" - "github.com/rotabot-io/rotabot/slack/slackclient" + "github.com/rotabot-io/rotabot/internal" - "github.com/testcontainers/testcontainers-go" - "github.com/testcontainers/testcontainers-go/modules/postgres" - "github.com/testcontainers/testcontainers-go/wait" + "github.com/rotabot-io/rotabot/slack/slackclient" "github.com/jackc/pgx/v5" . "github.com/onsi/ginkgo/v2" @@ -17,37 +15,31 @@ import ( "github.com/rotabot-io/rotabot/lib/db" "github.com/rotabot-io/rotabot/slack/slackclient/mock_slackclient" "github.com/slack-go/slack" + "github.com/testcontainers/testcontainers-go/modules/postgres" "go.uber.org/mock/gomock" ) var _ = Describe("SaveRota", func() { var ( - ctx context.Context - sc *mock_slackclient.MockSlackClient - addRota *SaveRota - connString string - tx pgx.Tx - conn *pgx.Conn - container *postgres.PostgresContainer - + ctx context.Context + sc *mock_slackclient.MockSlackClient + addRota *SaveRota + tx pgx.Tx + conn *pgx.Conn channelID string teamID string triggerID string ) BeforeEach(func() { - var err error ctx = context.Background() - container, err = postgres.RunContainer(ctx, - testcontainers.WithWaitStrategy(wait.ForLog("database system is ready to accept connections").WithOccurrence(2).WithStartupTimeout(5*time.Second)), + container, err := internal.RunContainer(ctx, + postgres.WithInitScripts(filepath.Join("..", "..", "assets", "structure.sql")), ) Expect(err).ToNot(HaveOccurred()) - connString, err = container.ConnectionString(ctx, "sslmode=disable") - Expect(err).ToNot(HaveOccurred()) - - err = db.Migrate(ctx, connString) + connString, err := container.ConnectionString(ctx, "sslmode=disable") Expect(err).ToNot(HaveOccurred()) conn, err = pgx.Connect(ctx, connString) diff --git a/sqlc.yaml b/sqlc.yaml index 5ef9c5a..21d0d72 100644 --- a/sqlc.yaml +++ b/sqlc.yaml @@ -14,7 +14,7 @@ sql: go_type: type: "RotaMetadata" database: - uri: "postgresql://postgres:postgres@localhost:5432/postgres?sslmode=disable" + uri: "postgresql://rotabot@localhost:5432/rotabot?sslmode=disable" rules: - sqlc/db-prepare - has-index