我对GitHub Actions相对较新,我有2个工作-一个运行我的测试,一个将我的项目部署到服务器上。

显然,我希望测试在每个分支上运行,但是部署应该只在某些东西被推到master时进行。

我正在努力寻找一种在特定分支上运行工作的方法。我知道在一个特定的分支上只运行整个工作流是可能的,但是这意味着我将有一个“测试”工作流和一个“部署”工作流。

这听起来像是一个解决方案,但它们是并行的。在理想的情况下,测试将首先运行,并且只有当测试成功时,才会启动部署作业。当使用两个单独的工作流时,情况就不是这样了。

我怎样才能做到这一点呢?是否可以在特定的分支上运行作业?


当前回答

已经有了一些很好的答案。下面是在条件语句中指定多个分支的方法:

name: my workflow
on: push
jobs:
  deploy:
    if: contains(fromJson('["refs/heads/master", "refs/heads/main"]'), github.ref)
    runs-on: ubuntu-latest
    steps:
      - name: Execute tests
        run: exit 0

其他回答

虽然你目前不能在作业级别拥有条件,但你可以在步骤级别拥有条件-请参阅GitHub动作的上下文和表达式语法。

要获得分支名称,目前的解决方案是检查GITHUB_REF环境变量-参见默认环境变量和这个问题的详细信息。

把它们放在一起——如果你决定在最后一个链接中使用公认的答案,你的工作流程可能是这样的:

jobs:

 test:
  runs-on: ubuntu-latest
  steps:
  - name: Run tests
    run: ./my-tests.sh

 deploy:
  runs-on: ubuntu-latest
  needs: test
  steps:
  - name: Extract branch name
    shell: bash
    run: echo "##[set-output name=branch;]$(echo ${GITHUB_REF##*/})"
    id: extract_branch
  - name: Deploy
    run: ./deploy.sh
    if: steps.extract_branch.outputs.branch == 'master'

如果你宁愿把所有的东西都保存在工作流文件中,而不是分开的脚本,你可以在给定的工作中的每个步骤中添加If。


我希望这只是一个临时的解决方案,工作条件将在测试结束前添加。

虽然这个讨论很老了,但最近我遇到了同样的问题,只是稍微增加了一点。If条件检查分支是否主要工作,但如果有人推动他们的分支和更新工作流yml文件删除If条件呢?deploy作业将在其分支未被检查或合并到main中时被触发,这可能会破坏生产环境。这可能是开源项目中的一个问题。

我在任何地方都找不到答案,所以想分享我的发现。我希望这是正确的线程。

为了确保只有在特定分支中才能触发作业,可以使用环境。部署作业很可能有一些api密钥用于连接到目标服务器,这些密钥可能存储在秘密中。我们应该将它们存储在各自的环境中,而不是存储在可以在存储库中全局访问的存储库秘密中。

环境的官方文档包含了详细的解释和示例脚本,但这里分享了一个简单的示例。假设我们希望只在main更新时运行生产部署

从存储库设置中创建一个生产环境 在“部署分支”下拉菜单中选择“选定的分支”,并在模式中添加main 在生产环境机密中添加api密钥

在工作流yml中,我们只需要添加环境信息environment: production,如下所示(使用来自@peterevans的回答的脚本)

name: my workflow
on: push
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Execute tests
        run: exit 0
  deploy:
    runs-on: ubuntu-latest
    needs: test
    if: github.ref == 'refs/heads/main'
    environment: production
    steps:
      - name: Deploy app
        run: exit 0

The environment information indicates where the secrets have to be read from. If the current branch name doesn't match the pattern provided in Selected Branches then the job will immediately fail with an error. Since we have a condition to only run this on main, normally that won't bother us because this job will be skipped on other branches anyways. But if someone, mistakenly or with ill intentions, modifies the yml file and removes the condition before pushing their branch, they'll get an error. So, our system remains secure at least from the threat here.

希望这对有同样疑惑的人有所帮助。

在最近的更新中,您现在可以将if条件放在工作级别。请在这里查看文档。https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idif

我测试了这个工作流,它在每次推送时运行作业测试,但只在主分支上运行部署。

name: my workflow
on: push
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Execute tests
        run: exit 0
  deploy:
    runs-on: ubuntu-latest
    needs: test
    if: github.ref == 'refs/heads/master'
    steps:
      - name: Deploy app
        run: exit 0

以下是我最初的答案,如果您喜欢有单独的工作流,则可以选择另一种解决方案。

第一个工作流运行于除master之外的每个分支。在此工作流中只运行测试。

on:
  push:
    branches:
      - '*'
      - '!master'

第二个工作流仅为master运行,如果测试成功通过,则运行您的测试和部署。

on:
  push:
    branches:
      - master

已经有了一些很好的答案。下面是在条件语句中指定多个分支的方法:

name: my workflow
on: push
jobs:
  deploy:
    if: contains(fromJson('["refs/heads/master", "refs/heads/main"]'), github.ref)
    runs-on: ubuntu-latest
    steps:
      - name: Execute tests
        run: exit 0

对于步骤或作业,您也可以使用github。Ref_name,它是触发工作流运行的分支或标记名称。

name: my workflow
on: push
jobs:
  if: github.ref_name == 'main'
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Execute tests
        run: exit 0

有关github上下文的更多信息请查看这里。