GitHub Actions在Issue标题含#号时无法自动添加标签,如何解决?

Good“俊瑶 阅读 66

配置了GitHub Actions在Issue被创建时自动添加”待处理”标签,但当Issue标题包含#符号(比如”Bug#123: 页面崩溃”)时,任务会报错Error: Not Found。我用的workflow是:

on:
  issues:
    types: [opened]
jobs:
  add-label:
    runs-on: ubuntu-latest
    steps:
      - name: Add Label
        uses: actions/create-label@v3
        with:
          label-name: "待处理"
          color: "006b75"

尝试过将#转义成%,但问题依旧。有没有办法让Action正确处理包含#的标题?

我来解答 赞 16 收藏
二维码
手机扫码查看
2 条解答
新利
新利 Lv1
这个问题的根本原因在于 GitHub Actions 的触发事件中,issue.title 字段在某些上下文里会被当作 URL 片段(fragment identifier)来处理,而 # 在 URL 里是特殊字符,代表锚点的起始符。比如 Bug#123 会被解析成「路径是 Bug,锚点是 123」,导致后续某些操作(比如调用 Issues API 时带标题参数)把整个字符串误判为无效的 issue number 或 URL,最终返回 404 Not Found。

但注意:你贴出的 workflow 里其实根本没用到 issue 标题,只是单纯创建一个叫「待处理」的标签。按理说这个 workflow 不该报错,除非你实际部署的代码里还有别的步骤(比如复制标题、提取编号、拼接标签名等)——而这些步骤可能用到了 github.event.issue.title 并传给了某个 action 的参数,比如 label-name: ${{ github.event.issue.title }} 或类似逻辑。

先确认一点:actions/create-label@v3 这个 action 的 label-name 参数只接受合法的 label 名称(字母数字下划线横线,不能以特殊字符开头结尾,中间也不能有 #、空格等),但你这里写的是固定字符串 "待处理",中文字符在 GitHub label 里是允许的(只要不是控制字符),理论上没问题。

所以大概率是:你实际 workflow 比贴出来的复杂,比如可能还做了这样的事:

- name: Add Label Based on Title
uses: actions/create-label@v3
with:
label-name: ${{ contains(github.event.issue.title, '#') && '紧急' || '待处理' }}


或者用了某个自定义脚本提取 # 后面的数字作为标签(比如 #123 → 加标签 123),而 # 本身没被转义就传给 API 了。

正确解法分两步:

1. 如果你只是想加固定标签,和标题内容无关,那上面的 workflow 就该能跑通。报错可能另有原因,比如 token 权限不足(需要 issues: write)、repo 重命名过、或者 workflow 文件没提交到默认分支。建议先在 steps 里加个 debug:

- name: Debug title
run: echo "Title is: '${{ github.event.issue.title }}'"


看输出里 # 是不是被截断了(比如只输出了 Bug),如果是,说明事件上下文里标题确实被解析坏了——这在某些 webhook 代理或旧版 GitHub Actions runner 上偶尔发生。

2. 如果你确实需要根据标题内容动态生成标签(比如从 Bug#123 提取 123 做标签),那必须对 # 做显式处理,因为 shell 和 JSON 都会吃掉它。

具体来说,推荐用 jq 来安全读取事件 payload,因为 github.event.issue.title 直接插值时可能被 shell 解析,比如:

- name: Extract label from title
id: extract
run: |
TITLE='${{ github.event.issue.title }}'
# 先确保 # 被当成普通字符
# 用 jq 从完整事件 JSON 中取 title,避免 shell 转义问题
RAW_TITLE=$(jq -r '.issue.title' "$GITHUB_EVENT_PATH")
# 提取 # 后面的数字(如果存在)
LABEL=$(echo "$RAW_TITLE" | grep -oE '#[0-9]+' | sed 's/#//' | head -n1)
if [ -n "$LABEL" ]; then
echo "extracted label: $LABEL"
echo "label=$LABEL" >> $GITHUB_OUTPUT
else
echo "label=待处理" >> $GITHUB_OUTPUT
fi


然后后面用这个 label 创建标签:

- name: Add Label
uses: actions/create-label@v3
with:
label-name: ${{ steps.extract.outputs.label }}
color: "006b75"


或者更稳妥的做法是直接用 gh CLI 调用 GitHub API(比用第三方 action 更可控):

- name: Add label via GitHub API
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ISSUE_NUMBER: ${{ github.event.issue.number }}
RAW_TITLE: ${{ github.event.issue.title }}
run: |
# 用 jq 安全解析标题(避免 # 问题)
TITLE=$(echo "$RAW_TITLE" | jq -R -s '.')
# 提取 # 开头的数字串(如果存在)
LABEL=$(echo "$RAW_TITLE" | grep -oE '#[0-9]+' | head -n1 | sed 's/#//' || echo "待处理")
# 确保标签存在(不存在则创建)
if ! gh label list | grep -q "^$LABEL$"; then
gh label create "$LABEL" --color "006b75" || echo "Failed to create label $LABEL, using fallback"
fi
# 添加标签
gh issue edit "$ISSUE_NUMBER" --add-label "$LABEL"


这里的关键点是:永远不要让 # 直接出现在 shell 命令的字符串里不加引号,并且尽量用 jq$GITHUB_EVENT_PATH 里读原始 JSON,而不是依赖 GitHub 的插值语法——因为插值时 # 可能被 shell 当作注释起始符直接截断整行。

我之前踩过这个坑:用 echo ${{ github.event.issue.title }} 直接输出,结果 #123 后面的内容全没了,以为是 GitHub 的 bug,后来发现是 shell 解析问题。加了单引号和 jq 就好了。

另外提醒一句:actions/create-label 这个 action 其实已经两年没更新了(截至 2024 年底),它底层也是调用 REST API,但对中文和特殊字符支持很粗糙。如果遇到问题,直接上 gh CLI 或 curl 调 API 是最稳的——毕竟你掌控所有转义细节。比如:

curl -L 
-X POST
-H "Accept: application/vnd.github+json"
-H "Authorization: Bearer $GITHUB_TOKEN"
-H "X-GitHub-Api-Version: 2022-11-28"
https://api.github.com/repos/$GITHUB_REPOSITORY/issues/$ISSUE_NUMBER/labels
-d "{"labels":["待处理"]}"


总之,不是 # 本身不能用,而是你没处理好它在 shell 和 JSON 里的语义。把数据流里的 # 当作普通字符对待,用单引号包住、用 jq 解析,基本就能解决。
点赞 3
2026-02-24 09:12
设计师熙妍
你遇到的问题其实和GitHub Actions本身无关,而是对 actions/create-label@v3 这个动作的理解有偏差。这个动作是“创建标签”,不是“给issue打标签”。它会在仓库里新建一个叫“待处理”的标签,而不是把标签加到issue上。

当你标题里带#的时候报错 Not Found,大概率是因为这个 action 尝试操作时触发了某种解析问题,或者你的 workflow 逻辑本身就走错了。

正确的做法应该是用官方的 github-script 或者直接调用 GitHub API 来给 issue 添加已有标签。

推荐这样改:

on:
issues:
types: [opened]

jobs:
add-label:
runs-on: ubuntu-latest
steps:
- name: Add '待处理' label
uses: actions/github-script@v6
with:
script: |
github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ['待处理']
})


前提是你要先在仓库里手动创建好“待处理”这个标签,颜色设成006b75也行,这样更清晰。

这样不管标题有没有#都能正常运行,因为根本不依赖标题内容。而且这是标准做法,避免了误用 create-label 这类容易混淆的动作。

顺便说一句,我之前也被那个 create-label 的名字坑过,听起来像是打标签,其实是建标签,命名真够误导的。
点赞 7
2026-02-12 04:03