如何在Github行动中获得当前的分支?

我正在用Github动作构建Docker图像,并想用分支名称标记图像。

我找到了GITHUB_REF变量,但它的结果是refs/heads/feature-branch-1,我只需要feature-branch-1

205003 次浏览

我相信GITHUB_REF是唯一包含分支名称的环境变量。

你可以从字符串的其余部分提取分支名称,如下所示:

${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的虚拟环境页列出了执行环境中可用的所有环境变量。

我添加了一个单独的步骤,用于从$GITHUB_REF提取分支名称,并将其设置为步骤输出

- name: Extract branch name
shell: bash
run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF#refs/heads/})"
id: extract_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 }}

你可以使用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

我只是在GitHub Actions中使用bash脚本做了一个简单的测试:

#!/bin/bash


echo Reserved for REPO_NAME=${GITHUB_REPOSITORY##*/}
echo GITHUB_REF=${GITHUB_REF}
echo EXTRACT_GITHUB_REF=${GITHUB_REF##*/}
echo EXTRACT_GITHUB_REF_HEADS=$(echo ${GITHUB_REF#refs/heads/})


cd $REPO_NAME
git checkout ${GITHUB_REF##*/}
git checkout $(echo ${GITHUB_REF#refs/heads/})

以下是输出的截图:

enter image description here 所以${GITHUB_REF##*/}$(echo ${GITHUB_REF#refs/heads/})都是正确的

要将其设置为环境变量,我使用以下语法:

- name: Extract branch name
shell: bash
run: echo "::set-env name=BRANCH_NAME::$(echo ${GITHUB_REF#refs/heads/} | sed 's/\//_/g')"
- name: Test
run: echo "${BRANCH_NAME}"

我在这里找到了这个语法:Github动作-启动worflows#如何定义环境变量?# 68

Rmq: sed 's/\//_/g'将分支名称中的/替换为_

请注意,如果你在pull request触发器上执行你的GitHub动作,那么GITHUB_REF变量将包含类似refs/pull/421/merge的东西,所以如果你试图git push到那个名字,它很可能会失败。

你可以在YAML中使用GitHub上下文中的引用。类似于:$\{\{ github.head_ref }}

https://help.github.com/en/actions/automating-your-workflow-with-github-actions/contexts-and-expression-syntax-for-github-actions#github-context

Github action context refs

if: github.ref == 'refs/heads/integration' && github.event_name == 'push'

您可以使用上面的命令替换您想要运行的任何分支或事件。

如何在Github行动中获得当前的分支?

假设$\{\{ 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 comment

或者使用已接受答案的方法,这里是更短的版本(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 }}

注:

在Windows上运行?。 Windows默认命令为PowerShell终端

  - name: SET CURRENT_BRANCH
run: |
$branchName = "$\{\{github.ref}}".Split("/")["$\{\{github.ref}}".Split("/").Length -1]
echo "::set-env name=CURRENT_BRANCH::$(echo $branchName)"

在GitHub动作上使用分支名称

使用当前分支名称的方便操作。 使用< / p >

name: build
on: push


jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- run: npm ci
- uses: nelonoel/branch-name@v1
# Use branch name for whatever purpose
- run: echo ${BRANCH_NAME}

下面是一个适用于pushpull_request事件的完整工作流

name: whichBranch
on: [pull_request, push]


jobs:
which_branch:
runs-on: ubuntu-latest
steps:
- name: Extract branch name on push
if: github.event_name != 'pull_request'
shell: bash
run: echo "::set-env name=BRANCH_NAME::$(echo ${GITHUB_REF#refs/heads/})"
id: extract_branch


- name: Extract branch name on pull request
if: github.event_name == 'pull_request'
run: echo "::set-env name=BRANCH_NAME::$(echo ${GITHUB_HEAD_REF})"


- name: Print branch name
run: echo 'The branch name is' $BRANCH_NAME

GitHub Action FranzDiebold / github-env-vars-action公开了几个有用的环境变量,比如当前分支名称和它们的slug值。我为这个用例做了这个操作。

使用

steps:
- uses: FranzDiebold/github-env-vars-action@v1.2.0
- name: Print environment variables
run: |
echo "GITHUB_REPOSITORY_SLUG=$GITHUB_REPOSITORY_SLUG"
echo "GITHUB_REPOSITORY_OWNER=$GITHUB_REPOSITORY_OWNER"
echo "GITHUB_REPOSITORY_OWNER_SLUG=$GITHUB_REPOSITORY_OWNER_SLUG"
echo "GITHUB_REPOSITORY_NAME=$GITHUB_REPOSITORY_NAME"
echo "GITHUB_REPOSITORY_NAME_SLUG=$GITHUB_REPOSITORY_NAME_SLUG"
echo "GITHUB_REF_SLUG=$GITHUB_REF_SLUG"
echo "GITHUB_REF_NAME=$GITHUB_REF_NAME"
echo "GITHUB_REF_NAME_SLUG=$GITHUB_REF_NAME_SLUG"
echo "GITHUB_SHA_SHORT=$GITHUB_SHA_SHORT"

enter image description here

所有操作系统(Linux, macOS和Windows)的演示也可以在存储库的演示工作流文件中找到!

使用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 }}

对于使用Windows映像来运行操作的人,有几个要点需要了解:

  1. 假设GitHub动作使用CMD shell是不正确的。默认情况下它们使用PowerShell
  2. 您可以指定shell使用以下方式:
- run: |
...
shell: cmd
  1. 您可以使用值'bash'在bash shell上下文中执行命令。

所以,总而言之,你不需要浪费潜在的时间试图弄清楚如何以破旧的cmd方式做事(就像我做的那样)。

为了简单地获取当前分支的名称,你可以在将shell设置为'bash'时使用流行的解决方案,或者使用例如下面的简单方法在默认PowerShell中设置变量:

$branchName = $Env:GITHUB_REF -replace "refs/heads/", ""

我做了一个获取分支名称的操作,而不管是否触发pull_request。https://github.com/EthanSK/git-branch-name-action

如果你正在使用actions/checkout的V2,那么你总是可以运行git branch --show-current来获得当前签出的分支的名称。

下面是一个代码片段,它设置了一个基于$GITHUB_REF的环境变量,如果不存在,则默认为dev

根据您的需求调整sed命令。

export GIT_BRANCH=$(echo ${GITHUB_REF:-dev} | sed s/.*\\///g)

为了处理pull_request事件(在这种情况下,$GITHUB_REF包含一些像refs/pull/519/merge这样无用的东西),你可以使用下面这一行:

   - name: Set branch name
run: echo "::set-output name=branch_name::$(echo ${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}})"

通常,我总是有一个用nodejspython编写的脚本,该脚本从workflow.yaml中调用。该脚本通常负责获取适当的分支引用等工作。

我有一个函数如下,在prepare-deployment.js脚本-

const VALID_REF_PREFIX = 'refs/heads/';
...


function getBranchRef(isProd = false) {
let branchRef = 'origin/master';


if (isProd) {
return branchRef;
}
/**
* When the workflow is invoked from manual flow, the branch name
* is in GITHUB_REF, otherwise, we have to look into GITHUB_BASE_REF
*/
if (GITHUB_REF.startsWith(VALID_REF_PREFIX)) {
// coming from a manual workflow trigger
branchName = `origin/${GITHUB_REF.replace(VALID_REF_PREFIX, '')}`;
} else {
// coming from a PR
branchRef = `origin/${GITHUB_HEAD_REF}`;
}


return branchRef;
}

这涉及到以下场景-

  1. 我想从PR部署到我的开发环境的变化
  2. 我想通过手动触发器将任何分支的更改部署到我的dev env中
  3. 我想从master部署更改到我的prod环境
$\{\{ github.ref_name }}

至少对推送来说还行。更多细节参见ref_name。它说:

The branch or tag name that triggered the workflow run.

更新

GitHub现在支持GITHUB_REF_NAME,它代表:The branch or tag name that triggered the workflow run

这个https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables . GitHub文档

现在$\{\{github.ref}}是获取分支名称的正确方法。 请记住$\{\{github.ref}}refs/heads/..前缀

有一个非常简单的git命令来获取当前分支:

git rev-parse --abbrev-ref HEAD

To get the output in an env file variable simply put:

      - name: Set CURRENT_BRANCH
run: echo "CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)" >> $GITHUB_ENV

获取env变量的输出:

      - name: Get CURRENT_BRANCH
run: echo $\{\{ env.CURRENT_BRANCH}}

来源:https://www.techiedelight.com/determine-current-branch-name-git/

在这里重复一下,以便更好地看到其他人在之前的回复中作为简单注释写的内容:

https://docs.github.com/en/actions/learn-github-actions/environment-variables

分支名称仅针对拉请求被暴露在这个环境变量中:

GITHUB_HEAD_REF Only set for pull request events. The name of the head branch.

在GitHub动作中,对应的上下文键是:

github.head_ref

处理pull_requestpush事件的解决方案。由于set-env已弃用,因此实现了保存获得的分支名称以供后续步骤使用的变通方法。

.不需要第三方操作
name: CI
on: [ pull_request, push ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: "Get branch name and save to env"
env:
IS_PR: $\{\{ github.EVENT_NAME == 'pull_request' }}
run: |
if ${IS_PR}; then
BRANCH_NAME="${GITHUB_HEAD_REF}"
else
BRANCH_NAME="${GITHUB_REF##*/}"
fi
echo "BRANCH_NAME=${BRANCH_NAME}" >> $GITHUB_ENV


- name: "Another step uses branch name"
run: echo "Branch name is $\{\{ env.BRANCH_NAME }}"


< a href = " https://microsoft.github。/a> . io/code-with-engineering-playbook/continuous-delivery/devops-provider-recipes/ GitHub - Actions / Runtime - Variables / Runtime - Variables /" rel="nofollow noreferrer"> GitHub Actions中的运行时变量

博士TL;

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

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

解释

诀窍在于,github.head_ref只在工作流由pull_request触发时设置,并且它包含PR的源分支的值。github.ref_name只在工作流不是由pull_request触发时使用,而且它也只包含分支名称。

GitHub的文档

官方GitHub文档的详细解释:

github.ref_name string触发工作流运行的分支或标记的短引用名称。该值与GitHub上显示的分支或标记名称匹配。例如,feature-branch-1。

github.head_ref string工作流运行中pull请求的head_ref或源分支。此属性仅在触发工作流运行的事件为pull_request或pull_request_target时可用。

对于那些刚刚找到这个线程的人,你现在可以使用GITHUB_REF_NAME,例如$\{\{ github.ref_name }}https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables

因此,如果你触发的操作工作流分支是main,这个变量将被设置为main。例如,如果你有多个带有releasemain分支的回购,这就很有用。

我们目前有一个单独的作业,它运行之前所有其他作业。该步骤根据分支名称决定在什么环境中运行。我们的分支与部署基础设施和代码库的特定环境相关联。每个环境都有自己的秘密(github企业特性)。

输出环境变量可用于所有其他连续作业。您可以在步骤中使用该变量,例如将其设置为NODE_ENV,或者用它标记docker图像。您还可以在该特定变量上设置并发性,以确保同一时间只运行使用相同值的单个作业或工作流。这使得它非常强大。

下面是我上面描述的一个例子:

name: Build pipeline
on:
push:
branches:
- feature/*
- develop
- release/*
- main


jobs:
environments:
name: Set environment
runs-on: ubuntu-latest
steps:
- run: echo "Setting $ENVIRONMENT.."
outputs:
# Defaults to 'dev' in case of a feature branch
# You could also use the contains expression if needed
environment: $\{\{ github.ref == 'refs/heads/main' && 'prd' || (startsWith(github.ref, 'refs/heads/release/') && 'acc' || github.ref == 'refs/heads/develop' && 'tst' || 'dev') }}


build:
name: Docker build
runs-on: ubuntu-latest
needs: [environments]
environment: $\{\{ needs.environments.outputs.environment }} # Enterprise only
concurrency: $\{\{ needs.environments.outputs.environment }}
env:
ENVIRONMENT: $\{\{ needs.environments.outputs.environment }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Build
run: |
docker build . \
-t hello/world:$\{\{ needs.environments.outputs.environment }}

注意:因为提取环境名称不是在bash或powershell中完成的,你被绑定到有限的表达式 github动作提供。如果你需要更花哨的东西,你可以用不同的方式来做,这不是唯一的真理。然而,我总是喜欢让事情简单易懂。

替代(快速)选项

如果你不介意使用其他人的github动作,你可以使用市场上的许多动作之一,做一个找到一个替换。可以在在这里中找到一个例子,它看起来像:

on: [push]


jobs:
replace-job:
runs-on: ubuntu-latest
name: 'Find and replace'
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Remove refs/heads/ from string
uses: mad9000/actions-find-and-replace-string@1
id: findandreplace
with:
source: $\{\{ github.ref }}
find: 'refs/heads/'
replace: ''
- name: Branch name
run: echo "The branch name is $\{\{ steps.findandreplace.outputs.value }}"

为了获得delete事件上的ref名称,我最终使用了sed

on:
delete:
...
steps:
- name: Do something
shell: bash
run: |
refname=$(sed -e s:refs/heads/::g -e s:/:-:g <<< $\{\{ github.event.ref }})

剪掉指针/头/并将斜杠转换为破折号,例如。refs/heads/feature/somefeaturefeature-somefeature

我不得不这样做了几次不同的事件,在PR同步事件上运行,然后推到主(例如,构建标记容器图像),我不特别喜欢:

  1. 在私人回购中使用第三方行动。
  2. 使用表达式语法,因为我发现它是一个相当糟糕的开发经验。
  3. 必须记住变量展开替换是如何工作的,因为我也倾向于使用/分离的分支,例如fix/123

我想我应该添加一个小的bash片段,它将用于push和pull_request事件,因为我在这里没有看到一个:

echo "${GITHUB_REF_NAME}" | grep -P '[0-9]+/merge' &> /dev/null && export ref="${GITHUB_HEAD_REF}" || export ref="${GITHUB_REF_NAME}"

$ref变量将保存push和pull_request事件的分支名称,并将处理gitflow/style/branches

这是基于GH操作为在PR同步上运行的操作创建了一个(通常是意外的){pr number}/merge分支的假设,grep调用只会在分支名称与(perl风格)正则表达式匹配时返回0,并遵循&&路径导出ref作为GITHUB_HEAD_REF的值。或者,对于不匹配正则表达式的分支(如main)。

grep上的输出重定向只是防止正则表达式匹配打印到标准输出的情况。

当然,如果您需要在匹配正则表达式的分支上使用push事件,那么这将不起作用。

获取当前分支很简单,下面的代码适用于我和

github.ref_name

是用于获取分支名称的预定义变量吗

jobs:
main-branch-build:
if: github.ref_name == 'main'
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
feature-branch-build:
if: github.ref_name != 'main'
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3