Skip to content

Commit

Permalink
Merge pull request #1313 from openmeterio/feat/migrations
Browse files Browse the repository at this point in the history
Add versioned migrations
  • Loading branch information
GAlexIHU authored Aug 29, 2024
2 parents 67ebd9e + 46e603d commit 14bba4b
Show file tree
Hide file tree
Showing 42 changed files with 1,004 additions and 136 deletions.
52 changes: 52 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,42 @@ jobs:
engine.stderr.log
retention-days: 14

migrations:
name: Migration Checks
runs-on: depot-ubuntu-latest-8

steps:
# Required as a workaround for Dagger to properly detect Git metadata
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0 # Needed to compare against base branch

- name: Run pipeline
uses: dagger/dagger-for-github@29a88e72255e732147ba18a670978b90bcc59efd # v6.4.0
with:
verb: call
module: github.com/${{ github.repository }}@${{ github.ref }}
args: --ref ${{ github.ref }} migrate check
cloud-token: ${{ secrets.DAGGER_CLOUD_TOKEN }}
version: ${{ env.DAGGER_VERSION }}

- name: Export Dagger Engine logs
id: export-dagger-engine-logs
run: docker logs $(docker container list --all --filter 'name=^dagger-engine-*' --format '{{.Names}}') > engine.stdout.log 2> engine.stderr.log
if: always()
continue-on-error: true

- name: Upload Dagger Engine logs as artifact
uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5
if: always() && steps.export-dagger-engine-logs.outcome == 'success'
with:
name: "[${{ github.job }}] Dagger Engine logs"
path: |
engine.stdout.log
engine.stderr.log
retention-days: 14

lint:
name: Lint
runs-on: depot-ubuntu-latest-8
Expand Down Expand Up @@ -217,6 +253,22 @@ jobs:
cloud-token: ${{ secrets.DAGGER_CLOUD_TOKEN }}
version: ${{ env.DAGGER_VERSION }}

- name: Export Container Logs
id: export-container-logs
run: docker logs $(docker container list --all --filter 'name=^*-openmeter-*' --format '{{.Names}}') > container.stdout.log 2> container.stderr.log
if: always()
continue-on-error: true

- name: Upload Container logs as artifact
uses: actions/upload-artifact@834a144ee995460fba8ed112a2fc961b36a5ec5a # v4.3.6
if: always() && steps.export-container-logs.outcome == 'success'
with:
name: "[${{ github.job }}] Container logs"
path: |
container.stdout.log
container.stderr.log
retention-days: 14

- name: Cleanup Docker Compose
run: docker compose -f docker-compose.yaml -f docker-compose.ci.yaml down -v
working-directory: quickstart
Expand Down
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,7 @@
},
"gopls": {
"formatting.gofumpt": true
}
},
"go.lintTool": "golangci-lint",
"go.lintFlags": ["--fast", "--fix", "-c", ".golangci.yaml"]
}
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ gen-api: ## Generate API and SDKs
dagger call --source .:default generate web-sdk -o api/client/web
dagger call --source .:default generate python-sdk -o api/client/python

.PHONY: migrate-check
migrate-check: ## Validate migrations
$(call print-target)
dagger call --source .:default migrate check

.PHONY: generate
generate: ## Generate code
$(call print-target)
Expand Down
98 changes: 98 additions & 0 deletions atlas.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
env "local" {
src = "${local.schema_src}"

migration {
dir = "${local.migrations_dir}"
format = "${local.migrations_format}"
}

format {
migrate {
diff = "{{ sql . \" \" }}"
}
}

url = "${local.local_url}"

// Define the URL of the Dev Database for this environment
// See: https://atlasgo.io/concepts/dev-database
dev = "docker://postgres/15/dev?search_path=public"

lint {
// Lint the effects of the 100 latest migration files
latest = 100
}
}

env "ci" {
src = "${local.schema_src}"

migration {
dir = "${local.migrations_dir}"
format = "${local.migrations_format}"
}

format {
migrate {
diff = "{{ sql . \" \" }}"
}
}

dev = "${local.ci_url}"
}

// CAN be used for all remote deployments
env "remote" {
src = "${local.schema_src}"

migration {
// Define the directory where the migrations are stored.
dir = "file://tools/migrate/migrations"
// We use golang-migrate
format = "${local.migrations_format}"
// Remote deployments already had auto deploy present
baseline = "${local.init_migration_ts}"
}

format {
migrate {
diff = "{{ sql . \" \" }}"
}
}

// Define the URL of the Dev Database for this environment
// See: https://atlasgo.io/concepts/dev-database
dev = "docker://postgres/15/dev?search_path=public"
}

locals {
// Define the directory where the schema definition resides.
schema_src = "ent://openmeter/ent/schema"
// Define the initial migration timestamp
init_migration_ts = "20240826120919"
// Define the directory where the migrations are stored.
migrations_dir = "file://tools/migrate/migrations"
// We use golang-migrate
migrations_format = "golang-migrate"
// Define common connection URLs
local_url = "postgres://postgres:postgres@localhost:5432/postgres?search_path=public&sslmode=disable"
ci_url = "postgres://postgres:postgres@postgres:5432/postgres?search_path=public&sslmode=disable"
}

lint {
non_linear {
error = true
}

destructive {
error = false
}

data_depend {
error = true
}

incompatible {
error = true
}
}
18 changes: 13 additions & 5 deletions ci/e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ func (m *Ci) Etoe(
WithExec([]string{"openmeter-sink-worker", "--config", "/etc/openmeter/config.yaml"}).
AsService()

args := []string{"go", "test", "-count=1", "-v"}
args := []string{"go", "test", "-tags", "musl", "-count=1", "-v"}

if test != "" {
args = append(args, "-run", fmt.Sprintf("Test%s", test))
}

args = append(args, "./e2e/...")

return goModule().
return goModuleCross("").
WithModuleCache(cacheVolume("go-mod-e2e")).
WithBuildCache(cacheVolume("go-build-e2e")).
WithSource(m.Source).
Expand Down Expand Up @@ -67,14 +67,22 @@ func redis() *dagger.Service {
AsService()
}

func postgres() *dagger.Service {
func pg() *dagger.Container {
return dag.Container().
From(fmt.Sprintf("postgres:%s", postgresVersion)).
WithEnvVariable("POSTGRES_USER", "postgres").
WithEnvVariable("POSTGRES_PASSWORD", "postgres").
WithEnvVariable("POSTGRES_DB", "postgres").
WithExposedPort(5432).
AsService()
WithExposedPort(5432)
}

func postgres() *dagger.Service {
return pg().AsService()
}

// Creates a postgres service unique by name
func postgresNamed(name string) *dagger.Service {
return pg().WithLabel("uniq-name", name).AsService()
}

const (
Expand Down
85 changes: 85 additions & 0 deletions ci/migrate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package main

import (
"context"
"fmt"

"github.com/openmeterio/openmeter/ci/internal/dagger"
"github.com/sourcegraph/conc/pool"
)

func (m *Ci) Migrate() *Migrate {
return &Migrate{
Source: m.Source,
}
}

type Migrate struct {
Source *dagger.Directory
}

func (m *Migrate) Check(ctx context.Context) error {
app := goModuleCross("").
WithSource(m.Source).
Container().
WithEnvVariable("GOFLAGS", "-tags=musl")

bin := dag.Container(dagger.ContainerOpts{
Platform: "linux/amd64",
}).From(atlasImage).File("atlas")

atlas := app.
WithFile("/bin/atlas", bin).
WithDirectory("openmeter/ent", m.Source.Directory("openmeter/ent")).
WithDirectory("tools/migrate/migrations", m.Source.Directory("tools/migrate/migrations")).
WithFile("atlas.hcl", m.Source.File("atlas.hcl"))

p := pool.New().WithErrors().WithContext(ctx)

// Always validate schema is generated
p.Go(func(ctx context.Context) error {
result := app.
WithExec([]string{"go", "generate", "-x", "./openmeter/ent/..."}).
Directory("openmeter/ent")

source := m.Source.Directory("openmeter/ent")

err := diff(ctx, source, result)
if err != nil {
return fmt.Errorf("schema is not in sync with generated code")
}
return nil
})

// Always validate migrations are in sync with schema
p.Go(func(ctx context.Context) error {
result := atlas.
WithServiceBinding("postgres", postgresNamed("no-diff")).
WithExec([]string{"atlas", "migrate", "--env", "ci", "diff", "test"}).
Directory("tools/migrate/migrations")

source := m.Source.Directory("tools/migrate/migrations")
err := diff(ctx, source, result)
if err != nil {
return fmt.Errorf("migrations are not in sync with schema")
}

return nil
})

// Always lint last 10 migrations
p.Go(syncFunc(
atlas.
WithServiceBinding("postgres", postgresNamed("last-10")).
WithExec([]string{"atlas", "migrate", "--env", "ci", "lint", "--latest", "10"}),
))

// Validate checksum is intact
p.Go(syncFunc(
atlas.
WithServiceBinding("postgres", postgresNamed("validate")).
WithExec([]string{"atlas", "migrate", "--env", "ci", "validate"}),
))

return p.Wait()
}
2 changes: 2 additions & 0 deletions ci/versions_pinned.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,6 @@ const (
xxBaseImage = "tonistiigi/xx:1.5.0@sha256:0c6a569797744e45955f39d4f7538ac344bfb7ebf0a54006a0a4297b153ccf0f"

alpineBaseImage = "alpine:3.20.2@sha256:0a4eaa0eecf5f8c050e5bba433f58c052be7587ee8af3e8b3910ef9ab5fbe9f5"

atlasImage = "arigaio/atlas:0.26.1@sha256:f77152f5458255410d2e59ad80a0fc661524067a90d297a0b62e6bda23437893"
)
9 changes: 4 additions & 5 deletions cmd/balance-worker/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,14 @@ import (
"github.com/openmeterio/openmeter/openmeter/entitlement/balanceworker"
"github.com/openmeterio/openmeter/openmeter/meter"
registrybuilder "github.com/openmeterio/openmeter/openmeter/registry/builder"
"github.com/openmeterio/openmeter/openmeter/registry/startup"
"github.com/openmeterio/openmeter/openmeter/streaming/clickhouse_connector"
"github.com/openmeterio/openmeter/openmeter/watermill/driver/kafka"
watermillkafka "github.com/openmeterio/openmeter/openmeter/watermill/driver/kafka"
"github.com/openmeterio/openmeter/openmeter/watermill/eventbus"
"github.com/openmeterio/openmeter/openmeter/watermill/router"
"github.com/openmeterio/openmeter/pkg/contextx"
entdriver "github.com/openmeterio/openmeter/pkg/framework/entutils/driver"
entdriver "github.com/openmeterio/openmeter/pkg/framework/entutils/entdriver"
"github.com/openmeterio/openmeter/pkg/framework/operation"
"github.com/openmeterio/openmeter/pkg/framework/pgdriver"
"github.com/openmeterio/openmeter/pkg/gosundheit"
Expand Down Expand Up @@ -238,10 +239,8 @@ func main() {

entClient := entPostgresDriver.Client()

// Run database schema creation
err = entClient.Schema.Create(ctx)
if err != nil {
logger.Error("failed to create database schema", "error", err)
if err := startup.DB(ctx, conf.Postgres, entClient); err != nil {
logger.Error("failed to initialize database", "error", err)
os.Exit(1)
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/jobs/entitlement/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
"github.com/openmeterio/openmeter/openmeter/streaming/clickhouse_connector"
watermillkafka "github.com/openmeterio/openmeter/openmeter/watermill/driver/kafka"
"github.com/openmeterio/openmeter/openmeter/watermill/eventbus"
entdriver "github.com/openmeterio/openmeter/pkg/framework/entutils/driver"
entdriver "github.com/openmeterio/openmeter/pkg/framework/entutils/entdriver"
"github.com/openmeterio/openmeter/pkg/framework/pgdriver"
"github.com/openmeterio/openmeter/pkg/models"
"github.com/openmeterio/openmeter/pkg/slicesx"
Expand Down
8 changes: 4 additions & 4 deletions cmd/notification-service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,14 @@ import (
notificationservice "github.com/openmeterio/openmeter/openmeter/notification/service"
notificationwebhook "github.com/openmeterio/openmeter/openmeter/notification/webhook"
registrybuilder "github.com/openmeterio/openmeter/openmeter/registry/builder"
"github.com/openmeterio/openmeter/openmeter/registry/startup"
"github.com/openmeterio/openmeter/openmeter/streaming/clickhouse_connector"
"github.com/openmeterio/openmeter/openmeter/watermill/driver/kafka"
watermillkafka "github.com/openmeterio/openmeter/openmeter/watermill/driver/kafka"
"github.com/openmeterio/openmeter/openmeter/watermill/eventbus"
"github.com/openmeterio/openmeter/openmeter/watermill/router"
"github.com/openmeterio/openmeter/pkg/contextx"
entdriver "github.com/openmeterio/openmeter/pkg/framework/entutils/driver"
entdriver "github.com/openmeterio/openmeter/pkg/framework/entutils/entdriver"
"github.com/openmeterio/openmeter/pkg/framework/operation"
"github.com/openmeterio/openmeter/pkg/framework/pgdriver"
"github.com/openmeterio/openmeter/pkg/gosundheit"
Expand Down Expand Up @@ -241,9 +242,8 @@ func main() {
entClient := entPostgresDriver.Client()

// Run database schema creation
err = entClient.Schema.Create(ctx)
if err != nil {
logger.Error("failed to create database schema", "error", err)
if err := startup.DB(ctx, conf.Postgres, entClient); err != nil {
logger.Error("failed to initialize database", "error", err)
os.Exit(1)
}

Expand Down
Loading

0 comments on commit 14bba4b

Please sign in to comment.