Tips - カスタムアクションの開発と公開
GitHub Actionsのカスタムアクションを開発し、GitHub Marketplaceに公開することで、自分のツールやワークフローを世界中の開発者と共有できます。GitHub公式ドキュメントをもとに、アクションの開発から公開、継続的なメンテナンスまでの実践的な手法を解説します。
1. アクションの配置戦略
1.1 公開用アクションは専用リポジトリに
他のユーザーに公開するアクションを開発する場合、専用リポジトリでの管理を推奨します。この方式には以下のメリットがあります。
- バージョン管理が明確になる
- リリースサイクルを独立して管理できる
- コミュニティによる発見が容易になる
- イシューやPRの管理範囲が明確になる
- アプリケーションコードとアクションのバージョニングが分離される
1.2 個人利用の場合
公開を予定していないアクションであれば、リポジトリ内の任意の場所に配置できます。特にアクション、ワークフロー、アプリケーションコードを1つのリポジトリで管理する場合は、.githubディレクトリ配下を使用することを推奨します。
.github/
└── actions/
├── action-a/
│ └── action.yml
└── action-b/
└── action.yml
2. プラットフォーム互換性の確保
GitHub Actionsは、GitHub.com以外にもGitHub Enterprise Server等の様々な環境で実行されます。アクションの互換性を高めるために、以下の点に注意してください。
2.1 API URLのハードコーディングを避ける
https://api.github.comのような固定URLを使用せず、環境変数を活用します。
- REST API:
GITHUB_API_URL環境変数を使用 - GraphQL:
GITHUB_GRAPHQL_URL環境変数を使用
または、@actions/githubのようなツールキットを使用することで、自動的に正しいURLが設定されます。
const github = require('@actions/github');
// 環境に応じて適切なURLが自動設定される
3. リリース管理の戦略
3.1 セマンティックバージョニングの採用
ユーザーが安定したバージョンを選択できるよう、セマンティックバージョニングを採用します。パッチバージョンには重要な修正やセキュリティパッチが含まれ、既存のワークフローとの互換性を維持します。
3.2 タグを使用したリリース管理
通常のリリース管理では、タグを使用する方法を推奨します。
開発フロー:
- リリースブランチ(例:
release/v1)で開発・検証 - セマンティックバージョニングでリリース作成(例:
v1.0.1) - メジャーバージョンタグ(例:
v1)を最新リリースに移動
ユーザー側の参照方法:
steps:
# メジャーバージョンで参照(推奨)
- uses: yamada/javascript-action@v1
steps:
# 特定のパッチバージョンで参照
- uses: yamada/javascript-action@v1.0.1
3.3 ブランチを使用したリリース管理
ブランチ名でのリリース管理も可能です。
steps:
- uses: yamada/javascript-action@v1-beta
3.4 コミットSHAを使用したリリース管理
最も信頼性の高い方法として、コミットの完全なSHA値を使用できます。この方法では、タグの削除や移動の影響を受けません。ただし、アクションの更新を受け取れなくなる点に注意が必要です。
steps:
- uses: yamada/javascript-action@a824008085750b8e136effc585c3cd6082bd575f
3.5 Immutable Releasesを使用した管理
サプライチェーン攻撃や意図しない変更を防ぐために、Immutable Releasesを有効化している場合は、以下のフローを採用します。
変更不可能なバージョンの共有:
GitHub上でリリース固有のタグ(例:v1.0.0)でリリースを作成します。
更新可能なタグの管理:
GitHub上でリリースを作成せず、Gitタグのみを使用します。
- 破壊的変更を含む場合:メジャーバージョンタグ(例:
v1)を作成 - 後方互換性のある新機能:マイナーバージョンタグ(例:
v1.1)を作成 - バグ修正:パッチバージョンタグ(例:
v1.1.1)を作成
タグの移動は以下のコマンドで実行します。
git tag -f v1
git push -f --tags
4. GitHub Marketplaceへの公開
4.1 公開前の準備
GitHub Marketplaceにアクションを公開するには、以下の要件を満たす必要があります。
必須要件:
- パブリックリポジトリであること
- リポジトリのルートに単一のメタデータファイル(
action.ymlまたはaction.yaml)が存在すること - サブフォルダーに他のアクションメタデータファイルを含むことは可能だが、自動的にMarketplaceに掲載されない
- ワークフローファイルを含まないこと
- メタデータファイルの
nameが一意であること
名前の制約:
- 既存のGitHub Marketplaceアクション名と重複不可
- GitHubのユーザー名や組織名と重複不可(該当するユーザー・組織が公開する場合を除く)
- 既存のGitHub Marketplaceカテゴリ名と重複不可
- GitHub機能の予約名と重複不可
4.2 公開手順
以下の図は、GitHub Marketplaceへの公開の全体的な流れを示しています。
具体的な手順は以下の通りです。
- リポジトリのメインページへ移動
-
action.ymlファイルにアクセスし、「Draft a release」をクリック - 「Publish this Action to the GitHub Marketplace」にチェック
- GitHub Marketplace Developer Agreementに同意(未同意の場合)
- メタデータのラベルに問題がないか確認し、エラーがあれば修正
- Primary Categoryを選択(必須)
- Another Categoryを選択(任意)
- バージョンタグを入力(例:
v1.0.0) - リリースタイトルを入力
- その他の項目を入力して「Publish release」をクリック(2要素認証が必要)
4.3 Marketplaceからの削除
公開済みアクションを削除する場合、各リリースごとに以下の手順を実行します。
- リポジトリのメインページから「Releases」をクリック
- 編集したいリリースの横にある鉛筆アイコンをクリック
- 「Publish this action to the GitHub Marketplace」のチェックを外す
- ページ下部の「Update release」をクリック
4.4 リポジトリの移譲
アクションリポジトリを他のユーザーや組織に移譲できます。リポジトリを移譲すると、GitHubは自動的に旧URLから新URLへのリダイレクトを作成するため、既存のワークフローを更新する必要はありません。
GitHub Marketplaceに公開されているアクションは、一意の名前識別子でリポジトリにリンクされています。移譲後も同じGitHub Marketplaceリストから新しいリリースを公開できます。
注意点:
- リポジトリが削除されると、GitHub Marketplaceリストも削除され、名前識別子が再利用可能になります
- 移譲先が認証済みクリエーターでない場合、verified creator badgeは失われます
5. 開発とリリースプロセスの自動化
5.1 JavaScriptアクションの特性
JavaScriptアクションはNode.jsリポジトリにメタデータを追加したものですが、従来のNode.jsプロジェクトとは異なる特性があります。
- 依存パッケージはコンパイル・ミニファイされた形式でコードと一緒にコミットされる
- タグ付きリリースをGitHub Marketplaceに直接公開できる
- GitHub APIやサードパーティAPIを使用するため、エンドツーエンドテストが重要
5.2 GitHub Actionsワークフローのセットアップ
開発プロセスを支援するため、2つのワークフローを設定します。
テストワークフロー:
フィーチャーブランチやmainブランチへのコミット、PRの作成時にトリガーされ、ユニットテストと統合テストを実行します。
name: "テスト"
on:
push:
branches:
- main
- 'feature/**'
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: "依存関係のインストール"
run: npm ci
- name: "テスト実行"
run: npm test
リリースワークフロー:
リリースの公開または編集時にトリガーされ、JavaScriptのコンパイルとバンドル、セマンティックタグの調整を行います。
name: "リリース"
on:
release:
types: [published, edited]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: "ビルドとタグ付け"
uses: tanaka/build-and-tag-action@v2
注意: Immutable Releasesを有効化している場合、force pushを使用するアクションは利用できません。
5.3 推奨開発フロー
- フィーチャーブランチで開発: GitHub Flowに従い、ブランチごとに機能を開発
- 自動テスト実行: コミットプッシュ時にテストワークフローが実行される
- PR作成とレビュー: mainブランチへのPRを作成し、議論とレビューを実施
- PRでのテスト: PRのマージコミットに対してテストが実行される
-
リリース作成: セマンティックバージョンでリリースを作成(例:
v1.1.3) - 自動リリース処理: リリースワークフローがコンパイルとタグ調整を自動実行
セキュリティに関する注意:
フォークからのpull_requestイベントでトリガーされるワークフローは、GITHUB_TOKENの権限が制限され、シークレットへのアクセスができません。テストやワークフローがシークレットを必要とする場合は、手動トリガーやpull_request_targetなどの別のイベントの使用を検討してください。
5.4 依存関係管理の戦略
このプロセスでは、mainブランチには依存関係をコミットせず、タグ付きリリースコミットにのみコミットします。この方法には以下のメリットがあります。
- ユーザーが名前付きタグやSHAを参照することを促進
- リリース時に自分でビルドを実行することで、サードパーティPRのセキュリティを確保
- mainブランチの履歴が簡潔に保たれる
6. コミュニティとの協働
6.1 READMEの充実
詳細なREADMEファイルを作成し、以下の情報を含めます。
- アクションの詳細な説明
- 必須の入力・出力引数
- オプションの入力・出力引数
- アクションが使用するシークレット
- アクションが使用する環境変数
- ワークフローでの使用例
READMEの例:
# My Action
このアクションは○○を実行します。
## 入力
### `version`
**必須** インストールするツールのバージョン。デフォルトは `latest`。
### `cache`
**オプション** ツールをキャッシュするかどうか。デフォルトは `true`。
## 出力
### `path`
インストールされたツールのパス。
## 使用例
\`\`\`yaml
- uses: yamada/my-action@v1
with:
version: '1.2.3'
cache: true
\`\`\`
6.2 ステータスバッジの追加
ワークフローステータスバッジをREADMEに追加し、アクションの品質を可視化します。

6.3 コミュニティヘルスファイルの整備
以下のファイルを追加し、コミュニティとの健全なコミュニケーションを促進します。
-
CODE_OF_CONDUCT.md: 行動規範 -
CONTRIBUTING.md: コントリビューションガイドライン -
SECURITY.md: セキュリティポリシーと脆弱性報告方法
6.4 イシューの管理
actions/staleのようなアクションを使用し、イシューを最新の状態に保ちます。
name: "古いイシューの管理"
on:
schedule:
- cron: "0 0 * * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
with:
stale-issue-message: "このイシューは長期間更新されていません。"
days-before-stale: 60
days-before-close: 7
6.5 セキュリティ機能の活用
GitHubのセキュリティ機能を使用し、脆弱性の報告と修正方法を明確にします。
- Security Advisoriesで脆弱性を開示
- Dependabotで依存関係を最新に保つ
- Code scanningで潜在的な問題を検出
7. CLIツールセットアップアクションの作成
サーバーへのアクセスを提供するCLI環境をGitHub Actionsランナー上にセットアップするアクションの作成例を紹介します。このタイプのアクションは、setup-$TOOLという命名規則で呼ばれることが多いです。
7.1 設計目標
- ユーザーが簡単にCLIバージョンを指定できる
- 複数のオペレーティングシステムをサポート
- 実行時間とコストを最小化する効率的な動作
- GitHub ホストランナーとセルフホストランナーの両方で動作
- 可能な限りコミュニティツールを活用
7.2 実装例
const core = require('@actions/core');
const tc = require('@actions/tool-cache');
async function setup() {
// ユーザー指定のバージョンを取得
const version = core.getInput('version');
// 特定バージョンのツールをダウンロード(tarball等)
const pathToTarball = await tc.downloadTool(getDownloadURL(version));
// ランナー上でtarballを展開
const pathToCLI = await tc.extractTar(pathToTarball);
// PATHに追加してツールを公開
core.addPath(pathToCLI);
}
module.exports = setup;
この実装では、GitHub公式のactions/toolkitを使用しています。actions/coreとactions/tool-cacheパッケージにより、入力の取得、ツールのダウンロード・展開、PATHへの追加が簡潔に記述できます。
7.3 メタデータファイルの作成
action.ymlファイルで、version入力を定義し、スクリプトを実行します。
name: 'Setup My CLI'
description: 'My CLIをセットアップします'
inputs:
version:
description: 'インストールするCLIのバージョン'
required: true
default: 'latest'
runs:
using: 'node20'
main: 'index.js'
7.4 参考実装
このパターンは以下のアクションで採用されています。
ruby/setup-rubygoogle-github-actions/setup-gcloudhashicorp/setup-terraform
8. 終了コードの設定
アクションのステータスをGitHubに伝えるため、終了コードを適切に設定します。
8.1 終了コードとステータスの関係
| 終了コード | チェックランステータス | 説明 |
|---|---|---|
0 |
success |
アクションが正常に完了し、依存する他のタスクを開始できる |
| 0以外の値 | failure |
アクションが失敗。すべての並行アクションがキャンセルされ、今後のアクションはスキップされる |
8.2 JavaScriptアクションでの設定
@actions/coreパッケージを使用して、メッセージのログ出力と失敗終了コードの設定を行います。
try {
// 何らかの処理
const result = performOperation();
core.info(`処理が成功しました: ${result}`);
} catch (error) {
core.setFailed(error.message);
}
8.3 Dockerコンテナアクションでの設定
entrypoint.shスクリプトで失敗終了コードを設定します。
#!/bin/bash
if [ -z "$INPUT_VERSION" ]; then
echo "エラー: versionが指定されていません"
exit 1
fi
# 処理を実行
if ! perform_operation; then
echo "処理に失敗しました"
exit 1
fi
echo "処理が成功しました"
exit 0
9. まとめ
GitHub Actionsのカスタムアクション開発は、適切なリリース管理とコミュニティとの協働により、持続可能なOSSプロジェクトとして成長させることができます。
重要なポイント:
- 公開アクションは専用リポジトリで管理
- セマンティックバージョニングでユーザーに安定性を提供
- GitHub ActionsでCI/CDを自動化
- 充実したドキュメントとコミュニティヘルスファイルでコントリビューションを促進
- プラットフォーム互換性を確保し、幅広い環境で動作させる
これらの実践により、信頼性が高く、メンテナンスしやすいアクションを開発できます。