Files
wangairnan b1ea89ba3d
Release / release (push) Successful in 5m16s
fix(ci): 发版重跑幂等:刷新发布说明并替换旧附件
同 tag 重跑时 POST 冲突走查询回退,需 PATCH 以本次构建为准补写
发布说明,并先清空旧附件再重传,避免同名副本。
2026-09-09 23:31:26 +08:00

110 lines
4.7 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.
# 发版工作流:推送 v* 标签 → 构建前端并嵌入 → 交叉编译多平台二进制
# → 生成发布说明 → 通过 Gitea API 创建 Release 并上传产物。
#
# 发版操作:
# git tag -a v0.0.1 -m "v0.0.1"
# git push origin v0.0.1
#
# 实现说明:刻意不使用任何 JS 类 action(checkout/setup-*/release-*)——
# 自托管 runner 常把实例地址注册成 localhost,job 容器内不可达,
# 且默认容器镜像可能没有 node。此处全程纯 run 步骤 + 公网域名访问实例,
# 容器固定 node:24-bookworm(自带 node 与 git,npm 构建前端所需)。
name: Release
on:
push:
tags:
- 'v*'
permissions:
contents: write
env:
SITE: https://git.airnan.cn
REPO: wangairnan/pure-note
jobs:
release:
runs-on: ubuntu-latest
container:
image: node:24-bookworm
env:
# 这台 runner 只保证 GITHUB_* 兼容层(GITEA_REF_NAME 等别名不可靠),
# 一律经表达式显式注入,不直接读 GITEA_* 环境变量
TAG: ${{ github.ref_name }}
TOKEN: ${{ secrets.GITHUB_TOKEN || secrets.GITEA_TOKEN || secrets.FORGEJO_TOKEN }}
steps:
# 完整历史:供 git log 生成上一个 tag 以来的变更日志
- name: 检出代码
run: |
git clone "$SITE/$REPO.git" .
git checkout --detach "$TAG"
git log --oneline -1
- name: 安装 Go(版本取自 go.mod)
run: |
set -euo pipefail
GOVER=$(awk '$1 == "go" {print $2}' go.mod)
echo "==> 安装 Go $GOVER"
# go.dev 在部分网络不可达,回退官方中国镜像
curl -fsSL "https://go.dev/dl/go${GOVER}.linux-amd64.tar.gz" -o /tmp/go.tgz \
|| curl -fsSL "https://golang.google.cn/dl/go${GOVER}.linux-amd64.tar.gz" -o /tmp/go.tgz
tar -C /usr/local -xzf /tmp/go.tgz
/usr/local/go/bin/go version
- name: 构建前端并嵌入(web/dist → internal/webui/dist)
run: make web sync-assets || (npm config set registry https://registry.npmmirror.com && make web sync-assets)
- name: 交叉编译发布产物
run: |
set -euo pipefail
export PATH=/usr/local/go/bin:$PATH
# 模块代理双层回退:官方代理不可达时走 goproxy.cn
export GOPROXY=https://proxy.golang.org,https://goproxy.cn,direct
scripts/build-release.sh "$TAG"
# 首个 tag 无上一版本,变更日志段自动省略
- name: 生成发布说明
run: |
set -euo pipefail
prev=$(git describe --tags --abbrev=0 "HEAD^" 2>/dev/null || true)
short=$(git rev-parse --short HEAD)
{
echo "## pn ${TAG}"
echo
echo "- commit: \`$short\`"
echo "- 构建时间: $(date -u '+%Y-%m-%dT%H:%M:%SZ')"
if [ -n "$prev" ]; then
echo
echo "### 自 ${prev} 以来的变更"
echo
git log --oneline --no-decorate "${prev}..HEAD" | sed 's/^/- /'
fi
} > release-notes.md
cat release-notes.md
# 重跑幂等:release 已存在时更新说明、清旧附件后重传
- name: 创建 Release 并上传产物
run: |
set -euo pipefail
API="$SITE/api/v1/repos/$REPO"
AUTH="Authorization: token ${TOKEN}"
REQ=$(node -e 'const fs=require("fs");process.stdout.write(JSON.stringify({tag_name:process.env.TAG,name:"pn "+process.env.TAG,body:fs.readFileSync("release-notes.md","utf8")}))')
# 同 tag release 已存在(如失败重跑)时回退为查询
REL=$(curl -fsS -X POST "$API/releases" -H "$AUTH" -H 'Content-Type: application/json' -d "$REQ") \
|| REL=$(curl -fsS "$API/releases/tags/${TAG}" -H "$AUTH")
RID=$(REL="$REL" node -e 'process.stdout.write(String(JSON.parse(process.env.REL).id))')
echo "==> release id=$RID"
# 发布说明以本次构建为准(回退路径下 POST 已冲突,须补写)
curl -fsS -X PATCH "$API/releases/$RID" -H "$AUTH" -H 'Content-Type: application/json' -d "$REQ" >/dev/null
# 清除旧附件,避免重跑产生同名副本
ASSETS=$(curl -fsS "$API/releases/$RID/assets" -H "$AUTH")
ASSETS="$ASSETS" node -e 'JSON.parse(process.env.ASSETS).forEach(a=>console.log(a.id))' | while read -r aid; do
curl -fsS -X DELETE "$API/releases/$RID/assets/$aid" -H "$AUTH" >/dev/null
done
for f in dist/*; do
echo "==> 上传 $(basename "$f")"
curl -fsS -X POST "$API/releases/$RID/assets?name=$(basename "$f")" -H "$AUTH" -F "attachment=@$f" >/dev/null
done
echo "==> 完成:$SITE/$REPO/releases/tag/${TAG}"