Files
lunar-mini/.gitea/workflows/server-deploy.yml
T
goukiandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> 7c7880bbd8
Build and Publish Commercial Web / build (push) Failing after 3m18s
Build and Publish Server / build (push) Successful in 9m33s
fix(ci): GOPROXY 与 npm 镜像源修复两条流水线的依赖下载失败
server-deploy 在 Install dependencies 失败、web-deploy 在 Install pnpm
失败——亚洲 runner 直连 proxy.golang.org / registry.npmjs.org 不稳定。
Go 侧加 goproxy.cn 优先回落官方源;pnpm 安装与前端依赖安装走
registry.npmmirror.com。

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-21 08:34:04 +00:00

217 lines
9.2 KiB
YAML
Raw 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 and Publish Server
on:
push:
branches:
- main
paths:
- "server/**"
- ".gitea/workflows/server-deploy.yml"
jobs:
build:
# 标准标签:hk / bt-runner 均带 ubuntu-latest,任一空闲 runner 接单
runs-on: ubuntu-latest
steps:
# 精简 runner(Alpine)无 node,无法跑 action-checkout;直接用 git 浅克隆
- name: Checkout
env:
REPO_URL: ${{ gitea.server_url }}/${{ gitea.repository }}
REF_NAME: ${{ gitea.ref_name }}
run: |
git init -q .
git remote add origin "$REPO_URL"
git fetch -q --depth 20 origin "$REF_NAME"
git checkout -q FETCH_HEAD
git log --oneline -3
- name: Ensure curl available
run: |
# 精简 runner(Alpine 等)可能未预装 curl,发布 release 需要它
if ! command -v curl >/dev/null 2>&1; then
if command -v apk >/dev/null 2>&1; then apk add --no-cache curl
elif command -v apt-get >/dev/null 2>&1; then apt-get update -qq && apt-get install -y -qq curl
elif command -v dnf >/dev/null 2>&1; then dnf install -y -q curl
else echo "无法安装 curl"; exit 1; fi
fi
curl --version | head -1
- name: Prepare Go toolchain
run: |
# 优先复用 runner 宿主机缓存的工具链(工作目录持久化)
TOOLDIR="$RUNNER_WORKSPACE/.lunar-toolchain"
mkdir -p "$TOOLDIR"
if [ -x "$TOOLDIR/go/bin/go" ]; then
echo "复用缓存 Go 工具链"
else
# 官方源与阿里云镜像双通道,先到先用
wget -q --tries=2 --timeout=60 -O "$TOOLDIR/go.tgz" \
"https://go.dev/dl/go1.22.10.linux-amd64.tar.gz" \
|| wget -q --tries=2 --timeout=60 -O "$TOOLDIR/go.tgz" \
"https://mirrors.aliyun.com/golang/go1.22.10.linux-amd64.tar.gz"
rm -rf "$TOOLDIR/go"
tar -C "$TOOLDIR" -xzf "$TOOLDIR/go.tgz"
rm -f "$TOOLDIR/go.tgz"
fi
"$TOOLDIR/go/bin/go" version
echo "LUNAR_GO=$TOOLDIR/go/bin/go" >> "$GITEA_ENV"
- name: Install dependencies
working-directory: server
run: |
export HOME="$RUNNER_WORKSPACE"
# 国内 runner 优先 goproxy.cn,海外 runner 自动回落官方源
export GOPROXY="https://goproxy.cn,https://proxy.golang.org,direct"
"$LUNAR_GO" mod download
- name: Run tests
working-directory: server
run: |
export HOME="$RUNNER_WORKSPACE"
"$LUNAR_GO" test ./...
- name: Build application
working-directory: server
env:
GITEA_SHA: ${{ gitea.sha }}
GITEA_RUN_NUMBER: ${{ gitea.run_number }}
run: |
export HOME="$RUNNER_WORKSPACE"
mkdir -p bin
# 生成版本号(基线 1.1 + 构建编号,与小程序版本段对齐)
VERSION="1.1.${GITEA_RUN_NUMBER}"
BUILD_TIME="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
COMMIT_SHORT="${GITEA_SHA:0:7}"
echo "Building server version: $VERSION"
# ldflags 注入版本信息;目标平台为 doc79(linux/amd64)
# 本流水线构建的是小程序接口二进制(cmd/mini);
# 商业版 Web(cmd/web)由 web-deploy.yml 单独构建发布
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 "$LUNAR_GO" build -ldflags "\
-X main.Version=$VERSION \
-X main.BuildTime=$BUILD_TIME \
-X main.CommitSha=$COMMIT_SHORT" \
-o bin/server ./cmd/mini
# 版本元数据随包分发,便于服务器侧追溯
cat > bin/version.env <<EOF
APP_VERSION=$VERSION
APP_BUILD_TIME=$BUILD_TIME
APP_COMMIT_SHA=$COMMIT_SHORT
EOF
cat bin/version.env
# 注意:不写入 GITEA_ENV,避免跨步骤/跨运行残留值干扰发布步骤
- name: Create deployment package
working-directory: server
run: |
mkdir -p deploy
cp -r bin/ deploy/
cp -r migrations/ deploy/
cp -r scripts/ deploy/
# 管理后台已迁移到商业版 Web 服务(cmd/web),
# 小程序接口二进制不再注册 /admin,无需随包发布 web/ 静态资源
tar -czf deploy.tar.gz deploy/
sha256sum deploy.tar.gz
- name: Publish release with deployment package
env:
GITEA_SHA: ${{ gitea.sha }}
GITEA_RUN_NUMBER: ${{ gitea.run_number }}
LUNAR_PUBLISH_TOKEN: ${{ secrets.LUNAR_PUBLISH_TOKEN }}
run: |
set -e
# 自行计算版本号;绝不复用环境中的 SERVER_VERSION(GITEA_ENV 会跨步骤持久化,
# 可能残留早期运行的旧值,曾导致构建 1.1.48 却发布成 1.0.48)
unset SERVER_VERSION
VERSION="1.1.${GITEA_RUN_NUMBER}"
TAG="server-v${VERSION}"
API="https://gitea.neatcn.com/api/v1/repos/gouki/lunar-mini"
# 优先用仓库 Secret 令牌(GITEA_TOKEN 内建令牌在部分 runner 版本不注入)
TOKEN="${LUNAR_PUBLISH_TOKEN:-$GITEA_TOKEN}"
test -n "$TOKEN"
AUTH="Authorization: token $TOKEN"
# 幂等:同 tag 已存在则先删除(重跑场景);不依赖 python3,纯 grep/sed 解析
EXISTING=$(curl -sS -H "$AUTH" "$API/releases/tags/$TAG" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2 || true)
if [ -n "$EXISTING" ]; then
curl -sS -X DELETE -H "$AUTH" "$API/releases/$EXISTING" -o /dev/null -w "删除旧 release: HTTP %{http_code}\n"
fi
CREATE_RESP=$(curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
-d "{\"tag_name\":\"$TAG\",\"name\":\"server $VERSION\",\"target_commitish\":\"main\",\"body\":\"CI 自动构建,commit ${GITEA_SHA:0:7}。doc79 由 deploy-watch.sh 拉取本附件完成部署。\"}" \
"$API/releases")
RELEASE_ID=$(printf '%s' "$CREATE_RESP" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2 || true)
if [ -z "$RELEASE_ID" ]; then
echo "创建 release 失败,API 响应: $CREATE_RESP"
exit 1
fi
echo "Release created: id=$RELEASE_ID tag=$TAG"
curl -sS -X POST -H "$AUTH" \
-F "attachment=@server/deploy.tar.gz" \
"$API/releases/$RELEASE_ID/assets" \
-o /dev/null -w "附件上传: HTTP %{http_code}\n"
echo "发布地址: https://gitea.neatcn.com/gouki/lunar-mini/releases/tag/$TAG"
- name: Cleanup old releases (keep latest 10)
env:
LUNAR_PUBLISH_TOKEN: ${{ secrets.LUNAR_PUBLISH_TOKEN }}
run: |
# 只保留最近 10 个 server-v* 发布,避免附件无限堆积占满磁盘
API="https://gitea.neatcn.com/api/v1/repos/gouki/lunar-mini"
TOKEN="${LUNAR_PUBLISH_TOKEN:-$GITEA_TOKEN}"
AUTH="Authorization: token $TOKEN"
KEEP=10
# Gitea Release JSON 中 id 与 tag_name 相邻且按新到旧排序;
# 附件随 release 删除一并清理
PAIRS=$(curl -sS -H "$AUTH" "$API/releases?limit=50" \
| grep -oE '"id":[0-9]+,"tag_name":"server-v[^"]*"' || true)
TOTAL=$(printf '%s\n' "$PAIRS" | grep -c '"id"' || true)
if [ "$TOTAL" -le "$KEEP" ]; then
echo "当前 $TOTAL 个发布版本,未超过 $KEEP,无需清理"
exit 0
fi
printf '%s\n' "$PAIRS" | tail -n +$((KEEP + 1)) | while IFS= read -r line; do
[ -z "$line" ] && continue
RID=$(printf '%s' "$line" | grep -oE '"id":[0-9]+' | cut -d: -f2)
RTAG=$(printf '%s' "$line" | sed 's/.*"tag_name":"\([^"]*\)".*/\1/')
curl -sS -X DELETE -H "$AUTH" "$API/releases/$RID" -o /dev/null -w "删除旧发布 $RTAG: HTTP %{http_code}\n"
# 同步删除自动创建的 tag,避免 tag 堆积
curl -sS -X DELETE -H "$AUTH" "$API/tags/$RTAG" -o /dev/null -w "删除 tag $RTAG: HTTP %{http_code}\n"
done
- name: Send success notification
if: success()
env:
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
GITEA_RUN_NUMBER: ${{ gitea.run_number }}
run: |
VERSION="1.1.${GITEA_RUN_NUMBER}"
bash .gitea/scripts/notify.sh success \
"后端构建发布成功" \
"版本: v${VERSION}\n产物: releases/tag/server-v${VERSION}\ndoc79 将自动拉取部署" || echo "通知发送失败,不影响主流程"
- name: Send failure notification
if: failure()
env:
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
run: |
bash .gitea/scripts/notify.sh failure \
"后端构建失败" \
"请检查 Actions 日志了解失败原因" || echo "通知发送失败"
- name: Cleanup
if: always()
run: |
rm -rf server/deploy/
rm -f server/deploy.tar.gz