labels-as-code

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

labels-as-code

labels-as-code

Brings a single GitHub repository's labels under version control and keeps pull-request labeling in sync with the files that changed.
将单个 GitHub 仓库的标签纳入版本控制,并使 pull request 标签与变更文件保持同步。

Where this skill fits

本 skill 的适用范围

ConcernSkill
One repo's label set, tracked in a file, synced on demand or on schedule
/labels-as-code
(this skill)
Path-based PR auto-labeling for one repo
/labels-as-code
(this skill)
Label policy across many repos, reconciled from one admin repo
/safe-settings
Issue forms, PR templates, community health files
/oss-hygiene
/safe-settings
can also manage labels org-wide through its
labels
block (rename via
oldname
, exclusion patterns), reconciled every
full-sync
run. Reach for
/safe-settings
when label policy must stay in sync across many repos from a central admin repo. Reach for this skill when the scope is one repository and the file lives in that repository.
关注事项Skill
单个仓库的标签集,以文件进行跟踪,并按需或定时同步
/labels-as-code
(本 skill)
单个仓库基于路径的 PR 自动标签
/labels-as-code
(本 skill)
从一个中央管理仓库协调多个仓库的标签策略
/safe-settings
Issue forms、PR templates、community health files
/oss-hygiene
/safe-settings
也可以通过其
labels
块管理组织范围内的标签(通过
oldname
重命名、排除模式),并在每次
full-sync
运行时进行协调。当标签策略必须从中央管理仓库跨多个仓库保持同步时,使用
/safe-settings
。当范围是单个仓库且文件位于该仓库中时,使用本 skill。

What gets configured

配置内容

FilePurpose
.github/labels.yml
The label set:
name
,
color
,
description
per label
.github/labeler.yml
Path-to-label rules consumed by
actions/labeler
.github/workflows/labels-sync.yml
(optional)
Scheduled/on-push sync of
.github/labels.yml
to the repo
.github/workflows/labeler.yml
(optional)
Runs
actions/labeler
on every pull request
文件用途
.github/labels.yml
标签集:每个标签包含
name
、
color
、
description
.github/labeler.yml
actions/labeler
使用的路径到标签映射规则
.github/workflows/labels-sync.yml
(可选)
通过定时触发或 push 触发,将
.github/labels.yml
同步到仓库
.github/workflows/labeler.yml
(可选)
在每个 pull request 上运行
actions/labeler

Protocol

协议

1. Export current labels and diff

1. 导出当前标签并进行差异对比

bash
gh label list --json name,color,description
Compare the export against the proposed
.github/labels.yml
(create it from
assets/labels.yml
if the file does not exist yet). Print the diff — labels to create, labels to recolor or redescribe, and labels present on GitHub but absent from the file — before proposing any change.
bash
gh label list --json name,color,description
将导出结果与拟议的
.github/labels.yml
进行比较(如果文件尚不存在,则根据
assets/labels.yml
创建)。在提出任何更改之前,先打印差异——包括要创建的标签、要重新着色或重新描述的标签,以及 GitHub 上存在但文件中缺失的标签。

2. Propose a default label set

2. 提出默认标签集

assets/labels.yml
ships a starting set grouped by prefix:
  • type/*
    — one label per Conventional Commits type (
    feat
    ,
    fix
    ,
    docs
    ,
    style
    ,
    refactor
    ,
    perf
    ,
    test
    ,
    build
    ,
    ci
    ,
    chore
    ,
    revert
    ), aligned with the types
    /pr-title-lint
    checks in the PR title.
  • priority/*
    —
    critical
    ,
    high
    ,
    medium
    ,
    low
    .
  • status/*
    —
    blocked
    ,
    in-progress
    ,
    needs-review
    .
  • good first issue
    ,
    help wanted
    — GitHub's own community-standards labels.
  • dependencies
    — Dependabot and manual dependency-bump PRs.
  • breaking
    — a breaking change, called out at release time.
Read
references/label-scheme.md
for the full table and for how
type/*
and
breaking
map onto
/gh-bootstrap
's
.github/release.yml
categories (that file's
Breaking changes
bucket keys on
breaking-change
/
breaking
; its
Features
/
Fixes
/
Documentation
/
Internal
buckets key on bare Conventional-Commits-style names, not the
type/
prefix). If the repo already runs
/gh-bootstrap
's release notes, either keep both label spellings on the affected PRs or extend
release.yml
's category lists with the
type/*
names —
/gh-bootstrap
owns that file; this skill only documents the mapping.
Ask the user whether to adopt the default set as-is, trim it, or start from the exported labels instead. Do not assume — a repo with an established label set may prefer to keep its own names.
assets/labels.yml
附带一组按前缀划分的初始标签:
  • type/*
    ——每个 Conventional Commits 类型对应一个标签(
    feat
    、
    fix
    、
    docs
    、
    style
    、
    refactor
    、
    perf
    、
    test
    、
    build
    、
    ci
    、
    chore
    、
    revert
    ),与
    /pr-title-lint
    在 PR 标题中检查的类型保持一致。
  • priority/*
    ——
    critical
    、
    high
    、
    medium
    、
    low
    。
  • status/*
    ——
    blocked
    、
    in-progress
    、
    needs-review
    。
  • good first issue
    、
    help wanted
    ——GitHub 自带的社区标准标签。
  • dependencies
    ——Dependabot 和手动依赖升级 PR。
  • breaking
    ——破坏性变更,在发布时突出显示。
阅读
references/label-scheme.md
了解完整表格,以及
type/*
和
breaking
如何映射到
/gh-bootstrap
的
.github/release.yml
类别(该文件的
Breaking changes
分类基于
breaking-change
/
breaking
;其
Features
/
Fixes
/
Documentation
/
Internal
分类基于不带
type/
前缀的纯 Conventional Commits 风格名称)。如果仓库已经运行
/gh-bootstrap
的 release notes,请在受影响的 PR 上同时保留两种标签拼写,或者扩展
release.yml
的类别列表,加入
type/*
名称——
/gh-bootstrap
负责该文件;本 skill 仅记录映射关系。
询问用户是要原样采用默认集合、进行删减,还是从导出的标签开始。不要擅自假设——已有成熟标签集的仓库可能更希望保留自己的名称。

3. Sync options

3. 同步选项

Two ways to apply
.github/labels.yml
to the repo. Ask the user which one before doing either.
The workflow templates in this step and in step 4 pin Node 24 actions. Before you copy either workflow, confirm that any self-hosted runner is Actions Runner v2.327.1 or later. GitHub-hosted runners already meet this requirement.
将
.github/labels.yml
应用到仓库有两种方式。在执行任一方式前,先询问用户选择哪一种。
本步骤及第 4 步中的 workflow 模板固定使用 Node 24 actions。复制任一 workflow 前,确认任何 self-hosted runner 的 Actions Runner 版本为 v2.327.1 或更高版本。GitHub-hosted runners 已满足此要求。

One-shot sync

一次性同步

bash
undefined
bash
undefined

Create or update one label (never deletes):

Create or update one label (never deletes):

gh label create "<name>" --color "<hex>" --description "<text>" --force
gh label create "<name>" --color "<hex>" --description "<text>" --force

Clone another repo's full label set (adds only; existing labels keep

Clone another repo's full label set (adds only; existing labels keep

their color/description unless the label doesn't exist yet):

their color/description unless the label doesn't exist yet):

gh label clone <owner>/<repo>

`--force` overwrites color/description on an existing label; it does not delete labels that are absent from the source. **Never delete a label without explicit, per-label user authorization** — list the labels that would be removed and wait for a yes before running `gh label delete`.
gh label clone <owner>/<repo>

`--force` 会覆盖现有标签的 color/description;它不会删除源中缺失的标签。**绝不在没有用户逐标签明确授权的情况下删除标签**——列出将被移除的标签,并等到用户回答“yes”后再运行 `gh label delete`。

Scheduled sync workflow

定时同步 workflow

For drift correction without a human running
gh label create
by hand, copy
assets/labels-sync.yml
to
.github/workflows/labels-sync.yml
. It runs
crazy-max/ghaction-github-labeler
, the maintained action verified for this skill (see
references/label-scheme.md
for the verification command and the current pinned SHA). The template ships with
skip-delete: true
— labels absent from
.github/labels.yml
are left alone, not deleted. Flip
skip-delete
to
false
only after the user explicitly authorizes deletions; the diff in step 1 shows exactly which labels that would remove. The template runs weekly on a
schedule
trigger, on each push to
main
that changes
.github/labels.yml
or the workflow file itself, and on manual
workflow_dispatch
.
EndBug/label-sync
is a viable alternative with the same shape (sync from a YAML file, delete-by-default gated by an option). Verify either action's latest release and SHA with
gh api repos/{owner}/{repo}
and the tag-to-commit lookup in
references/label-scheme.md
before pinning — do not reuse a SHA from this skill without re-verifying it against the current release.
若要在无需人工手动运行
gh label create
的情况下修正漂移,将
assets/labels-sync.yml
复制到
.github/workflows/labels-sync.yml
。它运行
crazy-max/ghaction-github-labeler
,这是本 skill 验证过的维护中 action(有关验证命令和当前固定 SHA,请参阅
references/label-scheme.md
)。模板设置了
skip-delete: true
——
.github/labels.yml
中不存在的标签将保持不变,不会被删除。只有在用户明确授权删除后,才可将其改为
false
;第 1 步的差异结果会准确显示将删除哪些标签。模板通过
schedule
触发器每周运行,在每次推送到
main
且变更涉及
.github/labels.yml
或 workflow 文件本身时运行,也支持手动
workflow_dispatch
。
EndBug/label-sync
是一个形态相同的可行替代方案(从 YAML 文件同步,默认删除行为由选项控制)。在固定版本前,使用
gh api repos/{owner}/{repo}
以及
references/label-scheme.md
中的 tag-to-commit 查询,验证任一 action 的最新 release 和 SHA——不要直接复用本 skill 中的 SHA,而不针对当前 release 重新验证。

4. Path-based PR labeling

4. 基于路径的 PR 标签

Copy
assets/labeler.yml
to
.github/labeler.yml
and adapt the path globs to the repo's directory layout — the shipped file is an example, not a fit-all config. Copy
assets/pr-labeler.yml
to
.github/workflows/labeler.yml
; it runs
actions/labeler
with
permissions: contents: read, pull-requests: write
(the minimum the action needs to read changed files and write labels).
Verify the pinned SHA before relying on it:
bash
LATEST=$(gh api repos/actions/labeler/releases/latest --jq '.tag_name')
gh api repos/actions/labeler/git/ref/tags/"$LATEST" --jq '.object.sha'
If the returned SHA does not match the comment in
assets/pr-labeler.yml
, update both the
uses:
line and its trailing version comment together — a stale comment next to a fresh SHA is worse than no comment.
将
assets/labeler.yml
复制到
.github/labeler.yml
,并根据仓库目录结构调整 path globs——随附文件只是示例,并非通用配置。将
assets/pr-labeler.yml
复制到
.github/workflows/labeler.yml
;它以
permissions: contents: read, pull-requests: write
运行
actions/labeler
(这是该 action 读取变更文件和写入标签所需的最小权限)。
依赖固定 SHA 前先进行验证:
bash
LATEST=$(gh api repos/actions/labeler/releases/latest --jq '.tag_name')
gh api repos/actions/labeler/git/ref/tags/"$LATEST" --jq '.object.sha'
如果返回的 SHA 与
assets/pr-labeler.yml
中的注释不一致,请同时更新
uses:
行及其末尾的版本注释——陈旧注释紧挨着最新 SHA 比没有注释更糟糕。

5. Verify

5. 验证

bash
gh label list --json name,color,description
Confirm the output matches
.github/labels.yml
exactly (same names, colors, descriptions — modulo any labels the user chose to keep unmanaged). Then open a pull request that touches a path matched in
.github/labeler.yml
and confirm the expected label lands on it, either by watching the
labeler.yml
run or with:
bash
gh pr view <number> --json labels --jq '.labels[].name'
Report what was created, updated, and left alone, and which labels (if any) are still pending user authorization to delete.
bash
gh label list --json name,color,description
确认输出与
.github/labels.yml
完全匹配(名称、颜色、描述均相同——不包括用户选择保持不受管理的标签)。然后创建一个触及
.github/labeler.yml
中匹配路径的 pull request,并确认预期标签已添加,可以通过观察
labeler.yml
的运行情况或使用以下命令:
bash
gh pr view <number> --json labels --jq '.labels[].name'
报告已创建、已更新和保持不变的标签,以及仍等待用户授权删除的标签(如有)。

What this skill is NOT for

本 skill 不适用于

  • Org-wide label policy reconciled across many repos — use
    /safe-settings
  • Issue forms, PR templates, or other community-health files — use
    /oss-hygiene
  • Deleting labels without the user's explicit, per-label go-ahead
  • Branch protection, merge settings, or release-notes plumbing — use
    /gh-bootstrap
  • 跨多个仓库协调的组织级标签策略——使用
    /safe-settings
  • Issue forms、PR templates 或其他 community health files——使用
    /oss-hygiene
  • 未经用户逐标签明确许可而删除标签
  • Branch protection、merge settings 或 release-notes plumbing——使用
    /gh-bootstrap

Gotchas

注意事项

  • gh label create --force
    is idempotent for color/description but never deletes. Deletion is a separate, explicit
    gh label delete
    call — never bundle it into a routine sync without asking first.
  • crazy-max/ghaction-github-labeler
    deletes labels that are absent from the YAML file unless
    skip-delete: true
    is set. Confirm that flag before wiring the workflow into a repo with labels the file doesn't enumerate.
  • actions/labeler
    's
    sync-labels
    input removes a path-based label when the PR no longer touches that path. Leave it at its default (
    false
    ) unless the user wants that behavior — it is a form of automatic deletion.
  • Label colors in
    gh label create --color
    take a bare hex string without
    #
    ;
    .github/labels.yml
    conventionally also stores the hex without
    #
    for
    actions/labeler
    's upstream ecosystem, but
    crazy-max/ghaction-github-labeler
    accepts either. Keep one convention within a repo's file.
  • Renaming a label with
    gh label create --force
    does not rename — it creates a new label. Use
    gh label edit <old-name> --name <new-name>
    for renames, or
    from_name:
    in the sync tool's config format if it supports it.
  • gh label create --force
    对 color/description 是幂等的,但绝不会删除标签。删除是单独的、显式的
    gh label delete
    调用——绝不在未询问用户的情况下将删除操作打包进常规同步。
  • crazy-max/ghaction-github-labeler
    会删除 YAML 文件中不存在的标签,除非设置了
    skip-delete: true
    。在将 workflow 接入包含文件未枚举标签的仓库前,务必确认该 flag 已正确设置。
  • actions/labeler
    的
    sync-labels
    输入项会在 PR 不再触及某个路径时移除基于该路径添加的标签。除非用户需要此行为,否则保持默认值(
    false
    )——这也是一种自动删除形式。
  • gh label create --color
    中的标签颜色采用不带
    #
    的纯十六进制字符串;按照
    actions/labeler
    上游生态的惯例,
    .github/labels.yml
    通常也不带
    #
    存储十六进制值,但
    crazy-max/ghaction-github-labeler
    两者都接受。在单个仓库的文件中保持统一约定。
  • 使用
    gh label create --force
    不会重命名标签——它会创建一个新标签。重命名请使用
    gh label edit <old-name> --name <new-name>
    ,或者在同步工具的配置格式支持时使用
    from_name:
    。