From f777cdebd7ac83483f11e34eefd08e1d1a3efcfe Mon Sep 17 00:00:00 2001 From: gewuyou <95328647+GeWuYou@users.noreply.github.com> Date: Sun, 26 Apr 2026 11:59:06 +0800 Subject: [PATCH] =?UTF-8?q?ci(release):=20=E6=94=B6=E6=95=9B=20PAT=20?= =?UTF-8?q?=E6=A0=A1=E9=AA=8C=E5=B9=B6=E5=BD=92=E6=A1=A3=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E8=B7=9F=E8=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增复用的 PAT 校验 composite action,并统一 preview 与 release 的鉴权入口 - 修复 read-only PAT 会误过 API 探活的问题,提前校验 push 权限并清理临时文件 - 归档 semantic-release 迁移历史完成项,精简 active tracking 与 trace 恢复点 --- .github/actions/validate-pat/action.yml | 66 +++++++++++++ .github/workflows/auto-tag.yml | 76 +++------------ .../semantic-release-versioning-2026-04-26.md | 77 +++++++++++++++ .../semantic-release-versioning-tracking.md | 93 ++++--------------- .../semantic-release-versioning-trace.md | 16 ++-- 5 files changed, 184 insertions(+), 144 deletions(-) create mode 100644 .github/actions/validate-pat/action.yml create mode 100644 ai-plan/public/semantic-release-versioning/archive/todos/semantic-release-versioning-2026-04-26.md diff --git a/.github/actions/validate-pat/action.yml b/.github/actions/validate-pat/action.yml new file mode 100644 index 00000000..534f183b --- /dev/null +++ b/.github/actions/validate-pat/action.yml @@ -0,0 +1,66 @@ +name: Validate PAT +description: Validate that the release PAT can access the repository and push tags. + +inputs: + pat-token: + description: Personal access token used by semantic-release. + required: true + repo-api-url: + description: GitHub repository API URL, for example https://api.github.com/repos/owner/repo. + required: true + repository: + description: Repository slug used in error messages. + required: true + missing-token-message: + description: Error message emitted when the PAT is absent. + required: true + +runs: + using: composite + steps: + - name: Validate PAT can push + shell: bash + env: + PAT_TOKEN: ${{ inputs.pat-token }} + REPO_API_URL: ${{ inputs.repo-api-url }} + REPOSITORY: ${{ inputs.repository }} + MISSING_TOKEN_MESSAGE: ${{ inputs.missing-token-message }} + run: | + if [ -z "${PAT_TOKEN}" ]; then + echo "::error::${MISSING_TOKEN_MESSAGE}" + exit 1 + fi + + response_file="$(mktemp)" + trap 'rm -f "${response_file}"' EXIT + + status_code="$( + curl -sS -o "${response_file}" -w "%{http_code}" \ + -H "Authorization: Bearer ${PAT_TOKEN}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "${REPO_API_URL}" + )" + + case "${status_code}" in + 200) + # The repository endpoint returns 200 for read-only tokens as well. + # semantic-release still performs a remote push probe, so require push permission here. + push_ok="$(jq -r '.permissions.push // false' "${response_file}")" + if [ "${push_ok}" != "true" ]; then + echo "::error::PAT_TOKEN can read ${REPOSITORY} but lacks push permission. semantic-release requires contents:write." + cat "${response_file}" + exit 1 + fi + ;; + 401|403) + echo "::error::PAT_TOKEN is invalid or lacks access to ${REPOSITORY} (HTTP ${status_code})." + cat "${response_file}" + exit 1 + ;; + *) + echo "::error::Failed to validate PAT_TOKEN against ${REPO_API_URL} (HTTP ${status_code})." + cat "${response_file}" + exit 1 + ;; + esac diff --git a/.github/workflows/auto-tag.yml b/.github/workflows/auto-tag.yml index 51e51095..4e6b6017 100644 --- a/.github/workflows/auto-tag.yml +++ b/.github/workflows/auto-tag.yml @@ -30,38 +30,12 @@ jobs: # semantic-release 在 dry-run 中仍会执行一次 git push --dry-run 权限探测。 # 这里提前要求与正式 release 相同的 PAT,避免 github-actions[bot] 因只读上下文触发误导性的 403。 - name: Validate PAT token - env: - PAT_TOKEN: ${{ secrets.PAT_TOKEN }} - REPO_API_URL: ${{ github.api_url }}/repos/${{ github.repository }} - run: | - if [ -z "${PAT_TOKEN}" ]; then - echo "::error::PAT_TOKEN is required because semantic-release preview performs a git push --dry-run permission check." - exit 1 - fi - - response_file="$(mktemp)" - status_code="$( - curl -sS -o "${response_file}" -w "%{http_code}" \ - -H "Authorization: Bearer ${PAT_TOKEN}" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "${REPO_API_URL}" - )" - - case "${status_code}" in - 200) - ;; - 401|403) - echo "::error::PAT_TOKEN is invalid or lacks access to ${GITHUB_REPOSITORY} (HTTP ${status_code})." - cat "${response_file}" - exit 1 - ;; - *) - echo "::error::Failed to validate PAT_TOKEN against ${REPO_API_URL} (HTTP ${status_code})." - cat "${response_file}" - exit 1 - ;; - esac + uses: ./.github/actions/validate-pat + with: + pat-token: ${{ secrets.PAT_TOKEN }} + repo-api-url: ${{ github.api_url }}/repos/${{ github.repository }} + repository: ${{ github.repository }} + missing-token-message: PAT_TOKEN is required because semantic-release preview performs a git push --dry-run permission check. # preview 始终先运行,用于给当前 SHA 生成待发布版本预览。 - name: Semantic release preview @@ -130,38 +104,12 @@ jobs: ref: ${{ github.sha }} - name: Validate PAT token - env: - PAT_TOKEN: ${{ secrets.PAT_TOKEN }} - REPO_API_URL: ${{ github.api_url }}/repos/${{ github.repository }} - run: | - if [ -z "${PAT_TOKEN}" ]; then - echo "::error::PAT_TOKEN is required because a tag created with GITHUB_TOKEN will not trigger publish.yml." - exit 1 - fi - - response_file="$(mktemp)" - status_code="$( - curl -sS -o "${response_file}" -w "%{http_code}" \ - -H "Authorization: Bearer ${PAT_TOKEN}" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - "${REPO_API_URL}" - )" - - case "${status_code}" in - 200) - ;; - 401|403) - echo "::error::PAT_TOKEN is invalid or lacks access to ${GITHUB_REPOSITORY} (HTTP ${status_code})." - cat "${response_file}" - exit 1 - ;; - *) - echo "::error::Failed to validate PAT_TOKEN against ${REPO_API_URL} (HTTP ${status_code})." - cat "${response_file}" - exit 1 - ;; - esac + uses: ./.github/actions/validate-pat + with: + pat-token: ${{ secrets.PAT_TOKEN }} + repo-api-url: ${{ github.api_url }}/repos/${{ github.repository }} + repository: ${{ github.repository }} + missing-token-message: PAT_TOKEN is required because a tag created with GITHUB_TOKEN will not trigger publish.yml. - name: Semantic release id: semantic_release diff --git a/ai-plan/public/semantic-release-versioning/archive/todos/semantic-release-versioning-2026-04-26.md b/ai-plan/public/semantic-release-versioning/archive/todos/semantic-release-versioning-2026-04-26.md new file mode 100644 index 00000000..131c995f --- /dev/null +++ b/ai-plan/public/semantic-release-versioning/archive/todos/semantic-release-versioning-2026-04-26.md @@ -0,0 +1,77 @@ +# Semantic Release 版本迁移归档(2026-04-26) + +## 归档范围 + +- Phase 1 初始迁移结论 +- `SEMREL-RP-001` 到 `SEMREL-RP-003` 期间已稳定的 PR review 修复 +- active tracking 中已不需要继续占据默认恢复入口的历史验证明细 + +## 历史完成项 + +- 已确认当前版本入口为 `.github/workflows/auto-tag.yml`,现状始终执行 `PATCH + 1` +- 已确认当前 `.github/workflows/publish.yml` 由 tag 触发,并负责 `.nupkg` 打包、发布和 GitHub Release +- 已确认最新 tag 为 `v0.0.222` +- 已确认 `v0.0.222..HEAD` 之间存在 `feat(...)` 提交,按目标规则首次 dry-run 预期版本应为 `v0.1.0` +- 已新增 `.releaserc.json`,仅保留 `@semantic-release/commit-analyzer` 与 + `@semantic-release/release-notes-generator`,避免 `semantic-release` 直接创建 GitHub Release +- 已将 `.releaserc.json` 的 `commit-analyzer` / `release-notes-generator` 同步切换到 `conventionalcommits` + preset,并显式声明: + - `breaking -> major` + - `revert -> patch` + - `feat -> minor` + - `fix/perf/refactor -> patch` + - `docs/test/chore/build/ci/style -> no release` +- 已将 `.github/workflows/auto-tag.yml` 重写为: + - `workflow_dispatch` 启动后总是先跑 `preview` + - `preview` 只执行 dry-run,输出 `last_tag`、`next_version` 与 `next_tag` + - `release` job 依赖 `preview` 输出,并通过 `release-approval` environment 暂停等待人工确认 + - 人工批准后,`release` 在同一 SHA 上执行真实打 tag,并把 preview / release 结果都写入 job summary +- 已按上一轮 PR review 修复 `auto-tag.yml`: + - 删除 preview job 中与 job 级 `if` 重复的运行时分支校验 + - 为 release job 增加 `needs.preview.result == 'success'` 守卫 + - 为 preview / release 的 semantic-release action 显式安装 `conventional-changelog-conventionalcommits@9.1.0` + - 在 release 前通过 GitHub API 校验 `PAT_TOKEN` 是否真实可访问当前仓库 + - 在 preview / release summary 中补充 snapshot 语义与生成的 release notes +- 已修复 preview 链路的第一轮鉴权前提: + - 在 preview 开始前通过 GitHub API 校验 `PAT_TOKEN` + - 将 preview 的 `semantic-release` 令牌从 `${{ github.token }}` 切换为 `${{ secrets.PAT_TOKEN }}` + - 在 preview summary 中明确说明 dry-run 仍会执行远端 push 权限探测,避免将 403 误判为版本计算失败 +- 已明确真实打 tag 仍使用 `PAT_TOKEN`,因为 `GITHUB_TOKEN` 推送的 tag 不会继续触发 `publish.yml` +- 已更新 `AGENTS.md` 的 Conventional Commit 规则,显式补充: + - `fix/perf/refactor -> patch` + - `docs/test/chore/build/ci/style -> no release` + - `BREAKING CHANGE` 或 `!` header -> major +- 已移除基于 `workflow_run` 和 `[release ci]` 的自动发版门闸,后续版本预览与真实发版都由维护者手动触发 +- 已将 release 流程从“两次独立 workflow_dispatch”收敛为“同一次 run 里 preview + 审批 + release”的链路 +- 已精简 active trace,移除已废弃的 `release_mode=preview|release` 中间方案,保留当前有效恢复点 + +## 历史验证 + +- `git describe --tags --abbrev=0` + - 结果:通过 + - 备注:当前最新 tag 为 `v0.0.222` +- `git log --pretty=format:%h%x09%s v0.0.222..HEAD` + - 结果:通过 + - 备注:最近版本窗口内存在多条 `feat(...)`,后续 dry-run 预期应提升 `minor` +- `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=` + - 结果:通过 + - 备注:`GFramework.Core.Abstractions` 与 `GFramework.Cqrs.Abstractions` Release 构建通过,`0 warning / 0 error` +- `npx --yes semantic-release --dry-run --no-ci` + - 结果:受阻 + - 备注:当前工作树的本地 tag 历史在 `git fetch --tags` 阶段出现 `would clobber existing tag` 冲突,不能直接作为 dry-run 环境 +- `git clone --branch main --single-branch git@github.com:GeWuYou/GFramework.git /tmp/gframework-semrel-dryrun` + - 结果:通过 + - 备注:已建立干净临时克隆用于 dry-run 验证 +- `npx --yes semantic-release --dry-run --no-ci`(在 `/tmp/gframework-semrel-dryrun`) + - 结果:通过 + - 备注:dry-run 成功识别 `v0.0.222` 为最新 release,并分析 `269` 个提交;按当前规则会提升到下一次 `minor` 发布,预期 tag 为 `v0.1.0` +- `npx --yes -p semantic-release -p conventional-changelog-conventionalcommits@9.1.0 semantic-release --dry-run --no-ci`(在 `/tmp/gframework-semrel-dryrun`) + - 结果:通过 + - 备注:成功加载 `@semantic-release/commit-analyzer` 与 `@semantic-release/release-notes-generator`,证明 + `conventionalcommits` preset 包可被解析;本次 dry-run 未继续出版本,是因为干净克隆的 `main` 已落后远端 +- `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=`(手动发版入口调整后复验) + - 结果:通过 + - 备注:`0 warning / 0 error` +- `dotnet build GFramework.sln -c Release` + - 结果:通过 + - 备注:Release 构建通过,`639 warning / 0 error`;warning 为仓库既有基线;preview 鉴权修复后复验结果与基线一致 diff --git a/ai-plan/public/semantic-release-versioning/todos/semantic-release-versioning-tracking.md b/ai-plan/public/semantic-release-versioning/todos/semantic-release-versioning-tracking.md index e71a79e2..1e49a193 100644 --- a/ai-plan/public/semantic-release-versioning/todos/semantic-release-versioning-tracking.md +++ b/ai-plan/public/semantic-release-versioning/todos/semantic-release-versioning-tracking.md @@ -13,18 +13,18 @@ ## 当前恢复点 -- 恢复点编号:`SEMREL-RP-003` +- 恢复点编号:`SEMREL-RP-004` - 当前阶段:`Phase 2` - 当前焦点: - - 消除 `auto-tag.yml` preview job 中由 `github-actions[bot]` 触发的 `EGITNOPERMISSION` / `git push --dry-run` 403 - - 让 preview 与 release 共用同一条 `PAT_TOKEN` 身份验证链路,避免 dry-run 与真实 release 的权限前提不一致 - - 将本轮 preview 身份验证修复同步回 active trace,并等待 CI 复验结果 + - 将 preview / release 的 PAT 校验收敛为同一个复用入口,避免后续修复在两段脚本间漂移 + - 在 PAT 校验阶段提前识别“仅有 read、没有 push”的 token,真正覆盖 `git push --dry-run` 的权限前提 + - 将 active tracking 中已稳定的历史完成项归档,恢复默认入口的可读性 ### 已知风险 - `GITHUB_TOKEN` 推送 tag 不会再触发另一个 workflow,真实发布仍需要 `PAT_TOKEN` -- `semantic-release` preview 虽然不会真实推送 tag,但仍会执行远端 `git push --dry-run` 权限探测;如果 preview 没有使用 - 可写入仓库的令牌,仍然会先于版本分析阶段失败 +- `semantic-release` preview 虽然不会真实推送 tag,但仍会执行远端 `git push --dry-run` 权限探测;如果 PAT 仅具备 + read 权限、没有 `contents:write`,仍然会先于版本分析阶段失败 - `semantic-release` 的版本判断完全依赖 Conventional Commits;不规范提交会直接影响版本计算 - `cycjimmy/semantic-release-action@v6` 需要在 preview / release 两端都安装 `conventional-changelog-conventionalcommits` 以保证 `conventionalcommits` preset 在 GitHub Actions 中可解析 @@ -32,79 +32,24 @@ ## 已完成 -- 已确认当前版本入口为 `.github/workflows/auto-tag.yml`,现状始终执行 `PATCH + 1` -- 已确认当前 `.github/workflows/publish.yml` 由 tag 触发,并负责 `.nupkg` 打包、发布和 GitHub Release -- 已确认最新 tag 为 `v0.0.222` -- 已确认 `v0.0.222..HEAD` 之间存在 `feat(...)` 提交,按目标规则首次 dry-run 预期版本应为 `v0.1.0` -- 已新增 `.releaserc.json`,仅保留 `@semantic-release/commit-analyzer` 与 - `@semantic-release/release-notes-generator`,避免 `semantic-release` 直接创建 GitHub Release -- 已将 `.releaserc.json` 的 `commit-analyzer` / `release-notes-generator` 同步切换到 `conventionalcommits` - preset,并显式声明: - - `breaking -> major` - - `revert -> patch` - - `feat -> minor` - - `fix/perf/refactor -> patch` - - `docs/test/chore/build/ci/style -> no release` -- 已将 `.github/workflows/auto-tag.yml` 重写为: - - `workflow_dispatch` 启动后总是先跑 `preview` - - `preview` 只执行 dry-run,输出 `last_tag`、`next_version` 与 `next_tag` - - `release` job 依赖 `preview` 输出,并通过 `release-approval` environment 暂停等待人工确认 - - 人工批准后,`release` 在同一 SHA 上执行真实打 tag,并把 preview / release 结果都写入 job summary -- 已按 PR review 修复 `auto-tag.yml`: - - 删除 preview job 中与 job 级 `if` 重复的运行时分支校验 - - 为 release job 增加 `needs.preview.result == 'success'` 守卫 - - 为 preview / release 的 semantic-release action 显式安装 `conventional-changelog-conventionalcommits@9.1.0` - - 在 release 前通过 GitHub API 校验 `PAT_TOKEN` 是否真实可访问当前仓库 - - 在 preview / release summary 中补充 snapshot 语义与生成的 release notes -- 已修复 preview 链路的鉴权前提: - - 在 preview 开始前通过 GitHub API 校验 `PAT_TOKEN` - - 将 preview 的 `semantic-release` 令牌从 `${{ github.token }}` 切换为 `${{ secrets.PAT_TOKEN }}` - - 在 preview summary 中明确说明 dry-run 仍会执行远端 push 权限探测,避免将 403 误判为版本计算失败 -- 已明确真实打 tag 仍使用 `PAT_TOKEN`,因为 `GITHUB_TOKEN` 推送的 tag 不会继续触发 `publish.yml` -- 已更新 `AGENTS.md` 的 Conventional Commit 规则,显式补充: - - `fix/perf/refactor -> patch` - - `docs/test/chore/build/ci/style -> no release` - - `BREAKING CHANGE` 或 `!` header -> major -- 已移除基于 `workflow_run` 和 `[release ci]` 的自动发版门闸,后续版本预览与真实发版都由维护者手动触发 -- 已将 release 流程从“两次独立 workflow_dispatch”收敛为“同一次 run 里 preview + 审批 + release”的链路 -- 已精简 active trace,移除已废弃的 `release_mode=preview|release` 中间方案,保留当前有效恢复点 +- 历史迁移结论与 `SEMREL-RP-001` 到 `SEMREL-RP-003` 的稳定完成项已归档到 + `ai-plan/public/semantic-release-versioning/archive/todos/semantic-release-versioning-2026-04-26.md` +- 已将 preview / release 两段重复的 PAT 校验提取到 `.github/actions/validate-pat/action.yml` +- 已在 PAT 校验中补充 `permissions.push` 断言,避免 read-only token 通过 API 探活却在 + `semantic-release` 的 `git push --dry-run` 阶段才失败 +- 已为 PAT 校验的 `mktemp` 文件补充 `trap` 清理,避免异常退出时遗留临时文件路径干扰日志 +- 已同步更新 active trace 到 `SEMREL-RP-004`,记录本轮 PR review 收敛结果 ## 验证 -- `git describe --tags --abbrev=0` - - 结果:通过 - - 备注:当前最新 tag 为 `v0.0.222` -- `git log --pretty=format:%h%x09%s v0.0.222..HEAD` - - 结果:通过 - - 备注:最近版本窗口内存在多条 `feat(...)`,后续 dry-run 预期应提升 `minor` -- `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=` - - 结果:通过 - - 备注:`GFramework.Core.Abstractions` 与 `GFramework.Cqrs.Abstractions` Release 构建通过,`0 warning / 0 error` -- `npx --yes semantic-release --dry-run --no-ci` - - 结果:受阻 - - 备注:当前工作树的本地 tag 历史在 `git fetch --tags` 阶段出现 `would clobber existing tag` 冲突,不能直接作为 dry-run 环境 -- `git clone --branch main --single-branch git@github.com:GeWuYou/GFramework.git /tmp/gframework-semrel-dryrun` - - 结果:通过 - - 备注:已建立干净临时克隆用于 dry-run 验证 -- `npx --yes semantic-release --dry-run --no-ci`(在 `/tmp/gframework-semrel-dryrun`) - - 结果:通过 - - 备注:dry-run 成功识别 `v0.0.222` 为最新 release,并分析 `269` 个提交;按当前规则会提升到下一次 `minor` 发布,预期 tag 为 `v0.1.0` -- `npx --yes -p semantic-release -p conventional-changelog-conventionalcommits@9.1.0 semantic-release --dry-run --no-ci`(在 `/tmp/gframework-semrel-dryrun`) - - 结果:通过 - - 备注:成功加载 `@semantic-release/commit-analyzer` 与 `@semantic-release/release-notes-generator`,证明 - `conventionalcommits` preset 包可被解析;本次 dry-run 未继续出版本,是因为干净克隆的 `main` 已落后远端 -- `dotnet build GFramework.Core.Abstractions/GFramework.Core.Abstractions.csproj -c Release -p:RestoreFallbackFolders=`(手动发版入口调整后复验) - - 结果:通过 - - 备注:`0 warning / 0 error` - `dotnet build GFramework.sln -c Release` - 结果:通过 - - 备注:Release 构建完成,`639 warning / 0 error`;warning 为仓库既有基线,与本轮 workflow / doc 改动无新增关联项 -- `dotnet build GFramework.sln -c Release`(preview 鉴权修复后复验) - - 结果:通过 - - 备注:Release 构建完成,`639 warning / 0 error`;warning 基线与修复前一致,本轮仅涉及 workflow / `ai-plan` 变更 + - 备注:Release 构建通过,`639 warning / 0 error`;warning 为仓库既有基线,preview 鉴权修复后与本轮 PAT 校验收敛后复验结果一致 +- 更早阶段的 dry-run / tag /抽象项目验证已归档到 + `ai-plan/public/semantic-release-versioning/archive/todos/semantic-release-versioning-2026-04-26.md` ## 下一步 -1. 手动重跑 `Semantic Release Version and Tag` 的 preview job,确认不再出现 `git push --dry-run ... 403` -2. 若 preview 通过,再复核当前 PR review 的 open threads 是否只剩等待 push 的已修复项 -3. 将本轮修复提交到当前分支,等待 GitHub reviewer 重新评估 +1. 手动重跑 `Semantic Release Version and Tag` 的 preview job,确认 read-only PAT 会在校验步骤提前失败、可写 PAT 不再进入 `git push --dry-run ... 403` +2. 推送本轮修复后重新抓取 PR review,确认 CodeRabbit / Greptile 的 open threads 已转为过时或可关闭 +3. 如 CI 仍报告权限边界问题,再决定是否将 PAT 校验升级为更贴近真实链路的远端 git 探测 diff --git a/ai-plan/public/semantic-release-versioning/traces/semantic-release-versioning-trace.md b/ai-plan/public/semantic-release-versioning/traces/semantic-release-versioning-trace.md index 25885702..2dde02af 100644 --- a/ai-plan/public/semantic-release-versioning/traces/semantic-release-versioning-trace.md +++ b/ai-plan/public/semantic-release-versioning/traces/semantic-release-versioning-trace.md @@ -2,7 +2,7 @@ ## 2026-04-26 -### 当前恢复点(SEMREL-RP-003) +### 当前恢复点(SEMREL-RP-004) - 当前链路: - `workflow_dispatch` 手动启动 @@ -17,7 +17,8 @@ - `breaking -> major` - 当前 workflow 加固: - `release` 额外要求 `needs.preview.result == 'success'` - - `PAT_TOKEN` 在真实 release 前通过 GitHub API 做存活性校验 + - `PAT_TOKEN` 通过复用的 composite action 统一校验 + - GitHub API 校验额外断言 `.permissions.push == true`,避免 read-only PAT 混过 preview - preview / release summary 会展示 snapshot 语义与生成的 release notes - `preview` 改为先校验并使用 `PAT_TOKEN`,避免 `github-actions[bot]` 在 dry-run 的远端 push 权限探测中触发 403 @@ -29,9 +30,12 @@ - preview 与 release 共用 `PAT_TOKEN`: - `semantic-release` dry-run 仍会执行 `git push --dry-run` - preview 如果继续使用 `${{ github.token }}`,会先被 `github-actions[bot]` 的仓库写权限拦住,日志不再具有可读性 +- API 探活必须覆盖 push 权限: + - 单纯 `GET /repos/{owner}/{repo}` 的 `200` 只能证明 read access + - 本轮直接读取响应体里的 `permissions.push`,让 preview 在更接近真实失败原因的位置终止 - 不保留已废弃的 `release_mode=preview|release` 中间方案: - active trace 只保留当前有效链路 - - 历史演进以 tracking 文档的已完成项为准 + - 历史演进以 tracking 归档文件为准,active tracking 仅保留当前恢复入口 ### 验证结论 @@ -40,10 +44,10 @@ - 本次 dry-run 未继续出版本,因为干净克隆的 `main` 已落后远端 2. `dotnet build GFramework.sln -c Release` - 通过,`639 warning / 0 error` - - warning 为仓库既有基线,本轮未新增关联 warning + - warning 为仓库既有基线,本轮 workflow / ai-plan 调整未新增关联 warning ### 下一步 -1. 重跑 `auto-tag.yml` 的 preview,确认 `EGITNOPERMISSION` 已消失 -2. 复查当前 PR 的 open review threads 是否只剩等待 push 的已修复项 +1. 重跑 `auto-tag.yml` 的 preview,确认 read-only PAT 会在校验步骤提前失败、可写 PAT 不再落到 `EGITNOPERMISSION` +2. 复查当前 PR 的 open review threads 是否已与本地修复对齐 3. 创建提交并推送当前分支