publish / npm (push) Successful in 5s
The publish step now tries the built-in Gitea job token first, prints which user it belongs to, falls back to NPM_TOKEN when the registry rejects it, and reports which token actually published. A 409 keeps meaning 'already published', so a re-run stays harmless.
153 lines
6.7 KiB
YAML
153 lines
6.7 KiB
YAML
# 把打了 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)时这一步记为
|
||
# “已存在,本次跳过”,所以手动重跑同一个版本是安全的。
|
||
#
|
||
# 需要的凭据:
|
||
# 发包需要一个「对目标包命名空间有写权限」的令牌。工作流优先用 secret NPM_TOKEN
|
||
# (个人访问令牌,权限勾 write:package;仓库级或组织级 secret 均可),没配才退回
|
||
# 内置任务令牌 ${{ secrets.GITEA_TOKEN }}。
|
||
# 内置任务令牌能否发包,取决于实例/组织 Settings → Actions 的令牌权限(permissive 还是
|
||
# restricted,以及上限),以及该令牌是否覆盖目标的包命名空间;Gitea 文档只承诺它访问
|
||
# “本仓库”。因此**想稳定发布就配 NPM_TOKEN**,除非你实测过本实例的内置令牌可用。
|
||
# 工作流已声明 permissions: packages: write —— 没有这行时,restricted 模式下令牌是只读的。
|
||
#
|
||
# 依赖前提:
|
||
# - 实例启用了 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)"
|
||
|
||
# 内置任务令牌到底是谁、能不能写这个包命名空间:先打印身份,便于事后判断。
|
||
if [ -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 "内置任务令牌身份:${who:-(查询失败,可能是 curl 不可用或令牌被拒)}"
|
||
else
|
||
echo "实例没有注入内置任务令牌(secrets.GITEA_TOKEN 为空)"
|
||
fi
|
||
|
||
RESULT=""
|
||
# 结果分类: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 "${JOB_TOKEN:-}" ]; then
|
||
run_publish "内置任务令牌 GITEA_TOKEN" "${JOB_TOKEN}"
|
||
fi
|
||
if [ "${RESULT}" = "auth" ]; then
|
||
echo "内置任务令牌无法发布这个包(见上面的错误码),改用 NPM_TOKEN 重试"
|
||
RESULT=""
|
||
if [ -n "${NPM_TOKEN:-}" ]; then
|
||
run_publish "个人访问令牌 NPM_TOKEN" "${NPM_TOKEN}"
|
||
else
|
||
echo "没有配置 NPM_TOKEN,无处回退" >&2
|
||
exit 1
|
||
fi
|
||
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
|