Skip to content
Development
Skill

/release-tag

Cut a release tag behind a real tier gate and cloud approval readback. The approval, task, approved commit, and resulting tag are bound; self-approval and HEAD drift fail closed. Prod prefixes remain refused.

BOOST
From plugin
prismercloud
1.6k102 skills
Install
$ npx -y skills add Prismer-AI/PrismerCloud --skill release-tag --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/release-tag

Context preview

The summary Claude sees to decide when to auto-load this skill.

Cut a release tag behind a real tier gate and cloud approval readback. The approval, task, approved commit, and resulting tag are bound; self-approval and HEAD drift fail closed. Prod prefixes remain refused.

SKILL.md

release-tag.SKILL.md
name: release-tag
description: Cut a release tag behind a real tier gate and cloud approval readback. The approval, task, approved commit, and resulting tag are bound; self-approval and HEAD drift fail closed. Prod prefixes remain refused.
license: MIT
scope: coding
compatibility:
  - claude-code
allowed-tools:
  - Bash
metadata:
  category: release

release-tag

发版打 tag(`apc/01` §2 release-tag,收口步 6)。它把**测试→上线的焊点**焊死:**没有 tier 全绿 / baseline 无新红的结构化证据,审批请求根本不创建、tag 绝不 push**。tier 门跑真 `run.ts` 读真退出码;tag 名按 `<channel>-<target>-YYYYMMDD-vX.Y.Z` 算;审批通过后 `git tag && push` 到**本地 bare mirror 替身**(真 GitLab push + pipeline 轮询 = M5)。

**什么时候用**:`release-preflight` 绿 + `release-db-config-sync` 无阻塞之后,要把一个 test 版本推上 CI。

承重纪律(发版 skill 的命根子,先记死)

  • **prod 前缀 tag 必拒**(不变量 2 · 两人闸)。四个映射 `APP_ENV=prod` 的前缀——`k8s-prod-*` / `desktop-prod-*` / `prod-*` / `ali-k8s-prod-*`——**先于一切 git / tier 动作硬拒**,本 verb 不做任何 git 动作。**别试 prod**:真 prod 红线由 GitLab protected tags(P-1,运维配置)落地,本 skill 只护到"不替你打 prod tag"。要发 prod = 人走 M5 路径。
  • **`--tier` 必须显式传,没有默认值**。`TD`(桌面冒烟)在 `apps/desktop/e2e/smoke/` 无 spec 时会自动 `skipped-with-note`(`passed:0/failed:0`),单独拿它当发版门是一道**不可能红**的空门——之前 SKILL 范例全不带 `--tier` 让 agent 照抄默认值正是这么踩的坑(`apc/12` §0.12)。**选一个会真执行断言的层**,例如 `--tier=T0,T1`;prod 前缀路径(下方触发)例外——它先于 tier 门拒绝,不需要 `--tier`。
  • **tier 绿是 push 的硬前置,"绿"必须是真跑过用例**。tier 红 / `env_blocked` / **空跑**(该轮所有 tier 的 `passed+failed` 合计为 0,即一个用例都没真执行)⇒ `blocked`,审批请求不创建、tag 不 push。**不许**放松 tier、挑能绿的层、或拿一个恰好全 skip 的层骗过门。
  • **审批门不可跳**。tier 绿但未审批 = `staged`(dry-run:出 tag + tier 证据,不 push)。批准路径必须同时传 `--task <taskId> --approved <approvalId>`;CLI 从 cloud 读回批件和 task,校验 `approved` / `release_tag` / task 绑定 / 非自批,且两者 metadata 的 commit SHA 必须一致。随机 token 不再能放行。
  • **tag 打获批 commit,不打 HEAD**。并行工作使 HEAD 漂移也不得把未审内容带入 tag;获批 SHA 不在 repo 则 fail-closed。

Anti-pattern(直接判红)

  • ❌ **给 `--target prod` 或手拼 prod 前缀 tag** 想让 skill 打 prod。命中即 blocked,别绕。
  • ❌ **tier `blocked` 时先打 tag 再补测试**。焊点就是不让这发生。
  • ❌ **拿到 `staged` 就以为发版完成**。staged 是"等审批",tag 还没 push。
  • ❌ **用 `git tag` + 裸 `git push origin`** 手工绕过本 verb,跳过 tier 门和审批门。

工具契约(签名以此为准)

> `apc` **不在 PATH**——在仓库根用 `npx tsx sdk/apc/bin/apc.ts <sub>`。

| 命令 | 作用 | 退出码 | | --- | --- | --- | | `npx tsx sdk/apc/bin/apc.ts release tag [--channel k8s\|desktop] [--target test\|prod] [--version X.Y.Z] --tier=<tiers> [--task <taskId> --approved <approvalId>] [--json]` | prod 人闸 → tier 门 → cloud 批件/task/commit 他证 → 把获批 SHA push 到本地 bare mirror | `0` green(pushed)· `3` staged(tier 绿待审批)· `1` blocked(tier 红 / 他证失败 / prod 拒 / push 失败)· `2` 用法错 |

`--tier` **没有默认值**(`--target prod` 路径除外——它先于 tier 门拒绝);不传直接 usage 错 exit 2。选一个会真执行断言的层,例如 `--tier=T0,T1`——**别用 `--tier=TD`** 当唯一层:无桌面冒烟 spec 时它是空门。

`--json` 字段(**名以此为准**):

  • 顶层:`{ verb:'tag', decision, tag, target, channel, tier, approved, approvalId, taskId, commitSha, pushed, mirror, blockers:[], notes:[] }`
  • `tag`:算出的 tag 名(如 `k8s-test-20260724-v2.0.7`);`--version` 缺省读 `/VERSION`
  • `tier`:`{ tier, exitCode, envBlocked, regressions, emptyRun }`(prod 拒时 `exitCode:-1`,因为压根没跑到 tier;`emptyRun:true` = 该轮所有 tier 的 `passed+failed` 合计为 0,一个用例都没真跑,即便 `exitCode` 是 0 也判 `blocked`)
  • `mirror`:push 目标(默认 `.dev-stack/apc-bare-origin.git` bare 替身)

Workflow

1. dry-run:算 tag + 过 tier 门(不带 `--approved`)

npx tsx sdk/apc/bin/apc.ts release tag --channel k8s --target test --tier=T0,T1 --json > /tmp/tag-dry.json; T=$?
echo "tag(dry) exit=$T"
  • `decision:staged`(exit 3)+ tier 绿 → 拿到 `tag` 名,进审批。
  • `decision:blocked`(exit 1)→ 读 `tier`/`blockers`;tier 红 / 空跑(`tier.emptyRun:true`)就停手回 bugfix,别往下走。
  • 忘了 `--tier` → exit 2 用法错,不是"用了默认 TD"——没有默认值。

2. 审批后 push(cloud 批件 + task 绑定)

# approval 必须是 cloud 中已被另一个人批准的 release_tag 记录,并且与 task 携带同一 commit SHA
npx tsx sdk/apc/bin/apc.ts release tag --channel k8s --target test --tier=T0,T1 \
  --task "$PRISMER_TASK_ID" --approved "$APPROVAL_ID" --json > /tmp/tag.json; T=$?
echo "tag(push) exit=$T"
  • `decision:green`(exit 0)+ `approved:true` + `pushed:true` → tag 已落 bare mirror;必须用 `git rev-parse refs/tags/<tag>^{commit}` 核验结果等于产物的 `commitSha`。

3. prod 一律拒(验证人闸,不是要发 prod)

npx tsx sdk/apc/bin/apc.ts release tag --channel k8s --target prod --json; echo "prod exit=$?"
# 预期:decision=blocked, exit 1, blockers 含 "prod 人闸",无任何 git 动作
# 注意:这条命令没带 --tier ——prod 人闸先于 tier 门开火,压根不需要它

Failure / 边界

  • push 失败(bare mirror 不存在 / git 错误)→ `blocked` + `blockers` 含真 git stderr。bare 替身由 `apc env up --safe` 拉起。
  • 本机替身:push 只到 **本地 bare mirror**,**不推 GitLab**;cloud approval/task/commit 他证已是真路径。真 GitLab push + pipeline 轮询仍是 M5(诚实 ⬜)。

输出契约(机器判据按这个复算,别自由发挥格式)

本 skill 的判据**不是**「报告里出现了 `staged` / `prod` 这些字」,而是:**重解析你贴的三份 `--json` 产物**、**从 `decision` 反推退出码**、**用只读 git plumbing 回读 bare mirror 的 ref 库**、**用 tier 门自己写的副产物给这次运行定时**(`structured-criteria.ts` 的 `json-claim` + `git-claim-readback`)。

先在**隔离沙箱**里搭演示(**绝不在共享工作树打 tag/push**):

mkdir -p .e2e-tmp/apc-release-tag && git init -q --bare .e2e-tmp/apc-release-tag/mirror.git
mkdir -p .e2e-tmp/apc-release-tag/work && cd .e2e-tmp/apc-release-tag/work
git init -q -b main && echo demo > f.txt && git add f.txt && git commit -qm init
git remote add mirror "$REPO/.e2e-tmp/apc-release-tag/mirror.git"

> `--repo` / `--mirror` **必须传绝对路径**——verb 内部会把相对 `--repo` 再解析一次(`git -C <rel>` 又在 `cwd=<rel>` 下跑),相对路径必失败。

报告必须带下面这组行 + **三份原样 JSON**:

RUN-AT: <审批那次运行的 ISO-8601 墙钟时间>
STAGED-TAG: <dry-run 产物的 tag>
STAGED-PUSHED: false
STAGED-EXIT: 3
TAG-NAME: <审批产物的 tag>
TIER-EXIT: 0
TAG-EXIT: 0
PROD-TAG: <verb 算出并拒掉的 k8s-prod-… tag>
PROD-DECISION: blocked
GIT-REPO: .e2e-tmp/apc-release-tag/work
GIT-TAG: <tag> | remote: mirror | sha: <该 tag 在 mirror 上解析出的 commit sha>
GIT-REFUSED-TAG: <k8s-prod-… tag> | remote: mirror

紧跟着把三次 `--json` 的 stdout **一字不改**贴进三个 fenced json 块(dry-run → 审批 → prod)。

判据会判红的情况(任一):

  • 没有可解析的 fenced JSON(只有散文「tag 打好了」);
  • `STAGED-EXIT` / `TAG-EXIT` 不是从 `decision` 推出来的那个(green→0 · staged→3 · blocked→1)——**退出码是 decision 的函数,不是措辞**;
  • 审批产物 `decision:green` 却 `tier.e
Read more
Ships withprismercloud

Prismer Cloud

Get the whole plugin
Stats
1,554
Stars
17
Forks
Active
Maintenance
TypeScript
Language
MIT
License
2d ago
Last commit
6mo ago
Created

Repo: Prismer-AI/PrismerCloud

Other skills on prismercloud.