744dc806ffc2cf3998692a0e41a1d0a14415cf8e
- Author
- TheEdgeOfRage <git@theedgeofrage.com>
- Committer
- TheEdgeOfRage <git@theedgeofrage.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
2index acc2ab1716cfe82f9b0173e363cc61fc89237133..1f07be58c7ba79f1602b3c44efa27c9ecd5b7cca 100644
3--- a/.github/workflows/ci.yaml
4+++ b/.github/workflows/ci.yaml
5@@ -64,14 +64,5 @@ jobs:
6 push: true
7 tags: theedgeofrage/ytrssil:api
8 target: api
9- cache-from: type=gha,scope=api
10- cache-to: type=gha,scope=api,mode=max
11-
12- - name: Build and push migrations image
13- uses: docker/build-push-action@v7
14- with:
15- push: true
16- tags: theedgeofrage/ytrssil:migrations
17- target: migrations
18- cache-from: type=gha,scope=migrations
19- cache-to: type=gha,scope=migrations,mode=max
20+ cache-from: type=gha
21+ cache-to: type=gha,mode=max
22diff --git a/AGENTS.md b/AGENTS.md
23index b024fb202974a0ca0898165a20f284cedb780fc7..e52273a1420dfdae0df0c568258a676afaa206a3 100644
24--- a/AGENTS.md
25+++ b/AGENTS.md
26@@ -13,7 +13,7 @@
27
28 - **HTTP**: Gin router with dual interfaces (HTML pages + JSON API), authentication middleware, Datastar SSE-driven templates
29 - **Handler**: Business logic layer orchestrating channels, videos, downloads, and cleanup routines
30-- **Database**: PostgreSQL with pgx connection pooling, 7 migrations tracking schema evolution
31+- **Database**: PostgreSQL with pgx connection pooling, embedded migrations run at startup via golang-migrate
32 - **External**: YouTube API client, RSS feed parser, yt-dlp downloader wrapper
33
34 **Key Features**: Subscribe to YouTube channels via RSS, track watched/unwatched videos with progress, async video downloads with status polling, automatic file cleanup (2 days after watched), YouTube Shorts detection
35@@ -44,6 +44,6 @@ All Go tooling is managed via `make` targets. Never run `go` commands directly.
36 - `make test` — runs `go test -timeout=30s -race ./...`
37 - `make templ` — generates Go code from `.templ` files via `templ generate`. Required before build.
38 - `make gen-mocks` — regenerates mock files in `mocks/` using moq. Run after changing interfaces in `db/`, `feedparser/`, or `lib/clients/youtube/`.
39-- `make migrate` — applies PostgreSQL migrations from `migrations/` dir. Configurable via `DB_URI` env var (default: `postgres://ytrssil:ytrssil@localhost:5432/ytrssil?sslmode=disable`)
40diff --git a/Dockerfile b/Dockerfile
41index 676ba6f6a86234b7b1cb579d094c04acb8384cfc..6c8b808c4ede8e1cb750624bee09b3db55242d0a 100644
42--- a/Dockerfile
43+++ b/Dockerfile
44@@ -26,6 +26,3 @@ COPY ./assets/ ./assets/
45 RUN assets/load.sh && rm assets/load.sh;
46
47 COPY --from=builder /app/dist/ ./
48-
49-FROM migrate/migrate:4 AS migrations
50-COPY ./migrations/ /migrations/
51diff --git a/Makefile b/Makefile
52index fbe57c00e75b42244bfbbcef3a4bbbe730b606d4..195062957fa8cf7ffccadb1c9ae4f9c5d3aa9038 100644
53--- a/Makefile
54+++ b/Makefile
55@@ -48,4 +48,3 @@ migrate: bin/migrate
56
57 image-build:
58 docker buildx build --push -t theedgeofrage/ytrssil:api --target api .
59- docker buildx build --push -t theedgeofrage/ytrssil:migrations --target migrations .
60diff --git a/cmd/main.go b/cmd/main.go
61index ed201362e6d11d0408775531d83d9306025da6a3..3abe536474a367d3a50c57ba710047dd17302b62 100644
62--- a/cmd/main.go
63+++ b/cmd/main.go
64@@ -52,6 +52,11 @@ func main() {
65 return
66 }
67
68+ if err := db.RunMigrations(cfg.DBURI); err != nil {
69+ logger.Error("Failed to run migrations", "error", err)
70+ return
71+ }
72+
73 db, err := db.NewPostgresDB(logger, cfg.DBURI)
74 if err != nil {
75 logger.Error(
76diff --git a/compose.yaml b/compose.yaml
77index 12ef6cdf4a85f99d32fe4c51027ae780273dc307..2eaf10c2eb060ae5671631057f73d878f8c92349 100644
78--- a/compose.yaml
79+++ b/compose.yaml
80@@ -31,17 +31,6 @@ services:
81 volumes:
82 - data:/var/lib/ytrssil
83
84- migrations:
85- image: theedgeofrage/ytrssil:migrations
86- restart: unless-stopped
87- depends_on:
88- - postgres
89- command:
90- - "-path=/migrations/"
91- - "-database"
92- - "postgresql://ytrssil:ytrssil@postgres/ytrssil?sslmode=disable"
93- - "up"
94-
95 volumes:
96 postgres:
97 data:
98diff --git a/db/migrate.go b/db/migrate.go
99new file mode 100644
100index 0000000000000000000000000000000000000000..32b18a8584e57cf0619948a4e38dc278aa331257
101--- /dev/null
102+++ b/db/migrate.go
103@@ -0,0 +1,26 @@
104+package db
105+
106+import (
107+ "github.com/golang-migrate/migrate/v4"
108+ _ "github.com/golang-migrate/migrate/v4/database/postgres"
109+ "github.com/golang-migrate/migrate/v4/source/iofs"
110+
111+ "github.com/TheEdgeOfRage/ytrssil-api/migrations"
112+)
113+
114+func RunMigrations(databaseURL string) error {
115+ source, err := iofs.New(migrations.FS, ".")
116+ if err != nil {
117+ return err
118+ }
119+
120+ m, err := migrate.NewWithSourceInstance("iofs", source, databaseURL)
121+ if err != nil {
122+ return err
123+ }
124+
125+ if err := m.Up(); err != nil && err != migrate.ErrNoChange {
126+ return err
127+ }
128+ return nil
129+}
130diff --git a/go.mod b/go.mod
131index 92e6b390416b0644de5ceda90c2fcc774f445448..0660eaa83f73497dcdf3a52670201e3bbba0d0fe 100644
132--- a/go.mod
133+++ b/go.mod
134@@ -6,6 +6,7 @@ require (
135 github.com/a-h/templ v0.3.1001
136 github.com/dustin/go-humanize v1.0.1
137 github.com/gin-gonic/gin v1.11.0
138+ github.com/golang-migrate/migrate/v4 v4.19.1
139 github.com/jackc/pgx/v5 v5.8.0
140 github.com/jessevdk/go-flags v1.6.1
141 github.com/oklog/ulid/v2 v2.1.1
142@@ -20,7 +21,7 @@ require (
143 github.com/bytedance/sonic v1.14.0 // indirect
144 github.com/bytedance/sonic/loader v0.3.0 // indirect
145 github.com/cloudwego/base64x v0.1.6 // indirect
146- github.com/davecgh/go-spew v1.1.1 // indirect
147+ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
148 github.com/gabriel-vasile/mimetype v1.4.8 // indirect
149 github.com/gin-contrib/sse v1.1.0 // indirect
150 github.com/go-playground/locales v0.14.1 // indirect
151@@ -36,11 +37,12 @@ require (
152 github.com/klauspost/cpuid/v2 v2.3.0 // indirect
153 github.com/kr/text v0.2.0 // indirect
154 github.com/leodido/go-urn v1.4.0 // indirect
155+ github.com/lib/pq v1.10.9 // indirect
156 github.com/mattn/go-isatty v0.0.20 // indirect
157 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
158 github.com/modern-go/reflect2 v1.0.2 // indirect
159 github.com/pelletier/go-toml/v2 v2.2.4 // indirect
160- github.com/pmezard/go-difflib v1.0.0 // indirect
161+ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
162 github.com/quic-go/qpack v0.5.1 // indirect
163 github.com/quic-go/quic-go v0.54.0 // indirect
164 github.com/rogpeppe/go-internal v1.14.1 // indirect
165@@ -49,13 +51,13 @@ require (
166 github.com/valyala/bytebufferpool v1.0.0 // indirect
167 go.uber.org/mock v0.5.0 // indirect
168 golang.org/x/arch v0.20.0 // indirect
169- golang.org/x/crypto v0.41.0 // indirect
170- golang.org/x/mod v0.27.0 // indirect
171- golang.org/x/net v0.43.0 // indirect
172- golang.org/x/sync v0.17.0 // indirect
173- golang.org/x/sys v0.35.0 // indirect
174- golang.org/x/text v0.29.0 // indirect
175- golang.org/x/tools v0.36.0 // indirect
176+ golang.org/x/crypto v0.45.0 // indirect
177+ golang.org/x/mod v0.29.0 // indirect
178+ golang.org/x/net v0.47.0 // indirect
179+ golang.org/x/sync v0.18.0 // indirect
180+ golang.org/x/sys v0.38.0 // indirect
181+ golang.org/x/text v0.31.0 // indirect
182+ golang.org/x/tools v0.38.0 // indirect
183 google.golang.org/protobuf v1.36.9 // indirect
184 gopkg.in/yaml.v3 v3.0.1 // indirect
185 )
186diff --git a/go.sum b/go.sum
187index 59babae028cf07a2f65a296b57686a29b41559f9..717be2bd97c642838341e42dcf1486e6d261e2fd 100644
188--- a/go.sum
189+++ b/go.sum
190@@ -1,5 +1,9 @@
191+github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
192+github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
193 github.com/CAFxX/httpcompression v0.0.9 h1:0ue2X8dOLEpxTm8tt+OdHcgA+gbDge0OqFQWGKSqgrg=
194 github.com/CAFxX/httpcompression v0.0.9/go.mod h1:XX8oPZA+4IDcfZ0A71Hz0mZsv/YJOgYygkFhizVPilM=
195+github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
196+github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
197 github.com/a-h/templ v0.3.1001 h1:yHDTgexACdJttyiyamcTHXr2QkIeVF1MukLy44EAhMY=
198 github.com/a-h/templ v0.3.1001/go.mod h1:oCZcnKRf5jjsGpf2yELzQfodLphd2mwecwG4Crk5HBo=
199 github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
200@@ -11,18 +15,39 @@ github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZw
201 github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
202 github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
203 github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU=
204+github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
205+github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
206+github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
207+github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
208 github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
209 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
210-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
211 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
212+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
213+github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
214+github.com/dhui/dktest v0.4.6 h1:+DPKyScKSEp3VLtbMDHcUq6V5Lm5zfZZVb0Sk7Ahom4=
215+github.com/dhui/dktest v0.4.6/go.mod h1:JHTSYDtKkvFNFHJKqCzVzqXecyv+tKt8EzceOmQOgbU=
216+github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
217+github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
218+github.com/docker/docker v28.3.3+incompatible h1:Dypm25kh4rmk49v1eiVbsAtpAsYURjYkaKubwuBdxEI=
219+github.com/docker/docker v28.3.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
220+github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
221+github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
222+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
223+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
224 github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
225 github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
226+github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
227+github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
228 github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
229 github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
230 github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
231 github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
232 github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk=
233 github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls=
234+github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
235+github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
236+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
237+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
238 github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
239 github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
240 github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
241@@ -35,6 +60,10 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
242 github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
243 github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
244 github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
245+github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
246+github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
247+github.com/golang-migrate/migrate/v4 v4.19.1 h1:OCyb44lFuQfYXYLx1SCxPZQGU7mcaZ7gH9yH4jSFbBA=
248+github.com/golang-migrate/migrate/v4 v4.19.1/go.mod h1:CTcgfjxhaUtsLipnLoQRWCrjYXycRz/g5+RWDuYgPrE=
249 github.com/google/brotli/go/cbrotli v0.0.0-20230829110029-ed738e842d2f h1:jopqB+UTSdJGEJT8tEqYyE29zN91fi2827oLET8tl7k=
250 github.com/google/brotli/go/cbrotli v0.0.0-20230829110029-ed738e842d2f/go.mod h1:nOPhAkwVliJdNTkj3gXpljmWhjc4wCaVqbMJcPKWP4s=
251 github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
252@@ -64,15 +93,27 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
253 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
254 github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
255 github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
256+github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
257+github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
258 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
259 github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
260+github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
261+github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
262+github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
263+github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
264 github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
265 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
266 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
267 github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
268 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
269+github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
270+github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
271 github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
272 github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
273+github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
274+github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
275+github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
276+github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
277 github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c h1:P6XGcuPTigoHf4TSu+3D/7QOQ1MbL6alNwrGhcW7sKw=
278 github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c/go.mod h1:YnNlZP7l4MhyGQ4CBRwv6ohZTPrUJJZtEv4ZgADkbs4=
279 github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
280@@ -80,8 +121,11 @@ github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0
281 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
282 github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
283 github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
284-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
285+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
286+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
287 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
288+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
289+github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
290diff --git a/migrations/embed.go b/migrations/embed.go
291new file mode 100644
292index 0000000000000000000000000000000000000000..91cca1c33b8d3a236e0a2fb0f1e59a281ffec944
293--- /dev/null
294+++ b/migrations/embed.go
295@@ -0,0 +1,6 @@
296+package migrations
297+
298+import "embed"
299+
300+//go:embed *.sql
301+var FS embed.FS