Skip to content

Commit 84c3308

Browse files
authored
feat(migrate): add database migration functionality (#16)
1 parent 9d202d4 commit 84c3308

File tree

7 files changed

+127
-85
lines changed

7 files changed

+127
-85
lines changed

Dockerfile

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
FROM dwarvesf/sql-migrate as sql-migrate
2-
31
FROM golang:1.23-alpine as builder
42
RUN mkdir /build
53
WORKDIR /build
@@ -18,10 +16,8 @@ RUN apk --no-cache add ca-certificates
1816
RUN ln -fs /usr/share/zoneinfo/Asia/Ho_Chi_Minh /etc/localtime
1917
WORKDIR /
2018

21-
COPY --from=sql-migrate /usr/local/bin/sql-migrate /usr/bin/
2219
COPY --from=builder /go/bin/* /usr/bin/
20+
COPY migrations /migrations
2321
COPY docs /docs
24-
# COPY migrations /migrations
25-
# COPY dbconfig.yml /
2622

27-
ENTRYPOINT [ "server" ]
23+
CMD [ "server" ]

cmd/migrate/main.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
8+
"github.com/golang-migrate/migrate/v4"
9+
"github.com/golang-migrate/migrate/v4/database/postgres"
10+
_ "github.com/golang-migrate/migrate/v4/source/file"
11+
"gorm.io/gorm"
12+
13+
pgstore "github.com/dwarvesf/icy-backend/internal/store/postgres"
14+
"github.com/dwarvesf/icy-backend/internal/utils/config"
15+
"github.com/dwarvesf/icy-backend/internal/utils/logger"
16+
)
17+
18+
func runMigrations(db *gorm.DB, logger *logger.Logger) error {
19+
// Open database connection
20+
sqlDB, err := db.DB()
21+
if err != nil {
22+
return fmt.Errorf("failed to get database connection: %w", err)
23+
}
24+
25+
// Create migrate instance
26+
migrationPath := fmt.Sprintf("file://%s", filepath.Join("migrations", "schema"))
27+
driver, err := postgres.WithInstance(sqlDB, &postgres.Config{})
28+
if err != nil {
29+
return fmt.Errorf("failed to create postgres driver: %w", err)
30+
}
31+
32+
m, err := migrate.NewWithDatabaseInstance(
33+
migrationPath,
34+
"postgres", driver)
35+
if err != nil {
36+
return fmt.Errorf("failed to create migrate instance: %w", err)
37+
}
38+
39+
// Run migrations
40+
if err := m.Up(); err != nil && err != migrate.ErrNoChange {
41+
return fmt.Errorf("migration failed: %w", err)
42+
}
43+
44+
logger.Info("Migrations completed successfully")
45+
return nil
46+
}
47+
48+
func main() {
49+
appConfig := config.New()
50+
logger := logger.New(appConfig.Environment)
51+
52+
db := pgstore.New(appConfig, logger)
53+
54+
if err := runMigrations(db, logger); err != nil {
55+
logger.Error("[main][runMigrations] failed to run migrations", map[string]string{
56+
"error": err.Error(),
57+
})
58+
os.Exit(1)
59+
}
60+
}

docs/deploy.md

+7-20
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,20 @@
1818

1919
## Deployment Steps
2020

21-
### 1. Initialize Fly.io Configuration
21+
### 1. Configure Secrets
22+
Create a `.env.prod` file with your application's environment variables. Then import them:
23+
```bash
24+
flyctl secrets import < .env.prod
25+
```
26+
27+
### 2. Initialize Fly.io Configuration
2228
```bash
2329
flyctl launch --ha=false
2430
```
2531
- This command will detect your Dockerfile and create a `fly.toml` configuration file
2632
- Choose a name for your application
2733
- Select the region closest to your primary users
2834

29-
### 2. Configure Secrets
30-
Create a `.env.prod` file with your application's environment variables. Then import them:
31-
```bash
32-
flyctl secrets import < .env.prod
33-
```
34-
3535
### 3. Set Required Environment Variables
3636
Ensure all necessary environment variables are set:
3737
```bash
@@ -53,19 +53,6 @@ flyctl status
5353
flyctl open # Opens the deployed application in your browser
5454
```
5555

56-
### 6. Run Database Migrations
57-
To run database migrations, use the following command:
58-
```bash
59-
export $(grep -v '^#' .env.prod | xargs) \
60-
&& migrate -path ./migrations/schema \
61-
-database "postgres://${DB_USER}:${DB_PASS}@${DB_HOST}:${DB_PORT}/${DB_NAME}?sslmode=${DB_SSL_MODE}" \
62-
up
63-
```
64-
Notes:
65-
- Ensure `.env.prod` contains all necessary database connection variables
66-
- The `migrate` command applies all pending schema migrations
67-
- Run this command after initial deployment or when new migrations are added
68-
6956
## Additional Fly.io Commands
7057

7158
- Scale your app:

fly.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# fly.toml app configuration file generated for icy-backend-dev on 2025-02-13T10:52:05+07:00
1+
# fly.toml app configuration file generated for icy-backend on 2025-02-13T19:55:30+07:00
22
#
33
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
44
#
@@ -8,6 +8,9 @@ primary_region = 'sin'
88

99
[build]
1010

11+
[deploy]
12+
release_command = 'migrate'
13+
1114
[http_service]
1215
internal_port = 8080
1316
force_https = true

go.mod

+6-21
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ require (
88
github.com/gin-contrib/cors v1.7.2
99
github.com/gin-gonic/gin v1.10.0
1010
github.com/go-playground/validator/v10 v10.22.1
11+
github.com/golang-migrate/migrate/v4 v4.18.2
1112
github.com/joho/godotenv v1.5.1
1213
github.com/onsi/ginkgo/v2 v2.21.0
1314
github.com/onsi/gomega v1.35.1
@@ -37,11 +38,9 @@ require (
3738
github.com/PuerkitoBio/purell v1.1.1 // indirect
3839
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
3940
github.com/StackExchange/wmi v1.2.1 // indirect
40-
github.com/VictoriaMetrics/fastcache v1.12.2 // indirect
4141
github.com/bits-and-blooms/bitset v1.20.0 // indirect
4242
github.com/bytedance/sonic v1.12.4 // indirect
4343
github.com/bytedance/sonic/loader v0.2.1 // indirect
44-
github.com/cespare/xxhash/v2 v2.3.0 // indirect
4544
github.com/cloudwego/base64x v0.1.4 // indirect
4645
github.com/cloudwego/iasm v0.2.0 // indirect
4746
github.com/consensys/bavard v0.1.29 // indirect
@@ -54,7 +53,6 @@ require (
5453
github.com/ethereum/go-verkle v0.2.2 // indirect
5554
github.com/fsnotify/fsnotify v1.6.0 // indirect
5655
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
57-
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
5856
github.com/gin-contrib/sse v0.1.0 // indirect
5957
github.com/go-logr/logr v1.4.2 // indirect
6058
github.com/go-ole/go-ole v1.3.0 // indirect
@@ -66,51 +64,38 @@ require (
6664
github.com/go-playground/universal-translator v0.18.1 // indirect
6765
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
6866
github.com/goccy/go-json v0.10.3 // indirect
69-
github.com/gofrs/flock v0.8.1 // indirect
70-
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
7167
github.com/google/go-cmp v0.6.0 // indirect
7268
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
73-
github.com/google/uuid v1.3.0 // indirect
69+
github.com/google/uuid v1.6.0 // indirect
7470
github.com/gorilla/websocket v1.5.0 // indirect
75-
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
71+
github.com/hashicorp/errwrap v1.1.0 // indirect
72+
github.com/hashicorp/go-multierror v1.1.1 // indirect
7673
github.com/holiman/uint256 v1.3.2 // indirect
77-
github.com/huin/goupnp v1.3.0 // indirect
7874
github.com/jackc/pgpassfile v1.0.0 // indirect
7975
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
8076
github.com/jackc/pgx/v5 v5.5.5 // indirect
8177
github.com/jackc/puddle/v2 v2.2.1 // indirect
82-
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
8378
github.com/jinzhu/inflection v1.0.0 // indirect
8479
github.com/jinzhu/now v1.1.5 // indirect
8580
github.com/josharian/intern v1.0.0 // indirect
8681
github.com/json-iterator/go v1.1.12 // indirect
87-
github.com/karalabe/hid v1.0.1-0.20240306101548-573246063e52 // indirect
8882
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
8983
github.com/leodido/go-urn v1.4.0 // indirect
84+
github.com/lib/pq v1.10.9 // indirect
9085
github.com/mailru/easyjson v0.7.6 // indirect
9186
github.com/mattn/go-isatty v0.0.20 // indirect
92-
github.com/mattn/go-runewidth v0.0.13 // indirect
9387
github.com/mmcloughlin/addchain v0.4.0 // indirect
9488
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
9589
github.com/modern-go/reflect2 v1.0.2 // indirect
96-
github.com/olekukonko/tablewriter v0.0.5 // indirect
9790
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
98-
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 // indirect
99-
github.com/pion/dtls/v2 v2.2.7 // indirect
100-
github.com/pion/logging v0.2.2 // indirect
101-
github.com/pion/stun/v2 v2.0.0 // indirect
102-
github.com/pion/transport/v2 v2.2.1 // indirect
103-
github.com/pion/transport/v3 v3.0.1 // indirect
10491
github.com/pmezard/go-difflib v1.0.0 // indirect
105-
github.com/rivo/uniseg v0.2.0 // indirect
10692
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
107-
github.com/status-im/keycard-go v0.2.0 // indirect
10893
github.com/supranational/blst v0.3.13 // indirect
109-
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
11094
github.com/tklauser/go-sysconf v0.3.12 // indirect
11195
github.com/tklauser/numcpus v0.6.1 // indirect
11296
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
11397
github.com/ugorji/go/codec v1.2.12 // indirect
98+
go.uber.org/atomic v1.11.0 // indirect
11499
go.uber.org/multierr v1.10.0 // indirect
115100
golang.org/x/arch v0.12.0 // indirect
116101
golang.org/x/crypto v0.33.0 // indirect

0 commit comments

Comments
 (0)