GitHub Actions CI 条件正则表达式

34

我正试图将我的CI工作流从CircleCI迁移到GitHub Actions。我面临的最大困难是部署。

目前,我的工作流程是这样的:当我向GitHub存储库推送标签时,它会运行测试,然后运行部署。唯一的问题是CircleCI会过滤标签,只有当标签与正则表达式匹配时才运行作业:/v[0-9]+(\.[0-9]+)*/

在运行部署之前,我该如何检查确保我推送的标签与上述正则表达式模式匹配?

我目前拥有以下GitHub Actions yml文件:

name: CI
on: [create]

jobs:
  # ...

  deploy:
    runs-on: ubuntu-latest
    if: github.event.ref_type == 'tag' && github.event.ref == SOMETHING HERE
    steps:
      - uses: actions/checkout@v1
      # ...

if 块中,我需要将 github.event.ref == SOMETHING HERE 更改为其他内容。我已经查看了GitHub Actions 的上下文和表达式语法文档页面。但由于 GitHub Actions 的灵活性和强大性,似乎应该有一种方法或方式来做到这一点,或者至少有一些解决方法。

我该如何确保标签(github.event.ref)与正则表达式模式(/v[0-9]+(\.[0-9]+)*/)匹配?

3个回答

48

很遗憾,我认为目前还没有办法在if条件语句中进行正则表达式匹配。

一个选择是在push事件上使用过滤器。

on:
  push:
    tags:
      - 'v*.*.*'

另一个选项是将正则表达式检查单独作为一步进行,在此步骤中,它会创建一个步骤输出。然后可以在if条件语句中使用。

      - name: Check Tag
        id: check-tag
        run: |
          if [[ ${{ github.event.ref }} =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
              echo "match=true" >> $GITHUB_OUTPUT
          fi
      - name: Build
        if: steps.check-tag.outputs.match == 'true'
        run: |
          echo "Tag is a match"

2
是的。由于我的工作流程,我希望在部署之前运行的作业可以在所有创建的标签上运行,而不仅仅是“v*.*.*”。匹配也不如我的正则表达式强大。然后单独的步骤选项可能有效,但当你有很多步骤时感觉非常混乱。希望GitHub尽快支持这个功能! - Charlie Fish
1
你的“检查标签”操作步骤非常棒,它像魔法一样运行! - Huan
@peterevans 看起来不错,但你能解释一下后面的例子是做什么的,或者它是如何工作的,或者至少添加一些文档参考吗? - j3141592653589793238
1
@user0800 我已经添加了有关 set-output 的文档链接。正则表达式部分只是 shell 脚本,与 GitHub Actions 无关。 - peterevans
1
如果你使用用户输入(例如pr标题或分支名称),那么匹配的shell可能非常危险。这个例子非常令人担忧,我建议将其删除。如果你把分支命名为true]]||["a"呢?(如果允许使用方括号)? - Niton

22
我通过两个步骤成功实现了这一点。第一部分是过滤您想要运行的标签。第二部分是在您的deploy任务上创建一个条件。
我的工作流程的简化版本如下所示:
name: CI-CD

on:
  push:
    branches:
    - stable
    tags:
    - '[0-9]+.[0-9]+.[0-9]+'
    - '[0-9]+.[0-9]+.[0-9]+rc[0-9]+'
  pull_request:
    branches:
    - stable


jobs:
  test:
    steps:
      ...

  deploy:
    needs: test
    if: startsWith(github.ref, 'refs/tags')
    steps:
      ...

我在特定分支上运行我的工作流程,包括推送、标签和拉取请求。你可以根据自己的需求灵活设置标签过滤条件。查看过滤模式
我在如何设置正确的条件来运行“deploy”任务方面遇到了一些困难。最终我选择了以下方式:
needs: test

这确保它只会在test任务成功运行时才执行。
然后,我利用了github.ref在推送到分支时将为'refs/heads/stable',在推送标签时将为'refs/tags/<your tag>'的事实。因此,我只需使用以下条件测试这种差异。
if: startsWith(github.ref, 'refs/tags')

对我来说,这个功能非常好用,但可能会根据你的设置而有所不同。
当然,你也可以创建单独的工作流程,但在我的情况下,我总是希望先运行测试套件。
编辑:正如@alex-povel在下面评论中提到的,一个更明确的检查是:
if: github.ref_type == 'tag'

请注意,比较符号的另一侧应该是一个单引号字符串。使用双引号字符串会导致错误:意外符号:'"tag"'

1
供参考,startsWith 和其他表达式的文档在此处:https://docs.github.com/en/actions/learn-github-actions/expressions#startswith - Arthur
4
可以用 github.ref_type == 'tag' 替换 startsWith(github.ref, 'refs/tags') 的检查。 - Alex Povel
在if表达式中,双引号是错误的。它必须是单引号字符串(如@AlexPovel的评论所述)。 - suvayu

16
根据文档,你可以这样做:
on:
  create:
    tags:
      - "v[0-9]+.[0-9]+"

我尝试了上述方法并确认其有效。这并不是完整的正则表达式能力,但应该足以满足您的需求。


1
为了更完整,最好使用“v[0-9]+.[0-9]+”(带反斜杠),否则你的正则表达式也会匹配3.6和3a6,因为点字符在正则表达式中代表“任何字符”。你可以在 https://regex101.com/ 上进行验证。 - Dennis Ameling
6
请查看他提到的“docs”链接。您会发现,“.”不像完全传统的正则表达式那样受影响。 - Isometriq
-1,分支和标签过滤器仅支持推送和拉取请求事件。此配置将无法工作。参考:https://github.com/actions/runner/issues/1007#issuecomment-808904408 - hiropon

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