mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-28 11:16:37 +08:00
306 lines
10 KiB
YAML
306 lines
10 KiB
YAML
name: AuTo Docker Image
|
||
|
||
|
||
on:
|
||
push:
|
||
branches: [main]
|
||
|
||
# 保留手动触发作为备选
|
||
workflow_dispatch:
|
||
inputs:
|
||
version_type:
|
||
description: '版本递增类型'
|
||
required: true
|
||
default: 'patch'
|
||
type: choice
|
||
options:
|
||
- patch # 0.0.x
|
||
- minor # 0.x.0
|
||
- major # x.0.0
|
||
|
||
permissions:
|
||
contents: write # 需要写入权限来更新版本文件
|
||
packages: write
|
||
|
||
jobs:
|
||
version-and-publish:
|
||
runs-on: ubuntu-latest
|
||
outputs:
|
||
new_version: ${{ steps.bump_version.outputs.new_version }}
|
||
tag: ${{ steps.bump_version.outputs.tag }}
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
with:
|
||
fetch-depth: 0 # 获取完整历史以便版本计算
|
||
token: ${{ secrets.GITHUB_TOKEN }}
|
||
|
||
# 1. 获取或初始化版本号
|
||
- name: Get current version
|
||
id: get_version
|
||
run: |
|
||
# 从文件读取版本号,或使用默认值
|
||
if [ -f VERSION ]; then
|
||
CURRENT_VERSION=$(cat VERSION)
|
||
else
|
||
CURRENT_VERSION="0.0.0"
|
||
echo $CURRENT_VERSION > VERSION
|
||
fi
|
||
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
||
|
||
# 分离版本组成部分
|
||
MAJOR=$(echo $CURRENT_VERSION | cut -d. -f1)
|
||
MINOR=$(echo $CURRENT_VERSION | cut -d. -f2)
|
||
PATCH=$(echo $CURRENT_VERSION | cut -d. -f3)
|
||
echo "major=$MAJOR" >> $GITHUB_OUTPUT
|
||
echo "minor=$MINOR" >> $GITHUB_OUTPUT
|
||
echo "patch=$PATCH" >> $GITHUB_OUTPUT
|
||
|
||
# 2. 计算新版本号
|
||
- name: Bump version
|
||
id: bump_version
|
||
run: |
|
||
MAJOR=${{ steps.get_version.outputs.major }}
|
||
MINOR=${{ steps.get_version.outputs.minor }}
|
||
PATCH=${{ steps.get_version.outputs.patch }}
|
||
|
||
# 手动触发时根据选择递增
|
||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||
TYPE="${{ github.event.inputs.version_type }}"
|
||
if [ "$TYPE" = "major" ]; then
|
||
MAJOR=$((MAJOR + 1))
|
||
MINOR=0
|
||
PATCH=0
|
||
elif [ "$TYPE" = "minor" ]; then
|
||
MINOR=$((MINOR + 1))
|
||
PATCH=0
|
||
else # patch
|
||
PATCH=$((PATCH + 1))
|
||
fi
|
||
else
|
||
# 自动触发时默认 patch 递增
|
||
PATCH=$((PATCH + 1))
|
||
fi
|
||
|
||
NEW_VERSION="${MAJOR}.${MINOR}.${PATCH}"
|
||
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
||
echo "tag=MeBox-v${NEW_VERSION}" >> $GITHUB_OUTPUT
|
||
echo "tag=mebox-v${NEW_VERSION}" >> $GITHUB_OUTPUT
|
||
|
||
# 3. 更新 VERSION 文件
|
||
- name: Update version file
|
||
run: |
|
||
echo "${{ steps.bump_version.outputs.new_version }}" > VERSION
|
||
|
||
# 如果存在 go.mod,也更新其中的版本(可选)
|
||
# if [ -f go.mod ]; then
|
||
# sed -i "s/^version .*/version ${{ steps.bump_version.outputs.new_version }}/" go.mod
|
||
# fi
|
||
|
||
# 4. 提交版本变更
|
||
- name: Commit version bump
|
||
run: |
|
||
git config user.name "github-actions[bot]"
|
||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||
git add VERSION
|
||
git commit -m "chore: bump version to ${{ steps.bump_version.outputs.new_version }} [skip ci]"
|
||
git push
|
||
|
||
# 5. 创建 Git Tag
|
||
- name: Create and push tag
|
||
run: |
|
||
TAG="${{ steps.bump_version.outputs.tag }}"
|
||
git tag $TAG
|
||
git push origin $TAG
|
||
|
||
# 6. 设置 Docker QEMU 和 Buildx
|
||
- uses: docker/setup-qemu-action@v3
|
||
- uses: docker/setup-buildx-action@v3
|
||
|
||
# 7. 登录 GHCR
|
||
- name: Log in to GHCR
|
||
uses: docker/login-action@v3
|
||
with:
|
||
registry: ghcr.io
|
||
username: ${{ github.actor }}
|
||
password: ${{ secrets.GITHUB_TOKEN }}
|
||
|
||
# 8. 提取镜像元数据
|
||
- name: Extract image metadata
|
||
id: meta
|
||
uses: docker/metadata-action@v5
|
||
with:
|
||
images: ghcr.io/${{ github.repository_owner }}/mebox
|
||
tags: |
|
||
type=raw,value=latest
|
||
type=raw,value=${{ steps.bump_version.outputs.tag }}
|
||
type=raw,value=${{ steps.bump_version.outputs.new_version }}
|
||
|
||
# 9. 构建并推送
|
||
- name: Build & push
|
||
uses: docker/build-push-action@v6
|
||
with:
|
||
context: .
|
||
platforms: linux/amd64,linux/arm64
|
||
push: true
|
||
provenance: false
|
||
sbom: false
|
||
tags: ${{ steps.meta.outputs.tags }}
|
||
labels: ${{ steps.meta.outputs.labels }}
|
||
build-args: |
|
||
VERSION=${{ steps.bump_version.outputs.new_version }}
|
||
cache-from: type=gha
|
||
cache-to: type=gha,mode=max
|
||
|
||
# 单文件可执行构建:把前端打包进二进制(go:embed),交叉编译 Windows /
|
||
# Linux / macOS 的 amd64 / arm64 产物,作为 GitHub Release 附件发布。
|
||
build-frontend:
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '20'
|
||
cache: 'npm'
|
||
cache-dependency-path: web/package-lock.json
|
||
- name: Install
|
||
working-directory: web
|
||
run: npm ci
|
||
- name: Build SPA
|
||
working-directory: web
|
||
run: npm run build
|
||
- name: Upload web/dist
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: web-dist
|
||
path: web/dist
|
||
retention-days: 1
|
||
|
||
# 先创建(幂等)空的 GitHub Release,供后续 build-binaries 并行上传附件,
|
||
# 也避免矩阵各 job 并发 upload 时 release 尚不存在而互相竞争。
|
||
publish-create-release:
|
||
needs: [version-and-publish]
|
||
runs-on: ubuntu-latest
|
||
permissions:
|
||
contents: write
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- name: Create release
|
||
env:
|
||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
RELEASE_TAG: ${{ needs.version-and-publish.outputs.tag }}
|
||
run: |
|
||
set -eux
|
||
# tag 已由 version-and-publish 推送;若 release 已存在则忽略(--verify-tag 幂等)
|
||
gh release create "$RELEASE_TAG" \
|
||
--title "MeBox ${{ needs.version-and-publish.outputs.new_version }}" \
|
||
--notes "自动化发布 ${{ needs.version-and-publish.outputs.new_version }}" \
|
||
--verify-tag --latest || true
|
||
|
||
build-binaries:
|
||
needs: [version-and-publish, build-frontend, publish-create-release]
|
||
runs-on: ubuntu-latest
|
||
permissions:
|
||
contents: write
|
||
strategy:
|
||
fail-fast: false
|
||
matrix:
|
||
include:
|
||
- goos: linux
|
||
goarch: amd64
|
||
ext: ""
|
||
- goos: linux
|
||
goarch: arm64
|
||
ext: ""
|
||
- goos: windows
|
||
goarch: amd64
|
||
ext: .exe
|
||
- goos: windows
|
||
goarch: arm64
|
||
ext: .exe
|
||
- goos: darwin
|
||
goarch: amd64
|
||
ext: ""
|
||
- goos: darwin
|
||
goarch: arm64
|
||
ext: ""
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
- uses: actions/setup-go@v5
|
||
with:
|
||
go-version: '1.25'
|
||
cache: true
|
||
- name: Download web/dist
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
name: web-dist
|
||
path: web/dist
|
||
- name: Build binary
|
||
run: |
|
||
CGO_ENABLED=0 GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} \
|
||
go build -trimpath -ldflags="-s -w -X main.version=${{ needs.version-and-publish.outputs.tag }}" \
|
||
-o "dist/mebox-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.ext }}" ./cmd/server
|
||
- name: Package
|
||
run: |
|
||
mkdir -p package/mebox
|
||
cp "dist/mebox-${{ matrix.goos }}-${{ matrix.goarch }}${{ matrix.ext }}" package/mebox/mebox${{ matrix.ext }}
|
||
cp README.md package/mebox/ 2>/dev/null || true
|
||
if [ "${{ matrix.goos }}" = "windows" ]; then
|
||
(cd package && zip -r "../mebox_${{ matrix.goos }}_${{ matrix.goarch }}.zip" mebox)
|
||
else
|
||
tar -czf "mebox_${{ matrix.goos }}_${{ matrix.goarch }}.tar.gz" -C package mebox
|
||
fi
|
||
- name: Upload to GitHub Release
|
||
env:
|
||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||
RELEASE_TAG: ${{ needs.version-and-publish.outputs.tag }}
|
||
run: |
|
||
set -eux
|
||
PKG="mebox_${{ matrix.goos }}_${{ matrix.goarch }}.zip"
|
||
TAR="mebox_${{ matrix.goos }}_${{ matrix.goarch }}.tar.gz"
|
||
# 并发上传到同一 release 各自文件,--clobber 幂等覆盖
|
||
if [ -f "$PKG" ]; then
|
||
for i in 1 2 3; do gh release upload "$RELEASE_TAG" "$PKG" --clobber && break || sleep 5; done
|
||
fi
|
||
if [ -f "$TAR" ]; then
|
||
for i in 1 2 3; do gh release upload "$RELEASE_TAG" "$TAR" --clobber && break || sleep 5; done
|
||
fi
|
||
|
||
deploy:
|
||
name: Deploy to Server
|
||
needs: [version-and-publish]
|
||
runs-on: ubuntu-latest
|
||
steps:
|
||
- name: Deploy via SSH
|
||
uses: appleboy/ssh-action@v1.0.3
|
||
with:
|
||
host: ${{ secrets.SERVER_HOST }}
|
||
username: ${{ secrets.SERVER_USER }}
|
||
password: ${{ secrets.SERVER_PASSWORD }}
|
||
port: ${{ secrets.SERVER_PORT }}
|
||
script: |
|
||
set -e
|
||
echo "==== 开始部署 MeBox ===="
|
||
cd /root/dockerData/mebox
|
||
|
||
# 判断 compose 命令版本兼容性(docker compose 或 docker-compose)
|
||
if docker compose version >/dev/null 2>&1; then
|
||
COMPOSE_CMD="docker compose"
|
||
elif command -v docker-compose >/dev/null 2>&1; then
|
||
COMPOSE_CMD="docker-compose"
|
||
else
|
||
echo "错误: 未找到 docker compose 或 docker-compose"
|
||
exit 1
|
||
fi
|
||
|
||
echo "正在拉取最新镜像..."
|
||
$COMPOSE_CMD pull
|
||
|
||
echo "正在重启服务..."
|
||
$COMPOSE_CMD up -d
|
||
|
||
echo "清理旧的无用镜像..."
|
||
docker image prune -f
|
||
|
||
echo "==== 部署完成并已启动 ===="
|
||
|