如何有条件地仅针对在特定分支上创建的标签运行Github工作流程操作?

14

我使用了几种不同的 Github 工作流,其中一种只应该在正式发布时运行。在 .github/workflows/release.yml 文件中,有这个 on 条件:

on:
  push:
    tags:
      - 'v*'

然而,如果我们团队中的某个人意外(或故意)从develop分支推送标记,这仍然可以运行。理想情况下,我们希望将其锁定,使得标记必须在main分支上(因为它是受保护的),甚至更进一步,如果我们能确保标记只参考与相应发布相关的特定合并提交,那将很不错。例如,如果我运行:

git branch --contains tags/v1.2.3

这通常会输出我标记所在的main分支。我可以在Github工作流中添加条件来检查输出结果吗?

查看Github操作文档,不清楚多个条件是使用逻辑AND还是逻辑OR进行评估。

1个回答

23
on中指定的事件类型之间使用逻辑运算符OR。因此,例如:
on:
  push:
    tags: ['v[0-9].[0-9]+.[0-9]+']
    branches: [master]

不幸的是,这将触发任何分支上匹配标记的工作流程,以及任何带有或不带有标记的主分支推送。我还更新了标记模式,遵循文档中的示例。

您需要决定是否仅运行标记的工作流程,然后过滤掉除主分支外的所有内容:

on:
  push:
    tags: ['v[0-9].[0-9]+.[0-9]+']

jobs:
  myjob:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/master'
    steps: [...]

或者反过来:

on:
  push:
    branches: [master]

jobs:
  myjob:
    runs-on: ubuntu-latest
    if: startsWith(github.ref, 'refs/tags/v')
    steps: [...]

如果你的工作流包含其他可能在推送到主分支时运行的作业,那么你可能会选择第二种解决方案。另外你会注意到,标签过滤器在第二种方案上不太准确,这可能会成为一个问题。同样重要的一点是,你可以使用on中的条件跳过整个工作流程,使用jobs.<job_id>.if跳过整个作业,或者只使用jobs.<job_id>.steps[*].if跳过某些步骤。


我以为这个已经可以工作了,但是现在我尝试在另一个仓库中重复它,但无论是触发推送到 main 分支并检查 ${{ startsWith('refs/tags/v', github.ref) }} 还是推送标签并检查 ${{ github.ref == 'refs/heads/main' }},都无法使其工作。难道还有其他问题吗? - Everett
9
当通过标签推送时,触发操作时github.ref类似于 refs/tags/xxx;当通过分支推送时,触发操作时github.refrefs/heads/main。这似乎是个进退两难的境地:当我推送一个分支时,我看不到标签,当我推送标签时,我看不到分支。 - Everett
当你从标签推送触发时,你可以检查主分支并使用 git merge-base --is-ancestor $tag HEAD 命令来检查标签是否存在于主分支上。 - ITChap
1
很棒的回复,非常有用。我正在编辑startWith的参数并将其倒置。非常感谢你的回答@ITChap。 - Kanekotic

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