ようこそ、自動化の深淵へ。
GitHub Actionsを触り始めたばかりの皆さんは、おそらく「YAMLの中にシェルスクリプトを書く」か「別途JavaScriptファイルを用意して実行する」かの二択で迷っているのではないでしょうか。しかし、現場で本当に求められるのは、「メンテナンスコストを最小限に抑えつつ、GitHubの機能をフル活用するエレガントな自動化」です。
今日は、外部ファイルを作る手間を省き、ワークフローYAMLの中に直接「魔法」を記述できる、`actions/github-script` を使い倒す方法を伝授します。これを知っているだけで、あなたのCI/CDは「ただのコマンド実行」から「自律的に動くインテリジェントな相棒」へと進化しますよ。
—
なぜ「外部スクリプト」ではなく「Script step」なのか?
通常、複雑なロジックを組もうとすると、`script.js` を作成してリポジトリにコミットし、それを `node script.js` で呼び出すことになります。しかし、これにはいくつかの欠点があります。
1. コンテキストの受け渡しが面倒: GitHubのイベント情報(PR番号やコミットメッセージなど)を引数や環境変数で渡す設計が必要になります。
2. 認証(TOKEN)の管理: GitHub APIを叩くための認証処理を毎回書く必要があります。
3. ファイルの散らかり: 数行のロジックのためにファイルが増え、リポジトリが汚れます。
これらを一気に解決するのが、公式が提供している `actions/github-script` です。これは、GitHub Actions専用にカスタマイズされたNode.js環境を、YAMLの中に直接展開する強力なアクションです。
—
基礎:まずは「Hello, GitHub!」から始めよう
まずは、最もシンプルな形でこのアクションの威力を体感してみましょう。
以下のコードは、プルリクエストが作成されたときに、自動で「確認しました!」というコメントを残すシンプルなワークフローです。
name: Great Greeting
on:
pull_request:
types: [opened]
jobs:
greeting:
runs-on: ubuntu-latest
steps:
- name: Welcome Comment
uses: actions/github-script@v7
with:
# ここに直接JavaScriptを書けます!
script: |
const { owner, repo } = context.repo;
const pull_number = context.payload.pull_request.number;
github.rest.issues.createComment({
owner,
repo,
issue_number: pull_number,
body: “🎉 素晴らしいコントリビューションをありがとうございます!順次レビューしますね。”
});
ここが「極限」のポイント:
- `github` オブジェクト: すでに認証済みのGitHub APIクライアント(Octokit)が注入されています。`github.rest…` と書くだけでAPIが叩けます。
- `context` オブジェクト: 現在のワークフローを実行している「背景(PRの情報、リポジトリ名など)」が最初から入っています。わざわざ環境変数からパースする必要はありません。
—
応用:OSコマンドを自在に操る(@actions/exec の活用)
「JavaScriptの中でシェルコマンドを実行したい」という場面は多々あります。例えば、ファイルの差分を確認したり、特定のツールをインストールしてその結果をGitHub APIに投げたい時などです。
`github-script` の中では、実はGitHub Actions Toolkitの強力なライブラリ群が最初からインポートされています。その中でも最強なのが `exec` です。
- name: Advanced OS Control
uses: actions/github-script@v7
with:
script: |
// 1. OSコマンドを実行して出力をキャプチャする
let output = ”;
const options = {
listeners: {
stdout: (data) => {
output += data.toString();
}
}
};
// `ls -la` を実行してみましょう
await exec.exec(‘ls’, [‘-la’], options);
// 2. 実行結果をワークフローのログにきれいに表示
core.info(“— 現在のディレクトリ一覧 —“);
core.info(output);
// 3. もし特定のファイルがなければジョブを失敗させる
if (!output.includes(‘package.json’)) {
core.setFailed(“このプロジェクトには package.json が見当たりません!”);
}
現場の知見:
この書き方の素晴らしいところは、「条件分岐はJavaScriptの柔軟な構文で行い、重い処理はOSのネイティブコマンドに任せる」というハイブリッドな設計ができる点です。
—
最も重要なツールセット:Toolkitの5大要素
`github-script` 内で自由に使える、現場で必須のオブジェクトを紹介します。これらを組み合わせることで、もはや不可能な自動化はなくなります。
1. `github`: API操作の王様。Issue作成、PR承認、ラベル付与、何でもござれ。
2. `context`: イベント情報の宝庫。誰が、いつ、どのブランチで動かしたかが一目瞭然。
3. `core`: ワークフローの制御。ログの出力(`info`, `error`)、変数の出力(`setOutput`)、ジョブの失敗(`setFailed`)。
4. `glob`: ファイル検索の達人。特定のパターン(`/.js`など)にマッチするファイルを一括取得。
5. `io`: ファイル操作の基本。ディレクトリ作成(`mkdirP`)や移動(`mv`)をOS依存なしで実行。
—
実戦:複数のOSコマンド結果をGitHubにフィードバックする
最後に、これらをすべて組み合わせた「現場でそのまま使える」HelloWorldを超えた実戦例を紹介します。
「コードの行数を数えて、それをPRのサマリーに表示する」という気の利いた自動化です。
- name: Lines of Code Report
uses: actions/github-script@v7
with:
script: |
// 1. OSコマンドで全ファイルの行数をカウント(wcコマンドを利用)
let lineCount = ”;
await exec.exec(‘sh’, [‘-c’, ‘find . -name “.js” | xargs wc -l’], {
listeners: { stdout: (data) => { lineCount += data.toString(); } }
});
// 2. 結果を整形してGitHubの「Step Summary」に書き込む
// これにより、ログを見に行かなくてもPRの画面上で結果が確認できます
await core.summary
.addHeading(‘📊 コード統計レポート’)
.addCodeBlock(lineCount)
.addRaw(‘この統計は GitHub Actions によって自動生成されました。’)
.write();
core.info(“サマリーの書き込みが完了しました。”);
最後に
いかがでしたか? `actions/github-script` をマスターすることは、GitHub Actionsという舞台で「自由な翼」を手に入れることと同じです。
外部のNode.jsスクリプトを管理する煩わしさから解放され、YAMLの中に凝縮された知性を宿らせる。この手法を使いこなせば、チームメンバーから「このワークフロー、魔法みたいにスマートだね」と驚かれること間違いありません。
まずは、簡単な `core.info()` や `github.rest.issues.createComment()` から始めてみてください。一歩ずつ、しかし確実に、あなたの開発環境は楽に、そして強くなっていきます。
自動化の旅を、楽しんでくださいね。応援しています。