バージョンタグをプッシュした時のみ実行

バージョンタグとはセマンティック バージョニング (SemVer) 2.0.0のような1.2.3というバージョンの頭にvが付いたv1.2.3のようなタグの事をここでは指します。

例えば以下のようなワークフローがあるとします。これがv1.2.3のようなタグをプッシュした時のみ、ジョブが実行されるワークフローです。これはecho fooと表示されます。

on:
  push:
    branches-ignore:
      - '**'
    tags:
      - 'v*'

jobs:
  build:
    runs-on: ubuntu-18.04
    steps:
      - run: echo foo

これは全体をタグがプッシュした時に実行というフィルターを掛けているような形になっています。ただケースによってはブランチプッシュでもタグプッシュでも共に実行したい共通ステップが出てきてしまったりするかもしれません。
この対応方法にはざっと以下のようなものがあります。

  1. ブランチとタグで別々のワークフローを実行
  2. ブランチとタグで同じワークフローを実行し、バージョンタグのプッシュ時にだけしか実行されないようなステップで対応

どちらが良いのかは規模感によって変わります。個人プロジェクトのような小さなものなら 1 で良いでしょうし、大きいなら 1 だと管理が辛くなるかもしれません。

1. ブランチとタグで別々のワークフローを実行

これは単にワークフローファイルを別々に置くというだけです。

例えば上記のワークフローがバージョンタグのプッシュ時のみというものだったので、ブランチプッシュ時のみ実行されるワークフローは以下のように書き始めます。

on: push

jobs: # 略

pushイベントはbrannchstagsで何もフィルタリングしていない時、すべてのブランチが対象で全てのタグが除外という設定になるので、これだけでブランチ用のワークフローになります。

2. ブランチとタグで同じワークフローを実行し、バージョンタグのプッシュ時にだけしか実行されないようなステップで対応

同じワークフローで実行というのは、<job>.if<step>-ifなどの制御を活用して、バージョンタグをプッシュした時だけに実行される領域をワークフロー内に作ろうという意味です。これにはまず 2 つの要素の理解をします。

1 つ目は参照の名前の存在です。何かしらをプッシュするとgithubコンテキストのref値に参照の名前が入ります。参照の名前というのはブランチのプッシュであればrefs/heads/<branch-name>(refs/heads/masterなど)、タグのプッシュであればrefs/tags/<tag-name>(refs/tags/v0.0.2など)のような名前のことです。

2 つ目はワークフロー内ではstartsWithという関数が使えます。これは引数を文字列として 2 つ取り、 1 つ目の文字列が 2 つ目に渡した文字列から始まっていればtrueを返します。

この 2 つの要素を組み合わせます。例えばタグの参照名はrefs/tags/から始まると分かったので、startsWith( github.ref, 'refs/tags/' )のようにすればタグの時だけtrueになりそうです。ただ今回はバージョンダグを扱うので、refs/tags/vとします。

上記から作成したブランチとバージョンタグが共存したワークフローが以下のようなものです。

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

jobs:
  build:
    runs-on: ubuntu-18.04
    steps:
      - run: echo ${{ github.ref }}
      - if: startsWith( github.ref, 'refs/tags/v' )
        env:
          REF: ${{ github.ref }}
        run: echo "${REF##*/}"

これに対してブランチプッシュバージョンタグプッシュを行いました。想定通り、バージョンタグをプッシュした時だけ 2 つ目のステップが実行されました。

2 つ目のステップのenv.REFecho "${REF##*/}はちょっとしたテクニックで、シェルが Bash (デフォルト)の時だけですが、このようにするとechov0.0.3のような値が表示(取得)できます。(ちなみにecho "${REF##*/v}とすると0.0.3という値になります)