diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml index 36fabb0..a7f9d77 100644 --- a/.gitea/workflows/release.yml +++ b/.gitea/workflows/release.yml @@ -1,9 +1,14 @@ # 发版工作流:推送 v* 标签 → 构建前端并嵌入 → 交叉编译多平台二进制 -# → 生成发布说明 → 创建 Gitea Release 并上传全部产物。 +# → 生成发布说明 → 通过 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: @@ -14,52 +19,80 @@ on: permissions: contents: write +env: + SITE: https://git.airnan.cn + REPO: wangairnan/pure-note + jobs: release: runs-on: ubuntu-latest - # runner 默认镜像无 node,而 checkout/setup-go/release 等 JS 类 action 依赖 node: - # 显式指定含 node 与 git 的镜像;node 已就位则无需 setup-node(npm 直接可用) container: image: node:24-bookworm steps: # 完整历史:供 git log 生成上一个 tag 以来的变更日志 - name: 检出代码 - uses: https://gitea.com/actions/checkout@v4 - with: - fetch-depth: 0 + run: | + git clone "$SITE/$REPO.git" . + git checkout --detach "$GITEA_REF_NAME" + git log --oneline -1 - name: 安装 Go(版本取自 go.mod) - uses: https://gitea.com/actions/setup-go@v5 - with: - go-version-file: 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 + run: make web sync-assets || (npm config set registry https://registry.npmmirror.com && make web sync-assets) - name: 交叉编译发布产物 - run: scripts/build-release.sh "${GITEA_REF_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 "${GITEA_REF_NAME}" # 首个 tag 无上一版本,变更日志段自动省略 - name: 生成发布说明 run: | - prev=$(git describe --tags --abbrev=0 "${GITEA_SHA}^" 2>/dev/null || true) + set -euo pipefail + prev=$(git describe --tags --abbrev=0 "HEAD^" 2>/dev/null || true) + short=$(git rev-parse --short HEAD) { echo "## pn ${GITEA_REF_NAME}" echo - echo "- commit: \`${GITEA_SHA}\`" + 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}..${GITEA_SHA}" | sed 's/^/- /' + git log --oneline --no-decorate "${prev}..HEAD" | sed 's/^/- /' fi } > release-notes.md cat release-notes.md - name: 创建 Release 并上传产物 - uses: https://gitea.com/actions/release-action@main - with: - files: |- - dist/* - body_path: release-notes.md + env: + TOKEN: ${{ secrets.GITEA_TOKEN || secrets.GITHUB_TOKEN }} + 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.GITEA_REF_NAME,name:"pn "+process.env.GITEA_REF_NAME,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/${GITEA_REF_NAME}" -H "$AUTH") + RID=$(node -e 'let s="";process.stdin.on("data",d=>s+=d);process.stdin.on("end",()=>process.stdout.write(String(JSON.parse(s).id))' <<<"$REL") + echo "==> release id=$RID" + 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/${GITEA_REF_NAME}"