actions/github-script と composite アクションでカスタムアクションをかんたんに作れる
GitHub Actions 小ネタです。
actions/github-script
と composite アクションを使えば、再利用可能なアクションかんたんに作ることができます。
前提
この記事は 2022 年 05 月に書きました。 時間が経つと GitHub Actions の仕様変更などで情報が古くなるので参考にされる際は注意してください。
おさらい
GitHub Actions とは
GitHub Actions とは GitHub 上で使える作業自動化の仕組みです。
2018 年に発表され 2019 年年末に一般公開されたサービスです。 CI サービスとしてはかなり後発ですが、元々の GitHub の利用者数の多さを背景にいまではソフトウェアエンジニアに最も多く利用されている CI サービスのひとつになっています。
actions/github-script
とは
actions/gitub-script
とは GitHub が作成・公開している GitHub Actions 用アクションです。
actions/gitub-script
を使えばちょっとした処理を JavaScript で手軽に書くことができます。
たとえば、 output として「 Hello 」を返すアクションは actions/gitub-script
を使って次のように書くことができます(公式 REAMDE のサンプルです):
- uses: actions/github-script@v6
id: set-result
with:
script: return "Hello!"
result-encoding: string
- name: Get result
run: echo "${{steps.set-result.outputs.result}}"
実行したい JavaScript コードを with.script
で指定します。
id
はその後のステップで参照するために必要なだけなので処理には影響しません。
with.script
のコードでは以下のパッケージが利用できます:
otcokit/rest
@actions/core
@actions/glob
@actions/io
@actions/exec
私が理解するかぎり GitHub / GitHub Actions の API を使用する処理のほとんどをこれひとつで書けるようになっています。
なお、 script
に渡されたコードは JavaScript の async
関数の body として実行されるので、 await
キーワードも使うことができます。
await
を使ったサンプル:
- name: npm outdated を実行して結果をサマリーに出力する
uses: actions/github-script@v6
id: set-result
with:
script: |
const { stdout } = await exec.getExecOutput('npm outdated', [], {
ignoreReturnCode: true,
})
await core.summary
.addHeading('Outdated packages')
.addCodeBlock(stdout)
.write()
actions/github-script
の詳細についてはリポジトリのページを参照してください。
composite アクションとは
composite アクションとは GitHub Actions のカスタムアクション(≒再利用可能なアクション)を作成する方法の 1 つです。
A composite action allows you to combine multiple workflow steps within one action. For example, you can use this feature to bundle together multiple run commands into an action, and then have a workflow that executes the bundled commands as a single step using that action.
拙訳:
composite アクションを使えば、ワークフローの複数のステップを組み合わせて 1 つのアクションにすることができます。 たとえば、複数の
run
コマンドを 1 つのアクションにまとめて、そのアクションを 1 つのステップとしてワークフローから呼び出して実行することができます。
composite アクションは通常のワークフローと作り方が似ているため、通常のワークフローとほぼ同じ感覚で作ることができます。 ワークフローの設定を作ったことがある人であれば初期にかかる学習コストはわずかです。
カスタムアクションを作る方法として composite アクションの他に「 Docker コンテナアクション」「 JavaScript アクション」の 2 つがありますが、 composite アクションは Docker コンテナアクションや JavaScript アクションに比べてかんたんに作れることが大きな特徴です。
composite アクションの最小構成は定義ファイル action.yml
1 つだけです。
次のサンプルは「 Hello world 」メッセージを出力するだけの composite アクションです(公式のサンプルを少し変えたものです):
action.yml
:
name: 'Hello World'
description: 'Greet someone'
inputs:
who-to-greet:
description: 'Who to greet'
required: true
default: 'World'
runs:
using: "composite"
steps:
- run: echo Hello ${{ inputs.who-to-greet }}.
shell: bash
composite アクションの場合はこの定義ファイル action.yml
を所定の場所に設置すればすぐに再利用可能なアクションとして利用し始めることができます。
composite アクションの action.yml
の置き場所には 2 つの選択肢があります:
タイプ | 設置場所 | 公開設定 | 利用範囲 |
---|---|---|---|
A) | リポジトリの .github/actions/[アクション名]/ ディレクトリ以下 |
public / private どちらも可 | 同一リポジトリ内 |
B) | リポジトリのルート直下 | public のみ | 制限なし |
A) のタイプのアクションは同一リポジトリ内のワークフローから利用できます。 リポジトリの公開設定は public でも private でもどちらでも大丈夫です。
B) のタイプのアクションは他のリポジトリからも利用できます。 ただし、アクションを提供する側のリポジトリの公開設定を public にしておく必要があります。
actions/github-script
と composite アクションでカスタムアクションを作る
本題の actions/github-script
を使って composite アクションをカスタムアクションを作る方法についてです。
今回は上の A) B) のうち B) のタイプで作る想定です。
手順は次のとおりです。
- public なリポジトリを作る
action.yaml
を追加する- タグを付ける
1. public なリポジトリを作る
GitHub 上で公開設定を public にしてリポジトリを作成します。
以下 owner/repo を gh640/hello-composite-action
にした想定で話を進めます。
2. action.yml
を追加する
続いて action.yml
ファイルを作成してコミット & リポジトリにプッシュします。
設置場所はリポジトリのルートである必要があります。
名前は action.yml
でも action.yaml
でもどちらでも問題ありません。
この action.yml
の中で actions/github-script
を呼び出して使用します。
次のサンプルは Hello World を出力するアクションです。
action.yml
:
name: 'Hello World'
description: 'Greet someone'
inputs:
who-to-greet:
description: 'Who to greet'
required: true
default: 'World'
runs:
using: "composite"
steps:
- uses: actions/github-script@v6
with:
script: |
const { WHO_TO_GREET } = process.env
console.log(`Hello ${WHO_TO_GREET}.`)
env:
WHO_TO_GREET: ${{ inputs.who-to-greet }}
アクションに渡された input を actions/github-script
の script
の中で利用したい場合は、環境変数を介して渡します(公式の README にそのように説明されています)。
ここではアクションの input
を WHO_TO_GREET
という環境変数を介して script
に渡しています。
script
には JavaScript で処理を記述しますが、ここでは GitHub / GitHub Actions の API を使用するために便利な変数がもろもろ利用できるようになっています。
公式 README の拙訳:
github
認証済みの octokit/rest.js クライアント(ページネーションプラグイン付き)context
ワークフローランのコンテキスト を格納したオブジェクトcore
@actions/core パッケージへの参照glob
@actions/glob パッケージへの参照io
@actions/io パッケージへの参照exec
@actions/exec パッケージへの参照require
Node.js の通常のrequire
のプロキシラッパー。作業ディレクトリからの相対パスでスクリプトを読み込める。作業ディレクトリにインストールされた npm パッケージも読み込める。
3. タグを付ける
action.yml
をリポジトリのルートに追加できたら最後にタグを付けます。
git tag v1
git tag v1.0.0
厳密に言うとタグをつけなくてもアクションを利用することはできますが、タグを付けておくと
- 将来破壊的な変更を入れやすくなる
- Marketplace で公開するときには必須となる
ので、個人利用の場合でも最初からタグを付けて運用するのがよいのかなと思います。
これにて actions/github-script
を使用した composite アクションの作成は完了です。
あとはどのリポジトリでもよいのでワークフローを作成して uses
でこのアクションを利用します。
uses: gh640/hello-composite-action@v1
(実際にはこの gh640/hello-composite-action
リポジトリは存在しません)
以上です。
サンプル
npm outdated
を実行してその出力をサマリーに表示するアクションです。