このガイドでは、GitHub のアクションとは何か、どのように動作するのかを説明します。
> このガイドでは、GitHubアクションとは何か、どのように動作するのか、そしてPythonを使ってワークフローを構築し、GitHubアクションを使ってタスクを自動化する方法について紹介します。
2008年の創業以来、GitHubは開発プロジェクトのホスティングにおけるデファクト・リーダーとなるまでに成長しました。
GitHubは、オープンソースプログラムのホスティングを一元化して無料で提供するという、コミュニティ指向のアイディアが爆発的に広がりました。
GitHubはとても人気があり、git
と同義語になりました。
gitとGitHubがいかに違うか、またその逆を説明するオンライン記事を何十本も見つけることができます。
10周年を迎えたGitHubは、ある大企業に75億ドルで買収されました。
その会社の名は、Microsoft。
GitHubの買収はさておき、WSLを構築し、VS Code、.NET、TypeScriptなど多くのオープンソースプロジェクトを持つMicrosoftは、Windows 10という会社のプライバシー侵害に対する開発ゲームと一般大衆の意見を変えたのである。
コミュニティ指向であることに変わりはないが、GitHubの次の目標は、エンタープライズシーンに参入して、収益を上げることだった。
既存の企業向けソリューションに目を向ける
Microsoft が GitHub を手に入れたとき、ソフトウェア開発のためのエンタープライズシーンはいくつかの大手企業によって既に確立されていました。
- AtlassianのBitBucketは、課題管理と組織化のリーダーであるJiraとTrelloとのシームレスな統合を可能にしました。
- AmazonのCodeCommitは、AWSを使用する組織が1つのUIと1つのCLIツールの快適さを離れることがないようにしました。
- GitLabは、DevOps指向のアプローチで、開発プロセス全体を一つ屋根の下に集中させることを目的としていました。
過去数年間で、GitHubはCI/CDを含む、企業向け競合製品の多くの機能を追加することができた。
CI/CDと自動化
現代のソフトウェア開発は自動化に大きく依存しており、その理由は単純です。
新しいバージョンは、自動的にビルドされ、テストされ、適切な環境にデプロイされます。
必要なのは、いくつかのスクリプトを書き上げ、それを実行するためにいくつかのマシンを設定する一手間だけです。
GitHubのこのような機能は、GitHub Actionsという形で提供されています。
GitHubのアクションの概要
このガイドを書いている時点では、GitHub Actions はまだ 2 年も経っていません。
若いとはいえ、GitHub の機能である以上、かなり成熟しています。
コミュニティ
数え切れないほどのユーザーが GitHub Actions に参加し、再利用可能なモジュール (アクション) を作成し、それを世界中に公開しました。
GitHubは、そのマーケティングモデルにおいて、このような貢献に大きく依存しています。
現在、9,500以上のアクションがあり、数行のコードで、環境のセットアップ、リンターやテスターの実行、多数の主要なプラットフォームAPIとのインタラクションなどを行うことができます。
すべて、git
とお気に入りのエディタ以外にソフトウェアをインストールする必要はありません。
ウォーフクロー
ワークフローを通じて、自動化されたプロセスを定義します。
ワークフローは YAML ファイルで、ワークフローの名前、トリガーイベント、ジョブ、パイプラインのステップ、それらを実行するランナーなどが含まれています。
YAML
YAML Ain’t a Markup Language または YAML (再帰的頭字語) は、主に設定ファイルを記述するために使用される言語です。
書きやすさと読みやすさから、しばしばJSONよりも好まれます。
JSON のほうがシリアライズが速く、より厳密であるにもかかわらず、YAML は速度があまり重要でない場所で使用されます。
もしあなたがYAMLを使ったことがないのであれば、X=YAMLをY分で学ぶにアクセスすることを強く推奨します。
経験豊富な方は、YAMLの特質とゴッチャについて読むことをお勧めします。
トリガーイベント
キーワード on
には、ワークフローのトリガーとなる GitHub (注: git だけではありません) のイベントをひとつ以上指定します。
このイベントは、たとえばリポジトリへのプッシュのたびに発生するような広範囲のものから、プルリクエストに新しいコメントがつくたびに発生するような特殊なものまであります。
イベントは、cronのような方法でスケジュールすることもできます。
name: my workflow
on:
push:
branches: [main, test]
ここでは、 main
または test
ブランチにプッシュするたびにトリガーイベントを設定しています。
トリガーを登録するもう一つの方法は、以下のようなスケジュールです。
name: my nightly build workflow
on:
schedule:
cron: '0 22 * * *'
これは、毎日午後10時にビルドするようにスケジュールされています。
求人情報
ここまでで、ワークフローに名前を付け、それを起動する様々なイベントを設定しました。
キーワード jobs
は実行されるアクションをリストアップします。
一つのワークフローに複数のジョブがあり、それぞれ複数のステップを持つことができます。
jobs:
job1:
steps:
.
.
job2:
steps:
.
.
デフォルトでは、すべてのジョブは並行して実行されますが、needs
キーワードを使用して、あるジョブを他のジョブの実行を待つようにすることができます。
jobs:
job1:
steps:
.
.
job2:
needs: job1
steps:
.
.
job3:
needs: [job1, job2]
steps:
.
.
1つ1つのジョブが正常に実行されるようにする。
また、各ジョブの環境を個別に設定したり、matrix strategy
を使用して複数の構成でジョブを実行したりすることも可能です。
ドキュメントにはこう記されています。
>
> マトリックスでは、1つのジョブ定義で変数の置換を行うことにより、複数のジョブを作成することができます。
以下は、複数のプラットフォームで動作するように構成されたマトリックスビルドの例です。
jobs:
ubuntu_job:
runs-on: ubuntu-latest
steps:
.
.
multi_os_job:
runs-on: {{matrix.os}}
strategy:
matrix:
os: [ubuntu-latest, windows-2016, macos-latest ]
steps:
.
.
アクション
アクションは再利用可能なモジュールで、他のジョブやステップと同様にワークフローに配置することができます。
アクションは入力を受け取り、出力を生成することができます。
コミュニティマーケットプレイスには、環境を準備するための多くのブートストラップアクションが豊富にあります; 今日はそのいくつかを使用します。
あなた自身のアクションを docker コンテナとして、あるいは vanilla JavaScript を使って書き、マーケットプレイスに貢献することもできますし、自分だけのために残しておくこともできます。
アクションは、他のステップと同じようにワークフローで簡単に参照できます。
jobs:
compile_code:
runs-on: ubuntu-latest
steps:
- name: check out repo
uses: actions/checkout@v2
- name: compile code
run: gcc main.c
.
.
ここでは、他のステップのようにアクションを使用する例を見ることができます。
ステップは、ジョブとは異なり、常に連続して実行されることに注意してください。
ランナー
ランナーとは、エージェントまたはワーカーとして知られ、ワークフローを実行するタスクを持つマシンです。
それぞれのランナーは異なる設定をすることができます。
例えば、GitHubは3つの最も人気のあるOSフレーバー、Ubuntu, Windows, MacOSでランナーを提供しています。
GitHubは独自のランナーを提供していますが、GitHub Actionsランナーアプリケーションを設定して独自のランナーをホストすることも可能です。
価格について
GitHub ランナーは、リポジトリが公開されており、月間の閾値が 2000 分を超えなければ、無料でワークフローを実行することができます。
TeamsとEnterpriseには、それぞれ特典と価格が異なる独自の価格カテゴリ(typical)があり、このガイドを執筆している時点では、それぞれ$4/user per monthと$21/user per monthとなっています。
GitHubのプランの完全な概要については、GitHubの更新された価格ページをご確認ください。
アーティファクト – ワークフローの永続的なデータ
GitHub のランナーは一時的にしか利用できないので、ランナーが処理・生成するデータも一時的にしか利用できません。
アーティファクトは、ランナー実行後もリポジトリページで利用可能なデータで、特別な upload-artifact
アクションでアップロードする必要があります。
デフォルトの保存期間は90日ですが、変更することができます。
概要画面では、ワークフローの実行番号、実行待ちまたは実行済みの全ジョブのリスト、異なるジョブとその接続の視覚的表現、ワークフローによって生成された成果物など、多くのデータで私たちを迎えてくれます。
GitHub Actionsの実際 – Python Benchmarker
注:この例では、この記事のために作成したリポジトリを使用しています。
当然のことながら、GitHubにあります。
ここまでで学んだことを組み合わせて、本格的なワークフローを作りましょう。
Pythonのベンチマークワークフローを作成し、 .github/workflows/benchmark.yml
に配置します。
このワークフローは、mainブランチにpushされるたびに起動されます。
name: python version benchmarker
on:
push:
branches: [main]
ワークフローは3つのステージで構成されています。
リントステージ
最初のジョブは benchmarker.py
の内容を lint して、少なくとも 8.0 のスコアを持つようにすることです。
jobs:
pylint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2 # checkout repo
- uses: actions/setup-python@v2 # set up environment for python
with:
python-version: 3.7
- uses: py-actions/py-dependency-install@v2 # install dependencies from requirements.txt
with:
path: requirements.txt
- name: run pylint, fail under 8.5
run: pip install pylint; pylint benchmarker.py --fail-under=8
ベンチマーク
Pythonの6つの異なるバージョンと実装でベンチマークを実行し、コードがそれらの全てと互換性がない場合は失敗します(matrix戦略の fail-fast
パラメータで設定、デフォルトは true
です)。
benchmark:
runs-on: ubuntu-latest
needs: pylint
outputs:
pypy2: ${{ steps.result.outputs.pypy2 }}
pypy3: ${{ steps.result.outputs.pypy3 }}
py2-7: ${{ steps.result.outputs.py2-7 }}
py3-6: ${{ steps.result.outputs.py3-6 }}
py3-7: ${{ steps.result.outputs.py3-7 }}
py3-8: ${{ steps.result.outputs.py3-8 }}
strategy:
matrix:
include:
- python-version: pypy2
out: pypy2
- python-version: pypy3
out: pypy3
- python-version: 2.7
out: py2-7
- python-version: 3.6
out: py3-6
- python-version: 3.7
out: py3-7
- python-version: 3.8
out: py3-8
steps:
- uses: actions/checkout@v2
- name: setup py
uses: actions/setup-python@v2
with:
python-version: ${{matrix.python-version}}
- name: save benchmark stats
id: result
run: |
echo "::set-output name=${{matrix.out}}::$(python benchmarker.py)"
GitHub Actions を使用する際に遭遇する可能性のある、より細かい問題について見ていきましょう。
outputsキーワードは、ジョブが生成して他のジョブが参照できる
key:valueのペアを指定します。
key は出力の名前で、value
は指定された id
を持つステップの特定の出力への参照です。
GitHub のオブジェクトアクセス構文では、オブジェクト名にドットを使用できないため、out
パラメータで修正する必要がありました。
また、最初の位置には数字も含まれています。
出力を1つのjsonにまとめ、JSONオブジェクトとして steps.result.outputs
を参照する固有の方法はありませんでした – 次の段階で見るように、読み取り専用の目的で行うことはできます。
代わりに、各出力を明示的に定義する必要があります。
Pastebinへのアップロードと新しいアーティファクトの作成
最後の第3ステージでは、前のステージの出力を読み込んで、1つのファイルにまとめます。
このファイルはアーティファクトとしてアップロードされ、pastebinにアップロードされます。
pastebinに post
リクエストを行うには、アカウントを設定し、そのAPIキーを使用する必要があります。
pastebin:
runs-on: ubuntu-latest
needs: benchmark
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: 3.9
- uses: py-actions/py-dependency-install@v2
with:
path: requirements.txt
- name: use benchmark data
run: echo '${{ toJSON(needs.benchmark.outputs) }}' > matrix-outputs.json
- name: pastebin API request
env:
PASTEBIN_API_KEY: ${{ secrets.PASTEBIN_API_KEY }}
run: python pastebin.py
- name: upload newly created artifact
uses: actions/upload-artifact@v2
with:
name: benchmark-stats
path: newpaste.txt
この秘密はジョブの環境変数として置かれ、Pythonの os.environ[PASTEBIN_API_KEY]
で簡単にアクセスできるようになっています。
GitHubでのシークレット管理
GitHub では、リポジトリやプロジェクト単位で秘密を安全に管理することができます。
シークレットを保存するには、リポジトリの設定に移動して Secrets タブで新しい値を追加します。
CI/CDツールとしてGitHub Actionsを選んではいけない場合とは?
GitHub の新機能に可能性を感じたとしても、いくつか考慮すべき点があります。
それは、自動化ツールを他で探さなければならないような、致命的な点です。
- GitHubが提供するランナーは、かなり不足しています。2コアと8GBのRAMで、リンターの実行とテストには適していますが、本格的なコンパイルは考えないでください。
- REWRITE ワークフローのデバッグは不愉快な経験になることがあります。一つのジョブを再実行する方法はなく、ワークフロー全体を再実行する必要があります。最終段階で問題が発生した場合、ワークフローを書き換えてトラブルシューティングに耐えられるようにするか、ワークフロー全体が実行されるのを待ってからトラブルシューティングのポイントに到達する必要があります。
- 分散ビルドをサポートしていません。
結論
GitHub Actions はここ数年でかなり成熟してきましたが、まだ十分ではありません。
しかし、その可能性は十分にあります。
すべての git プラットフォームの中で最高の API と、JavaScript でアクションを書くという革新的なアプローチ、そして世界最大の git コミュニティに支えられた GitHub Actions は、間違いなく CI/CD ゲーム全体を支配する可能性を持っています。
しかし、まだです。
今のところ、このツールは単純なコンパイルやパッケージング、コミットへのタグ付けに使うだけで、企業ではまだ Jenkins や Travis CI、GitLab CI などに頼っているのです。