GitHub Actions:ベストプラクティス


この_作業中_のドキュメントは、GitHub Actionsを活用するためのベストプラクティスをまとめたものです。提案や追加があれば、ぜひGitHubでプルリクエストを送ってください!

ベストプラクティス集

ワークフローにタイムアウトを設定する

デフォルトでは、GitHub Actionsはワークフローが6時間以内に終わらないと、それを強制終了します。多くのワークフローはそこまで時間を必要としませんが、ときには予期しないエラーが起きたり、ジョブがハングしたまま実行開始から6時間後にワークフローが強制終了されることがあります。そのため、もっと短いタイムアウトを指定することをおすすめします。

理想的なタイムアウトはワークフローごとに異なりますが、Exercismのリポジトリで使われるワークフローなら、通常30分もあれば十分です。

これには次のような利点があります。

  • PRが半日もCI待ちのままになることがなくなり、問題を早い段階で見つけたり、ワークフローの実行を再開したりできます。
  • 全体の並列ビルド数には限りがあるので、ハングしたジョブを早めにキャンセルすれば、他のPRに影響を与えずに済みます。

例

jobs:
  configlet:
    timeout-minutes: 30
    runs-on: ubuntu-latest
    steps:
      - [...]

(サードパーティの)アクションが本当に必要なのか検討する

アクションは、お気に入りのプログラミング言語の依存関係と同じように扱うべきです1。それらはExercismの管理外にある第三者の作者が書いたコードです。アクションの作者を信頼していたとしても、そのリポジトリが乗っ取られる可能性があり、そうなると間接的にExercismのリポジトリへのアクセス、それも書き込み権限まで渡してしまうことになります。

ですから、新しいアクションを導入することが本当に価値があるのか、それともコードをExercismの管理下にある(新しい)アクションに移したほうがよいのか、よく検討してください。

そのアクションが活発にメンテナンスされているかどうかも検討しましょう。たとえば、リポジトリの最近の活動を確認したり、そのアクションが個人アカウントではなく組織の一部であることを確かめたりします。

GitHubやExercismの組織によって公開されているアクションは、通常、特別な検討なしに導入しても(ほぼ)安全とみなせます。

ワークフロートークンのスコープを制限する

デフォルトでは、ワークフローに与えられるアクセストークンは、読み取りと書き込みの両方について幅広い権限を持っています。

最小権限の原則は、ワークフローにも当てはめるべきです。

ワークフローが必要とする権限は、ワークフローごとに指定できます。

例

ワークフローが、たとえば通常のCIチェックのように、リポジトリの内容を読み取るだけで書き込む必要がない場合は、次のようにトークンを制限できます。

permissions:
  contents: read

権限の完全なリストは、GitHubのドキュメントを確認してください。

アクションをSHAに固定する

他のアクションを使うときは、ブランチやタグではなく、コミット(そのSHA)に固定してください。こうすると毎回同じコードが実行されることが保証されますが、ブランチやタグに固定した場合は保証されません。

これには2つの利点があります。

  1. ビルドが_安定する_
  2. 攻撃者がブランチやタグを悪意のあるコードを指すように書き換えるのを防げる

このルールの唯一の例外は、Exercism自身が作ったアクションでしょう。

コミットSHAの探し方

通常は、特定のリリースのコミットSHAに固定します。リリースのコミットSHAを探すには、アクションのリポジトリのリリースページ(例:https://github.com/actions/checkout/releases)を開きます。使いたいリリースを見つけ、リリースの左側にある概要セクションに表示されている短縮SHA(例:a12a394)をクリックします。するとリリースの詳細ページに移動し、そこで使用できる完全なコミットSHAが表示されます。

例

- name: Checkout code
  uses: actions/checkout@a12a3943b4bdde767164f792f33f40b04645d846

テストランナーをバージョンに固定する

ほとんどのワークフローは、GitHubがサポートするランナーで実行されます。これらのランナーを使うときは、最新バージョンではなく特定のバージョンを使います。

こうすると、ワークフローが常に同じランナーで実行されることが保証され、ビルドが_安定します_。

例

次のように書きます。

runs-on: ubuntu-22.04

次のように書くのではなく:

runs-on: ubuntu-latest

並行実行の戦略を設定することを検討する

途中のコミットでCIを実行することは、その間に新しいコミットがプッシュされている場合、多くの場合必要でも有益でもありません。

並行実行の戦略を設定すると、同じコンテキストで実行中のワークフローを自動的にキャンセルできます。

例

PR内の途中のビルドをキャンセルするには、次の並行実行の設定を使います。

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
サードパーティのライセンス表示

上の例は、MITライセンスで公開されているPkgTemplates.jlのCIワークフローに基づいています。

MIT License

Copyright (c) 2017-2020 Chris de Graaf, Invenia Technical Computing Corporation

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

どのトリガーが本当に必要なのか検討する

「GitHub Actionsのセキュリティ強化」ガイドを読む

ここで挙げたプラクティスは、決してすべてを網羅しているわけではありません。GitHub Actionsを安全に使うための優れたセキュリティプラクティスの包括的なガイドについては、GitHubのセキュリティガイドを参照してください。

ワークフローのチェックリスト

次のチェックリストを使って、ワークフローがベストプラクティスに従っているか確認できます。このチェックリストは完全であることを意図したものではなく、最も重要な項目に焦点を当てています。

そのままコピー&ペーストできる版(PRなどに)

  1. その言語がnpmエコシステムを使っている場合は除きます。 ↩