Github Actions 2年使ってみてわかったことまとめ

# 対象の読者

Travis-CIやCircleCIなどのGithubと統合されたモダンなCIサービスを使ったことがあり、その使い方をおおよそ理解している人向けに書いています。

# Travis-CIやCircleCIなどのモダンCIサービスとGithub Actionsで違う点

使い方はほぼ同じです。GitリポジトリそのものにコミットされたCI設定ファイル( `.github/workflows/workflow-a.yml` など)を読み取りGitリポジトリへのアクション駆動でCIが走ります。

CIの実行状況やログがウェブ上で確認できる点も同じです。
以下のようにCIステータス確認用のCIバッジの機能もあります。

![CI](https://github.com/bigwheel/tfinfermv/workflows/CI/badge.svg)

# おすすめポイント

## [利用料金が安い(というかだいたい無料)](https://github.com/features/actions#pricing-details)

[^1]: 多くの場合選択されるであろうPERFORMANCEプランの想定
[^5]: [Features • GitHub Actions](https://github.com/features/actions#pricing-details)

個人ではなく組織で利用することを考えた場合、例えばCircleCIの利用料金は1ユーザー$15です[^1]([料金プラン \- CircleCI](https://circleci.com/ja/pricing/#comparison-table))。
それに対してGithub Actionsの利用料金はGithub自体の利用料金へ含まれており、基本的に追加の費用はかかりません。従来Githubの有料プランを使っていた人は追加投資0で利用できることになります[^5]。各プランごとに基本で提供されるCI実行時間(Teamプランで3,000分/月 = 計50時間/月)を超えるとCIが実行できなくなりますが、追加料金を支払うことでそれ以上の実行も可能になります([About billing for GitHub Actions \- GitHub ヘルプ](https://help.github.com/ja/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions#))。

### 蛇足: Github Actions安すぎない？

<details><summary>本筋じゃないので折りたたみました</summary><div>

Jenkins, Travis, Circle, bitrise, CodeBuildなどを渡り歩いた筆者の経験からするとGithub Actionsはいくらなんでも安すぎます(というかほぼ無料)。
Travis, Circle, bitriseなどが同じコンピューティングコストに揃えることでだいたい同一の料金程度に落ち着くことを考えれば、この価格設定はほとんどダンピングレベルのものです。
この動きの背景にはMicrosoftによるGithubの買収が大きく影響していそうです。

* [［速報］GitHub、マイクロソフトによる買収を正式発表 － Publickey](https://www.publickey1.jp/blog/18/github_3.html)

この動きによりGithubは資金的な余裕ができました(つまり赤字でも長期・継続的な資金投入ができる)。
またGithub ActionsのバックエンドがMicrosoft Azureであることからも技術的・コンピューティングリソース的な支援も強力に受けていることが伺えます。

[新 GitHub Actions 入門 \- 生産性向上ブログ](https://www.kaizenprogrammer.com/entry/2019/08/18/205010#GitHub-Actions-%E3%81%A8-Azure-Pipelines)

> 訳: GitHub Actions の仮想環境は Microsoft Azure 上の VM に GitHub Actions runner をインストールしてホストされています。GitHub Actions runner は Azure Pipelines Agent の fork です。

安すぎることに不安を覚える人もいるかもしれませんが、みんながWindowsやOfficeを使うために払った料金がGithub Actionsへ投入されていると考えれば良いと思います。

</div></details>

## Githubとの高い統合性(使いやすさ)

Travis-CIやCricleCIなどのCIサービスがよく普及した背景にはwebhookによるCIの自動キックやコミットへのCI結果表示、最新のCIステータスバッジなどもあると思います。それらがGithubとの統合性を高め、サービス初心者でも簡単に利用できるようにしています。

Github Actionsでは更にそれらより一歩楽になっています。
Github Actionsは標準で有効になっているため設定ファイルを追加するだけでCIが自動的に走ります。TravisやCircleなどでやるような初期設定が不要です。
またGithubからの遷移の面でも「Actions」タブによってより理解しやすくアクセスがよりしやすくなっています。

<img width="758" alt="無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30316/4819fe6f-e1f0-f00e-395e-92a0f86cc2f8.png">

またCircleやTravisが備えているものと同様のステータスバッジ生成機能もあります。

<img width="938" alt="4無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30316/c788e36e-50f4-eb9d-a81a-d583f68bef29.png">


<!-- これうまく説明できなさそう& 詳細にすぎるので割愛 GITHUB_TOKENが標準でセットされている -->

## 再利用可能なCI処理パーツというアイデア(Action)

これまでに書いた利点が「自身がGitリポジトリホスティングサービスであるポジショニング的利点」「Microsoftという強力な資金源」というやや卑怯なメリットであったのに対して、この利点は純粋にCIサービスの機能であり、個人的には革新的な改善だと思っています。
詳しく説明しましょう。

[GitHub Actionsのワークフロー構文 \- GitHub ヘルプ](https://help.github.com/ja/actions/reference/workflow-syntax-for-github-actions)

Github Actionsの用語として、まずCI設定ファイルはワークフローファイルと呼ばれます。1つのワークフローファイルには1つ以上のジョブから構成されます。1つのジョブは逐次実行される1つ以上のステップからなります。

* ワークフローファイルα
    * …
* ワークフローファイルβ
    * ジョブA
        * …
    * ジョブB
        * ステップ1
        * ステップ2
            * 以下のどれか
                * コマンドの実行
                * 設定タスクの実行
                * Actionの実行
        * …
    * ジョブC
        * …
    * …
* …

> ステップでは、コマンドを実行する、設定タスクを実行する、あるいはリポジトリやパブリックリポジトリ、Dockerレジストリで公開されたアクションを実行することができます。 

ドキュメントにかかれている通りこのステップではTravisやCircleでやったようなシェルスクリプトのプリミティブな実行(= コマンドの実行)もできますが、**アクション**も実行することができます。
この**アクション**、簡単に言うと再利用可能なCIスクリプトです。
代表的なものが[Actions \| GitHub](https://github.co.jp/features/actions)のページに並んでいますがAWSへの接続に必要な認証の設定をよしなにしてくれる[aws\-actions/configure\-aws\-credentials](https://github.com/aws-actions/configure-aws-credentials)やKubernetesへのデプロイをしてくれる[Azure/k8s\-deploy](https://github.com/Azure/k8s-deploy)などがあります。
これを使えばCIのスクリプトを自分で書くことなく、十分に検証された処理を選ぶだけで良くなります。

## ディレクトリ単位でCIをキックするかを判定できる

地味ながら重要な点です。自分が知る限りTravic-CIでもCircleCIでも特定のディレクトリ以下が変更された場合のみCIを実行する、という設定はできません。
Github Actionsでは[`on.<push|pull_request>.paths`という設定](https://help.github.com/ja/actions/reference/workflow-syntax-for-github-actions)でそれを行うことができます。
最近ではモノレポと言われる戦略が有名になってきたりそうでなくとも1つのリポジトリへterraformファイル・アプリケーションコード・lambda定義など複数の種類のデプロイに関わるコードが集約されることがあります。そういったときにはこの設定ができないとCIのためにリポジトリを分ける、ということをしなければなりません。
地味ですが非常に重要な機能だと思います。

# 頑張ってほしいポイント

## UI・UXはTravisやCircleに劣る

主観や慣れによるところも大きいですが実行中のジョブの状態表示や実行ログの表示などはまだTravisやCircleなど既存のサービスのほうが洗練されている印象です。

特にGithub Actions側は実行されたワークフローのログに到達するまでの遷移数・クリック数が非常に多いです。
Travisがページさえ開けば即座にログが表示されるのに対してGithub Actionsはログを表示するまで2,3回多くのクリックを必要とします。

[<img width="954" alt="6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30316/7128ed77-e595-2466-fe2e-51a768227c7c.png">](https://github.com/bigwheel/tfinfermv/runs/465978295)

[<img width="944" alt="5無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30316/2f3485f2-0c36-8a13-d8f1-879a145348e0.png">](https://travis-ci.org/bigwheel/util-backports/builds/639459064)

### 2020/09/24 ログの表示が改善されました！

詳細はこちら: [A better logs experience with GitHub Actions \- The GitHub Blog](https://github.blog/2020-09-23-a-better-logs-experience-with-github-actions/)

あまりに重すぎて長いログだと使えるかギリギリの品質だったログ表示がだいぶ改善されました。
ただ、他のCIサービスと比べると正直まだまだかなと思います。




## 外部のActionsを使ったときのセキュリティが非常に怖い

現在Actionは[GitHub Marketplace · Actions to improve your workflow](https://github.com/marketplace?type=actions)で公式に列挙されていますが、これらもセキュリティ的になんらチェックされているわけではありません。
例えば最悪のケースとして[awsの認証情報を設定するAction](https://github.com/aws-actions/configure-aws-credentials)が裏で外部に認証情報を送っていた、ということも考えられます。また現在はそういったコードになっていなかったとしても多くのactionはmasterブランチないしv1, v2などのタグで参照されているため、あとからそういったコードに入れ替えられる可能性もあります。
Actionの開発元がAWSやAzure、あるいは有名企業である場合はそれがある意味の担保になりますのでそこを信用して使っているという人もいると思いますが、そのノリで個人開発のActionをうっかり使うと知らずにリスクを抱えてしまいます。

解決策ですが、以下に書かれています。

[GitHub Actionsのワークフロー構文 \- GitHub ヘルプ](https://help.github.com/ja/actions/reference/workflow-syntax-for-github-actions)

> リリースされたアクションバージョンのコミットSHAを使用するのが、安定性とセキュリティのうえで最も安全です。

GitのコミットSHAはコードの状態ごとに変わるためコミットSHAで指定すると勝手にコードを改変される恐れはありません。もちろんその時点でコードに不審な処理がない前提ですので、個人やよくわからない企業のActionを使う際には①コードの中身をチェックする ②その時点のコミットのSHAでワークフロー中は指定する の行程が必須になります。

ただ、現実には多くのhow to useで@materや@v1などが書かれているのが現状です。
[Github公式のActionですらほとんどタグ指定やブランチ指定で書かれています](https://github.com/actions/cache#example-workflow)。
コミットSHAによる指定は啓蒙していきたいですね。

### 2020/10/06 外部のアクションを使用するときのセキュリティが向上しました！

詳細はこちら: [Fine\-tune access to external actions \- The GitHub Blog](https://github.blog/2020-10-05-fine-tune-access-to-external-actions/)

## [些細な点]生成されるステータスバッジのコードが微妙

CIサービスにおけるステータスバッジとはこれです。

![CI](https://github.com/bigwheel/tfinfermv/workflows/CI/badge.svg)

僕はこれがとても好きなんですが現在のGithub Actionsが生成してくれるバッジのコードは微妙にイケてないです。

[Actions · bigwheel/tfinfermv](https://github.com/bigwheel/tfinfermv/actions?query=workflow%3ACI)

<img width="949" alt="2無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30316/413499f6-d596-44cb-bd94-17f839eec7a2.png">

上のようにActionsタブから個別のワークフロー画面へ行くと右上へ「Create status badge」ボタンが出るのですが、それによりGithub Actionsが生成するコードが以下です。

```markdown
![CI](https://github.com/bigwheel/tfinfermv/workflows/CI/badge.svg)
```

一方Travis-CIなどが生成するコードはこうなっていることが多いです。

```markdown
[![Build Status](https://travis-ci.org/bigwheel/util-backports.svg?branch=master)](https://travis-ci.org/bigwheel/util-backports)
```

何が違うのかというとステータスバッジをクリックしたときの挙動が違います。
Github Actions側は単なる画像へのリンク(実例 → ![CI](https://github.com/bigwheel/tfinfermv/workflows/CI/badge.svg))なので画像が表示されるだけなのに対して後者はそのCI実行結果へのリンクになっているためGreen/Redになったその原因のCIへ直接飛べます(実例 → [![Build Status](https://travis-ci.org/bigwheel/util-backports.svg?branch=master)](https://travis-ci.org/bigwheel/util-backports))。
これでは不便なので僕は毎回Github Actionsのステータスバッジコードを以下のように修正しているのですが(実例 → [![CI](https://github.com/bigwheel/tfinfermv/workflows/CI/badge.svg)](https://github.com/bigwheel/tfinfermv/actions?query=workflow%3ACI))なかなか面倒です。

```markdown
[![CI](https://github.com/bigwheel/tfinfermv/workflows/CI/badge.svg)](https://github.com/bigwheel/tfinfermv/actions?query=workflow%3ACI)
```

### 2021/10/18 期待通りの文字列生成に改善されていることを確認！

今日ステータスバッジを生成したところ、こうあってほしいと書いたとおりリンクとして生成されるようになっていました :tada:

![Screenshot from 2021-10-18 01-32-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30316/27e4537c-8998-4f1d-3c63-6ce80f218165.png)

# 落とし穴

Github Actionsは正式公開が2019/11と、まだ4ヶ月しか経っていないサービスです(初稿作成時点)。そのためいろいろと行き届いていなかったりまだ良く知られていない機能や事項があります。ここでは個人的にハマったりした点を上げます。

## 公開されているActionの種類・品質がまだまだ低い

現状GithubのMarketplaceへ登録されたActionは2020/02/29時点で2390個あります。

[GitHub Marketplace · Actions to improve your workflow](https://github.com/marketplace?type=actions)

一見たくさんあるように見えますが、同じ目的のActionが乱立しており定評があるActionなどが定まっておらず選択にはそこそこ苦労します。例えばSlackへの通知に使えるActionはだいたい30個ぐらいあり([GitHub Marketplace · Actions to improve your workflow](https://github.com/marketplace?type=actions))、選択基準の一つであるStarの数も最高で140かつ100前後のActionが4つあります。

またより辛いのはGithub自身やMicrosoftなどの大手IT企業が管理しているActionもまだ動向が定まっておらず安定して使えないケースがあることです。

* [aws/kubectl at master · actions/aws](https://github.com/actions/aws/tree/master/kubectl)

ここにはgithub公式が管理しているaws向けのactionがあったのですが2019/12/04に「このActionは年内に廃止するよ」と言われて急いで移行する必要がありました(すでにリポジトリごと消されています)。
また同じくkubernetes関連ですがMicrosoftが管理している[kubectl用Action](https://github.com/Azure/k8s-deploy)には[かなり致命的なバグがv1](https://github.com/Azure/k8s-deploy/issues/10)に含まれていたのですが、その修正PRがマージされてから2ヶ月以上経っても[まだv2やv1.1はリリースされていません](https://github.com/Azure/k8s-deploy/releases)。ではmasterブランチを参照しようと思ったんですがmasterブランチには別の致命的なバグがあり、結局私は[PRを作った人のfork版リポジトリ](https://github.com/lennartschoch/k8s-deploy/tree/10-fix-missing-name-key)を参照している状態です。


このように正式公開されたとはいえまだカオス度が高いのが公開Actionの現状です。
公開ActionはほとんどOSSなので最悪自分でforkする、などの対応は覚悟しましょう。

## 正式公開(2019/11)以前と以後でワークフローファイルのフォーマットから構造まで違う

Github Actionsは2018年からベータ状態で提供されていたのですが、その少し前にワークフローファイルのフォーマットがHCLからyamlへ変更されています。

[新 GitHub Actions 入門 \- 生産性向上ブログ](https://www.kaizenprogrammer.com/entry/2019/08/18/205010#HCL-%E3%81%8B%E3%82%89-YAML-%E3%81%B8)

> Support for the HCL syntax in GitHub Actions will be deprecated on September 30, 2019.

ただ、現時点ではまだまだ古いHCLの書き方で書かれたドキュメントやサンプル・ワークフローファイルが多く初心者には結構なつまずきポイントとなりました。
混乱の元となるため基本的にはHCLのフォーマットで書かれた資料は極力参照しないほうが良いかと思います。

## Actionの種類はJavaScriptベースのそれとdockerベースのそれがある

大体はTravisやCircleCIと同じGithub ActionsですがActionの部分だけはそれらと大きく違います。
特にActionにはJavaScriptベースのものとDockerベースのものがあり、それによって[ワークフローファイルの書き方](https://help.github.com/ja/actions/reference/workflow-syntax-for-github-actions)も結構違う点は気をつけましょう。例えば以下の項目はDockerタイプでしか働きません。

* `jobs.<job_id>.steps.with.args`
* `jobs.<job_id>.steps.with.entrypoint`

基本的にはActionのREADMEに書いてあるはずです。

また、Dockerタイプのものはワークフロー実行の最初にまずイメージをビルドする必要があるため実行時間が結構伸びます。ですので同じ機能のActionが複数ある場合可能ならJavaScriptタイプを選ぶほうが良いです。

## ~~成功したCI実行はリトライできない~~ [2020/05/26に再実行機能が実装されました！](https://github.blog/changelog/2020-05-26-github-actions-re-run-successful-jobs/)

これは地味な問題でした。github actionsでは失敗したワークフローは再実行できるものの成功したそれは再実行することができません。

<img width="948" alt="3無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30316/5c724490-dfc7-1c91-0478-41be18de9ea7.png">

<img width="947" alt="4無題.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30316/2a19b8c7-5c8f-c612-edae-c5a9960ba5b7.png">

失敗したワークフローは画面の右上に「Re-run all jobs」というボタンがあるのですが成功したワークフローではこのボタンが存在しないのでした。