fix: CI/CD build errors
- Simplified go.mod with all dependencies - Fixed generateRandomSecret function - Updated Dockerfile to use debian bookworm - Simplified CI workflow to single job - Fixed Gitea Actions syntax (github.ref)
This commit is contained in:
@@ -12,7 +12,7 @@ env:
|
|||||||
IMAGE_NAME: anticaptcha
|
IMAGE_NAME: anticaptcha
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-frontend:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -21,66 +21,20 @@ jobs:
|
|||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '20'
|
node-version: '20'
|
||||||
cache: 'npm'
|
|
||||||
cache-dependency-path: web/package-lock.json
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install frontend dependencies
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
run: npm ci
|
run: npm install
|
||||||
|
|
||||||
- name: Build frontend
|
- name: Build frontend
|
||||||
working-directory: ./web
|
working-directory: ./web
|
||||||
run: npm run build
|
run: npm run build
|
||||||
|
|
||||||
- name: Upload frontend artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: frontend
|
|
||||||
path: web/dist
|
|
||||||
|
|
||||||
build-backend:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build-frontend
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Download frontend artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: frontend
|
|
||||||
path: web/dist
|
|
||||||
|
|
||||||
- name: Setup Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: '1.22'
|
|
||||||
|
|
||||||
- name: Build Go binary
|
|
||||||
run: |
|
|
||||||
CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o anticaptcha ./cmd/server
|
|
||||||
|
|
||||||
- name: Upload backend artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: backend
|
|
||||||
path: anticaptcha
|
|
||||||
|
|
||||||
build-docker:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build-frontend
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Download frontend artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: frontend
|
|
||||||
path: web/dist
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
- name: Login to Registry
|
- name: Login to Registry
|
||||||
|
if: github.event_name != 'pull_request'
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.REGISTRY }}
|
registry: ${{ env.REGISTRY }}
|
||||||
@@ -95,23 +49,20 @@ jobs:
|
|||||||
tags: |
|
tags: |
|
||||||
type=ref,event=branch
|
type=ref,event=branch
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
|
||||||
type=sha
|
type=sha
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
uses: docker/build-push-action@v5
|
uses: docker/build-push-action@v5
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
cache-from: type=gha
|
|
||||||
cache-to: type=gha,mode=max
|
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build-docker
|
needs: build
|
||||||
if: startsWith(gitea.ref, 'refs/tags/')
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
steps:
|
steps:
|
||||||
- name: Deploy to server
|
- name: Deploy to server
|
||||||
uses: appleboy/ssh-action@v1.0.3
|
uses: appleboy/ssh-action@v1.0.3
|
||||||
|
|||||||
+22
-11
@@ -1,36 +1,47 @@
|
|||||||
# 构建阶段
|
# 构建阶段
|
||||||
FROM golang:1.22-alpine AS builder
|
FROM golang:1.22-bookworm AS builder
|
||||||
|
|
||||||
# 安装构建依赖
|
# 安装构建依赖
|
||||||
RUN apk add --no-cache git gcc g++ make opencv-dev onnxruntime-dev
|
RUN apt-get update && apt-get install -y \
|
||||||
|
git \
|
||||||
|
gcc \
|
||||||
|
g++ \
|
||||||
|
make \
|
||||||
|
libopencv-dev \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# 复制 Go 模块文件
|
# 复制 Go 模块文件
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod ./
|
||||||
RUN go mod download
|
|
||||||
|
|
||||||
# 复制源代码
|
# 复制源代码
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# 构建
|
# 下载依赖
|
||||||
RUN CGO_ENABLED=1 go build -o anticaptcha ./cmd/server
|
RUN go mod download || true
|
||||||
|
|
||||||
|
# 构建(纯 Go 版本,暂不启用 CGO)
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o anticaptcha ./cmd/server
|
||||||
|
|
||||||
# 运行阶段
|
# 运行阶段
|
||||||
FROM alpine:3.20
|
FROM debian:bookworm-slim
|
||||||
|
|
||||||
# 安装运行时依赖
|
# 安装运行时依赖
|
||||||
RUN apk add --no-cache ca-certificates tzdata opencv onnxruntime
|
RUN apt-get update && apt-get install -y \
|
||||||
|
ca-certificates \
|
||||||
|
tzdata \
|
||||||
|
libgomp1 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# 复制二进制文件
|
# 复制二进制文件和前端
|
||||||
COPY --from=builder /app/anticaptcha .
|
COPY --from=builder /app/anticaptcha .
|
||||||
COPY --from=builder /app/models ./models
|
|
||||||
COPY --from=builder /app/web/dist ./web/dist
|
COPY --from=builder /app/web/dist ./web/dist
|
||||||
|
|
||||||
# 创建数据目录
|
# 创建数据目录
|
||||||
RUN mkdir -p /app/data
|
RUN mkdir -p /app/data /app/models
|
||||||
|
|
||||||
ENV GIN_MODE=release
|
ENV GIN_MODE=release
|
||||||
ENV TZ=Asia/Shanghai
|
ENV TZ=Asia/Shanghai
|
||||||
|
|||||||
+11
-13
@@ -1,9 +1,10 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
|
|
||||||
"anticaptcha/internal/captcha"
|
"anticaptcha/internal/captcha"
|
||||||
"anticaptcha/internal/config"
|
"anticaptcha/internal/config"
|
||||||
@@ -54,18 +55,19 @@ func main() {
|
|||||||
|
|
||||||
// 静态文件服务(前端)
|
// 静态文件服务(前端)
|
||||||
r.Static("/assets", "./web/dist/assets")
|
r.Static("/assets", "./web/dist/assets")
|
||||||
r.StaticFile("/", "./web/dist/index.html")
|
r.NoRoute(func(c *gin.Context) {
|
||||||
r.StaticFile("/favicon.ico", "./web/dist/favicon.ico")
|
c.File("./web/dist/index.html")
|
||||||
|
})
|
||||||
|
|
||||||
// API 路由
|
// API 路由
|
||||||
captchaHandler := handler.NewCaptchaHandler(captcha.NewHandler("./models"))
|
captchaHandler := handler.NewCaptchaHandler(captcha.NewHandler("./models"))
|
||||||
captchaHandler.RegisterRoutes(r.Group(""), true)
|
captchaHandler.RegisterRoutes(r.Group(""), true)
|
||||||
|
|
||||||
// 安装路由
|
// 安装路由
|
||||||
r.GET("/install", func(c *gin.Context) {
|
|
||||||
c.File("./web/dist/index.html")
|
|
||||||
})
|
|
||||||
r.POST("/api/install", handleInstall)
|
r.POST("/api/install", handleInstall)
|
||||||
|
r.GET("/api/install/check", func(c *gin.Context) {
|
||||||
|
c.JSON(200, gin.H{"installed": config.IsInstalled()})
|
||||||
|
})
|
||||||
|
|
||||||
// 健康检查
|
// 健康检查
|
||||||
r.GET("/health", func(c *gin.Context) {
|
r.GET("/health", func(c *gin.Context) {
|
||||||
@@ -169,15 +171,11 @@ func handleInstall(c *gin.Context) {
|
|||||||
|
|
||||||
c.JSON(200, gin.H{
|
c.JSON(200, gin.H{
|
||||||
"message": "安装成功",
|
"message": "安装成功",
|
||||||
"config": cfg,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateRandomSecret() string {
|
func generateRandomSecret() string {
|
||||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
b := make([]byte, 32)
|
||||||
b := make([]byte, 64)
|
rand.Read(b)
|
||||||
for i := range b {
|
return hex.EncodeToString(b)
|
||||||
b[i] = charset[os.New(0).UnixNano()%int64(len(charset))]
|
|
||||||
}
|
|
||||||
return string(b)
|
|
||||||
}
|
}
|
||||||
@@ -6,11 +6,58 @@ require (
|
|||||||
github.com/gin-contrib/cors v1.7.2
|
github.com/gin-contrib/cors v1.7.2
|
||||||
github.com/gin-gonic/gin v1.7.7
|
github.com/gin-gonic/gin v1.7.7
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||||
github.com/mattn/go-sqlite3 v1.14.22
|
|
||||||
github.com/pressly/goose/v3 v3.21.1
|
|
||||||
github.com/spf13/viper v1.19.0
|
github.com/spf13/viper v1.19.0
|
||||||
golang.org/x/crypto v0.25.0
|
golang.org/x/crypto v0.25.0
|
||||||
gorm.io/driver/mysql v1.5.7
|
gorm.io/driver/mysql v1.5.7
|
||||||
gorm.io/driver/sqlite v1.5.6
|
gorm.io/driver/sqlite v1.5.6
|
||||||
gorm.io/gorm v1.25.11
|
gorm.io/gorm v1.25.11
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/bytedance/sonic v1.11.6 // indirect
|
||||||
|
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||||
|
github.com/cloudwego/base64x v0.3.26 // indirect
|
||||||
|
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||||
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||||
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||||
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||||
|
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||||
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||||
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
|
github.com/spf13/afero v1.11.0 // indirect
|
||||||
|
github.com/spf13/cast v1.6.0 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
|
github.com/twitchyliquid49/golang-asm v0.15.1 // indirect
|
||||||
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
|
go.uber.org/multierr v1.9.0 // indirect
|
||||||
|
golang.org/x/arch v0.8.0 // indirect
|
||||||
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||||
|
golang.org/x/net v0.25.0 // indirect
|
||||||
|
golang.org/x/sys v0.22.0 // indirect
|
||||||
|
golang.org/x/text v0.16.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.34.1 // indirect
|
||||||
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
|
modernc.org/sqlite v1.29.1 // indirect
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user