chore: skip AppleDouble migrations + Alpine mirror for CN builds
- migrations_runner: filter ._* / .hidden.sql so macOS metadata files don't break the migration scanner; new helper + regression tests cover this. - Docker images switch Alpine repo to mirrors.aliyun.com (CN build speed) and pin frontend pnpm to 9.15.9 to dodge v10 interactive build prompts. - dockerignore (root + backend): exclude **/.DS_Store and ._* AppleDouble artefacts so they don't sneak into image context.
This commit is contained in:
parent
35c6c2b097
commit
27f2b442cb
@ -20,6 +20,9 @@ docs/
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
**/.DS_Store
|
||||
._*
|
||||
**/._*
|
||||
Thumbs.db
|
||||
|
||||
# Build artifacts
|
||||
|
||||
11
Dockerfile
11
Dockerfile
@ -18,10 +18,13 @@ ARG GOSUMDB=sum.golang.google.cn
|
||||
# -----------------------------------------------------------------------------
|
||||
FROM ${NODE_IMAGE} AS frontend-builder
|
||||
|
||||
RUN sed -i 's#https://dl-cdn.alpinelinux.org/alpine#https://mirrors.aliyun.com/alpine#g' /etc/apk/repositories
|
||||
|
||||
WORKDIR /app/frontend
|
||||
|
||||
# Install pnpm
|
||||
RUN corepack enable && corepack prepare pnpm@latest --activate
|
||||
# Install pnpm. Keep this on v9 so Docker builds do not fail on pnpm v10's
|
||||
# interactive build-script approval flow.
|
||||
RUN corepack enable && corepack prepare pnpm@9.15.9 --activate
|
||||
|
||||
# Install dependencies first (better caching)
|
||||
COPY frontend/package.json frontend/pnpm-lock.yaml ./
|
||||
@ -36,6 +39,8 @@ RUN pnpm run build
|
||||
# -----------------------------------------------------------------------------
|
||||
FROM ${GOLANG_IMAGE} AS backend-builder
|
||||
|
||||
RUN sed -i 's#https://dl-cdn.alpinelinux.org/alpine#https://mirrors.aliyun.com/alpine#g' /etc/apk/repositories
|
||||
|
||||
# Build arguments for version info (set by CI)
|
||||
ARG VERSION=
|
||||
ARG COMMIT=docker
|
||||
@ -83,6 +88,8 @@ FROM ${POSTGRES_IMAGE} AS pg-client
|
||||
# -----------------------------------------------------------------------------
|
||||
FROM ${ALPINE_IMAGE}
|
||||
|
||||
RUN sed -i 's#https://dl-cdn.alpinelinux.org/alpine#https://mirrors.aliyun.com/alpine#g' /etc/apk/repositories
|
||||
|
||||
# Labels
|
||||
LABEL maintainer="Wei-Shaw <github.com/Wei-Shaw>"
|
||||
LABEL description="Sub2API - AI API Gateway Platform"
|
||||
|
||||
@ -1,2 +1,5 @@
|
||||
.cache/
|
||||
.DS_Store
|
||||
**/.DS_Store
|
||||
._*
|
||||
**/._*
|
||||
|
||||
@ -8,6 +8,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@ -144,11 +145,10 @@ func applyMigrationsFS(ctx context.Context, db *sql.DB, fsys fs.FS) error {
|
||||
|
||||
// 获取所有 .sql 迁移文件并按文件名排序。
|
||||
// 命名规范:使用零填充数字前缀(如 001_init.sql, 002_add_users.sql)。
|
||||
files, err := fs.Glob(fsys, "*.sql")
|
||||
files, err := migrationFiles(fsys)
|
||||
if err != nil {
|
||||
return fmt.Errorf("list migrations: %w", err)
|
||||
}
|
||||
sort.Strings(files) // 确保按文件名顺序执行迁移
|
||||
|
||||
for _, name := range files {
|
||||
// 读取迁移文件内容
|
||||
@ -392,14 +392,13 @@ func tableExists(ctx context.Context, db *sql.DB, tableName string) (bool, error
|
||||
}
|
||||
|
||||
func latestMigrationBaseline(fsys fs.FS) (string, string, string, error) {
|
||||
files, err := fs.Glob(fsys, "*.sql")
|
||||
files, err := migrationFiles(fsys)
|
||||
if err != nil {
|
||||
return "", "", "", err
|
||||
}
|
||||
if len(files) == 0 {
|
||||
return "baseline", "baseline", "", nil
|
||||
}
|
||||
sort.Strings(files)
|
||||
name := files[len(files)-1]
|
||||
contentBytes, err := fs.ReadFile(fsys, name)
|
||||
if err != nil {
|
||||
@ -412,6 +411,23 @@ func latestMigrationBaseline(fsys fs.FS) (string, string, string, error) {
|
||||
return version, version, hash, nil
|
||||
}
|
||||
|
||||
func migrationFiles(fsys fs.FS) ([]string, error) {
|
||||
files, err := fs.Glob(fsys, "*.sql")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := files[:0]
|
||||
for _, name := range files {
|
||||
base := filepath.Base(name)
|
||||
if strings.HasPrefix(base, ".") || strings.HasPrefix(base, "._") {
|
||||
continue
|
||||
}
|
||||
out = append(out, name)
|
||||
}
|
||||
sort.Strings(out)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func checksumSet(values ...string) map[string]struct{} {
|
||||
out := make(map[string]struct{}, len(values))
|
||||
for _, value := range values {
|
||||
|
||||
@ -47,7 +47,8 @@ func TestLatestMigrationBaseline(t *testing.T) {
|
||||
|
||||
t.Run("uses_latest_sorted_sql_file", func(t *testing.T) {
|
||||
fsys := fstest.MapFS{
|
||||
"001_init.sql": &fstest.MapFile{Data: []byte("CREATE TABLE t1(id int);")},
|
||||
"._999_final.sql": &fstest.MapFile{Data: []byte("AppleDouble metadata")},
|
||||
"001_init.sql": &fstest.MapFile{Data: []byte("CREATE TABLE t1(id int);")},
|
||||
"010_final.sql": &fstest.MapFile{
|
||||
Data: []byte("CREATE TABLE t2(id int);"),
|
||||
},
|
||||
@ -68,6 +69,19 @@ func TestLatestMigrationBaseline(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestMigrationFiles_SkipsHiddenAppleDoubleSQL(t *testing.T) {
|
||||
fsys := fstest.MapFS{
|
||||
"._001_init.sql": &fstest.MapFile{Data: []byte("AppleDouble metadata")},
|
||||
".hidden.sql": &fstest.MapFile{Data: []byte("hidden")},
|
||||
"001_init.sql": &fstest.MapFile{Data: []byte("SELECT 1;")},
|
||||
"002_next.sql": &fstest.MapFile{Data: []byte("SELECT 2;")},
|
||||
}
|
||||
|
||||
files, err := migrationFiles(fsys)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []string{"001_init.sql", "002_next.sql"}, files)
|
||||
}
|
||||
|
||||
func TestIsMigrationChecksumCompatible_AdditionalCases(t *testing.T) {
|
||||
require.False(t, isMigrationChecksumCompatible("unknown.sql", "db", "file"))
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user