🐈

複数リポジトリでのGithub Actions運用 2021年の状況総まとめ

2021/12/22に公開

「複数のリポジトリでGithub Actions運用しているけど横展開が大変」
「似たような処理が多いからうまくまとめたい」
「でもどうすればいいんだろう」

Github Actionsを扱っているとそう思う機会って結構ありませんか?解決する方法もいくつかあるんですが、それぞれが一長一短ですし注意が必要な点もいくつかあります。

なので2021年末時点で何が使えるのか、どれを使うべきか、今後どうなっていくのかを全部まとめました。
この記事を読めばまるっと状況を把握できる...はずです!(多分)

(shellをゴリゴリ書くなどやり方次第で色々突破できるかもですが、この記事ではあくまでgithub actionsの機能として用意されているものをスコープに話を進めていきます。)

なおこの記事はMakuake Advent Calendar 2021GitHub Actions Advent Calendar 2021の22日目の記事です。

今現在何が使えるのか

「複数のリポジトリでGithub Actionsに同じような処理をさせる」方法は大きく以下の2つです。

  1. 別のリポジトリにあるactionをcheckoutで取得して使用する
  2. 別のリポジトリにあるReusable workflowを使用する

それぞれメリット・デメリットがあります。

別のリポジトリにあるactionをcheckoutで取得して使用する

一つ目の方法は別リポジトリのactionsを使うものです。

使い方

流れとしては

  1. 使用側のworkflowから使いたいリポジトリをcheckoutする
  2. checkoutしたactionをuseし実行する

というシンプルなものになるのですが、checkout時には色々と注意が必要です。

例を見ながら注意点をコメントで説明していきます。以下のymlはまさに上記の通り2つの(checkoutし、useする)ステップを記述しています。

.github/workflows/example.yml
name: example

on:
  push:

jobs:
  use-other-action:
    name: Use other action from this repository
    runs-on: ubuntu-latest
    steps:
      # まずcheckoutして他のリポジトリの内容を持ってくる
      - name: Checkout other repository
        uses: actions/checkout@v2
        with:
          # 使いたいactionがあるorganization/repositoryをcheckoutする対象に指定
          repository: organization-name/repository-name
          # branch名だけでなくtagやcommit hashなど取得元を一意に特定できるものなら何でもok
	  ref: main
	  # 取得したアクションをこのリポジトリのどこのディレクトリに持ってくるか決める
          path: .github/actions/other-repository
	  # private repoのactionを使う時のみ必要。
	  # ここで使うtokenはsecrets.GITHUB_TOKENでは不可
          token: ${{ secrets.YOUR_ACCESS_TOKEN_FOR_PRIVATE_REPOS }}
      - name: Use the action in the other repository
        # checkout時にpathで指定した場所 + 使用するactionの場所をつなげて記述する
	# ディレクトリを指定しているので./から始める必要がある点に注意
        uses: ./.github/actions/other-repository/.github/actions/other-action
        with:
	  # 引数は好きに渡せる
          message: "Any args can be passed to the action"
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # ここで使うgithub tokenはsecrets.GITHUB_TOKENでok

基本的に上記のコメントの通りですが、特にハマりがちなのはcheckout時のtokenの設定です。publicリポジトリしか触らない方であればtokenの設定は不要なのでここは読み飛ばしていただいて構いません。

普段であればsecrets.GITHUB_TOKENと記述すればPersonal Access Token(PAT)を発行せずとも権限を持たせてworkflowを走らせることが可能です。
ですが、privateリポジトリをcheckoutする際はsecrets.GITHUB_TOKENでは権限が足りないため、privateリポジトリの権限を持つPATを事前に発行しておいて使う必要があります。

先述の通りPATを使う必要があるのはここだけで、checkout前後にactionを実行するためであればsecrets.GITHUB_TOKENで十分なはずです。

[参考: secrets.GITHUB_TOKENについて]
https://docs.github.com/ja/actions/security-guides/automatic-token-authentication

メリット・デメリット

この方法の大きなメリットとして、privateリポジトリのactionであっても使用できる、という点が挙げられます。後述する方法ではprivateリポジトリにある処理を使用することはできないのですが、こちらにはそうした制約がありません。

一方デメリットとしては、サードパーティー製のactionを使い回せないという点が挙げられます。というのも、actionには「別のactionを呼び出すことができない」という制約があるからです。 この方法では別リポジトリにあるactionの定義を拝借して実行するので、そこからさらにactionを呼び出すことはできません。

このため、github公式のaction(checkoutsetup-nodechacheなど)や、aws-actionsなどを使用するには、結局自身のworkflowに記述するしかありません。

別のリポジトリにあるReusable workflowを使用する

二つ目の方法は最近一般に公開されたReusable workflowという機能を使うものです。先程はactionを使い回していましたが、これは名前の通りworkflowを再利用するものです。 詳しくは後述しますが、あくまでworkflowなのでactionを使うことができ、複雑な処理であっても簡単に共通化することができます。

またこれも後述しますが、他のリポジトリのReusable workflowを利用する場合、Publicリポジトリに置いてあるReusable workflowしか使用できない という点も注意が必要です。

使い方

流れとしては

  1. 対象のworkflowを直接useする

というシンプルなものになっています。ですがこちらもいくつか注意は必要なので、実際の例と一緒に見ていきましょう。

使用する側

まず使用する側の記述です。

.github/workflows/reusable-user-example.yml
name: Reusable user

on:
  workflow_dispatch:

jobs:
  use-reusable-workflow:
    # runs-onの指定は不要
    # reusable workflowがあるorganiztion名/リポジトリ名/workflowまでのpath@ref で記述
    # refは一意に特定できるものならok(tag, branch, commit hashなど)
    uses: organiztion-name/repository-name/.github/workflows/reusable.yml@main
    # 引数はwithに渡す
    with:
      name: ${{ github.repository }}

workflowを丸ごと再利用するものなので、jobs.runs-onの定義が不要になっている点に注意が必要です。
また、actionを使用するのと異なり、ymlまでのpathをusesに指定する必要があります。actionの場合はaction.ymlが格納されているフォルダ名まで指定すれば良いのですが、この点は異なるので注意してください。

使用される側

次に使用される側です。

.github/workflows/reusable-provider-example.yml
name: Reusable provider

on:
  # workflow_callを設定することでreusableとして扱えるようにする
  workflow_call:
    # inputs/outputsはworkflow_call以下に定義
    inputs:
      name:
        required: true
        type: string

jobs:
  example_job:
    name: Run shared action and show passed value
    runs-on: ubuntu-latest
    steps:
      - run: echo Hello
      # reusable workflowを提供する側に定義されているactionを使う場合checkoutする必要あり
      - uses: actions/checkout@v2
        with: 
	  # organization名/リポジトリ名
          repository: organization-reusable-provider/repo-provider
          ref: main
	  # 使用側のどこにcheckoutするか決める
          path: .github/actions/other-repository
      # 使用側のworkflowとして実行されるので、使用側としてどれを使うのかという目線で書く
      - uses: ./.github/actions/other-repository/.github/actions/shared
      # inputsを使う場合は${{ inputs.hoge }}で使用する
      - run: echo this workflow is run by ${{ inputs.name }}

Reusable workflowとして扱うためにはon.workflow_callを定義する必要があります。

一点注意が必要なのが、Reusable workflowから同じリポジトリ(Reusable workflowを定義・提供しているリポジトリ)にあるactionを使用する場合です。Reusable workflowはあくまで使用側のworkflowとして実行されるため、実行時に元々のリポジトリを参照することができません。

そのため、そうしたactionを使用したい場合はあらかじめ他のリポジトリから利用することを意識してcheckoutしておく必要があります。 この点はハマりそうだと感じたので詳しくは別途記事にまとめようと思います。

なお文法全般について気になる方は、以前自分がざっとまとめた記事や公式ドキュメントを見てみてください。
https://zenn.dev/jerome/articles/618af7cc934f2f

メリット・デメリット

この方法ではworkflowを再利用するため先述のとおりどんなactionも使用できるというのが大きなメリットです。

一方でこちらも先述のとおり、publicリポジトリに定義されているworkflowしか再利用できないという制限があるのが難点です。正確に言うと、現時点では

  • publicリポジトリのworkflowを再利用する
  • 同一リポジトリ内のworkflowを再利用する(こちらはprivateリポジトリでもok)

の2パターンに限られています。

詳細は公式ドキュメントを確認してください。
https://docs.github.com/ja/actions/learn-github-actions/reusing-workflows#limitations

どれを使うべきか

ここまでいくつか方法を見てきましたが、フローチャート的にまとめると以下の通りです。

  • 単一リポジトリ内で共通化したい場合
    • Reusable workflowを利用しましょう!
  • 複数リポジトリ間で共通化したい場合
    • 処理内容を公開できる場合
      • publicリポジトリを作成し、Reusable workflowを定義して使い回しましょう!
    • 処理内容を公開できない場合
      • 自作でき、メンテもできる処理の場合
        • privateリポジトリ内にactionを作成し、checkoutして使い回しましょう!
      • 自作が大変 or メンテできない処理の場合
        • 共通化はせずに、各workflowで定義しましょう

privateリポジトリを多く使うユーザーの場合、基本的にactionを自分で作成・メンテするのは手間ですし、思ったより共通化できず何とももどかしい状況なのがわかると思います。

この状況はこれから変わっていくのでしょうか?

今後どうなっていくのか

github actionsの今後はロードマップとして公開されています。(下記のリンクはactionsでクエリしてあります)
https://github.com/orgs/github/projects/4247/views/1?filterQuery=actions
追記(2022/08/04): リンク切れを修正しました

最も興味深いissueは、下記のActions: Organization and enterprise workflows です。複数リポジトリで実行可能なorganizationレベルでのworkflowを定義できるようにするもので、これまで見てきた諸問題を解決できるように見えます。
ただし、現時点で実装時期はfutureとされており、いつ頃実装されるかわからないので気長に待つ必要があるでしょう。
https://github.com/github/roadmap/issues/52

ロードマップから逸れますが、Reusable workflowがprivate organization内で使い回せない件についてcommunityでも少し話題になっているようです。 もしこのトピックに対してLikeが集まれば何かしらアクションがあるかもしれません。 (私もLikeしておきました)
https://github.com/orgs/community/discussions/16838
追記(2022/08/04): リンク切れを修正しました

まとめ

  • publicリポジトリに公開できる処理ならReusable workflowに寄せられそうです
  • 公開できない処理のうち、自分で記述でき、かつメンテできそうな範囲であればaction単位で切り出してcheckoutして使いましょう
  • 上記に当てはまらないものは共通化するのは一旦待ちましょう...

最後に

明日もまだまだアドベントカレンダーは続くので楽しみにしてくださると嬉しいです!
https://adventar.org/calendars/6822
https://qiita.com/advent-calendar/2021/github-actions

また、MakuakeではエンジニアやPM、デザイナーを始めとしてほとんどの職種で採用中です!興味ある方は以下から見てみてください!
https://www.wantedly.com/companies/makuake/projects

Discussion