shanshanzhong b8dab70de5
Some checks failed
Build docker and publish / prepare (20.15.1) (push) Successful in 10s
Build docker and publish / build (map[dockerfile:deploy/Dockerfile.admin image_name:ppanel-admin name:admin]) (push) Successful in 1m16s
Build docker and publish / deploy (push) Has been cancelled
Build docker and publish / notify (push) Has been cancelled
Build docker and publish / build (map[dockerfile:deploy/Dockerfile.rpc-core image_name:ppanel-rpc-core name:rpc-core]) (push) Has been cancelled
Build docker and publish / build (map[dockerfile:deploy/Dockerfile.scheduler image_name:ppanel-scheduler name:scheduler]) (push) Has been cancelled
Build docker and publish / build (map[dockerfile:deploy/Dockerfile.node image_name:ppanel-node name:node]) (push) Has been cancelled
Build docker and publish / build (map[dockerfile:deploy/Dockerfile.queue image_name:ppanel-queue name:queue]) (push) Has been cancelled
Build docker and publish / build (map[dockerfile:deploy/Dockerfile.api image_name:ppanel-api name:api]) (push) Has been cancelled
feat: 新增设备登录开关配置,优化 CI Go 模块缓存机制,并添加解密中间件调试日志。
2026-03-01 20:21:02 -08:00

351 lines
13 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: Build docker and publish
run-name: zero-ppanel Docker构建和部署
on:
push:
branches:
- main
- dev
pull_request:
branches:
- main
- dev
env:
REPO: ${{ vars.REPO || 'registry.kxsw.us/vpn-server' }}
SSH_HOST: ${{ github.ref_name == 'main' && vars.SSH_HOST || vars.DEV_SSH_HOST }}
SSH_PORT: ${{ vars.SSH_PORT }}
SSH_USER: ${{ vars.SSH_USER }}
SSH_PASSWORD: ${{ github.ref_name == 'main' && vars.SSH_PASSWORD || vars.DEV_SSH_PASSWORD }}
TG_BOT_TOKEN: 8114337882:AAHkEx03HSu7RxN4IHBJJEnsK9aPPzNLIk0
TG_CHAT_ID: "-4940243803"
VERSION: ${{ github.sha }}
BUILDTIME: ${{ github.event.head_commit.timestamp }}
jobs:
# ============================================================
# Job 1: 设置环境变量,供后续 jobs 共享
# ============================================================
prepare:
runs-on: zero-ppanel-server
container:
image: node:20
strategy:
matrix:
# 只有node支持版本号别名
node: ['20.15.1']
outputs:
docker_tag: ${{ steps.vars.outputs.docker_tag }}
container_suffix: ${{ steps.vars.outputs.container_suffix }}
deploy_path: ${{ steps.vars.outputs.deploy_path }}
has_changes: ${{ steps.changes.outputs.has_changes }}
changed_services: ${{ steps.changes.outputs.changed_services }}
deploy_services: ${{ steps.changes.outputs.deploy_services }}
steps:
- name: ⚙️ 计算部署变量
id: vars
run: |
case "${{ github.ref_name }}" in
main)
echo "docker_tag=latest" >> $GITHUB_OUTPUT
echo "container_suffix=" >> $GITHUB_OUTPUT
echo "deploy_path=/root/bindbox" >> $GITHUB_OUTPUT
;;
dev)
echo "docker_tag=dev" >> $GITHUB_OUTPUT
echo "container_suffix=-dev" >> $GITHUB_OUTPUT
echo "deploy_path=/root/bindbox-dev" >> $GITHUB_OUTPUT
;;
*)
echo "docker_tag=${{ github.ref_name }}" >> $GITHUB_OUTPUT
echo "container_suffix=-${{ github.ref_name }}" >> $GITHUB_OUTPUT
echo "deploy_path=/root/vpn_server_other" >> $GITHUB_OUTPUT
;;
esac
- name: 📥 下载代码
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: 🔍 检测变更服务
id: changes
shell: bash
run: |
set -euo pipefail
BEFORE="${{ github.event.before }}"
SHA="${{ github.sha }}"
RANGE=""
if [ -n "${BEFORE}" ] && [ "${BEFORE}" != "0000000000000000000000000000000000000000" ]; then
RANGE="${BEFORE}..${SHA}"
elif git rev-parse HEAD~1 >/dev/null 2>&1; then
RANGE="HEAD~1..HEAD"
else
RANGE="HEAD"
fi
if [ "${RANGE}" = "HEAD" ]; then
git show --pretty=format: --name-only HEAD | sed '/^$/d' > changed_files.txt
else
git diff --name-only "${RANGE}" > changed_files.txt
fi
echo "Changed files:"
cat changed_files.txt || true
has_file() {
grep -Eq "$1" changed_files.txt
}
add_service() {
local service="$1"
if [[ " ${services[*]} " != *" ${service} "* ]]; then
services+=("${service}")
fi
}
all=0
if has_file '^(go\.mod|go\.sum|pkg/|sql/|deploy/docker-compose\.cloud\.yml|deploy/docker-compose-env\.yml|deploy/\.env\.example|\.gitea/workflows/deploy\.yml)'; then
all=1
fi
services=()
if [ "${all}" -eq 1 ]; then
services=(rpc-core api admin node queue scheduler)
else
if has_file '^apps/rpc/' || has_file '^deploy/Dockerfile.rpc-core$' || has_file '^deploy/etc/core/'; then
add_service "rpc-core"
fi
if has_file '^apps/api/' || has_file '^deploy/Dockerfile.api$' || has_file '^deploy/etc/api/'; then
add_service "api"
fi
if has_file '^apps/admin/' || has_file '^deploy/Dockerfile.admin$' || has_file '^deploy/etc/admin/'; then
add_service "admin"
fi
if has_file '^apps/node/' || has_file '^deploy/Dockerfile.node$' || has_file '^deploy/etc/node/'; then
add_service "node"
fi
if has_file '^apps/queue/' || has_file '^deploy/Dockerfile.queue$' || has_file '^deploy/etc/queue/'; then
add_service "queue"
fi
if has_file '^apps/scheduler/' || has_file '^deploy/Dockerfile.scheduler$' || has_file '^deploy/etc/scheduler/'; then
add_service "scheduler"
fi
fi
if [ "${#services[@]}" -eq 0 ]; then
echo "No service changes detected, skip build/deploy."
echo "has_changes=false" >> "$GITHUB_OUTPUT"
echo "changed_services=" >> "$GITHUB_OUTPUT"
echo "deploy_services=" >> "$GITHUB_OUTPUT"
exit 0
fi
deploy_services=()
for service in "${services[@]}"; do
case "${service}" in
rpc-core) deploy_services+=("ppanel-rpc-core") ;;
api) deploy_services+=("ppanel-api") ;;
admin) deploy_services+=("ppanel-admin") ;;
node) deploy_services+=("ppanel-node") ;;
queue) deploy_services+=("ppanel-queue") ;;
scheduler) deploy_services+=("ppanel-scheduler") ;;
esac
done
changed_services="$(IFS=,; echo "${services[*]}")"
deploy_services_str="${deploy_services[*]}"
echo "has_changes=true" >> "$GITHUB_OUTPUT"
echo "changed_services=${changed_services}" >> "$GITHUB_OUTPUT"
echo "deploy_services=${deploy_services_str}" >> "$GITHUB_OUTPUT"
echo "Will build services: ${changed_services}"
echo "Will deploy services: ${deploy_services_str}"
# ============================================================
# Job 2: 并行矩阵构建 6 个服务镜像 - 💥 重点修改这里 💥
# ============================================================
build:
runs-on: zero-ppanel-server
container: # <-- 整个 build job 在 Node.js 容器中运行
image: node:20.15.1
volumes:
- /root/go/pkg/mod:/root/go/pkg/mod
- /root/.cache/go-build:/root/.cache/go-build
needs: prepare
if: needs.prepare.outputs.has_changes == 'true' && contains(needs.prepare.outputs.changed_services, matrix.service.name)
strategy:
fail-fast: false
matrix:
service:
- name: rpc-core
dockerfile: deploy/Dockerfile.rpc-core
image_name: ppanel-rpc-core
- name: api
dockerfile: deploy/Dockerfile.api
image_name: ppanel-api
- name: admin
dockerfile: deploy/Dockerfile.admin
image_name: ppanel-admin
- name: node
dockerfile: deploy/Dockerfile.node
image_name: ppanel-node
- name: queue
dockerfile: deploy/Dockerfile.queue
image_name: ppanel-queue
- name: scheduler
dockerfile: deploy/Dockerfile.scheduler
image_name: ppanel-scheduler
steps:
- name: 📥 下载代码
uses: actions/checkout@v4
- name: Set up Go environment # 在 build job 中也设置 Go 环境
uses: actions/setup-go@v2
with:
go-version: '1.24.0' # 确保使用 go.mod 中指定的精确版本
- name: 🔧 确保 Docker CLI 可用并初始化 Go Modules
run: |
set -e
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install -y ca-certificates curl gnupg
# 在 node 容器中安装 docker-ce-cli
curl -fsSL https://download.docker.com/linux/debian/gpg \
| gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
> /etc/apt/sources.list.d/docker.list
apt-get update -y
apt-get install -y docker-ce-cli # <<-- 确保 docker CLI 被安装
echo "Docker CLI 版本: $(docker --version)"
echo "Test Docker connectivity: $(docker info --format '{{.ServerVersion}}') (Server)"
go env -w GOPROXY=https://goproxy.cn,direct # 设置 Go Proxy
go mod download # 确保所有模块已下载(缓存命中时自动跳过)
- name: 📦 构建并推送 Docker 镜像
run: |
set -e
IMAGE_NAME="${{ matrix.service.image_name }}"
DOCKERFILE="${{ matrix.service.dockerfile }}"
DEPLOY_TAG="${{ needs.prepare.outputs.docker_tag }}"
REPO="${{ env.REPO }}"
FULL_IMAGE_NAME="${REPO}/${IMAGE_NAME}:${DEPLOY_TAG}"
echo "🚀 开始构建镜像: ${FULL_IMAGE_NAME} 从 ${DOCKERFILE}"
docker build -t "${FULL_IMAGE_NAME}" -f "${DOCKERFILE}" .
echo "⬆️ 推送镜像: ${FULL_IMAGE_NAME}"
docker push "${FULL_IMAGE_NAME}"
# ============================================================
# Job 3: 部署到服务器
# ============================================================
deploy:
runs-on: zero-ppanel-server
container: # <-- 新增deploy job 也在 Node.js 容器中运行
image: node:20.15.1
needs: [prepare, build]
# PR 不触发部署,只有直接推送才部署
if: github.event_name == 'push' && needs.prepare.outputs.has_changes == 'true'
steps:
- name: 📥 下载代码 (获取 docker-compose.cloud.yml)
uses: actions/checkout@v4
- name: 📂 传输 docker-compose.cloud.yml
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ env.SSH_HOST }}
username: ${{ env.SSH_USER }}
password: ${{ env.SSH_PASSWORD }}
port: ${{ env.SSH_PORT }}
source: "deploy/docker-compose.cloud.yml,deploy/etc,deploy/.env.example"
target: "${{ needs.prepare.outputs.deploy_path }}/"
strip_components: 1
- name: 🚀 部署服务
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ env.SSH_HOST }}
username: ${{ env.SSH_USER }}
password: ${{ env.SSH_PASSWORD }}
port: ${{ env.SSH_PORT }}
timeout: 300s
command_timeout: 600s
script: |
set -e
DEPLOY_PATH="${{ needs.prepare.outputs.deploy_path }}"
DOCKER_TAG="${{ needs.prepare.outputs.docker_tag }}"
REPO="${{ env.REPO }}"
DEPLOY_SERVICES="${{ needs.prepare.outputs.deploy_services }}"
echo "部署目录: ${DEPLOY_PATH}"
echo "镜像标签: ${DOCKER_TAG}"
cd ${DEPLOY_PATH}
# 保留已有业务配置,仅更新镜像仓库和标签
touch .env
grep -q '^PPANEL_TAG=' .env \
&& sed -i "s|^PPANEL_TAG=.*|PPANEL_TAG=${DOCKER_TAG}|" .env \
|| echo "PPANEL_TAG=${DOCKER_TAG}" >> .env
grep -q '^PPANEL_REPO=' .env \
&& sed -i "s|^PPANEL_REPO=.*|PPANEL_REPO=${REPO}|" .env \
|| echo "PPANEL_REPO=${REPO}" >> .env
if [ -z "${DEPLOY_SERVICES}" ]; then
echo "没有服务变更,跳过部署。"
exit 0
fi
# 拉取所有服务的最新镜像
docker-compose -f docker-compose.cloud.yml pull ${DEPLOY_SERVICES}
# 滚动更新所有 ppanel 服务
docker-compose -f docker-compose.cloud.yml up -d ${DEPLOY_SERVICES}
# 清理旧镜像
docker image prune -f || true
echo "✅ 部署完成,当前运行容器:"
docker-compose -f docker-compose.cloud.yml ps
# ============================================================
# Job 4: 通知
# ============================================================
notify:
runs-on: zero-ppanel-server
needs: [prepare, build, deploy]
if: always() && github.event_name == 'push'
steps:
- name: 📱 发送 Telegram 通知
uses: appleboy/telegram-action@master
with:
token: ${{ env.TG_BOT_TOKEN }}
to: ${{ env.TG_CHAT_ID }}
message: |
${{ needs.prepare.outputs.has_changes != 'true' && '⏭️ 无服务变更,已跳过构建与部署。' || ((needs.build.result == 'success' && needs.deploy.result == 'success') && '✅ 部署成功!' || '❌ 部署失败!') }}
📦 项目: zero-ppanel
🌿 分支: ${{ github.ref_name }}
🏷️ 标签: ${{ needs.prepare.outputs.docker_tag }}
📝 提交: `${{ github.sha }}`
👤 提交者: ${{ github.actor }}
🕐 时间: ${{ github.event.head_commit.timestamp }}
构建: ${{ needs.prepare.outputs.has_changes != 'true' && 'skipped(no changes)' || needs.build.result }} | 部署: ${{ needs.prepare.outputs.has_changes != 'true' && 'skipped(no changes)' || needs.deploy.result }}
${{ (needs.prepare.outputs.has_changes == 'true' && (needs.build.result != 'success' || needs.deploy.result != 'success')) && '⚠️ 请检查 Actions 日志获取详细信息' || '' }}
parse_mode: Markdown