2020年1月26日日曜日

開発中のGitHub ActionのテストをGitHub Actionsで行う

このタイトルを見て「あー、わかるわかる」と思った人はgit-flowやGitHub Flowなどの手順でGitHub Actionを自作したことがある人だと思います。

「え、普通にGitHub Actionsでテストできないの?」と思ったアナタ。最初は簡単だろうと思っていたんですが、意外と手こずったのでその顛末の記録です。

どちゃくそ紛らわしいですが、"GitHub Action"はGitHub Marketplaceにある個々のアクションのことを、"GitHub Actions"はCI/CDを自動化するGitHubの機能のことを指しています。
ここに"Use this GitHub Action with your project"と書いてあることと、GitHub Actionsの説明からして、多分公式でそういう扱いです。

ややこしいので、以下ではGitHub Actionを単にAction、GitHub ActionsをそのままGitHub Actionsと表記します。

git-flowとかGitHub Flowって何よ

開発時のブランチ運用モデルです。詳しい説明は面倒なので省略します。検索すればたくさん出てきます。

超簡単に説明すると、
  • masterブランチにはリリース用のコミットのみ存在し、リリースごとにタグを作成
  • 開発時はmasterブランチからトピックブランチを生やし、レビューが終わったらmasterにマージ
こんな開発の流れのことです。

名前を知らなくても、大なり小なり似たような方法で開発している人も多いと思います。

どこで手こずったの?

GitHub Actionsのワークフロー内でActionを使うには、使いたいバージョン(ブランチ名、タグ名、コミットハッシュ値等のgit checkoutで使える値)を指定する必要があります。
たとえばこんなかんじ。
steps:
- name: Checkout source codes
  uses: actions/checkout@v1 # @v1 のようにバージョン指定が必要
git-flowやGitHub Flowで開発中のAction自身をGitHub Actionsで動作チェックする場合、開発中のトピックブランチは毎回変わるのでどう指定すればいいのかわからないのです。

その1: トピックブランチを作るたびにワークフローファイルのバージョンを書き換える(失敗)

多分一番原始的というか、誰でも考えつきそうな方法です。

例えばInstall SSH Keyを開発しているときに自分自身にCIを適用する場合、ワークフローファイルをこのように書きます。
steps:
- name: Install SSH key
  uses: shimataro/ssh-key-action@master
これに対してfooというトピックブランチを生やして開発をするとき、トピックブランチ内でのみ以下のように使いたいバージョンを変更します。
steps:
- name: Install SSH key
  uses: shimataro/ssh-key-action@foo
一見これで動きそうですが、
  • トピックブランチを作るたびに書き換えないとダメ
    • 書き換え忘れると、トピックブランチの内容ではなくmasterブランチの内容でワークフローを実行することになるので、CIの意味がなくなる
  • masterへマージする前にワークフローファイルを忘れずに元に戻す必要がある
    • リバートコミットに対してもCIが走るため、互換性のない変更を加えた場合にリバートコミットに対するCIでエラーが起きてマージできない
  • masterへマージした後にリバートコミットを作ると、masterブランチが汚れる
という問題があります。

その2: 環境変数を使う(失敗)

ワークフローファイル内では環境変数を使えるようなので、該当コミットのハッシュ値を保持しているGITHUB_SHAという変数を使ってみました。
steps:
- name: Install SSH key
  uses: shimataro/ssh-key-action@${GITHUB_SHA} # GITHUB_SHAでバージョン指定
なかなかいいアイデアだと思ったのですが、いざ実行してみるとこんなエラーが出ました。
##[warning]Failed to download action 'https://api.github.com/repos/shimataro/ssh-key-action/zipball/${GITHUB_SHA}'. Error Response status code does not indicate success: 404 (Not Found).
どうやらuses内では環境変数は展開してくれないようです。

その3: コンテキストを使う(失敗)

環境変数と似たようなものにコンテキストがあるので、今度はこれを使ってみました。
steps:
- name: Install SSH key
  uses: shimataro/ssh-key-action@${{ github.sha }}
今度こそやったか?と思ったのですが、こんなエラーが。
- Your workflow file was invalid: The pipeline is not valid. .github/workflows/verify.yml (Line: 18, Col: 13): Unrecognized named-value: 'github'. Located at position 1 within expression: github.sha,.github/workflows/verify.yml (Line: 39, Col: 13): Unrecognized named-value: 'github'. Located at position 1 within expression: github.sha
コンテキストはwithのパラメータ指定では使えるけど、usesでは使えないようです。

その4: ローカルファイルへの参照を使う(失敗)

そもそも、ActionはGitHubリポジトリーにあるものだけじゃなくて、ローカルファイルにあるものも使えるんだよな…ということにようやく気づきました。

ということは、CI対象のコードをチェックアウトしてからローカルファイルを参照すればいいんじゃね?ということで
steps:
- name: Checkout source codes # まず最新のソースコードをチェックアウト
  uses: actions/checkout@v1
- name: Install SSH key
  uses: . # カレントディレクトリのソースコードを使う
これなら文句ないだろうとニヤニヤしながら実行したところ、今度はこんなエラーが出てきました。
- Your workflow file was invalid: The pipeline is not valid. .github/workflows/verify-on-ubuntu.yml (Line: 11, Col: 13): Expected format {org}/{repo}[/path]@ref. Actual '.',Input string was not in a correct format.
どうやらActionを使うには特定のフォーマットが必要のようです。

その5: ローカルファイルへの参照を使う 2(成功)

よろしい、ならば強引にフォーマットに合うような形で使ってやろうじゃないか。
steps:
- name: Checkout source codes
  uses: actions/checkout@v1
- name: Install SSH key
  uses: ./. # これならどうだ
今度こそ成功しました。

なんか指定の仕方がキモいんですが、とりあえずこれで常にCI対象のコードにCIを適用できるようになりました。

なんかいい方法があったら教えてください。

0 件のコメント:

コメントを投稿