feat: added migrations

This commit is contained in:
ITQ
2025-11-13 16:10:28 +03:00
parent c3def9dc26
commit c519941c5a
6 changed files with 170 additions and 2 deletions
+51
View File
@@ -0,0 +1,51 @@
ARG GOARCH=amd64
ARG GOOS=linux
ARG CGO_ENABLED=0
ARG VERSION=1.0.0
ARG BUILD_TIME=unknown
# Stage 1: Build
FROM docker.io/golang:1.24-alpine AS build
ARG GOOS
ARG GOARCH
ARG CGO_ENABLED
ARG VERSION
ARG BUILD_TIME
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=${CGO_ENABLED} \
GOOS=${GOOS} \
GOARCH=${GOARCH} \
go build -trimpath \
-ldflags="-s -w -X 'main.Version=${VERSION}' -X 'main.BuildTime=${BUILD_TIME}'" \
-o /bin/app ./cmd/migrate
# Stage 2: Runtime
FROM docker.io/alpine:3.22 AS runtime
ARG VERSION
ARG BUILD_TIME
RUN addgroup -S app && adduser -S -G app app
WORKDIR /app
COPY --from=build /bin/app /app/bin
RUN chown app:app /app/bin && chmod +x /app/bin
USER app
LABEL org.opencontainers.image.version=${VERSION}
LABEL org.opencontainers.image.created=${BUILD_TIME}
ENTRYPOINT ["/app/bin"]
CMD [""]
+18 -2
View File
@@ -1,9 +1,10 @@
# Go parameters
GOCMD=go
GOBUILD=$(GOCMD) build
GOBUILD=$(GOCMD) build -trimpath -ldflags="-s -w"
GOTEST=$(GOCMD) test
GODOWNLOAD=$(GOCMD) mod download
BINARY_NAME=orderservice
MIGRATE_BINARY_NAME=orderservice-migrate
BINARY_DIR=bin
# Protobuf parameters
@@ -12,7 +13,7 @@ PROTO_DIR=api/proto
PROTO_FILE=$(PROTO_DIR)/order.proto
PROTO_OUT=.
.PHONY: install i generate gen protoc test build run lint fmt format clean help
.PHONY: install i generate gen generate-gw test build run migrate lint fmt format clean help
install:
$(GODOWNLOAD)
@@ -38,9 +39,21 @@ build:
$(GOBUILD) -o ./$(BINARY_DIR)/$(BINARY_NAME) ./cmd/server
chmod +x ./$(BINARY_DIR)/$(BINARY_NAME)
build-migrate:
$(GOBUILD) -o ./$(BINARY_DIR)/$(MIGRATE_BINARY_NAME) ./cmd/migrate
chmod +x ./$(BINARY_DIR)/$(MIGRATE_BINARY_NAME)
run: build
./$(BINARY_DIR)/$(BINARY_NAME)
migrate: build-migrate
@cmd=$(word 2,$(MAKECMDGOALS)); \
if [ -z "$$cmd" ]; then \
echo "Usage: make migrate <command>"; \
exit 1; \
fi; \
./$(BINARY_DIR)/$(MIGRATE_BINARY_NAME) -cmd $$cmd
lint:
golangci-lint run -c .golangci.yaml ./...
@@ -68,3 +81,6 @@ help:
@echo " clean - Clean build artifacts"
.DEFAULT_GOAL := help
%:
@:
+78
View File
@@ -0,0 +1,78 @@
package main
import (
"database/sql"
"embed"
"errors"
"flag"
"log"
"orderservice/internal/config"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/database/postgres"
"github.com/golang-migrate/migrate/v4/source/iofs"
)
//go:embed migrations/*.sql
var migrationsFS embed.FS
func main() {
var cmd string
flag.StringVar(&cmd, "cmd", "up", "migration command: up|down|force|version")
flag.Parse()
cfg, err := config.Load()
if err != nil {
log.Fatalf("failed to load config: %v", err)
}
db, err := sql.Open("postgres", cfg.BuildPostgresDSN())
if err != nil {
log.Fatalf("open db: %v", err)
}
defer db.Close()
drv, err := postgres.WithInstance(db, &postgres.Config{})
if err != nil {
log.Printf("postgres driver: %v", err)
return
}
src, err := iofs.New(migrationsFS, "migrations")
if err != nil {
log.Printf("iofs source: %v", err)
return
}
m, err := migrate.NewWithInstance("iofs", src, "postgres", drv)
if err != nil {
log.Printf("migrate NewWithInstance: %v", err)
return
}
switch cmd {
case "up":
if err := m.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) {
log.Printf("m.Up failed: %v", err)
return
}
log.Println("migrations applied (up)")
case "down":
if err := m.Steps(-1); err != nil {
log.Printf("m.Steps(-1) failed: %v", err)
return
}
log.Println("stepped down 1 migration")
case "version":
v, dirty, verr := m.Version()
if verr != nil {
log.Printf("version: %v", verr)
return
}
log.Printf("version: %d dirty: %v\n", v, dirty)
default:
log.Printf("unknown cmd: %s", cmd)
}
}
@@ -0,0 +1 @@
drop table if exists orders;
+22
View File
@@ -6,6 +6,10 @@ services:
context: .
dockerfile: Containerfile
depends_on:
migrate:
restart: false
condition: service_completed_successfully
required: true
postgres:
restart: false
condition: service_healthy
@@ -35,6 +39,24 @@ services:
- default
restart: unless-stopped
shm_size: 4mb
migrate:
build:
context: .
dockerfile: Containerfile.migrate
depends_on:
postgres:
restart: false
condition: service_healthy
required: true
env_file:
- path: ./infrastructure/core/.env.template
required: true
- path: ./infrastructure/core/.env
networks:
- default
restart: no
shm_size: 4mb
postgres:
image: docker.io/postgres:17-alpine