Files
session-delete/.gitea/workflows/publish.yml
T
pyh acaca33c49 ci: publish with the token that actually works
The job token belongs to the gitea-actions pseudo user, which is not an organisation member, and Gitea grants package write only to members of the owning organisation; v1.0.2 proved it with E401 on the job token and a successful publish on the PAT. The step now prefers NPM_TOKEN and only falls back to the job token, printing its identity when it does.
2026-09-30 14:31:41 +08:00

143 lines
6.4 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.
# 把打了 v* 标签的版本发布到 Gitea 的 npm 包仓库。
#
# 触发方式:
# 1. 推送版本标签(推荐):git tag -a v1.0.1 -m "..." && git push origin v1.0.1
# 2. 仓库 → Actions → 选择本工作流 → Run workflow(手动,发布当前 ref 的版本)
#
# 本工作流刻意不使用任何 `uses:` 外部 action:runner 在中国大陆访问 github.com 往往超时
# (表现为所有步骤 cancelled,日志里是 dial tcp ...:443: i/o timeout),而 checkout 只是
# git fetch、Node 本来就在 runner 镜像里。这样工作流只依赖本实例的 git 与镜像自带的 node。
#
# 已发布的版本不会让工作流失败:注册表返回 409(version already exists)时这一步记为
# “已存在,本次跳过”,所以手动重跑同一个版本是安全的。
#
# 需要的凭据(实测结论,Gitea 1.27.2,本仓库 v1.0.2 那次发布):
# 内置任务令牌**不能**发布包。它在注册表眼里是伪用户 gitea-actions(id -2),不是组织成员,
# 而 Gitea 的包写权限要求「组织成员且具 admin/write 权限」——于是即使工作流声明了
# permissions: packages: write、组织也把 Actions 令牌权限设成宽松,npm publish 仍返回
# E401 Incorrect or missing password。(组织设置里那张“最大令牌权限”表也没有 packages 这一项。)
# 所以发布用 secret NPM_TOKEN = 个人访问令牌,权限勾 write:package;内置令牌只在没配它时兜底。
#
# 依赖前提:
# - 实例启用了 Actions 并注册了 act_runner;runs-on 的标签要与 runner 一致。
# - runner 镜像里要有 node 与 npm(Gitea 官方 runner-images 自带)。
# - 包名、`cordis.patch.yml` 的 name、客户端模块 id 三处必须一致,改名时别漏。
name: publish
on:
push:
tags:
- 'v*'
workflow_dispatch:
# 读取代码用于检出,向本组织写包。
permissions:
contents: read
packages: write
jobs:
npm:
runs-on: ubuntu-latest
env:
REGISTRY: https://gitea.iwake.top/api/packages/dsh-plugin/npm/
steps:
- name: Check out the pushed ref
run: |
set -eu
url="${GITHUB_SERVER_URL:-https://gitea.iwake.top}/${GITHUB_REPOSITORY:-dsh-plugin/session-delete}.git"
echo "从 ${url} 检出 ${GITHUB_REF}"
git init -q .
git remote add origin "${url}"
git fetch -q --depth 1 origin "${GITHUB_REF}"
git checkout -q FETCH_HEAD
git log --oneline -1
- name: Show the toolchain
run: |
set -eu
node -v
npm -v
- name: Read and check the version
id: version
run: |
set -eu
version="$(node -p "require('./package.json').version")"
name="$(node -p "require('./package.json').name")"
case "${GITHUB_REF}" in
refs/tags/*)
tag="${GITHUB_REF_NAME#v}"
if [ "$tag" != "$version" ]; then
echo "标签 ${GITHUB_REF_NAME} 与 package.json 的版本 ${version} 不一致" >&2
exit 1
fi
;;
esac
echo "name=${name}" >> "${GITHUB_OUTPUT}"
echo "version=${version}" >> "${GITHUB_OUTPUT}"
echo "目标:${name}@${version}"
- name: Pack (preview the published contents)
run: npm pack --dry-run
- name: Publish
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
JOB_TOKEN: ${{ secrets.GITEA_TOKEN }}
run: |
set -eu
# 作用域与默认注册表都指向本组织的 npm 仓库(默认注册表也要设,否则 npm 会拿
# registry.npmjs.org 的 packument 做“是否已发布”判断,甚至可能发错地方)。
# 注意:npm 不允许用 `npm config get` 读回 _authToken(会报 protected),所以不打印它。
npm config set registry "${REGISTRY}"
npm config set @dsh-plugin:registry "${REGISTRY}"
echo "registry = $(npm config get registry)"
RESULT=""
LAST_LABEL=""
# 结果分类:published 成功 / exists 版本已存在(不视为失败)/ auth 令牌被拒 / error 其他
run_publish() {
label="$1"
token="$2"
LAST_LABEL="${label}"
echo "--- 用 ${label} 发布 ---"
npm config set "//gitea.iwake.top/api/packages/dsh-plugin/npm/:_authToken" "${token}"
set +e
output="$(npm publish --registry "${REGISTRY}" --access public 2>&1)"
status=$?
set -e
printf '%s\n' "${output}"
if [ "${status}" -eq 0 ]; then RESULT="published"; return 0; fi
if printf '%s' "${output}" | grep -Eqi 'E409|already exists|previously published|cannot publish over'; then RESULT="exists"; return 0; fi
if printf '%s' "${output}" | grep -Eqi 'E401|E403|EOTP|unauthorized|forbidden'; then RESULT="auth"; return 0; fi
RESULT="error"
return 1
}
if [ -n "${NPM_TOKEN:-}" ]; then
run_publish "个人访问令牌 NPM_TOKEN" "${NPM_TOKEN}"
elif [ -n "${JOB_TOKEN:-}" ]; then
# 兜底路径:本实例实测内置令牌写不了包命名空间(见文件头),这里仍会打印它的身份,
# 方便在其它实例上判断到底是"令牌不存在"还是"权限不够"。
server="${GITHUB_SERVER_URL:-https://gitea.iwake.top}"
who="$(curl -fsS -H "Authorization: token ${JOB_TOKEN}" "${server}/api/v1/user" 2>/dev/null | head -c 300 || true)"
echo "没有配置 NPM_TOKEN,退回内置任务令牌;它的身份是:${who:-(查询失败)}"
run_publish "内置任务令牌 GITEA_TOKEN" "${JOB_TOKEN}"
else
echo "既没有 NPM_TOKEN 也没有内置任务令牌,无法发布" >&2
exit 1
fi
case "${RESULT}" in
published)
echo "已发布 ${{ steps.version.outputs.name }}@${{ steps.version.outputs.version }}(本次用的是 ${LAST_LABEL:-令牌})"
;;
exists)
echo "${{ steps.version.outputs.name }}@${{ steps.version.outputs.version }} 已存在,本次跳过(不算失败)"
;;
*)
echo "发布失败" >&2
exit 1
;;
esac