如何在Github Actions中获取当前的分支?

348

我正在使用Github Actions构建Docker镜像,想要对镜像打上分支名称的标签。

我找到了GITHUB_REF变量,但它返回refs/heads/feature-branch-1,而我只需要feature-branch-1


使用此操作:https://github.com/EthanSK/git-branch-name-action,它适用于pull_request和push触发器。 - Ethan SK
4
在我看来,https://dev59.com/GVMH5IYBdhLWcg3w1TyK#64210623 应该成为被采纳的答案;它解决了@ambientlight对当前被采纳答案的反对意见,避免了现在已经不再使用的 setenv 函数,并且没有使用任何外部库。 - michielbdejong
我在GitHub上发起了一个“功能请求”,希望能够添加本地支持。许多其他CI提供商(Travis CI、CircleCI、Semaphore CI)都有本地支持,因此增加类似的功能是有很好的先例的。如果您想看到这种行为被添加,请给该功能请求投票支持! - blimmer
13
${{ github.ref_name }} 对我有效。 - Neil McGuigan
https://docs.github.com/en/enterprise-cloud@latest/actions/learn-github-actions/variables#default-environment-variables - CatCatMcMeows
1
如果我需要在推送时(从特性分支到主分支)知道源分支名称,应该使用哪个上下文? 因为github.ref_name和github.head_ref都会给出主分支作为分支名称。 - DollyShukla
35个回答

297

我添加了一个单独的步骤来从$GITHUB_HEAD_REF/$GITHUB_REF¹(pr和push)中提取分支名称,并将其设置为步骤输出:

- name: Extract branch name
  shell: bash
  run: echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
  id: extract_branch

之后,我可以使用steps.<step_id>.outputs.branch在下一步骤中使用:

- name: Push to ECR
  id: ecr
  uses: jwalton/gh-ecr-push@master
  with:
    access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    region: us-west-2
    image: eng:${{ steps.extract_branch.outputs.branch }}

 


¹ 在 pull_request(合并请求)时使用$GITHUB_HEAD_REF,在 push 时使用$GITHUB_REF。说明:

变量 描述
GITHUB_HEAD_REF 工作流运行中拉取请求的源分支或头引用。仅当触发工作流运行的事件为pull_requestpull_request_target时,此属性才会被设置。例如,feature-branch-1。(source
GITHUB_REF 触发工作流运行的分支或标签的完整引用。对于由push触发的工作流,这是被推送的分支或标签引用。对于由pull_request触发的工作流,这是拉取请求合并分支。对于由release触发的工作流,这是创建的发布标签。对于其他触发器,这是触发工作流运行的分支或标签引用。仅当事件类型有可用的分支或标签时,才会设置此值。给定的引用是完整形式,即对于分支,格式为refs/heads/<branch_name>,对于拉取请求,格式为refs/pull/<pr_number>/merge,对于标签,格式为refs/tags/<tag_name>。例如,refs/heads/feature-branch-1。(source

关于所有默认环境变量的完整描述,以及其他内容,请参阅Learn Github Actions存档副本)。

寻找名为 github 的 Microsoft Github Action Context?请参考 ysfaran 提供的答案Dusan Plavak提供的答案


27
$GITHUB_REF 会长成这样(refs/pull/33/merge),$GITHUB_HEAD_REF 仅存储源分支名称,而 $GITHUB_BASE_REF 则代表 RP 目标分支。你可以更新你的答案以回退到 $ GITHUB_HEAD_REF,只要它被设置了,你觉得怎么样? - ambientlight
5
GITHUB_HEAD_REF 是指 head 引用,在格式上与其他引用相同,但仅适用于拉取请求。 - Alex Barker
3
简化版:run: echo "##[set-output name=branch;]${GITHUB_REF#refs/heads/}" 翻译:执行命令:echo "##[set-output name=branch;]${GITHUB_REF#refs/heads/}",其中${GITHUB_REF#refs/heads/}表示去掉GITHUB_REF变量值中的"refs/heads/"部分。最终输出名为branch。 - kenorb
1
现在set-output已经被弃用,因此第一步应该是- name: 提取分支名称 shell: bash run: echo "branch=$(echo ${GITHUB_REF#refs/heads/})" >>$GITHUB_OUTPUT id: extract_branch然后可以在下一步中使用${{ steps.extract_branch.outputs.branch }} - Ali Kahoot
不必通过GITHUB_OUTPUT来提供输出,您也可以设置一个环境变量。echo "GIT_BRANCH=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_ENV - undefined

203
我相信GITHUB_REF是唯一包含分支名称的环境变量。
如果您的分支名称中不包含/(例如deploy/abc),那么您可以从该字符串的其余部分中提取出分支名称。
${GITHUB_REF##*/}

例子:

$ GITHUB_REF=refs/heads/feature-branch-1
$ echo ${GITHUB_REF##*/}
feature-branch-1

更新:添加了一个完整的工作流示例。
工作流程
name: CI
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Git checkout
        uses: actions/checkout@v1
      - name: Branch name
        run: echo running on branch ${GITHUB_REF##*/}
      - name: Build
        run: docker build -t tedmiston/tag-example:${GITHUB_REF##*/} .

源代码:https://github.com/tedmiston/x/blob/master/.github/workflows/workflow.yml

示例输出 - 主分支

Run docker build -t tedmiston/tag-example:${GITHUB_REF##*/} .
  docker build -t tedmiston/tag-example:${GITHUB_REF##*/} .
  shell: /bin/bash -e {0}
Sending build context to Docker daemon  146.9kB

Step 1/1 : FROM alpine
latest: Pulling from library/alpine
9d48c3bd43c5: Pulling fs layer
9d48c3bd43c5: Verifying Checksum
9d48c3bd43c5: Download complete
9d48c3bd43c5: Pull complete
Digest: sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb
Status: Downloaded newer image for alpine:latest
 ---> 961769676411
Successfully built 961769676411
Successfully tagged tedmiston/tag-example:master

日志:https://github.com/tedmiston/x/commit/cdcc58a908e41d3d90c39ab3bf6fef1ad2c4238a/checks#step:4:16

示例输出 - 非主分支

Run docker build -t tedmiston/tag-example:${GITHUB_REF##*/} .
  docker build -t tedmiston/tag-example:${GITHUB_REF##*/} .
  shell: /bin/bash -e {0}
Sending build context to Docker daemon  144.9kB

Step 1/1 : FROM alpine
latest: Pulling from library/alpine
9d48c3bd43c5: Pulling fs layer
9d48c3bd43c5: Verifying Checksum
9d48c3bd43c5: Download complete
9d48c3bd43c5: Pull complete
Digest: sha256:72c42ed48c3a2db31b7dafe17d275b634664a708d901ec9fd57b1529280f01fb
Status: Downloaded newer image for alpine:latest
 ---> 961769676411
Successfully built 961769676411
Successfully tagged tedmiston/tag-example:branch-name-test

日志:https://github.com/tedmiston/x/commit/4e8d31259f861aaa2c30375756fc081c3659bddf/checks#step:4:16
查看此答案以了解更多关于参数扩展语法的内容。
参考GitHub Actions的虚拟环境页面,列出了执行环境中所有可用的环境变量。

3
这将在shell脚本中运行,但无法在工作流程YAML文件中运行。 - aborilov
1
是的,这对于“run”步骤有效,但当我将图像推送到ECR时,我还需要在ENV变量中包含分支名称。 - aborilov
我可以在这里使用 image: eng:${{ steps.extract_branch.outputs.branch }} 吗? 我尝试过,但对我没有起作用。 - aborilov
93
请注意,如果您使用Gitflow风格的分支名称例如feature/foo,那么${GITHUB_REF##*/}语法将不会按照您的意愿执行:它会从分支名称中剥离feature/并返回foo。我建议使用${GITHUB_REF#refs/heads/}代替${GITHUB_REF##*/},这样refs/heads/feature/foo将变成feature/foo。但是,如果您的ref是一个PR,那么$GITHUB_REF的值将不是refs/heads/branchname,而是pull/123/merge...但是,如果您的工作流脚本预期是一个PR,您可能已经知道了(例如,您正在触发pull_request)。 - rmunn
47
现在我们可以直接使用 GITHUB_REF_NAME,不需要从 GITHUB_REF 中提取。更多信息请参考文档 - Maneet
显示剩余7条评论

180

22
谢谢!FYI,这也可以作为环境变量 GITHUB_HEAD_REF 提供。 - Darian Moody
8
这个答案应该在列表中排名更高。 - Halil
3
你能否修改这个答案,以便提供一个适用于两种情况的选项,例如 ${GITHUB_HEAD_REF-${GITHUB_REF##*/}} - user319862
2
这个 ##*/ 语法是什么意思? - Boschie

180

简述

这适用于您可以在on下指定的每个触发器(例如pushpull_request):

env:
 BRANCH_NAME: ${{ github.head_ref || github.ref_name }} 

解释

关键在于,github.head_ref 仅在工作流由 pull_request 触发并且其中包含 PR 的源分支的值时才设置。如果工作流没有由 pull_request 触发,那么只会使用 github.ref_name,它仅包含分支名称。

GitHub 文档

来自官方 GitHub 文档的详细解释:

github.ref_name string 触发工作流运行的分支或标签的简短 ref 名称。此值与 GitHub 上显示的分支或标签名称相匹配。例如:feature-branch-1。

github.head_ref string 工作流运行中 PR 的 head_ref 或源分支。当触发工作流运行的事件为 pull_request 或 pull_request_target 时,才可用此属性。


9
尝试获取由新提交推动到拉取请求时触发的 GitHub Action 的分支名称时,这是我唯一有效的方法。 - Peter Brown
当标签触发操作时,此功能无法正常工作(它会返回标签名称)。 - Andris Silis
1
了不起的一行解决方案。只是要注意,如果期望的是拉取请求的目标分支,则应该设置环境变量BRANCH_NAME: ${{ github.base_ref || github.ref_name }},因为github.head_ref返回源分支(例如'feat/to-be-merged'),而不是目标分支(例如'main')。 - undefined
令人惊叹的一行解决方案。只需注意,如果期望是拉取请求的目标分支,则应设置环境变量BRANCH_NAME: ${{ github.base_ref || github.ref_name }},因为github.head_ref返回源分支(例如'feat/to-be-merged'),而不是目标分支(例如'main')。 - rffontenelle
workflow_dispatch 触发器是什么情况? - Sumit
workflow_dispatch 触发器是什么情况? - undefined

64

这适用于哪些事件? - Anshul Sahni
@AnshulSahni 我相信它适用于所有事件。 对于那些仅针对特定事件集合中可用的某个变量的情况,文档会指向哪些事件。 就像GITHUB_HEAD_REF一样,引用;“仅在拉取请求事件中设置。 头分支的名称。” - Federico Moya
6
2022年最相关的答案! - Kevin Wang
2
你也可以在 GitHub Actions 中使用 ${{ github.ref_name }} - Dantheman91
2
if: ${{ github.event_name == 'pull_request' }} run: echo "This is a PR for ${{ github.ref_name }}"Unfortunately this doesn't print out the branch name :(My branch name is feature/foo, but I get this instead: This is a PR for 438/merge - Jeremy Jao
如果我想要在触发操作时获取分支名称,该怎么办? - linSESH

51

使用setenv已被弃用。建议使用环境文件。在 @youjin 的答案 上进行改进,同时仍允许feature/分支(将所有/替换为-),我现在正在使用:

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Get branch name (merge)
        if: github.event_name != 'pull_request'
        shell: bash
        run: echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/} | tr / -)" >> $GITHUB_ENV

      - name: Get branch name (pull request)
        if: github.event_name == 'pull_request'
        shell: bash
        run: echo "BRANCH_NAME=$(echo ${GITHUB_HEAD_REF} | tr / -)" >> $GITHUB_ENV

      - name: Debug
        run: echo ${{ env.BRANCH_NAME }}

很好,谢谢。请注意,如果工作目录不同,可能会出现“错误:没有这样的文件或目录”的情况。在默认设置为不同路径的情况下,设置working-directory: .应该可以解决问题。 - lzap
很不幸,这对我来说不起作用。请参阅此GitHub问题 - petezurich

39

你可以使用 https://github.com/rlespinasse/github-slug-action

# Just add this  => 
- name: Inject slug/short variables
  uses: rlespinasse/github-slug-action@v3.x



# And you get this  => 
- name: Print slug/short variables
  run: |
    echo "Slug variables"
    echo " - ${{ env.GITHUB_REF_SLUG }}"    
    echo " - ${{ env.GITHUB_HEAD_REF_SLUG }}"
    echo " - ${{ env.GITHUB_BASE_REF_SLUG }}"
    echo " - ${{ env.GITHUB_REPOSITORY_SLUG }}"
    # output e.g. : master feat-new-feature v1.0.0 product-1.0.0-rc.2 new-awesome-product
    echo "Slug URL variables"
    echo " - ${{ env.GITHUB_REF_SLUG_URL }}"
    echo " - ${{ env.GITHUB_HEAD_REF_SLUG_URL }}"
    echo " - ${{ env.GITHUB_BASE_REF_SLUG_URL }}"
    echo " - ${{ env.GITHUB_REPOSITORY_SLUG_URL }}"
    # output e.g. : master feat-new-feature v1-0-0 product-1-0-0-rc-2 new-awesome-product
    echo "Short SHA variables"
    echo " - ${{ env.GITHUB_SHA_SHORT }}"
    # output e.g. : ffac537e

3
谢谢。在使用动作而不是在 shell 中运行命令的步骤中,这非常有用。 - ostmond
2
尝试了3-5个其他答案,但这个更容易使用。 - Vadorequest

24

这是目前最好的答案。 - Ryan

18
${{ github.ref_name }}

至少对于推送工作正常。请参阅ref_name以获取更多详细信息,它表示:

触发工作流运行的分支或标记名称。


18

如何在 Github Actions 中获取当前分支?

假设 ${{ github.ref }} 的值类似于 refs/heads/mybranch,您可以使用以下方法提取分支名称:

steps:
  - name: Prints the current branch name
    run: echo "${GITHUB_BRANCH##*/}"
    env:
      GITHUB_BRANCH: ${{ github.ref }}

如果你的分支包含斜杠(例如feature/foo),请使用以下语法:

steps:
  - name: Prints the current branch name
    run: echo "${GITHUB_REF#refs/heads/}"

致谢:@rmunn 评论

或者使用被采纳答案的方法,这里有一个更短的版本(符合lint规范):

steps:
  - name: Get the current branch name
    shell: bash
    run: echo "::set-output name=branch::${GITHUB_REF#refs/heads/}"
    id: myref

然后在其他步骤中引用 ${{ steps.myref.outputs.branch }}

注:


我喜欢这个使用输出的答案。其他答案中有很多问题。 - Someone Special

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接