feat: use goose as a db migration tool (#226)
continuous-integration/drone/push Build is passing Details

Reviewed-on: twhelp/core#226
This commit is contained in:
Dawid Wysokiński 2023-06-10 06:21:07 +00:00
parent 13b115d3d8
commit 161dc487f5
51 changed files with 586 additions and 1809 deletions

View File

@ -54,6 +54,25 @@ trigger:
branch:
- master
---
kind: pipeline
type: docker
name: migrations
steps:
- name: validate
image: golang:1.20
pull: always
commands:
- make validate-migrations
trigger:
event:
- push
- pull_request
branch:
- master
---
kind: pipeline
type: docker
@ -216,6 +235,103 @@ trigger:
depends_on:
- linux-amd64
---
kind: pipeline
type: docker
name: migrations-linux-amd64
platform:
os: linux
arch: amd64
steps:
- name: publish
image: plugins/docker
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
registry: gitea.dwysokinski.me
repo: gitea.dwysokinski.me/twhelp-packages/core-migrations
auto_tag: true
auto_tag_suffix: linux-amd64
dockerfile: ./build/docker/twhelp-migrations/Dockerfile
- name: notify
image: drillster/drone-email
settings:
from.address:
from_secret: email_from
from.name: Drone
host:
from_secret: email_host
username:
from_secret: email_username
password:
from_secret: email_password
recipients:
- notifications@dwysokinski.me
recipients_only: true
when:
status:
- failure
trigger:
event:
- tag
---
kind: pipeline
type: docker
name: migrations-manifest
steps:
- name: manifest
image: plugins/manifest
settings:
auto_tag: "true"
ignore_missing: "true"
spec: ./build/docker/twhelp-migrations/manifest.tmpl
username:
from_secret: docker_username
password:
from_secret: docker_password
- name: manifest-latest
image: plugins/manifest
settings:
tags: latest
ignore_missing: "true"
spec: ./build/docker/twhelp-migrations/manifest.tmpl
username:
from_secret: docker_username
password:
from_secret: docker_password
- name: notify
image: drillster/drone-email
settings:
from.address:
from_secret: email_from
from.name: Drone
host:
from_secret: email_host
username:
from_secret: email_username
password:
from_secret: email_password
recipients:
- notifications@dwysokinski.me
recipients_only: true
when:
status:
- failure
trigger:
event:
- tag
depends_on:
- migrations-linux-amd64
---
kind: pipeline
type: docker
@ -229,7 +345,7 @@ steps:
from_secret: kubeconfig
commands:
- "mkdir ~/.kube && echo \"$KUBECONFIG\" > ~/.kube/twhelp"
- "cd ./k8s/overlays/prod && kustomize edit set image twhelp=gitea.dwysokinski.me/twhelp-packages/core:${DRONE_TAG##v} && cd ../../.."
- "cd ./k8s/overlays/prod && kustomize edit set image twhelp=gitea.dwysokinski.me/twhelp-packages/core:${DRONE_TAG##v} twhelp-migrations=gitea.dwysokinski.me/twhelp-packages/core-migrations:${DRONE_TAG##v} && cd ../../.."
- "kubectl --kubeconfig ~/.kube/twhelp -n twhelp delete jobs.batch twhelp-migrations-job || true"
- kustomize build ./k8s/overlays/prod | kubectl --kubeconfig ~/.kube/twhelp apply -n twhelp -f -
- name: notify
@ -259,8 +375,9 @@ trigger:
depends_on:
- manifest
- migrations-manifest
---
kind: signature
hmac: 6108df5c8e8d06dd376f47a0aea7449d6eac5bb334b439474316df5634f572d0
hmac: d7875a536ec2ed51a691e44abe9e4a9c74e3d747e7fe1a2b1147b615c83318b9
...

View File

@ -7,6 +7,7 @@ endif
OSARCH=$(shell uname -m)
GOLANGCI_LINT_PATH=$(GOBIN)/golangci-lint
SWAG_PATH=$(GOBIN)/swag
GOOSE_PATH=$(GOBIN)/goose
.PHONY: install-git-hooks
install-git-hooks:
@ -22,15 +23,20 @@ install-counterfeiter:
.PHONY: install-swag
install-swag:
@echo "Installing github.com/swaggo/swag..."
@test -f $(SWAG_PATH) || (wget -qO- https://github.com/swaggo/swag/releases/download/v1.8.7/swag_1.8.7_$(GOOS)_$(OSARCH).tar.gz | tar -xz -C $(GOBIN)/)
@(test -f $(SWAG_PATH) && echo "github.com/swaggo/swag is already installed. Skipping...") || (wget -qO- https://github.com/swaggo/swag/releases/download/v1.8.7/swag_1.8.7_$(GOOS)_$(OSARCH).tar.gz | tar -xz -C $(GOBIN)/)
.PHONY: install-golangci-lint
install-golangci-lint:
@echo "Installing github.com/golangci/golangci-lint..."
@test -f $(GOLANGCI_LINT_PATH) || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOBIN) v1.53.2
@(test -f $(GOLANGCI_LINT_PATH) && echo "github.com/golangci/golangci-lint is already installed. Skipping...") || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOBIN) v1.53.2
.PHONY: install-goose
install-goose:
@echo "Installing github.com/pressly/goose..."
@(test -f $(GOOSE_PATH) && echo "github.com/pressly/goose is already installed. Skipping...") || (wget -q -O $(GOOSE_PATH) https://github.com/pressly/goose/releases/download/v3.11.2/goose_$(GOOS)_$(OSARCH) && chmod u+x $(GOOSE_PATH))
.PHONY: install-tools
install-tools: install-counterfeiter install-swag install-golangci-lint
install-tools: install-counterfeiter install-swag install-golangci-lint install-goose
.PHONY: install
install: install-tools install-git-hooks
@ -55,3 +61,11 @@ create-job-create-snapshots:
.PHONY: create-job-clean-up
create-job-clean-up:
kubectl create job --from=cronjob/twhelp-job-clean-up-dev twhelp-job-clean-up
.PHONY: create-sql-migration
create-sql-migration: install-goose
@goose -dir migrations create $(name) sql
.PHONY: validate-migrations
validate-migrations: install-goose
@goose -dir migrations -v validate

View File

@ -0,0 +1,13 @@
FROM alpine:3.18
WORKDIR /twhelp
RUN apk --no-cache add curl
RUN curl -fsSL \
https://raw.githubusercontent.com/pressly/goose/master/install.sh |\
sh -s v3.11.2
COPY ./migrations .
ENTRYPOINT ["goose"]

View File

@ -0,0 +1,13 @@
image: gitea.dwysokinski.me/twhelp-packages/core-migrations:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
{{#if build.tags}}
tags:
{{#each build.tags}}
- {{this}}
{{/each}}
{{/if}}
manifests:
-
image: gitea.dwysokinski.me/twhelp-packages/core-migrations:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
platform:
architecture: amd64
os: linux

View File

@ -1,187 +0,0 @@
package db
import (
"fmt"
"strconv"
"strings"
"gitea.dwysokinski.me/twhelp/core/cmd/twhelp/internal"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/migrations"
"github.com/urfave/cli/v2"
"go.uber.org/zap"
)
func New() *cli.Command {
return &cli.Command{
Name: "db",
Usage: "Manages database migrations",
Subcommands: []*cli.Command{
newMigrateCmd(),
newRollbackCmd(),
newCreateCmd(),
newStatusCmd(),
},
}
}
func newMigrateCmd() *cli.Command {
return &cli.Command{
Name: "migrate",
Usage: "Migrates database",
Action: func(c *cli.Context) error {
logger := zap.L()
db, err := internal.NewBunDB()
if err != nil {
return fmt.Errorf("internal.NewBunDB: %w", err)
}
defer func() {
_ = db.Close()
}()
migrator := migrations.NewMigrator(db)
if err = migrator.Init(c.Context); err != nil {
return fmt.Errorf("migrator.Init: %w", err)
}
if err = migrator.Lock(c.Context); err != nil {
return err
}
defer func() {
_ = migrator.Unlock(c.Context)
}()
group, err := migrator.Migrate(c.Context)
if err != nil {
return fmt.Errorf("migrator.Migrate: %w", err)
}
if group.ID == 0 {
logger.Info("there are no new migrations to run")
return nil
}
logger.Info("migrated to "+strconv.FormatInt(group.ID, 10), zap.Int64("id", group.ID))
return nil
},
}
}
func newRollbackCmd() *cli.Command {
return &cli.Command{
Name: "rollback",
Usage: "Rollbacks the last migration group",
Action: func(c *cli.Context) error {
logger := zap.L()
db, err := internal.NewBunDB()
if err != nil {
return fmt.Errorf("internal.NewBunDB: %w", err)
}
defer func() {
_ = db.Close()
}()
migrator := migrations.NewMigrator(db)
if err = migrator.Lock(c.Context); err != nil {
return err
}
defer func() {
_ = migrator.Unlock(c.Context)
}()
group, err := migrator.Rollback(c.Context)
if err != nil {
return fmt.Errorf("migrator.Rollback: %w", err)
}
if group.ID == 0 {
logger.Info("there are no groups to roll back")
return nil
}
logger.Info("rolled back "+strconv.FormatInt(group.ID, 10), zap.Int64("id", group.ID))
return nil
},
}
}
func newCreateCmd() *cli.Command {
return &cli.Command{
Name: "create",
Usage: "Creates migration",
Subcommands: []*cli.Command{
{
Name: "go",
Usage: "Creates Go migration",
Action: func(c *cli.Context) error {
logger := zap.L()
migrator := migrations.NewMigrator(nil)
mf, err := migrator.CreateGoMigration(c.Context, strings.Join(c.Args().Slice(), "_"))
if err != nil {
return fmt.Errorf("migrator.CreateGoMigration: %w", err)
}
logger.Info("created migration", zap.String("name", mf.Name), zap.String("path", mf.Path))
return nil
},
},
{
Name: "sql",
Usage: "Creates SQL migration",
Action: func(c *cli.Context) error {
logger := zap.L()
migrator := migrations.NewMigrator(nil)
files, err := migrator.CreateSQLMigrations(c.Context, strings.Join(c.Args().Slice(), "_"))
if err != nil {
return fmt.Errorf("migrator.CreateSQLMigrations: %w", err)
}
for _, mf := range files {
logger.Info("created migration", zap.String("name", mf.Name), zap.String("path", mf.Path))
}
return nil
},
},
},
}
}
func newStatusCmd() *cli.Command {
return &cli.Command{
Name: "status",
Usage: "Prints migrations status",
Action: func(c *cli.Context) error {
logger := zap.L()
db, err := internal.NewBunDB()
if err != nil {
return fmt.Errorf("internal.NewBunDB: %w", err)
}
defer func() {
_ = db.Close()
}()
migrator := migrations.NewMigrator(db)
ms, err := migrator.MigrationsWithStatus(c.Context)
if err != nil {
return fmt.Errorf("migrator.MigrationsWithStatus: %w", err)
}
logger.Info("migrations: " + ms.String())
logger.Info("last migration group: " + ms.LastGroup().String())
logger.Info("unapplied: " + ms.Unapplied().String())
return nil
},
}
}

View File

@ -7,7 +7,6 @@ import (
"gitea.dwysokinski.me/twhelp/core/cmd/twhelp/internal"
"gitea.dwysokinski.me/twhelp/core/cmd/twhelp/internal/appmode"
"gitea.dwysokinski.me/twhelp/core/cmd/twhelp/internal/consumer"
"gitea.dwysokinski.me/twhelp/core/cmd/twhelp/internal/db"
"gitea.dwysokinski.me/twhelp/core/cmd/twhelp/internal/job"
"gitea.dwysokinski.me/twhelp/core/cmd/twhelp/internal/serve"
"github.com/urfave/cli/v2"
@ -53,7 +52,6 @@ func newApp(mode string) *cli.App {
}
app.Commands = []*cli.Command{
consumer.New(),
db.New(),
job.New(),
serve.New(),
}

29
go.mod
View File

@ -17,6 +17,7 @@ require (
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa
github.com/kelseyhightower/envconfig v1.4.0
github.com/ory/dockertest/v3 v3.10.0
github.com/pressly/goose/v3 v3.11.2
github.com/realclientip/realclientip-go v1.0.0
github.com/stretchr/testify v1.8.4
github.com/swaggo/http-swagger/v2 v2.0.1
@ -30,18 +31,18 @@ require (
)
require (
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/Microsoft/go-winio v0.6.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
github.com/containerd/continuity v0.3.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/cli v20.10.17+incompatible // indirect
github.com/docker/docker v20.10.7+incompatible // indirect
github.com/docker/cli v23.0.6+incompatible // indirect
github.com/docker/docker v23.0.6+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/spec v0.20.6 // indirect
@ -50,36 +51,36 @@ require (
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/lithammer/shortuuid/v3 v3.0.7 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/opencontainers/runc v1.1.5 // indirect
github.com/opencontainers/image-spec v1.1.0-rc3 // indirect
github.com/opencontainers/runc v1.1.7 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rabbitmq/amqp091-go v1.2.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/swaggo/files/v2 v2.0.0 // indirect
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.7.0 // indirect
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/tools v0.7.0 // indirect
golang.org/x/tools v0.8.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
mellium.im/sasl v0.3.1 // indirect

127
go.sum
View File

@ -2,13 +2,12 @@ gitea.dwysokinski.me/Kichiyaki/chiclientip v0.1.0 h1:5e5Uh+Am1PBSW1cYsbAuEhrGSZH
gitea.dwysokinski.me/Kichiyaki/chiclientip v0.1.0/go.mod h1:zMTruKo30+qM3dG4yhAPOxK/5hUEBhKiDSrV0VRlZnI=
gitea.dwysokinski.me/Kichiyaki/chizap v0.4.0 h1:0xmeSFB4V+fEMSbCSDsXwiud5tg8FlAIjpzMWQwheZs=
gitea.dwysokinski.me/Kichiyaki/chizap v0.4.0/go.mod h1:FoXG8sBh3JgQhWNAWlTtSo6CkGGCkhNXq+wNqG3o3cw=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
github.com/ThreeDotsLabs/watermill v1.2.0 h1:TU3TML1dnQ/ifK09F2+4JQk2EKhmhXe7Qv7eb5ZpTS8=
@ -20,33 +19,26 @@ github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTx
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M=
github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v20.10.7+incompatible h1:Z6O9Nhsjv+ayUEeI1IojKbYcsGdgYSNqxe1s2MYzUhQ=
github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/cli v23.0.6+incompatible h1:CScadyCJ2ZKUDpAMZta6vK8I+6/m60VIjGIV7Wg/Eu4=
github.com/docker/cli v23.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/docker v23.0.6+incompatible h1:aBD4np894vatVX99UTx/GyOUOK4uEcROwA3+bQhEcoU=
github.com/docker/docker v23.0.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/elliotchance/phpserialize v1.3.3 h1:hV4QVmGdCiYgoBbw+ADt6fNgyZ2mYX0OgpnON1adTCM=
github.com/elliotchance/phpserialize v1.3.3/go.mod h1:gt7XX9+ETUcLXbtTKEuyrqW3lcLUAeS/AnGZ2e49TZs=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
github.com/garsue/watermillzap v1.2.0 h1:IA0zGb5b7mIGLXN9P2/6CmP5+f7Qgb00BdL2VCAk2SA=
github.com/garsue/watermillzap v1.2.0/go.mod h1:uo3SDSGYaw6RBzUx9jcHMYqypOTqlQ4/vz+8r1olRto=
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
@ -63,16 +55,9 @@ github.com/go-openapi/spec v0.20.6/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
@ -85,70 +70,64 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa h1:s+4MhCQ6YrzisK6hFJUX53drDT4UsSW3DEhKn0ifuHw=
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v0.0.0-20180327071824-d34b9ff171c2 h1:hRGSmZu7j271trc9sneMrpOW7GN5ngLm8YUZIPzf394=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8=
github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 h1:rzf0wL0CHVc8CEsgyygG0Mn9CNCCPZqOPaz8RiiHYQk=
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc=
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs=
github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8=
github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
github.com/opencontainers/runc v1.1.7 h1:y2EZDS8sNng4Ksf0GUYNhKbTShZJPJg1FiXJNH/uoCk=
github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50=
github.com/ory/dockertest/v3 v3.10.0 h1:4K3z2VMe8Woe++invjaTB7VRyQXQy5UY+loujO4aNE4=
github.com/ory/dockertest/v3 v3.10.0/go.mod h1:nr57ZbRWMqfsdGdFNLHz5jjNdDb7VVFnzAeW1n5N1Lg=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pressly/goose/v3 v3.11.2 h1:QgTP45FhBBHdmf7hWKlbWFHtwPtxo0phSDkwDKGUrYs=
github.com/pressly/goose/v3 v3.11.2/go.mod h1:LWQzSc4vwfHA/3B8getTp8g3J5Z8tFBxgxinmGlMlJk=
github.com/rabbitmq/amqp091-go v1.2.0 h1:1pHBxAsQh54R9eX/xo679fUEAfv3loMqi0pvRFOj2nk=
github.com/rabbitmq/amqp091-go v1.2.0/go.mod h1:ogQDLSOACsLPsIq0NpbtiifNZi2YOz0VTJ0kHRghqbM=
github.com/realclientip/realclientip-go v1.0.0 h1:+yPxeC0mEaJzq1BfCt2h4BxlyrvIIBzR6suDc3BEF1U=
github.com/realclientip/realclientip-go v1.0.0/go.mod h1:CXnUdVwFRcXFJIRb/dTYqbT7ud48+Pi2pFm80bxDmcI=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
@ -160,7 +139,6 @@ github.com/swaggo/http-swagger/v2 v2.0.1 h1:mNOBLxDjSNwCKlMxcErjjvct/xhc9t2KIO48
github.com/swaggo/http-swagger/v2 v2.0.1/go.mod h1:XYhrQVIKz13CxuKD4p4kvpaRB4jJ1/MlfQXVOE+CX8Y=
github.com/swaggo/swag v1.8.8 h1:/GgJmrJ8/c0z4R4hoEPZ5UeEhVGdvsII4JbVDLbR7Xc=
github.com/swaggo/swag v1.8.8/go.mod h1:ezQVUUhly8dludpVk+/PuwJWvLLanB13ygV5Pr9enSk=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
github.com/uptrace/bun v1.1.14 h1:S5vvNnjEynJ0CvnrBOD7MIRW7q/WbtvFXrdfy0lddAM=
@ -171,17 +149,15 @@ github.com/uptrace/bun/dialect/pgdialect v1.1.14 h1:b7+V1KDJPQSFYgkG/6YLXCl2uvwE
github.com/uptrace/bun/dialect/pgdialect v1.1.14/go.mod h1:v6YiaXmnKQ2FlhRD2c0ZfKd+QXH09pYn4H8ojaavkKk=
github.com/uptrace/bun/driver/pgdriver v1.1.14 h1:V2Etm7mLGS3mhx8ddxZcUnwZLX02Jmq9JTlo0sNVDhA=
github.com/uptrace/bun/driver/pgdriver v1.1.14/go.mod h1:D4FjWV9arDYct6sjMJhFoyU71SpllZRHXFRRP2Kd0Kw=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.25.5 h1:d0NIAyhh5shGscroL7ek/Ya9QYQE0KNabJgiUinIQkc=
github.com/urfave/cli/v2 v2.25.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
@ -205,54 +181,40 @@ golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@ -260,7 +222,16 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo=
lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo=
mellium.im/sasl v0.3.1 h1:wE0LW6g7U83vhvxjC1IY8DnXM+EU095yeo8XClvCdfo=
mellium.im/sasl v0.3.1/go.mod h1:xm59PUYpZHhgQ9ZqoJ5QaCqzWMi8IeS49dhp6plPCzw=
modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/sqlite v1.22.1 h1:P2+Dhp5FR1RlVRkQ3dDfCiv3Ok8XPxqpe70IjYVA9oE=
modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=

View File

@ -1,7 +1,6 @@
package bundbtest
import (
"context"
"database/sql"
"errors"
"fmt"
@ -9,14 +8,15 @@ import (
"net/url"
"os"
"strings"
"sync"
"time"
"unicode"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/migrations"
"github.com/cenkalti/backoff/v4"
"github.com/google/uuid"
"github.com/ory/dockertest/v3"
"github.com/ory/dockertest/v3/docker"
"github.com/pressly/goose/v3"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/uptrace/bun"
@ -102,7 +102,7 @@ func NewDBWithDSN(t TestingT, dsn string) *bun.DB {
_, err := bunDB.Exec("CREATE SCHEMA ?", bun.Safe(schema))
require.NoError(t, err, "couldn't create schema")
runMigrations(t, bunDB)
runMigrations(t, sqldb)
return bunDB
}
@ -121,16 +121,17 @@ func getHostPort(t TestingT, resource *dockertest.Resource, id string) string {
return net.JoinHostPort(u.Hostname(), resource.GetPort(id))
}
func runMigrations(t TestingT, db *bun.DB) {
var gooseSetUpOnce = sync.Once{}
func runMigrations(t TestingT, db *sql.DB) {
t.Helper()
migrator := migrations.NewMigrator(db)
ctx, cancel := context.WithTimeout(context.Background(), migrationTimeout)
defer cancel()
gooseSetUpOnce.Do(func() {
goose.SetBaseFS(os.DirFS("../../migrations"))
goose.SetLogger(goose.NopLogger())
})
require.NoError(t, migrator.Init(ctx), "couldn't migrate (1)")
_, err := migrator.Migrate(ctx)
require.NoError(t, err, "couldn't migrate (2)")
require.NoError(t, goose.Up(db, ""), "couldn't migrate")
}
func generateSchema() string {

View File

@ -8,11 +8,25 @@ import (
"github.com/uptrace/bun/dbfixture"
)
var modelsToRegister = []any{
&model.Version{},
&model.Server{},
&model.Tribe{},
&model.Player{},
&model.Village{},
&model.Ennoblement{},
&model.PlayerSnapshot{},
&model.TribeSnapshot{},
&model.TribeChange{},
}
type Fixture struct {
*dbfixture.Fixture
}
func NewFixture(bunDB *bun.DB) *Fixture {
// ensure that models are registered
bunDB.RegisterModel(modelsToRegister...)
return &Fixture{
Fixture: dbfixture.New(bunDB),
}

View File

@ -1,31 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateTable().
Model(&model.Version{}).
Varchar(defaultVarcharLength).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'versions' table: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropTable().
Model(&model.Version{}).
Cascade().
IfExists().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'versions' table: %w", err)
}
return nil
})
}

View File

@ -1,153 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
versions := getVersions()
if _, err := db.NewInsert().
Model(&versions).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't insert versions: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
versions := getVersions()
codes := make([]string, 0, len(versions))
for _, version := range versions {
codes = append(codes, version.Code)
}
if _, err := db.NewDelete().
Model(&model.Version{}).
Where("code IN (?)", codes).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't delete versions: %w", err)
}
return nil
})
}
func getVersions() []model.Version {
return []model.Version{
{
Code: "pl",
Name: "Poland",
Host: "plemiona.pl",
Timezone: "Europe/Warsaw",
},
{
Code: "uk",
Name: "United Kingdom",
Host: "tribalwars.co.uk",
Timezone: "Europe/London",
},
{
Code: "hu",
Name: "Hungary",
Host: "klanhaboru.hu",
Timezone: "Europe/Budapest",
},
{
Code: "it",
Name: "Italy",
Host: "tribals.it",
Timezone: "Europe/Rome",
},
{
Code: "fr",
Name: "France",
Host: "guerretribale.fr",
Timezone: "Europe/Paris",
},
{
Code: "us",
Name: "United States",
Host: "tribalwars.us",
Timezone: "America/New_York",
},
{
Code: "nl",
Name: "The Netherlands",
Host: "tribalwars.nl",
Timezone: "Europe/Amsterdam",
},
{
Code: "es",
Name: "Spain",
Host: "guerrastribales.es",
Timezone: "Europe/Madrid",
},
{
Code: "ro",
Name: "Romania",
Host: "triburile.ro",
Timezone: "Europe/Bucharest",
},
{
Code: "gr",
Name: "Greece",
Host: "fyletikesmaxes.gr",
Timezone: "Europe/Athens",
},
{
Code: "br",
Name: "Brazil",
Host: "tribalwars.com.br",
Timezone: "America/Sao_Paulo",
},
{
Code: "tr",
Name: "Turkey",
Host: "klanlar.org",
Timezone: "Europe/Istanbul",
},
{
Code: "cs",
Name: "Czech Republic",
Host: "divokekmeny.cz",
Timezone: "Europe/Prague",
},
{
Code: "ru",
Name: "Russia",
Host: "voyna-plemyon.ru",
Timezone: "Europe/Moscow",
},
{
Code: "ch",
Name: "Switzerland",
Host: "staemme.ch",
Timezone: "Europe/Zurich",
},
{
Code: "pt",
Name: "Portugal",
Host: "tribalwars.com.pt",
Timezone: "Europe/Lisbon",
},
{
Code: "en",
Name: "International",
Host: "tribalwars.net",
Timezone: "Europe/London",
},
{
Code: "de",
Name: "Germany",
Host: "die-staemme.de",
Timezone: "Europe/Berlin",
},
{
Code: "sk",
Name: "Slovakia",
Host: "divoke-kmene.sk",
Timezone: "Europe/Bratislava",
},
}
}

View File

@ -1,32 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateTable().
Model(&model.Server{}).
Varchar(defaultVarcharLength).
ForeignKey(`(version_code) REFERENCES versions (code)`).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'servers' table: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropTable().
Model(&model.Server{}).
Cascade().
IfExists().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'servers' table: %w", err)
}
return nil
})
}

View File

@ -1,53 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
specialServers := getSpecialServers()
if _, err := db.NewInsert().Model(&specialServers).Ignore().Exec(ctx); err != nil {
return fmt.Errorf("couldn't insert special servers: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
specialServers := getSpecialServers()
q := db.NewDelete().Model(&specialServers)
for _, server := range specialServers {
q = q.WhereOr("version_code = ? AND key = ?", server.VersionCode, server.Key)
}
if _, err := q.Exec(ctx); err != nil {
return fmt.Errorf("couldn't delete special servers: %w", err)
}
return nil
})
}
func getSpecialServers() []model.Server {
versions := getVersions()
specialServers := make([]model.Server, 0, len(versions)+1)
for _, version := range versions {
key := version.Code + "s1"
specialServers = append(specialServers, model.Server{
Key: version.Code + "s1",
URL: fmt.Sprintf("https://%s.%s", key, version.Host),
Special: true,
VersionCode: version.Code,
Open: false,
})
}
specialServers = append(specialServers, model.Server{
Key: "master",
URL: "https://www.tribalwars.co.uk",
Special: true,
VersionCode: "uk",
Open: false,
})
return specialServers
}

View File

@ -1,50 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewUpdate().
Model(&model.Version{}).
Where("code = ?", "ru").
Returning("NULL").
Set("host = ?", "voynaplemyon.com").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't update host for the RU version: %w", err)
}
if _, err := db.NewUpdate().
Model(&model.Server{}).
Where("key = ?", "rus1").
Returning("NULL").
Set("url = ?", "https://rus1.voynaplemyon.com").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't update url (server_key=rus1): %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewUpdate().
Model(&model.Version{}).
Where("code = ?", "ru").
Returning("NULL").
Set("host = ?", "voyna-plemyon.ru").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't update host for the RU version: %w", err)
}
if _, err := db.NewUpdate().
Model(&model.Server{}).
Where("key = ?", "rus1").
Returning("NULL").
Set("url = ?", "https://rus1.voyna-plemyon.ru").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't update url (server_key=rus1): %w", err)
}
return nil
})
}

View File

@ -1,32 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateTable().
Model(&model.Tribe{}).
Varchar(defaultVarcharLength).
ForeignKey(`(server_key) REFERENCES servers (key)`).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'tribes' table: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropTable().
Model(&model.Tribe{}).
Cascade().
IfExists().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'tribes' table: %w", err)
}
return nil
})
}

View File

@ -1,32 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateTable().
Model(&model.Player{}).
Varchar(defaultVarcharLength).
ForeignKey(`(server_key) REFERENCES servers (key)`).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'players' table: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropTable().
Model(&model.Player{}).
Cascade().
IfExists().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'players' table: %w", err)
}
return nil
})
}

View File

@ -1,32 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateTable().
Model(&model.Village{}).
Varchar(defaultVarcharLength).
ForeignKey(`(server_key) REFERENCES servers (key)`).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'villages' table: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropTable().
Model(&model.Village{}).
Cascade().
IfExists().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'villages' table: %w", err)
}
return nil
})
}

View File

@ -1,48 +0,0 @@
package migrations
import (
"context"
"database/sql"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
return db.RunInTx(ctx, &sql.TxOptions{}, func(ctx context.Context, tx bun.Tx) error {
models := []any{
&model.Player{},
&model.Tribe{},
}
for _, m := range models {
if _, err := tx.NewAddColumn().
Model(m).
ColumnExpr("deleted_at timestamp with time zone").
IfNotExists().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't add the deleted_at column (model=%T): %w", m, err)
}
}
return nil
})
}, func(ctx context.Context, db *bun.DB) error {
return db.RunInTx(ctx, &sql.TxOptions{}, func(ctx context.Context, tx bun.Tx) error {
models := []any{
&model.Player{},
&model.Tribe{},
}
for _, m := range models {
if _, err := tx.NewDropColumn().
Model(m).
Column("deleted_at").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the deleted_at column (model=%T): %w", m, err)
}
}
return nil
})
})
}

View File

@ -1,32 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateTable().
Model(&model.Ennoblement{}).
Varchar(defaultVarcharLength).
ForeignKey(`(server_key) REFERENCES servers (key)`).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'ennoblements' table: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropTable().
Model(&model.Ennoblement{}).
Cascade().
IfExists().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'ennoblements' table: %w", err)
}
return nil
})
}

View File

@ -1,37 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateIndex().
Model(&model.Ennoblement{}).
Unique().
Index("ennoblements_hash_key").
ColumnExpr("hash_record_extended((server_key, village_id, new_owner_id, new_tribe_id, old_owner_id, old_tribe_id, points, created_at), 0)").
IfNotExists().
Column().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'ennoblements_hash_key' index: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropIndex().
Model(&model.Ennoblement{}).
Index("ennoblements_hash_key").
IfExists().
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'ennoblements_hash_key' index: %w", err)
}
return nil
})
}

View File

@ -1,33 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewUpdate().
Model(&model.Version{}).
Set("host = ? || host", "www.").
Where("true").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't add prefix to Version.Host: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewUpdate().
Model(&model.Version{}).
Set("host = trim(leading ? from host)", "www.").
Where("true").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't remove prefix from Version.Host: %w", err)
}
return nil
})
}

View File

@ -1,36 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateIndex().
Model(&model.Ennoblement{}).
Index("ennoblements_server_key_created_at_idx").
IfNotExists().
Column("server_key", "created_at").
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'ennoblements_server_key_created_at_idx' index: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropIndex().
Model(&model.Ennoblement{}).
Index("ennoblements_server_key_created_at_idx").
IfExists().
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'ennoblements_server_key_created_at_idx' index: %w", err)
}
return nil
})
}

View File

@ -1,72 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
models := []struct {
m any
prefix string
}{
{
m: &model.Player{},
prefix: "players_",
},
{
m: &model.Tribe{},
prefix: "tribes_",
},
{
m: &model.Village{},
prefix: "villages_",
},
}
for _, m := range models {
if _, err := db.NewCreateIndex().
Model(m.m).
Index(m.prefix + "server_key_idx").
IfNotExists().
Column("server_key").
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the '%sserver_key_created_at_idx' index: %w", m.prefix, err)
}
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
models := []struct {
m any
prefix string
}{
{
m: &model.Player{},
prefix: "players_",
},
{
m: &model.Tribe{},
prefix: "tribes_",
},
{
m: &model.Village{},
prefix: "villages_",
},
}
for _, m := range models {
if _, err := db.NewDropIndex().
Model(m.m).
Index(m.prefix + "server_key_idx").
IfExists().
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the '%sserver_key_created_at_idx' index: %w", m.prefix, err)
}
}
return nil
})
}

View File

@ -1,80 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
var servers []model.Server
if err := db.NewSelect().Model(&servers).Column("key", "url").Scan(ctx); err != nil {
return fmt.Errorf("couldn't select servers from the db: %w", err)
}
models := []struct {
m any
screen string
}{
{
m: &model.Player{},
screen: "info_player",
},
{
m: &model.Tribe{},
screen: "info_ally",
},
{
m: &model.Village{},
screen: "info_village",
},
}
for _, m := range models {
if _, err := db.NewAddColumn().
Model(m.m).
ColumnExpr("profile_url varchar(150)").
IfNotExists().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't add the profile_url column (model=%T): %w", m.m, err)
}
for _, srv := range servers {
if _, err := db.NewUpdate().
With("data", db.NewSelect().
Model(m.m).
ColumnExpr("?TableAlias.id as id").
ColumnExpr("?TableAlias.server_key as server_key").
ColumnExpr(
"? || ?TableAlias.id as profile_url",
fmt.Sprintf("%s/game.php?screen=%s&id=", srv.URL, m.screen),
).
Where("?TableAlias.server_key = ?", srv.Key)).
Model(m.m).
Table("data").
Set("profile_url = data.profile_url").
Where("?TableAlias.id = data.id").
Where("?TableAlias.server_key = data.server_key").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't update profile urls (model=%T,server=%s): %w", m.m, srv.Key, err)
}
}
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
models := []any{
&model.Player{},
&model.Tribe{},
&model.Village{},
}
for _, m := range models {
if _, err := db.NewDropColumn().
Model(m).
Column("profile_url").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the profile_url column (model=%T): %w", m, err)
}
}
return nil
})
}

View File

@ -1,32 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateTable().
Model(&model.PlayerSnapshot{}).
Varchar(defaultVarcharLength).
ForeignKey(`(server_key) REFERENCES servers (key)`).
ForeignKey(`(player_id, server_key) REFERENCES players (id, server_key)`).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'player_snapshots' table: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropTable().
Model(&model.PlayerSnapshot{}).
Cascade().
IfExists().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'player_snapshots' table: %w", err)
}
return nil
})
}

View File

@ -1,47 +0,0 @@
package migrations
import (
"context"
"database/sql"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
return db.RunInTx(ctx, &sql.TxOptions{}, func(ctx context.Context, tx bun.Tx) error {
columns := []string{
"player_snapshots_created_at",
"tribe_snapshots_created_at",
}
for _, c := range columns {
if _, err := tx.NewAddColumn().
Model(&model.Server{}).
ColumnExpr("? timestamp with time zone", bun.Safe(c)).
IfNotExists().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't add the %s column: %w", c, err)
}
}
return nil
})
}, func(ctx context.Context, db *bun.DB) error {
return db.RunInTx(ctx, &sql.TxOptions{}, func(ctx context.Context, tx bun.Tx) error {
columns := []string{
"player_snapshots_created_at",
"tribe_snapshots_created_at",
}
for _, c := range columns {
if _, err := tx.NewDropColumn().
Model(&model.Server{}).
Column(c).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the %s column: %w", c, err)
}
}
return nil
})
})
}

View File

@ -1,32 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateTable().
Model(&model.TribeSnapshot{}).
Varchar(defaultVarcharLength).
ForeignKey(`(server_key) REFERENCES servers (key)`).
ForeignKey(`(tribe_id, server_key) REFERENCES tribes (id, server_key)`).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'tribe_snapshots' table: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropTable().
Model(&model.TribeSnapshot{}).
Cascade().
IfExists().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'tribe_snapshots' table: %w", err)
}
return nil
})
}

View File

@ -1,32 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateTable().
Model(&model.TribeChange{}).
Varchar(defaultVarcharLength).
ForeignKey(`(server_key) REFERENCES servers (key)`).
ForeignKey(`(player_id, server_key) REFERENCES players (id, server_key)`).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'tribe_changes' table: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropTable().
Model(&model.TribeChange{}).
Cascade().
IfExists().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'tribe_changes' table: %w", err)
}
return nil
})
}

View File

@ -1,165 +0,0 @@
package migrations
import (
"context"
"database/sql"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
//nolint:gocyclo
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
err := db.RunInTx(ctx, &sql.TxOptions{}, func(ctx context.Context, tx bun.Tx) error {
columns := [...]struct {
name string
defaultValue int64
}{
{"best_rank", 999999},
{"most_points", 0},
{"most_villages", 0},
}
models := [...]any{
&model.Tribe{},
&model.Player{},
}
for _, c := range columns {
for _, m := range models {
if _, err := tx.NewAddColumn().
Model(m).
ColumnExpr("? bigint default ?", bun.Safe(c.name), c.defaultValue).
IfNotExists().
Exec(ctx); err != nil {
return fmt.Errorf("%T - couldn't add the '%s' column: %w", m, c.name, err)
}
if _, err := tx.NewAddColumn().
Model(m).
ColumnExpr("?_at timestamp with time zone default CURRENT_TIMESTAMP not null", bun.Safe(c.name)).
IfNotExists().
Exec(ctx); err != nil {
return fmt.Errorf("%T - couldn't add the '%s_at' column: %w", m, c.name, err)
}
}
}
if _, err := tx.NewAddColumn().
Model(&model.Player{}).
ColumnExpr("last_activity_at timestamp with time zone default CURRENT_TIMESTAMP not null").
IfNotExists().
Exec(ctx); err != nil {
return fmt.Errorf("player - couldn't add the last_activity_at column: %w", err)
}
return nil
})
if err != nil {
return err
}
var servers []model.Server
if err = db.NewSelect().
Model(&servers).
Where("special = false").
Scan(ctx); err != nil {
return fmt.Errorf("couldn't select servers from the db: %w", err)
}
for _, srv := range servers {
if _, err = db.NewUpdate().
Model(&model.Player{}).
Set("best_rank = rank").
Set("best_rank_at = ?", srv.PlayerDataUpdatedAt).
Set("most_points = points").
Set("most_points_at = ?", srv.PlayerDataUpdatedAt).
Set("most_villages = num_villages").
Set("most_villages_at = ?", srv.PlayerDataUpdatedAt).
Set("last_activity_at = ?", srv.PlayerDataUpdatedAt).
Where("deleted_at IS NULL").
Where("server_key = ?", srv.Key).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't update players (server=%s): %w", srv.Key, err)
}
if _, err = db.NewUpdate().
Model(&model.Tribe{}).
Set("best_rank = rank").
Set("best_rank_at = ?", srv.TribeDataUpdatedAt).
Set("most_points = points").
Set("most_points_at = ?", srv.TribeDataUpdatedAt).
Set("most_villages = num_villages").
Set("most_villages_at = ?", srv.TribeDataUpdatedAt).
Where("deleted_at IS NULL").
Where("server_key = ?", srv.Key).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't update tribes (server=%s): %w", srv.Key, err)
}
}
if _, err = db.NewUpdate().
Model(&model.Player{}).
Set("best_rank = rank").
Set("best_rank_at = deleted_at").
Set("most_points = points").
Set("most_points_at = deleted_at").
Set("most_villages = num_villages").
Set("most_villages_at = deleted_at").
Set("last_activity_at = deleted_at").
Where("deleted_at IS NOT NULL").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't update players: %w", err)
}
if _, err = db.NewUpdate().
Model(&model.Tribe{}).
Set("best_rank = rank").
Set("best_rank_at = deleted_at").
Set("most_points = points").
Set("most_points_at = deleted_at").
Set("most_villages = num_villages").
Set("most_villages_at = deleted_at").
Where("deleted_at IS NOT NULL").
Exec(ctx); err != nil {
return fmt.Errorf("couldn't update tribes: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
return db.RunInTx(ctx, &sql.TxOptions{}, func(ctx context.Context, tx bun.Tx) error {
columns := []string{
"best_rank",
"most_villages",
"most_points",
}
models := [...]any{
&model.Tribe{},
&model.Player{},
}
for _, c := range columns {
for _, m := range models {
for _, col := range [...]string{c, c + "_at"} {
if _, err := tx.NewDropColumn().
Model(m).
Column(col).
Exec(ctx); err != nil {
return fmt.Errorf("%T - couldn't drop the %s column: %w", m, col, err)
}
}
}
}
if _, err := tx.NewDropColumn().
Model(&model.Player{}).
Column("last_activity_at").
Exec(ctx); err != nil {
return fmt.Errorf("player - couldn't add the last_activity_at column: %w", err)
}
return nil
})
})
}

View File

@ -1,109 +0,0 @@
package migrations
import (
"context"
"database/sql"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
//nolint:gocyclo
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
err := db.RunInTx(ctx, &sql.TxOptions{}, func(ctx context.Context, tx bun.Tx) error {
exprs := []string{
"ennoblement_data_updated_at timestamp with time zone",
"num_player_villages bigint default 0",
"num_barbarian_villages bigint default 0",
"num_bonus_villages bigint default 0",
}
for _, expr := range exprs {
if _, err := tx.NewAddColumn().
Model(&model.Server{}).
ColumnExpr(expr).
IfNotExists().
Exec(ctx); err != nil {
return fmt.Errorf(`couldn't add column: '%s': %w`, expr, err)
}
}
return nil
})
if err != nil {
return err
}
var servers []model.Server
if err = db.NewSelect().
Model(&servers).
Where("special = false").
Scan(ctx); err != nil {
return fmt.Errorf("couldn't select servers: %w", err)
}
for _, srv := range servers {
numPlayerVillages, err := db.NewSelect().
Model(&model.Village{}).
Where("server_key = ?", srv.Key).
Where("player_id IS NOT NULL").
Count(ctx)
if err != nil {
return fmt.Errorf("couldn't count player villages: '%s': %w", srv.Key, err)
}
numBarbarianVillages, err := db.NewSelect().
Model(&model.Village{}).
Where("server_key = ?", srv.Key).
Where("player_id IS NULL").
Count(ctx)
if err != nil {
return fmt.Errorf("couldn't count barbarian villages: '%s': %w", srv.Key, err)
}
numBonusVillages, err := db.NewSelect().
Model(&model.Village{}).
Where("server_key = ?", srv.Key).
Where("bonus > 0").
Count(ctx)
if err != nil {
return fmt.Errorf("couldn't count bonus villages: '%s': %w", srv.Key, err)
}
if _, err = db.NewUpdate().
Model(&model.Server{}).
Where("key = ?", srv.Key).
Set("num_player_villages = ?", numPlayerVillages).
Set("num_barbarian_villages = ?", numBarbarianVillages).
Set("num_bonus_villages = ?", numBonusVillages).
Set("ennoblement_data_updated_at = ?", srv.VillageDataUpdatedAt).
Exec(ctx); err != nil {
return fmt.Errorf("couldn't update server: '%s': %w", srv.Key, err)
}
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
return db.RunInTx(ctx, &sql.TxOptions{}, func(ctx context.Context, tx bun.Tx) error {
cols := []string{
"ennoblement_data_updated_at",
"num_player_villages",
"num_barbarian_villages",
"num_bonus_villages",
}
for _, expr := range cols {
if _, err := tx.NewDropColumn().
Model(&model.Server{}).
Column(expr).
Exec(ctx); err != nil {
return fmt.Errorf(`couldn't drop column: '%s': %w`, expr, err)
}
}
return nil
})
})
}

View File

@ -1,54 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateIndex().
Model(&model.TribeChange{}).
Index("tribe_changes_server_key_player_id_idx").
IfNotExists().
Column("server_key", "player_id").
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'tribe_changes_server_key_player_id_idx' index: %w", err)
}
if _, err := db.NewCreateIndex().
Model(&model.TribeChange{}).
Unique().
Index("tribe_changes_hash_key").
ColumnExpr("hash_record_extended((player_id, new_tribe_id, old_tribe_id, server_key, date_trunc('hours', created_at at time zone 'UTC')), 0)").
IfNotExists().
Column().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'tribe_changes_hash_key' index: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
indexes := []string{
"tribe_changes_server_key_player_id_idx",
"tribe_changes_hash_key",
}
for _, idx := range indexes {
if _, err := db.NewDropIndex().
Model(&model.TribeChange{}).
Index(idx).
IfExists().
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the '%s' index: %w", idx, err)
}
}
return nil
})
}

View File

@ -1,58 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
indexes := []struct {
idx string
columns []string
}{
{
idx: "tribe_changes_server_key_new_tribe_id_idx",
columns: []string{"server_key", "new_tribe_id"},
},
{
idx: "tribe_changes_server_key_old_tribe_id_idx",
columns: []string{"server_key", "old_tribe_id"},
},
}
for _, idx := range indexes {
if _, err := db.NewCreateIndex().
Model(&model.TribeChange{}).
Index(idx.idx).
IfNotExists().
Column(idx.columns...).
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the '%s' index: %w", idx.idx, err)
}
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
indexes := []string{
"tribe_changes_server_key_new_tribe_id_idx",
"tribe_changes_server_key_old_tribe_id_idx",
}
for _, idx := range indexes {
if _, err := db.NewDropIndex().
Model(&model.TribeChange{}).
Index(idx).
IfExists().
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the '%s' index: %w", idx, err)
}
}
return nil
})
}

View File

@ -1,73 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
indexes := []struct {
idx string
columns []string
}{
{
idx: "ennoblements_server_key_village_id_idx",
columns: []string{"server_key", "village_id"},
},
{
idx: "ennoblements_server_key_new_owner_id_idx",
columns: []string{"server_key", "new_owner_id"},
},
{
idx: "ennoblements_server_key_old_owner_id_idx",
columns: []string{"server_key", "old_owner_id"},
},
{
idx: "ennoblements_server_key_new_tribe_id_idx",
columns: []string{"server_key", "new_tribe_id"},
},
{
idx: "ennoblements_server_key_old_tribe_id_idx",
columns: []string{"server_key", "old_tribe_id"},
},
}
for _, idx := range indexes {
if _, err := db.NewCreateIndex().
Model(&model.Ennoblement{}).
Index(idx.idx).
IfNotExists().
Column(idx.columns...).
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the '%s' index: %w", idx.idx, err)
}
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
indexes := []string{
"ennoblements_server_key_village_id_idx",
"ennoblements_server_key_new_owner_id_idx",
"ennoblements_server_key_old_owner_id_idx",
"ennoblements_server_key_new_tribe_id_idx",
"ennoblements_server_key_old_tribe_id_idx",
}
for _, idx := range indexes {
if _, err := db.NewDropIndex().
Model(&model.Ennoblement{}).
Index(idx).
IfExists().
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the '%s' index: %w", idx, err)
}
}
return nil
})
}

View File

@ -1,38 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
var servers []model.Server
if err := db.NewSelect().
Model(&servers).
Where("special = false").
Scan(ctx); err != nil {
return fmt.Errorf("couldn't select servers from the db: %w", err)
}
for _, srv := range servers {
if _, err := db.NewUpdate().
Model(&model.Tribe{}).
Where("server_key = ?", srv.Key).
Where("most_points < all_points").
Set("most_points = all_points").
Set("most_points_at = ?", srv.TribeDataUpdatedAt).
Returning("NULL").
Exec(ctx); err != nil {
return fmt.Errorf("%s: couldn't set most p: %w", srv.Key, err)
}
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
return nil
})
}

View File

@ -1,34 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateIndex().
Model(&model.Village{}).
Index("villages_server_key_x_y_idx").
IfNotExists().
Column("server_key", "x", "y").
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'villages_server_key_x_y_idx' index: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropIndex().
Model(&model.Village{}).
Index("villages_server_key_x_y_idx").
IfExists().
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'villages_server_key_x_y_idx' index: %w", err)
}
return nil
})
}

View File

@ -1,34 +0,0 @@
package migrations
import (
"context"
"fmt"
"gitea.dwysokinski.me/twhelp/core/internal/bundb/internal/model"
"github.com/uptrace/bun"
)
func init() {
Migrations.MustRegister(func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewCreateIndex().
Model(&model.Village{}).
Index("villages_server_key_player_id_idx").
IfNotExists().
Column("server_key", "player_id").
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't create the 'villages_server_key_player_id_idx' index: %w", err)
}
return nil
}, func(ctx context.Context, db *bun.DB) error {
if _, err := db.NewDropIndex().
Model(&model.Village{}).
Index("villages_server_key_player_id_idx").
IfExists().
Concurrently().
Exec(ctx); err != nil {
return fmt.Errorf("couldn't drop the 'villages_server_key_player_id_idx' index: %w", err)
}
return nil
})
}

View File

@ -1,16 +0,0 @@
package migrations
import (
"github.com/uptrace/bun"
"github.com/uptrace/bun/migrate"
)
const (
defaultVarcharLength = 200
)
var Migrations = migrate.NewMigrations()
func NewMigrator(db *bun.DB, opts ...migrate.MigratorOption) *migrate.Migrator {
return migrate.NewMigrator(db, Migrations, opts...)
}

View File

@ -184,18 +184,12 @@ spec:
spec:
containers:
- name: twhelp-migrations
image: twhelp
args: ["db", "migrate"]
image: twhelp-migrations
args: ["up"]
env:
- name: APP_MODE
value: development
- name: DB_MAX_OPEN_CONNECTIONS
value: "1"
- name: DB_MAX_IDLE_CONNECTIONS
value: "1"
- name: DB_READ_TIMEOUT
value: "60s"
- name: DB_DSN
- name: GOOSE_DRIVER
value: "postgres"
- name: GOOSE_DBSTRING
valueFrom:
secretKeyRef:
name: twhelp-secret

View File

@ -12,3 +12,6 @@ images:
- name: twhelp
newName: twhelp
newTag: latest
- name: twhelp-migrations
newName: twhelp-migrations
newTag: latest

View File

@ -123,28 +123,3 @@ spec:
secretKeyRef:
name: twhelp-secret
key: amqp-uri
---
apiVersion: batch/v1
kind: Job
metadata:
name: twhelp-migrations-job
spec:
template:
spec:
containers:
- name: twhelp-migrations
image: twhelp
env:
- name: APP_MODE
value: production
- name: DB_MAX_OPEN_CONNECTIONS
value: "1"
- name: DB_MAX_IDLE_CONNECTIONS
value: "1"
- name: DB_READ_TIMEOUT
value: "60s"
- name: DB_DSN
valueFrom:
secretKeyRef:
name: twhelp-secret
key: db-dsn

View File

@ -0,0 +1,35 @@
-- +goose Up
create table if not exists versions
(
code varchar(6) not null
primary key,
name varchar(150) not null,
host varchar(150) not null
unique,
timezone varchar(150) not null
);
insert into versions (code, name, host, timezone)
values ('pl', 'Poland', 'www.plemiona.pl', 'Europe/Warsaw'),
('uk', 'United Kingdom', 'www.tribalwars.co.uk', 'Europe/London'),
('hu', 'Hungary', 'www.klanhaboru.hu', 'Europe/Budapest'),
('it', 'Italy', 'www.tribals.it', 'Europe/Rome'),
('fr', 'France', 'www.guerretribale.fr', 'Europe/Paris'),
('us', 'United States', 'www.tribalwars.us', 'America/New_York'),
('nl', 'The Netherlands', 'www.tribalwars.nl', 'Europe/Amsterdam'),
('es', 'Spain', 'www.guerrastribales.es', 'Europe/Madrid'),
('ro', 'Romania', 'www.triburile.ro', 'Europe/Bucharest'),
('gr', 'Greece', 'www.fyletikesmaxes.gr', 'Europe/Athens'),
('br', 'Brazil', 'www.tribalwars.com.br', 'America/Sao_Paulo'),
('tr', 'Turkey', 'www.klanlar.org', 'Europe/Istanbul'),
('cs', 'Czech Republic', 'www.divokekmeny.cz', 'Europe/Prague'),
('ch', 'Switzerland', 'www.staemme.ch', 'Europe/Zurich'),
('pt', 'Portugal', 'www.tribalwars.com.pt', 'Europe/Lisbon'),
('en', 'International', 'www.tribalwars.net', 'Europe/London'),
('de', 'Germany', 'www.die-staemme.de', 'Europe/Berlin'),
('sk', 'Slovakia', 'www.divoke-kmene.sk', 'Europe/Bratislava'),
('ru', 'Russia', 'www.voynaplemyon.com', 'Europe/Moscow')
ON CONFLICT DO NOTHING;
-- +goose Down
drop table if exists versions CASCADE;

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,39 @@
-- +goose Up
create table if not exists tribes
(
id bigint not null,
server_key varchar(100) not null
references servers,
name varchar(255) not null,
tag varchar(10) not null,
num_members bigint default 0,
num_villages bigint default 0,
points bigint default 0,
all_points bigint default 0,
rank bigint default 0,
dominance double precision default 0,
created_at timestamp with time zone default CURRENT_TIMESTAMP not null,
deleted_at timestamp with time zone,
rank_att bigint default 0,
score_att bigint default 0,
rank_def bigint default 0,
score_def bigint default 0,
rank_sup bigint default 0,
score_sup bigint default 0,
rank_total bigint default 0,
score_total bigint default 0,
profile_url varchar(150),
best_rank bigint default 999999,
best_rank_at timestamp with time zone default CURRENT_TIMESTAMP not null,
most_points bigint default 0,
most_points_at timestamp with time zone default CURRENT_TIMESTAMP not null,
most_villages bigint default 0,
most_villages_at timestamp with time zone default CURRENT_TIMESTAMP not null,
primary key (id, server_key)
);
create index if not exists tribes_server_key_idx
on tribes (server_key);
-- +goose Down
drop table if exists tribes cascade;

View File

@ -0,0 +1,37 @@
-- +goose Up
create table if not exists players
(
id bigint not null,
server_key varchar(100) not null
references servers,
name varchar(150) not null,
num_villages bigint default 0,
points bigint default 0,
rank bigint default 0,
tribe_id bigint,
created_at timestamp with time zone default CURRENT_TIMESTAMP not null,
deleted_at timestamp with time zone,
rank_att bigint default 0,
score_att bigint default 0,
rank_def bigint default 0,
score_def bigint default 0,
rank_sup bigint default 0,
score_sup bigint default 0,
rank_total bigint default 0,
score_total bigint default 0,
profile_url varchar(150),
best_rank bigint default 999999,
best_rank_at timestamp with time zone default CURRENT_TIMESTAMP not null,
most_points bigint default 0,
most_points_at timestamp with time zone default CURRENT_TIMESTAMP not null,
most_villages bigint default 0,
most_villages_at timestamp with time zone default CURRENT_TIMESTAMP not null,
last_activity_at timestamp with time zone default CURRENT_TIMESTAMP not null,
primary key (id, server_key)
);
create index if not exists players_server_key_idx
on players (server_key);
-- +goose Down
drop table if exists players cascade;

View File

@ -0,0 +1,29 @@
-- +goose Up
create table if not exists villages
(
id bigint not null,
server_key varchar(100) not null
references servers,
name varchar(150) not null,
points bigint default 0,
x bigint default 0,
y bigint default 0,
continent varchar(5),
bonus bigint default 0,
player_id bigint,
created_at timestamp with time zone default CURRENT_TIMESTAMP not null,
profile_url varchar(150),
primary key (id, server_key)
);
create index if not exists villages_server_key_idx
on villages (server_key);
create index if not exists villages_server_key_x_y_idx
on villages (server_key, x, y);
create index if not exists villages_server_key_player_id_idx
on villages (server_key, player_id);
-- +goose Down
drop table if exists villages cascade;

View File

@ -0,0 +1,42 @@
-- +goose Up
create table if not exists ennoblements
(
id bigint generated by default as identity
primary key,
server_key varchar(100) not null
references servers,
village_id bigint not null,
new_owner_id bigint,
new_tribe_id bigint,
old_owner_id bigint,
old_tribe_id bigint,
points bigint default 0,
created_at timestamp with time zone default CURRENT_TIMESTAMP not null
);
create unique index if not exists ennoblements_hash_key
on ennoblements (hash_record_extended(
ROW (server_key, village_id, new_owner_id, new_tribe_id, old_owner_id, old_tribe_id, points, created_at),
0::bigint));
create index if not exists ennoblements_server_key_created_at_idx
on ennoblements (server_key, created_at);
create index if not exists ennoblements_server_key_village_id_idx
on ennoblements (server_key, village_id);
create index if not exists ennoblements_server_key_new_owner_id_idx
on ennoblements (server_key, new_owner_id);
create index if not exists ennoblements_server_key_old_owner_id_idx
on ennoblements (server_key, old_owner_id);
create index if not exists ennoblements_server_key_new_tribe_id_idx
on ennoblements (server_key, new_tribe_id);
create index if not exists ennoblements_server_key_old_tribe_id_idx
on ennoblements (server_key, old_tribe_id);
-- +goose Down
drop table if exists ennoblements cascade;

View File

@ -0,0 +1,28 @@
-- +goose Up
create table if not exists player_snapshots
(
id bigint generated by default as identity
primary key,
player_id bigint not null,
num_villages bigint default 0,
points bigint default 0,
rank bigint default 0,
tribe_id bigint,
server_key varchar(100) not null
references servers,
date date not null,
created_at timestamp with time zone default CURRENT_TIMESTAMP not null,
rank_att bigint default 0,
score_att bigint default 0,
rank_def bigint default 0,
score_def bigint default 0,
rank_sup bigint default 0,
score_sup bigint default 0,
rank_total bigint default 0,
score_total bigint default 0,
unique (player_id, server_key, date),
foreign key (player_id, server_key) references players
);
-- +goose Down
drop table if exists player_snapshots cascade;

View File

@ -0,0 +1,30 @@
-- +goose Up
create table if not exists tribe_snapshots
(
id bigint generated by default as identity
primary key,
tribe_id bigint not null,
server_key varchar(100) not null
references servers,
num_members bigint default 0,
num_villages bigint default 0,
points bigint default 0,
all_points bigint default 0,
rank bigint default 0,
dominance double precision default 0,
date date not null,
created_at timestamp with time zone default CURRENT_TIMESTAMP not null,
rank_att bigint default 0,
score_att bigint default 0,
rank_def bigint default 0,
score_def bigint default 0,
rank_sup bigint default 0,
score_sup bigint default 0,
rank_total bigint default 0,
score_total bigint default 0,
unique (tribe_id, server_key, date),
foreign key (tribe_id, server_key) references tribes
);
-- +goose Down
drop table if exists tribe_snapshots cascade;

View File

@ -0,0 +1,30 @@
-- +goose Up
create table if not exists tribe_changes
(
id bigint generated by default as identity
primary key,
player_id bigint not null,
new_tribe_id bigint,
old_tribe_id bigint,
server_key varchar(100) not null
references servers,
created_at timestamp with time zone default CURRENT_TIMESTAMP not null,
foreign key (player_id, server_key) references players
);
create index if not exists tribe_changes_server_key_player_id_idx
on tribe_changes (server_key, player_id);
create unique index if not exists tribe_changes_hash_key
on tribe_changes (hash_record_extended(
ROW (player_id, new_tribe_id, old_tribe_id, server_key, date_trunc('hours'::text, (created_at AT TIME ZONE 'UTC'::text))),
0::bigint));
create index if not exists tribe_changes_server_key_new_tribe_id_idx
on tribe_changes (server_key, new_tribe_id);
create index if not exists tribe_changes_server_key_old_tribe_id_idx
on tribe_changes (server_key, old_tribe_id);
-- +goose Down
drop table if exists tribe_changes cascade;

View File

@ -13,6 +13,10 @@ build:
context: .
docker:
dockerfile: ./build/docker/twhelp/dev/Dockerfile
- image: twhelp-migrations
context: .
docker:
dockerfile: ./build/docker/twhelp-migrations/Dockerfile
manifests:
kustomize:
paths: