我正在用Github动作构建Docker图像,并想用分支名称标记图像。
我找到了GITHUB_REF变量,但它导致了refs/heads/feature-branch-1,我只需要feature-branch-1。
我正在用Github动作构建Docker图像,并想用分支名称标记图像。
我找到了GITHUB_REF变量,但它导致了refs/heads/feature-branch-1,我只需要feature-branch-1。
当前回答
通常,我总是有一个用nodejs或python编写的脚本,从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;
}
这涉及到以下场景-
我想从PR部署到我的开发环境的变化 我想通过手动触发器将任何分支的更改部署到我的dev env中 我想从master部署更改到我的prod环境
其他回答
要将其设置为环境变量,我使用以下语法:
- 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'将用_替换分支名称中的/
博士TL;
这适用于你可以在on下指定的每个触发器(例如push或pull_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。工作流运行中pull请求的head_ref或源分支。此属性仅在触发工作流运行的事件为pull_request或pull_request_target时可用。
我们目前有一个单独的作业,它在所有其他作业之前运行。该步骤根据分支名称决定在什么环境中运行。我们的分支与部署基础设施和代码库的特定环境相关联。每个环境都有自己的秘密(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 }}"
现在不建议使用setenv。建议使用环境文件。基于@youjin的回答,同时仍然允许功能/分支(用-替换所有/的出现),我现在使用这个:
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 }}
现在$ {{github。Ref}}是获取分支名称的正确方法。 请记住${{github。Ref}}有refs/heads/..前缀