diff --git a/.gitea/workflows/publish.yml b/.gitea/workflows/publish.yml index 8d2130c..ebc7317 100644 --- a/.gitea/workflows/publish.yml +++ b/.gitea/workflows/publish.yml @@ -2,24 +2,20 @@ # # 触发方式: # 1. 推送版本标签(推荐):git tag -a v1.0.1 -m "..." && git push origin v1.0.1 -# 2. 仓库 → Actions → 选择本工作流 → Run workflow(手动,发布当前 commit 的版本) +# 2. 仓库 → Actions → 选择本工作流 → Run workflow(手动,发布当前 ref 的版本) +# +# 已发布的版本会自动跳过:手动重跑同一个版本不会失败,只是什么都不发。 # # 需要的权限: -# 默认使用 Gitea 内置的任务令牌 ${{ secrets.GITEA_TOKEN }} 发布,无需额外配置密钥。 +# 默认使用 Gitea 内置的任务令牌 ${{ secrets.GITEA_TOKEN }} 发布。 # 若实例/组织把 Actions 的令牌上限设为只读,或任务令牌对包命名空间没有写权限, -# 请在仓库 Settings → Actions → Secrets 里添加 NPM_TOKEN = 一个带 package 写权限的个人访问令牌, -# 工作流会自动优先使用它(见最后一个步骤)。 -# -# 失败排查: -# 发布步骤在 1 秒内失败通常是鉴权问题——先看该步骤日志里 `npm whoami` 的输出: -# 打印出用户名说明令牌可用,报 E401/E403 说明令牌无效或权限不足。 +# 就配置一个带 write:package 权限的个人访问令牌: +# 仓库(或组织)Settings → Actions → Secrets → NPM_TOKEN。工作流会自动优先使用它。 # # 依赖前提: -# - 实例启用了 Actions,且注册了 act_runner(否则工作流只会排队)。 +# - 实例启用了 Actions 并注册了 act_runner;runs-on 的标签要与 runner 一致。 # - runner 需要能拉取 actions/checkout 与 actions/setup-node(默认从 github.com 取)。 -# 若 runner 在无外网环境,请在 app.ini 里设 actions.DEFAULT_ACTIONS_URL = self 并把这两个 -# action 镜像到自己的实例上。 -# - runs-on 的标签要与 runner 配置的标签一致(默认 ubuntu-latest;自建 runner 常用 docker/ubuntu-22.04 等)。 +# - 包名、`cordis.patch.yml` 的 name、客户端模块 id 三处必须一致,改名时别漏。 name: publish on: @@ -48,7 +44,8 @@ jobs: node-version: '22' registry-url: https://gitea.iwake.top/api/packages/dsh-plugin/npm/ - - name: Check the tag against package.json + - name: Read and check the version + id: version run: | set -eu version="$(node -p "require('./package.json').version")" @@ -62,15 +59,29 @@ jobs: fi ;; esac - echo "将发布 ${name}@${version}" + 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: Skip when this version is already published + id: published + run: | + set -eu + spec="${{ steps.version.outputs.name }}@${{ steps.version.outputs.version }}" + # 注册表里查得到就说明这个版本发布过了(Gitea 不允许同版本重复发布)。 + if npm view "${spec}" version --registry "${REGISTRY}" > /dev/null 2>&1; then + echo "already=true" >> "${GITHUB_OUTPUT}" + echo "${spec} 已经发布过,本次跳过" + else + echo "already=false" >> "${GITHUB_OUTPUT}" + fi + - name: Publish + if: steps.published.outputs.already == 'false' env: - # 优先使用带 package 写权限的 PAT(仓库 Settings → Actions → Secrets 里的 NPM_TOKEN); - # 没有配置时退回 Gitea 内置任务令牌 GITEA_TOKEN。 NPM_TOKEN: ${{ secrets.NPM_TOKEN }} JOB_TOKEN: ${{ secrets.GITEA_TOKEN }} run: | @@ -81,11 +92,8 @@ jobs: exit 1 fi # 作用域与默认注册表都指向本组织的 npm 仓库,并把令牌写进本机 .npmrc。 + # 注意:npm 不允许用 `npm config get` 读回 _authToken(会报 protected),所以不打印它。 npm config set @dsh-plugin:registry "${REGISTRY}" npm config set "//gitea.iwake.top/api/packages/dsh-plugin/npm/:_authToken" "${token}" echo "registry = $(npm config get registry)" - echo "auth = $(npm config get "//gitea.iwake.top/api/packages/dsh-plugin/npm/:_authToken" | sed 's/./*/g')" - # 鉴权自检:能取到用户就说明令牌对得上这个注册表(包不存在时报 404 也算通过)。 - npm whoami --registry "${REGISTRY}" || true npm publish --registry "${REGISTRY}" --access public - diff --git a/README.md b/README.md index aca0479..a60ef8f 100644 --- a/README.md +++ b/README.md @@ -88,8 +88,9 @@ git tag -a v1.0.1 -m "v1.0.1" && git push origin v1.0.1 前提与排查: - 实例启用了 Actions 并注册了 runner(`runs-on: ubuntu-latest` 要与 runner 的标签一致); -- 若组织把 Actions 令牌上限设成只读,或任务令牌对包命名空间没有写权限,发布步骤会很快失败:在仓库 Settings → Actions → Secrets 添加 `NPM_TOKEN` 即可,工作流会自动改用它; -- 失败时先看该步骤日志里 `npm whoami` 的输出:打印出用户名说明令牌可用(错误就只可能是版本已存在或包名不合法),报 `E401/E403` 则是令牌无效或权限不足。 +- 若组织把 Actions 令牌上限设成只读,或任务令牌对包命名空间没有写权限,发布步骤会很快失败:配置 `NPM_TOKEN` 即可,工作流会自动改用它; +- 已发布的版本会在发布前被检测到并**跳过**,所以手动重跑同一个版本是安全的(不会失败,也不再重复上传); +- 真失败时看 `Publish` 步骤日志:`registry =` 那行确认注册表地址,`npm error code` 给出原因(`E401/E403` = 令牌无效或权限不足)。注意 Gitea 的 npm 注册表**不实现** `/-/whoami`,`npm whoami` 返回 404 属正常现象;`npm config get ...:_authToken` 也必然报 protected,因为 npm 禁止读回令牌。 手工发布等价于: