Alex Liang

使用 golang-migrate 執行 database migration

前陣子團隊使用golang-migrate對 Cassandra 進行 migration。

覺得順手後,想用它當做 PostgreSQL migration tool。

這篇文章記錄該如何使用 golang-migrate 撰寫 docker-compose 檔案及 github action 的 yaml

docker-compose

假如要在本地端起一台 PG 和執行 migration,使用 docker 會是比較方便的選擇。以下為 docker-compose.yaml 的內容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
version: '3.3'

services:
postgres:
image: postgres:11.9
environment:
POSTGRES_DB: db
POSTGRES_USER: user
POSTGRES_PASSWORD: password
ports:
- 5432:5432
volumes:
- ./scripts:/docker-entrypoint-initdb.d/
migrate:
image: migrate/migrate
command: [ "-path", "/migrations", "-database", "postgresql://user:password@postgres:5432/db?sslmode=disable", "up" ]
volumes:
- ./migrations:/migrations
restart: on-failure
depends_on:
- postgres
  • PG 在初始化後要執行的任務放在 ./scripts 並掛到 docker-entrypoint-initdb.d,例如建 schema
  • 第二個 service migrate/migrate 是本文的主角,其 migration command 可以到官網查詢。
  • 由於 migration 要等 PG 初始化並允許連線才能執行,這裡用 restart: on-failure 不斷的去試,直到連到 DB 為止。

github action

如果在 github 上跑 CI 需要設定 github action。這裡以 node.js + PostgreSQL 為例,說明如何使用 golang-migrate:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
name: Unit Test

on:
push:
branches:
- main
- release
- 'feat/*'
- 'fix/*'
- 'refactor/*'
- 'chore/*'
pull_request:
branches:
- '*'

jobs:
build:
runs-on: ubuntu-latest

env:
POSTGRES_DB: db
POSTGRES_USER: user
POSTGRES_PASSWORD: password

services:
postgres:
image: postgres:11.9
env:
POSTGRES_DB: ${{env.POSTGRES_DB}}
POSTGRES_USER: ${{env.POSTGRES_USER}}
POSTGRES_PASSWORD: ${{env.POSTGRES_PASSWORD}}
ports:
- 5432:5432
volumes:
- /migrations:/migrations

steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Node.js 16.16.0
uses: actions/setup-node@v3
with:
node-version: 16.16.0
cache: 'npm'
- name: Create Schema
run: |
psql postgresql://${{env.POSTGRES_USER}}:${{env.POSTGRES_PASSWORD}}@localhost:5432/${{env.POSTGRES_DB}}?sslmode=disable -c 'CREATE SCHEMA IF NOT EXISTS demo;'
- name: Run migrations
uses: docker://migrate/migrate
with:
args: "-path ./migrations -database postgresql://${{env.POSTGRES_USER}}:${{env.POSTGRES_PASSWORD}}@postgres:5432/${{env.POSTGRES_DB}}?sslmode=disable up"
- name: run test
run: |
npm install
npm run test
  • 在 Create Schema 階段執行 psql 指令
  • 在 Run migrations 階段使用 uses 指定 docker image path,並帶入 migration 指令

以上是 docker-compose 和 github action 使用 golang-migrate 執行 migration 的設定。