BEACHSIDE BLOG

Azure と GitHub と C# が好きなエンジニアの個人メモ ( ・ㅂ・)و ̑̑

GitHub Actions のトリガーで任意のファイルやフォルダーを指定する・除外する

GitHub Actions を使っているとこんなことありますよね。

  • このフォルダー配下の変更があったときだけ特定の Actions を動かしたい
  • このファイルの変更されたときは、あの Actions は動かしたくない

これを実現するのが、paths または paths-ignore のフィルターです。

慣れてないと公式ドキュメントでは探しにくいせいか、この機能が認知されてないと感じることがよくあるのでまとめていきます😊

ブログのタイトルいまいちやなぁと思いながら書き始めました... paths って知らないとこんなんでググるかなぁとか思ったり、いやなんか違うやろと思ったり...

最初に知っておきたいこと

細かいこと抜きにとりあえず知っておきたいことは...

特定のファイル・フォルダーで GitHub Actions のトリガーを制御するには、paths または paths-ignore を使って定義することができます。

  • paths: ファイルやフォルダーを指定することで GitHub Actions のトリガーを制御することができます。無視する定義も可能です。無視する定義のみの定義はできません。
  • paths-ignore: 無視する定義のみをする場合はこっちを使います。

あとは、「 pathspaths-ignore の2つを1つのワークフローで一緒に使うことはできない」ということくらいです。

ユースケースのイメージとしては、

  • ファイル・フォルダーで、フィルターしたいものと無視したいものが混在する場合は paths を使う
    例: モノレポでフロントエンドとバックエンドのコードがあるので、フロントエンドの変更があった場合はフロントエンド用の Actions のみを起動したい。ルートの README.md の変更時は Actions を起動させない
  • 無視したいファイル・フォルダーのみの場合は、paths を使ってもいいし paths-ignore を使ってもいい:
    例...書くほどでもないですよね。

Paths フィルターの使い方

基本

GitHub Actions の Trigger (on) の定義で、events (pushpull_request など) の一段下で paths を定義します。branchs とかと同じインデントです。

frontend フォルダ配下の変更は全て含める、ルートにある README.md を無視するにはこんな書き方です。

on:
  push:
    branches:
      - main
    paths:
      - 'frontend/**'
      - '!README.md'

paths の中で無視したい場合は先頭に ! を付けます (上のサンプルの !README.md)。

ワイルドカードなどの正規表現

上のサンプルでも使ってますが、frontend フォルダ配下の変更は全て含める場合はワイルドカード ** を使って定義できます。

ワイルドカードで私的に最初に覚えておきたいのはこの2つ。

  • ** は、すべての文字列のワイルドカードとなります (0文字でも対象) 。'frontend/**' と定義することで frontend フォルダーの配下全てが対象になります。
  • * だと / はマッチしないので、つまりはそのフォルダの直下のみのワイルドカードになります (0文字でも対象) 。

他に使える正規表現は、以下の公式ドキュメントが参考になります。

Tips

順番は大事

書く順番も大事で、基本的には後に書いた方が強くなります。

具体的な例として、以下のようなフォルダー構成だったとします。

root
 ├ 📁 dir1
 │  ├ README.md
 │  ├ index.js
 │  ├ test.css
 │  └ ...
 └ 📁 dir 2
      └ ...

dir1 フォルダ配下の変更はトリガーに含めたいけど、dir1/README.md の変更だけは無視したい場合、以下のように書くのが正解です。後に書いた方が強いので「dir1 フォルダー配下を含める ( dir1/** )」→「dir1 直下の README.md は無視する ('!dir1/README.md')」という流れです。

# 正しい例
on:
  push:
    branches:
      - main
    paths:
      - 'dir1/**'
      - '!dir1/README.md'

これを以下のように反対に書くと、2つ目に書いた「dir1 フォルダー配下を含める ( dir1/** )」定義が強いので、最初に書いた「dir1 直下の README.md は無視する ('!dir1/README.md')」定義が打ち消されます。

# ダメな例
on:
  push:
    branches:
      - main
    paths:
      - '!dir1/README.md'  # これだとあかん!
      - 'dir1/**'

ということで順番には注意しましょう。

無視する定義だけしたけど Actions が全く動かない?!

前述してますが公式ドキュメントにも書いてある通り、paths の中で無視する定義のみをすることはできません。この場合、何を変更しても何をしても Actions は動きません (←2022年4月時点での動作確認)。

無視したいファイルだけを定義したい場合は paths-ignore を使いましょう。

たまにフィルターされない?!

Actions の yml が正しければおかしくなることはないです。が、突然ある日フィルターされず動かない・想定外に動く可能性は無きしもあらずです。その原因として2つ、1000 コミットより多い場合と diff のファイルが 300 までという制限です。

まぁ、私は遭遇する気がしないので気にしないでおきますが、正確な内容は公式ドキュメントは以下で書かれています。

paths-ignore フィルターの使い方

基本的な書き方は paths と一緒なのでもう書くことはないですが、こんな感じで使えます。

on:
  push:
    branches:
      - main
    paths-ignore:
      - 'docs/**'

参考

Workflow syntax for GitHub Actions - GitHub Docs