From cd00b1970a81d730aaf2a7aa77d5ff667ead7693 Mon Sep 17 00:00:00 2001 From: Ragot Geoffrey Date: Wed, 4 Sep 2024 17:56:16 +0200 Subject: [PATCH] fix: migration collection (#1677) --- components/ledger/go.mod | 2 +- components/ledger/go.sum | 4 +- .../internal/storage/ledgerstore/bucket.go | 2 +- components/payments/go.mod | 2 +- components/payments/go.sum | 4 +- ee/auth/go.mod | 1 + ee/auth/go.sum | 2 + ee/gateway/go.mod | 2 +- ee/gateway/go.sum | 4 +- ee/orchestration/go.mod | 2 +- ee/orchestration/go.sum | 4 +- ee/reconciliation/go.mod | 1 + ee/reconciliation/go.sum | 2 + ee/webhooks/go.mod | 1 + ee/webhooks/go.sum | 2 + go.mod | 6 -- go.sum | 10 --- libs/go-libs/Earthfile | 11 +++ libs/go-libs/go.mod | 1 + libs/go-libs/go.sum | 2 + libs/go-libs/migrations/collect.go | 44 ++++++++++-- libs/go-libs/migrations/collect_generated.go | 70 +++++++++++++++++++ libs/go-libs/migrations/collect_test.go | 70 +++++++++++++++++++ tests/integration/go.mod | 2 +- tests/integration/go.sum | 4 +- 25 files changed, 216 insertions(+), 39 deletions(-) create mode 100644 libs/go-libs/migrations/collect_generated.go create mode 100644 libs/go-libs/migrations/collect_test.go diff --git a/components/ledger/go.mod b/components/ledger/go.mod index bac4c57ba9..a0e1ba8e6d 100644 --- a/components/ledger/go.mod +++ b/components/ledger/go.mod @@ -30,7 +30,7 @@ require ( go.opentelemetry.io/otel/metric v1.28.0 go.opentelemetry.io/otel/trace v1.28.0 go.uber.org/fx v1.22.2 - go.uber.org/mock v0.3.0 + go.uber.org/mock v0.4.0 ) require ( diff --git a/components/ledger/go.sum b/components/ledger/go.sum index b1dc2206de..330399e82f 100644 --- a/components/ledger/go.sum +++ b/components/ledger/go.sum @@ -361,8 +361,8 @@ go.uber.org/fx v1.22.2 h1:iPW+OPxv0G8w75OemJ1RAnTUrF55zOJlXlo1TbJ0Buw= go.uber.org/fx v1.22.2/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= -go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= diff --git a/components/ledger/internal/storage/ledgerstore/bucket.go b/components/ledger/internal/storage/ledgerstore/bucket.go index 51a702e15f..86450da017 100644 --- a/components/ledger/internal/storage/ledgerstore/bucket.go +++ b/components/ledger/internal/storage/ledgerstore/bucket.go @@ -78,7 +78,7 @@ func (b *Bucket) IsInitialized(ctx context.Context) (bool, error) { } func registerMigrations(migrator *migrations.Migrator, name string) { - ret, err := migrations.CollectMigrationFiles(migrationsDir) + ret, err := migrations.CollectMigrationFiles(migrationsDir, "migrations") if err != nil { panic(err) } diff --git a/components/payments/go.mod b/components/payments/go.mod index e0158a178f..b11b97b908 100644 --- a/components/payments/go.mod +++ b/components/payments/go.mod @@ -39,7 +39,7 @@ require ( go.opentelemetry.io/otel/trace v1.28.0 go.uber.org/dig v1.18.0 go.uber.org/fx v1.22.2 - go.uber.org/mock v0.3.0 + go.uber.org/mock v0.4.0 golang.org/x/oauth2 v0.20.0 golang.org/x/sync v0.8.0 ) diff --git a/components/payments/go.sum b/components/payments/go.sum index 04eb430199..50d93f89d6 100644 --- a/components/payments/go.sum +++ b/components/payments/go.sum @@ -1270,8 +1270,8 @@ go.uber.org/fx v1.22.2 h1:iPW+OPxv0G8w75OemJ1RAnTUrF55zOJlXlo1TbJ0Buw= go.uber.org/fx v1.22.2/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= -go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= diff --git a/ee/auth/go.mod b/ee/auth/go.mod index b7d32b7115..f7520743a5 100644 --- a/ee/auth/go.mod +++ b/ee/auth/go.mod @@ -120,6 +120,7 @@ require ( go.opentelemetry.io/otel/sdk v1.28.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/dig v1.18.0 // indirect + go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.26.0 // indirect diff --git a/ee/auth/go.sum b/ee/auth/go.sum index 62c35f8ef7..0f6aaf7ee9 100644 --- a/ee/auth/go.sum +++ b/ee/auth/go.sum @@ -264,6 +264,8 @@ go.uber.org/fx v1.22.2 h1:iPW+OPxv0G8w75OemJ1RAnTUrF55zOJlXlo1TbJ0Buw= go.uber.org/fx v1.22.2/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= diff --git a/ee/gateway/go.mod b/ee/gateway/go.mod index 0ba57ec1b5..212de42fe1 100644 --- a/ee/gateway/go.mod +++ b/ee/gateway/go.mod @@ -94,7 +94,7 @@ require ( go.opentelemetry.io/contrib/propagators/ot v1.17.0 // indirect go.uber.org/dig v1.18.0 // indirect go.uber.org/fx v1.22.2 // indirect - go.uber.org/mock v0.3.0 // indirect + go.uber.org/mock v0.4.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect google.golang.org/api v0.171.0 // indirect google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect diff --git a/ee/gateway/go.sum b/ee/gateway/go.sum index ffc2def964..657f854f35 100644 --- a/ee/gateway/go.sum +++ b/ee/gateway/go.sum @@ -665,8 +665,8 @@ go.uber.org/fx v1.22.2 h1:iPW+OPxv0G8w75OemJ1RAnTUrF55zOJlXlo1TbJ0Buw= go.uber.org/fx v1.22.2/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= -go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= diff --git a/ee/orchestration/go.mod b/ee/orchestration/go.mod index b807977735..2d6ae3c1d8 100644 --- a/ee/orchestration/go.mod +++ b/ee/orchestration/go.mod @@ -24,7 +24,7 @@ require ( go.temporal.io/sdk v1.21.1 go.temporal.io/sdk/contrib/opentelemetry v0.2.0 go.uber.org/fx v1.22.2 - go.uber.org/mock v0.3.0 + go.uber.org/mock v0.4.0 golang.org/x/oauth2 v0.20.0 gopkg.in/yaml.v3 v3.0.1 ) diff --git a/ee/orchestration/go.sum b/ee/orchestration/go.sum index 6c29b4fe3d..e90c500e0f 100644 --- a/ee/orchestration/go.sum +++ b/ee/orchestration/go.sum @@ -956,8 +956,8 @@ go.uber.org/fx v1.22.2 h1:iPW+OPxv0G8w75OemJ1RAnTUrF55zOJlXlo1TbJ0Buw= go.uber.org/fx v1.22.2/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= -go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= diff --git a/ee/reconciliation/go.mod b/ee/reconciliation/go.mod index f29093ec96..b707eae01e 100644 --- a/ee/reconciliation/go.mod +++ b/ee/reconciliation/go.mod @@ -114,6 +114,7 @@ require ( go.opentelemetry.io/otel/trace v1.28.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/dig v1.18.0 // indirect + go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.26.0 // indirect diff --git a/ee/reconciliation/go.sum b/ee/reconciliation/go.sum index 8b898de02e..8ba3faab93 100644 --- a/ee/reconciliation/go.sum +++ b/ee/reconciliation/go.sum @@ -295,6 +295,8 @@ go.uber.org/fx v1.22.2 h1:iPW+OPxv0G8w75OemJ1RAnTUrF55zOJlXlo1TbJ0Buw= go.uber.org/fx v1.22.2/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= diff --git a/ee/webhooks/go.mod b/ee/webhooks/go.mod index dd38e03ec7..72b3300509 100644 --- a/ee/webhooks/go.mod +++ b/ee/webhooks/go.mod @@ -143,6 +143,7 @@ require ( go.opentelemetry.io/otel/sdk v1.28.0 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/dig v1.18.0 // indirect + go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.26.0 // indirect diff --git a/ee/webhooks/go.sum b/ee/webhooks/go.sum index a7f672ef5a..5d4b252303 100644 --- a/ee/webhooks/go.sum +++ b/ee/webhooks/go.sum @@ -339,6 +339,8 @@ go.uber.org/fx v1.22.2 h1:iPW+OPxv0G8w75OemJ1RAnTUrF55zOJlXlo1TbJ0Buw= go.uber.org/fx v1.22.2/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= diff --git a/go.mod b/go.mod index e67647a766..d92c7622ac 100644 --- a/go.mod +++ b/go.mod @@ -1,9 +1,3 @@ module github.com/formancehq/stack go 1.20 - -require ( - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/spf13/cobra v1.8.1 // indirect - github.com/spf13/pflag v1.0.5 // indirect -) diff --git a/go.sum b/go.sum index 912390a789..e69de29bb2 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +0,0 @@ -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/libs/go-libs/Earthfile b/libs/go-libs/Earthfile index 9dd14ebe41..70f2fcf3e8 100644 --- a/libs/go-libs/Earthfile +++ b/libs/go-libs/Earthfile @@ -25,6 +25,17 @@ lint: DO --pass-args stack+GO_LINT SAVE ARTIFACT * AS LOCAL ./ +generate: + FROM core+builder-image + RUN apk update && apk add openjdk11 + DO --pass-args core+GO_INSTALL --package=go.uber.org/mock/mockgen@latest + COPY (+sources/*) /src + WORKDIR /src + DO --pass-args core+GO_GENERATE + FOR dir IN $(ls -d */) + SAVE ARTIFACT $dir AS LOCAL ./ + END + pre-commit: WAIT BUILD --pass-args +tidy diff --git a/libs/go-libs/go.mod b/libs/go-libs/go.mod index 71d9d19887..966a5d7607 100644 --- a/libs/go-libs/go.mod +++ b/libs/go-libs/go.mod @@ -62,6 +62,7 @@ require ( go.opentelemetry.io/otel/sdk/metric v1.28.0 go.opentelemetry.io/otel/trace v1.28.0 go.uber.org/fx v1.22.2 + go.uber.org/mock v0.4.0 go.uber.org/zap v1.27.0 ) diff --git a/libs/go-libs/go.sum b/libs/go-libs/go.sum index 68c168899f..675d2eda44 100644 --- a/libs/go-libs/go.sum +++ b/libs/go-libs/go.sum @@ -417,6 +417,8 @@ go.uber.org/fx v1.22.2 h1:iPW+OPxv0G8w75OemJ1RAnTUrF55zOJlXlo1TbJ0Buw= go.uber.org/fx v1.22.2/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= diff --git a/libs/go-libs/migrations/collect.go b/libs/go-libs/migrations/collect.go index f04de51fb6..259ea6e471 100644 --- a/libs/go-libs/migrations/collect.go +++ b/libs/go-libs/migrations/collect.go @@ -2,28 +2,58 @@ package migrations import ( "context" - "embed" + "io/fs" "path/filepath" + "slices" + "strconv" + "strings" "github.com/pkg/errors" "github.com/uptrace/bun" ) -func CollectMigrationFiles(fs embed.FS) ([]Migration, error) { - entries, err := fs.ReadDir("migrations") +//go:generate mockgen -source collect.go -destination collect_generated.go -package migrations . MigrationFileSystem +type MigrationFileSystem interface { + ReadDir(dir string) ([]fs.DirEntry, error) + ReadFile(filename string) ([]byte, error) +} + +func CollectMigrationFiles(fs MigrationFileSystem, rootDir string) ([]Migration, error) { + entries, err := fs.ReadDir(rootDir) if err != nil { return nil, errors.Wrap(err, "collecting migration files") } - ret := make([]Migration, len(entries)) + filenames := make([]string, len(entries)) for i, entry := range entries { - fileContent, err := fs.ReadFile(filepath.Join("migrations", entry.Name())) + filenames[i] = entry.Name() + } + + slices.SortFunc(filenames, func(a, b string) int { + fileAVersionAsString := strings.SplitN(a, "-", 2)[0] + fileAVersion, err := strconv.ParseInt(fileAVersionAsString, 10, 64) + if err != nil { + panic(err) + } + + fileBVersionAsString := strings.SplitN(b, "-", 2)[0] + fileBVersion, err := strconv.ParseInt(fileBVersionAsString, 10, 64) + if err != nil { + panic(err) + } + + return int(fileAVersion - fileBVersion) + }) + + ret := make([]Migration, len(entries)) + for i, entry := range filenames { + fileContent, err := fs.ReadFile(filepath.Join(rootDir, entry)) if err != nil { - return nil, errors.Wrapf(err, "reading migration file %s", entry.Name()) + return nil, errors.Wrapf(err, "reading migration file %s", entry) } ret[i] = Migration{ - Name: entry.Name(), + Name: entry, UpWithContext: func(ctx context.Context, tx bun.Tx) error { _, err := tx.ExecContext(ctx, string(fileContent)) return err diff --git a/libs/go-libs/migrations/collect_generated.go b/libs/go-libs/migrations/collect_generated.go new file mode 100644 index 0000000000..5713f3123d --- /dev/null +++ b/libs/go-libs/migrations/collect_generated.go @@ -0,0 +1,70 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: collect.go +// +// Generated by this command: +// +// mockgen -source collect.go -destination collect_generated.go -package migrations . MigrationFileSystem +// + +// Package migrations is a generated GoMock package. +package migrations + +import ( + fs "io/fs" + reflect "reflect" + + gomock "go.uber.org/mock/gomock" +) + +// MockMigrationFileSystem is a mock of MigrationFileSystem interface. +type MockMigrationFileSystem struct { + ctrl *gomock.Controller + recorder *MockMigrationFileSystemMockRecorder +} + +// MockMigrationFileSystemMockRecorder is the mock recorder for MockMigrationFileSystem. +type MockMigrationFileSystemMockRecorder struct { + mock *MockMigrationFileSystem +} + +// NewMockMigrationFileSystem creates a new mock instance. +func NewMockMigrationFileSystem(ctrl *gomock.Controller) *MockMigrationFileSystem { + mock := &MockMigrationFileSystem{ctrl: ctrl} + mock.recorder = &MockMigrationFileSystemMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockMigrationFileSystem) EXPECT() *MockMigrationFileSystemMockRecorder { + return m.recorder +} + +// ReadDir mocks base method. +func (m *MockMigrationFileSystem) ReadDir(dir string) ([]fs.DirEntry, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadDir", dir) + ret0, _ := ret[0].([]fs.DirEntry) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadDir indicates an expected call of ReadDir. +func (mr *MockMigrationFileSystemMockRecorder) ReadDir(dir any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadDir", reflect.TypeOf((*MockMigrationFileSystem)(nil).ReadDir), dir) +} + +// ReadFile mocks base method. +func (m *MockMigrationFileSystem) ReadFile(filename string) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ReadFile", filename) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ReadFile indicates an expected call of ReadFile. +func (mr *MockMigrationFileSystemMockRecorder) ReadFile(filename any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReadFile", reflect.TypeOf((*MockMigrationFileSystem)(nil).ReadFile), filename) +} diff --git a/libs/go-libs/migrations/collect_test.go b/libs/go-libs/migrations/collect_test.go new file mode 100644 index 0000000000..91ce625ac5 --- /dev/null +++ b/libs/go-libs/migrations/collect_test.go @@ -0,0 +1,70 @@ +package migrations + +import ( + "fmt" + "io/fs" + "math/rand" + "path/filepath" + "testing" + + "github.com/formancehq/stack/libs/go-libs/collectionutils" + "github.com/stretchr/testify/require" + "go.uber.org/mock/gomock" +) + +func TestCollect(t *testing.T) { + t.Parallel() + + ctrl := gomock.NewController(t) + migrationsFS := NewMockMigrationFileSystem(ctrl) + + const numberOfFiles = 100 + + sortedFiles := make([]string, 0) + for i := 0; i < numberOfFiles; i++ { + filename := fmt.Sprintf("%d-migrate.sql", i) + sortedFiles = append(sortedFiles, filename) + + migrationsFS.EXPECT().ReadFile(filepath.Join("migrations", filename)).Return([]byte(""), nil) + } + + migrationsFS.EXPECT(). + ReadDir("migrations"). + Return(collectionutils.Map(sortedFiles, func(from string) fs.DirEntry { + return mockDirEntry(from) + }), nil) + + // shuffle migration names to ensure the collector sort them + shuffledFiles := make([]string, numberOfFiles) + copy(shuffledFiles, sortedFiles) + rand.Shuffle(len(sortedFiles), func(i, j int) { + shuffledFiles[i], shuffledFiles[j] = shuffledFiles[j], shuffledFiles[i] + }) + + migrations, err := CollectMigrationFiles(migrationsFS, "migrations") + require.NoError(t, err) + + require.Equal(t, sortedFiles, collectionutils.Map(migrations, func(from Migration) string { + return from.Name + })) +} + +type mockDirEntry string + +func (m mockDirEntry) Name() string { + return string(m) +} + +func (m mockDirEntry) IsDir() bool { + return false +} + +func (m mockDirEntry) Type() fs.FileMode { + return 0 +} + +func (m mockDirEntry) Info() (fs.FileInfo, error) { + return nil, nil +} + +var _ fs.DirEntry = (*mockDirEntry)(nil) diff --git a/tests/integration/go.mod b/tests/integration/go.mod index 5a89df1818..7840ec005f 100644 --- a/tests/integration/go.mod +++ b/tests/integration/go.mod @@ -255,7 +255,7 @@ require ( go.uber.org/atomic v1.10.0 // indirect go.uber.org/dig v1.18.0 // indirect go.uber.org/fx v1.22.2 // indirect - go.uber.org/mock v0.3.0 // indirect + go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.26.0 // indirect diff --git a/tests/integration/go.sum b/tests/integration/go.sum index 65e22f1949..a156aa7489 100644 --- a/tests/integration/go.sum +++ b/tests/integration/go.sum @@ -1442,8 +1442,8 @@ go.uber.org/fx v1.22.2 h1:iPW+OPxv0G8w75OemJ1RAnTUrF55zOJlXlo1TbJ0Buw= go.uber.org/fx v1.22.2/go.mod h1:o/D9n+2mLP6v1EG+qsdT1O8wKopYAsqZasju97SDFCU= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= -go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= +go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= +go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=