diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 32679fb..e8af6e8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.21' + go-version: '1.25' cache-dependency-path: server/go.sum - name: Build @@ -36,7 +36,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: '18' + node-version: '20' cache: 'npm' cache-dependency-path: web/package-lock.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4dc1d35..8a27443 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,63 +1,154 @@ +# 自动化发版流水线 +# +# 触发方式: +# 1. 推送 tag:git tag v1.2.3 && git push --tags +# 2. 手动触发:GitHub Actions 页面 → Run workflow → 输入版本号 +# +# 产出物: +# - GitHub Release:linux/amd64 + linux/arm64 预编译 tar.gz +# - Docker Hub:awuqing/backupx:latest + awuqing/backupx:v1.2.3(多架构) +# +# 前置配置: +# 在仓库 Settings → Secrets → Actions 添加: +# - DOCKERHUB_USERNAME(Docker Hub 用户名) +# - DOCKERHUB_TOKEN(Docker Hub Access Token) + name: Release on: push: tags: - 'v*' + workflow_dispatch: + inputs: + version: + description: '版本号(如 v1.2.3)' + required: true + type: string permissions: contents: write + packages: write + +# 统一版本号:tag 推送取 ref_name,手动触发取 inputs.version +env: + VERSION: ${{ github.event.inputs.version || github.ref_name }} jobs: - release: - name: Build & Release + # ─── Job 1: 构建前端 ─── + build-web: + name: Build Frontend + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'npm' + cache-dependency-path: web/package-lock.json + + - name: Install & Build + working-directory: web + run: | + npm ci + npm run build + + - name: Upload frontend artifact + uses: actions/upload-artifact@v4 + with: + name: web-dist + path: web/dist + retention-days: 1 + + # ─── Job 2: 预编译二进制 → GitHub Release ─── + build-release: + name: Build ${{ matrix.goarch }} + needs: build-web runs-on: ubuntu-latest strategy: matrix: - goos: [linux] - goarch: [amd64, arm64] + include: + - goos: linux + goarch: amd64 + - goos: linux + goarch: arm64 steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.21' + go-version: '1.25' cache-dependency-path: server/go.sum - - name: Set up Node.js - uses: actions/setup-node@v4 + - name: Download frontend artifact + uses: actions/download-artifact@v4 with: - node-version: '18' - cache: 'npm' - cache-dependency-path: web/package-lock.json + name: web-dist + path: web/dist - - name: Build frontend - working-directory: web - run: | - npm ci - npm run build - - - name: Build backend + - name: Build binary working-directory: server env: GOOS: ${{ matrix.goos }} GOARCH: ${{ matrix.goarch }} - CGO_ENABLED: 1 + CGO_ENABLED: '0' run: | - go build -ldflags "-s -w -X main.version=${{ github.ref_name }}" -o ../backupx-${{ matrix.goos }}-${{ matrix.goarch }} ./cmd/backupx + go build \ + -trimpath \ + -ldflags "-s -w -X main.version=${{ env.VERSION }}" \ + -o ../backupx \ + ./cmd/backupx - name: Package release run: | - mkdir -p release - cp backupx-${{ matrix.goos }}-${{ matrix.goarch }} release/ - cp -r web/dist release/web - cp server/config.example.yaml release/ - cp deploy/install.sh release/ 2>/dev/null || true - cd release && tar czf ../backupx-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz . + ARCHIVE_NAME="backupx-${{ env.VERSION }}-${{ matrix.goos }}-${{ matrix.goarch }}" + mkdir -p "${ARCHIVE_NAME}" + cp backupx "${ARCHIVE_NAME}/" + cp -r web/dist "${ARCHIVE_NAME}/web" + cp server/config.example.yaml "${ARCHIVE_NAME}/" + cp deploy/install.sh "${ARCHIVE_NAME}/" 2>/dev/null || true + tar czf "${ARCHIVE_NAME}.tar.gz" "${ARCHIVE_NAME}" - - name: Upload Release Asset + - name: Upload to GitHub Release uses: softprops/action-gh-release@v2 with: - files: backupx-${{ github.ref_name }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz + tag_name: ${{ env.VERSION }} + files: backupx-${{ env.VERSION }}-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz generate_release_notes: true + + # ─── Job 3: Docker 多架构 → Docker Hub ─── + build-docker: + name: Build & Push Docker + needs: build-web + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build & Push + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + build-args: | + VERSION=${{ env.VERSION }} + tags: | + ${{ secrets.DOCKERHUB_USERNAME }}/backupx:latest + ${{ secrets.DOCKERHUB_USERNAME }}/backupx:${{ env.VERSION }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile index 9dc2617..0103612 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,22 @@ +# BackupX 多阶段构建 +# +# 用法: +# 国际构建(默认):docker build -t backupx . +# 国内加速构建: docker build --build-arg USE_CHINA_MIRROR=true -t backupx . +# 注入版本号: docker build --build-arg VERSION=v1.2.3 -t backupx . + +# 全局构建参数 +ARG USE_CHINA_MIRROR=false + + # ---- Stage 1: Build frontend ---- FROM node:20-alpine AS web-builder +ARG USE_CHINA_MIRROR + +# 国内镜像:npm 使用淘宝源 +RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \ + npm config set registry https://registry.npmmirror.com; \ + fi WORKDIR /build/web COPY web/package.json web/package-lock.json ./ @@ -10,16 +27,29 @@ RUN npm run build # ---- Stage 2: Build backend ---- FROM golang:1.25-alpine AS server-builder +ARG USE_CHINA_MIRROR +ARG VERSION=dev + +# 国内镜像:Go 模块使用七牛代理 +RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \ + go env -w GOPROXY=https://goproxy.cn,direct; \ + fi WORKDIR /build/server COPY server/go.mod server/go.sum ./ RUN go mod download COPY server/ ./ -RUN go build -trimpath -ldflags="-s -w" -o backupx ./cmd/backupx +RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w -X main.version=${VERSION}" -o backupx ./cmd/backupx # ---- Stage 3: Production image ---- FROM alpine:3.21 +ARG USE_CHINA_MIRROR + +# 国内镜像:Alpine apk 使用阿里云源 +RUN if [ "$USE_CHINA_MIRROR" = "true" ]; then \ + sed -i 's|dl-cdn.alpinelinux.org|mirrors.aliyun.com|g' /etc/apk/repositories; \ + fi RUN apk add --no-cache \ nginx \ diff --git a/Makefile b/Makefile index 1a8dd6b..da55d5c 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,25 @@ -.PHONY: build dev test clean +.PHONY: build dev test clean docker docker-cn -# 一次性构建前后端 +# 自动获取版本号(从 git tag 或 commit hash) +VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev) + +# ── 一键构建 ── build: build-server build-web build-server: - cd server && go build -o bin/backupx ./cmd/backupx + cd server && CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.version=$(VERSION)" -o bin/backupx ./cmd/backupx build-web: cd web && npm run build -# 开发模式(分别在两个终端运行) +# ── 开发模式(分别在两个终端运行)── dev-server: cd server && go run ./cmd/backupx dev-web: cd web && npm run dev -# 运行所有测试 +# ── 测试 ── test: test-server test-web test-server: @@ -25,6 +28,14 @@ test-server: test-web: cd web && npm run test -# 清理构建产物 +# ── Docker 构建 ── +docker: + docker build --build-arg VERSION=$(VERSION) -t backupx:$(VERSION) -t backupx:latest . + +# 国内加速构建(使用国内镜像源) +docker-cn: + docker build --build-arg VERSION=$(VERSION) --build-arg USE_CHINA_MIRROR=true -t backupx:$(VERSION) -t backupx:latest . + +# ── 清理 ── clean: rm -rf server/bin web/dist diff --git a/README.md b/README.md index b817756..a9732d3 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,20 @@ make build cd server && ./bin/backupx ``` +### 国内用户构建 + +如果因网络原因下载依赖缓慢,可使用国内镜像加速: + +```bash +# 方式一:Docker 构建(推荐,一行搞定) +make docker-cn + +# 方式二:手动设置镜像后裸机构建 +export GOPROXY=https://goproxy.cn,direct # Go 模块代理 +npm config set registry https://registry.npmmirror.com # npm 淘宝源 +make build +``` + ### 访问 Web UI 打开浏览器访问 `http://your-server:8340`,首次使用会引导您创建管理员账户。 @@ -375,10 +389,28 @@ make test-web # npm run test # 构建前后端 make build +# Docker 构建 +make docker + +# 国内 Docker 构建(使用国内镜像加速) +make docker-cn + # 清理构建产物 make clean ``` +### 发版 + +推送 Git tag 即可自动触发 GitHub Actions 完成全部发布流程: + +```bash +git tag v1.2.3 +git push --tags +# GitHub Actions 自动:编译二进制 → 发布 Release → 推送 Docker Hub 镜像 +``` + +也可以在 GitHub Actions 页面手动触发 Release workflow,输入版本号即可。 + ## Deployment ### 一键安装 (推荐) diff --git a/README_EN.md b/README_EN.md index e6b3c20..c7210ff 100644 --- a/README_EN.md +++ b/README_EN.md @@ -152,6 +152,20 @@ make build cd server && ./bin/backupx ``` +### China Mirror Build + +If downloading dependencies is slow due to network restrictions, use China mirror acceleration: + +```bash +# Option 1: Docker build (recommended, one command) +make docker-cn + +# Option 2: Set mirrors manually, then build +export GOPROXY=https://goproxy.cn,direct +npm config set registry https://registry.npmmirror.com +make build +``` + ### Access Web UI Open `http://your-server:8340` in your browser. First-time use will guide you through creating an admin account. @@ -376,10 +390,28 @@ make test-web # npm run test # Build frontend and backend make build +# Docker build +make docker + +# Docker build with China mirrors +make docker-cn + # Clean build artifacts make clean ``` +### Release + +Push a Git tag to automatically trigger the full release pipeline via GitHub Actions: + +```bash +git tag v1.2.3 +git push --tags +# GitHub Actions will: compile binaries → publish GitHub Release → push Docker Hub image +``` + +You can also manually trigger the Release workflow from the GitHub Actions page. + ## Deployment ### One-Click Install (Recommended)