我对GitHub Actions相对较新,我有2个工作-一个运行我的测试,一个将我的项目部署到服务器上。
显然,我希望测试在每个分支上运行,但是部署应该只在某些东西被推到master时进行。
我正在努力寻找一种在特定分支上运行工作的方法。我知道在一个特定的分支上只运行整个工作流是可能的,但是这意味着我将有一个“测试”工作流和一个“部署”工作流。
这听起来像是一个解决方案,但它们是并行的。在理想的情况下,测试将首先运行,并且只有当测试成功时,才会启动部署作业。当使用两个单独的工作流时,情况就不是这样了。
我怎样才能做到这一点呢?是否可以在特定的分支上运行作业?
虽然这个讨论很老了,但最近我遇到了同样的问题,只是稍微增加了一点。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
2021年更新
我知道有可能只在特定的工作流上运行整个工作流
分支,然而,这意味着我将有一个“测试”工作流和一个
“部署”的工作流。
这听起来像是一个解决方案,但它们是并行的。在一个
理想的情况是,测试将首先运行,并且只有在他们成功的情况下
deploy作业将启动。当使用两个单独的时候,情况就不是这样了
工作流。
现在,您可以使用事件workflow_run来实现测试首先运行的部分,并且只有当测试成功时,才会启动部署作业(请继续阅读以了解如何执行):
workflow_run的文档页面
https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#workflow_run
请求或完成工作流运行时发生此事件
的完成结果允许您执行工作流
另一个工作流。不管结果如何,都会触发工作流运行
前面的工作流。
例如,如果您的pull_request工作流生成构建工件,
您可以创建一个新的工作流,使用workflow_run来分析
结果,并向原始拉请求添加注释。
现在,考虑OP的初始问题:
我希望测试在每个分支上运行,但是部署应该只在某些内容被推到master时进行
现在这个问题可以这样解决:
下面的设置正在工作,几分钟前,我刚刚在我的一个存储库中实现了相同的逻辑
工作流< your_repo > / .github /工作流/ tests.yml
name: My tests workflow
on:
push:
branches:
- master
pull_request: {}
jobs:
test:
# ... your implementation to run your tests
工作流< your_repo > / .github /工作流/ deploy.yml
name: My deploy workflow
on:
workflow_run:
workflows: My tests workflow # Reuse the name of your tests workflow
branches: master
types: completed
jobs:
deploy:
# `if` required because a workflow run is triggered regardless of
# the result of the previous workflow (see the documentation page)
if: ${{ github.event.workflow_run.conclusion == 'success' }}
# ... your implementation to deploy your project