dotnet-gha-patterns について
.NET プロジェクト向けに、再利用可能な GitHub Actions ワークフローを設計するスキルです。基本的なビルド・テストテンプレートを超えた構成と CI/CD 制御を扱います。
主な機能
- 01workflow_call によるワークフロー再利用
- 02複合アクションによる手順共有
- 03複数 TFM・OS のマトリックスビルド
- 04パスベースのトリガーと同時実行制御
- 05環境保護ルールとシークレット
- 06NuGet・SDK キャッシュと手動入力
活用シーン
- 01複数リポジトリでビルドジョブを共有
- 02複数 OS で .NET バージョンをテスト
- 03無関係な変更時に CI をスキップ
- 04デプロイ前に手動承認を求める
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ wshaddix/ dotnet-skills --skill dotnet-gha-patternsインストール後、Claude Code で/dotnet-gha-patternsを入力して読み込まれたか確認します。
詳細
dotnet-gha-patterns
.NET プロジェクト向けの構成可能な GitHub Actions ワークフローパターンです。workflow_call を使用した再利用可能なワークフロー、共有ステップシーケンス向けのコンポジットアクション、TFM とオペレーティングシステムをまたぐマトリックスビルド、パスベースのトリガー、重複実行をキャンセルするための同時実行グループ、環境保護ルール、NuGet と SDK のキャッシュ戦略、手動トリガー用の workflow_dispatch 入力を扱います。
バージョンに関する前提: GitHub Actions のワークフロー構文 v2。.NET 8/9/10 をサポートする actions/setup-dotnet@v4。依存関係のキャッシュには actions/cache@v4 を使用します。
対象範囲: このスキルでは、GitHub Actions の構成可能な CI/CD ワークフロー設計パターンを扱います。スターター CI テンプレート(基本的なビルド/テスト/パック)は [skill:dotnet-add-ci] が担当します。このスキルでは、これらのテンプレートを拡張する高度な構成を扱います。CLI 固有のリリースパイプライン(CLI バイナリの build-package-release)は [skill:dotnet-cli-release-pipeline] が担当します。このスキルでは、CLI パイプラインが利用する一般的なワークフローパターンを扱います。ベンチマークの CI 統合は [skill:dotnet-ci-benchmarking] が担当します。
対象外: スターター CI/CD テンプレートについては [skill:dotnet-add-ci] を参照してください。CLI リリースパイプライン(CLI ツール向けのタグをトリガーとする build-package-release)については [skill:dotnet-cli-release-pipeline] を参照してください。ベンチマーク CI ワークフローについては [skill:dotnet-ci-benchmarking] を参照してください。Azure DevOps のパイプラインパターンについては [skill:dotnet-ado-patterns] を参照してください。ビルド/テストの詳細については [skill:dotnet-gha-build-test] を参照してください。公開ワークフローについては [skill:dotnet-gha-publish] を参照してください。デプロイパターンについては [skill:dotnet-gha-deploy] を参照してください。
相互参照: これらのパターンで拡張するスターターテンプレートについては [skill:dotnet-add-ci]、CLI 固有のリリース自動化については [skill:dotnet-cli-release-pipeline]、ベンチマーク固有の CI 統合については [skill:dotnet-ci-benchmarking] を参照してください。
再利用可能なワークフロー(workflow_call)
再利用可能なワークフローの定義
再利用可能なワークフローを使用すると、呼び出し元はワークフロー全体を単一のステップとして呼び出せます。明確な契約を定めるため、入力、出力、シークレットを定義します。
# .github/workflows/build-reusable.yml
name: Build (Reusable)
on:
workflow_call:
inputs:
dotnet-version:
description: '.NET SDK version to install'
required: false
type: string
default: '8.0.x'
configuration:
description: 'Build configuration'
required: false
type: string
default: 'Release'
project-path:
description: 'Path to solution or project file'
required: true
type: string
outputs:
artifact-name:
description: 'Name of the uploaded build artifact'
value: ${{ jobs.build.outputs.artifact-name }}
secrets:
NUGET_AUTH_TOKEN:
description: 'NuGet feed authentication token'
required: false
jobs:
build:
runs-on: ubuntu-latest
outputs:
artifact-name: build-${{ github.sha }}
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ inputs.dotnet-version }}
- name: Restore
run: dotnet restore ${{ inputs.project-path }}
- name: Build
run: dotnet build ${{ inputs.project-path }} -c ${{ inputs.configuration }} --no-restore
- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: build-${{ github.sha }}
path: |
**/bin/${{ inputs.configuration }}/**
retention-days: 7
再利用可能なワークフローの呼び出し
# .github/workflows/ci.yml
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
uses: ./.github/workflows/build-reusable.yml
with:
dotnet-version: '8.0.x'
project-path: MyApp.sln
secrets:
NUGET_AUTH_TOKEN: ${{ secrets.NUGET_AUTH_TOKEN }}
test:
needs: build
uses: ./.github/workflows/test-reusable.yml
with:
dotnet-version: '8.0.x'
project-path: MyApp.sln
リポジトリ間での再利用可能なワークフロー
完全なパスを指定して、他のリポジトリのワークフローを参照します。
jobs:
build:
uses: my-org/.github-workflows/.github/workflows/dotnet-build.yml@v1
with:
dotnet-version: '9.0.x'
secrets: inherit # pass all secrets from caller
再利用可能なワークフローが、呼び出し元のワークフローと同じシークレットを明示的に列挙せずに利用する必要がある場合は、secrets: inherit を使用します。
コンポジットアクション
コンポジットアクションの作成
コンポジットアクションを使うと、複数のステップを単一の再利用可能なアクションにまとめられます。複数のワークフローで共有されるステップシーケンスに使用します。
# .github/actions/dotnet-setup/action.yml
name: 'Setup .NET Environment'
description: 'Install .NET SDK and restore NuGet packages with caching'
inputs:
dotnet-version:
description: '.NET SDK version'
required: false
default: '8.0.x'
project-path:
description: 'Path to solution or project'
required: true
runs:
using: 'composite'
steps:
- name: Setup .NET SDK
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ inputs.dotnet-version }}
- name: Cache NuGet packages
uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj', '**/Directory.Packages.props') }}
restore-keys: |
nuget-${{ runner.os }}-
- name: Restore dependencies
shell: bash
run: dotnet restore ${{ inputs.project-path }}
コンポジットアクションの使用
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET environment
uses: ./.github/actions/dotnet-setup
with:
dotnet-version: '9.0.x'
project-path: MyApp.sln
- name: Build
run: dotnet build MyApp.sln -c Release --no-restore
再利用可能なワークフローとコンポジットアクションの比較
| 機能 | 再利用可能なワークフロー | コンポジットアクション |
|---|---|---|
| 範囲 | ランナーを含むジョブ全体 | ジョブ内のステップ |
| ランナーの選択 | 独自の runs-on | 呼び出し元のランナー |
| シークレットへのアクセス | 明示的な指定または inherit | 呼び出し元のコンテキスト |
| 出力 | ジョブレベルの出力 | ステップレベルの出力 |
| 最適な用途 | ビルド/テスト/デプロイのジョブ全体 | 共有されるセットアップ/ティアダウンシーケンス |
マトリックスビルド
複数の TFM と OS のマトリックス
jobs:
test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
dotnet-version: ['8.0.x', '9.0.x']
include:
- os: ubuntu-latest
dotnet-version: '10.0.x'
exclude:
- os: macos-latest
dotnet-version: '8.0.x'
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Setup .NET ${{ matrix.dotnet-version }}
uses: actions/setup-dotnet@v4
with:
dotnet-version: ${{ matrix.dotnet-version }}
- name: Test
run: dotnet test --framework net${{ matrix.dotnet-version == '8.0.x' && '8.0' || matrix.dotnet-version == '9.0.x' && '9.0' || '10.0' }}
主な判断ポイント:
fail-fast: falseを指定すると、1 つの組み合わせで失敗してもマトリックスのすべての組み合わせが実行されるため、どのプラットフォーム/TFM に問題があるかをすべて把握できますincludeは、直積に含まれない特定の組み合わせを追加しますexcludeは、不要またはサポート対象外の組み合わせを除外します
JSON からの動的なマトリックス生成
複雑なシナリオでは、マトリックスの値を動的に生成します。
jobs:
compute-matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- uses: actions/checkout@v4
- id: set-matrix
shell: bash
run: |
set -euo pipefail
# Extract TFMs from Directory.Build.props or csproj files
TFMS=$(grep -rh '<TargetFrameworks\?>' **/*.csproj | \
sed 's/.*<TargetFrameworks\?>//' | sed 's/<.*//' | \
tr ';' '\n' | sort -u | jq -R . | jq -sc .)
echo "matrix={\"tfm\":$TFMS}" >> "$GITHUB_OUTPUT"
test:
needs: compute-matrix
strategy:
matrix: ${{ fromJson(needs.compute-matrix.outputs.matrix) }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: dotnet test --framework ${{ matrix.tfm }}
パスベースのトリガー
ワークフローの選択的な実行
関連ファイルが変更された場合にのみワークフローをトリガーします。これにより、CI のコストとフィードバックにかかる時間を削減できます。
on:
push:
branches: [main]
paths:
- 'src/**'
- 'tests/**'
- '*.sln'
- 'Directory.Build.props'
- 'Directory.Packages.props'
- '.github/workflows/ci.yml'
pull_request:
branches: [main]
paths:
- 'src/**'
- 'tests/**'
- '*.sln'
- 'Directory.Build.props'
- 'Directory.Packages.props'
コード以外の変更の無視
ドキュメントのみの変更ではビルドをスキップするため、paths-ignore を使用します。
on:
push:
branches: [main]
paths-ignore:
- 'docs/**'
- '*.md'
- 'LICENSE'
- '.editorconfig'
paths と paths-ignore はどちらか一方を選択してください。同時に指定すると、同じイベントで paths-ignore は無視されます。 対象を絞ったワークフローには paths(許可リスト)を、広範なワークフローには paths-ignore(拒否リスト)を使用します。
同時実行グループ
重複実行のキャンセル
同じブランチまたは PR に新しいコミットがプッシュされたときに、実行中のワークフローをキャンセルして、無駄な CI 時間を防ぎます。
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
環境ごとの同時実行制御
同じ環境への並列デプロイを防ぎます。
concurrency:
group: deploy-production
cancel-in-progress: false # queue, do not cancel deployments
ビルド/テストには cancel-in-progress: true を使用します(新しいコミットが古いコミットに取って代わります)。デプロイには cancel-in-progress: false を使用します(実行中のデプロイをキャンセルしません)。
環境の保護ルール
環境の設定
jobs:
deploy-staging:
runs-on: ubuntu-latest
environment:
name: staging
url: https://staging.example.com
steps:
- name: Deploy to staging
run: echo "Deploying..."
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment:
name: production
url: https://example.com
steps:
- name: Deploy to production
run: echo "Deploying..."
GitHub の「Settings」>「Environments」で保護ルールを設定します。
| ルール | 目的 |
|---|---|
| 必須のレビュアー | デプロイ前の手動承認 |
| 待機時間 | クールダウン期間(例:15 分) |
| ブランチ制限 | main または release/* ブランチのみデプロイ可能 |
| カスタムデプロイ保護ルール | サードパーティの連携(モニタリングチェック) |
環境シークレット
環境には、リポジトリレベルのシークレットを上書きする独自のシークレットを設定できます。デプロイ用の認証情報には、環境ごとのシークレットを使用します。
jobs:
deploy:
environment: production
runs-on: ubuntu-latest
steps:
- name: Deploy
env:
# These resolve to environment-specific values
CONNECTION_STRING: ${{ secrets.CONNECTION_STRING }}
API_KEY: ${{ secrets.API_KEY }}
run: ./deploy.sh
キャッシュ戦略
NuGet パッケージキャッシュ
- name: Cache NuGet packages
uses: actions/cache@v4
with:
path: ~/.nuget/packages
key: nuget-${{ runner.os }}-${{ hashFiles('**/*.csproj', '**/Directory.Packages.props') }}
restore-keys: |
nuget-${{ runner.os }}-
restore-keys のプレフィックス一致により、csproj ファイルが変更されても部分的にキャッシュがヒットします(ほとんどのパッケージはキャッシュされたままです)。
.NET SDK キャッシュ
セルフホストランナーや、SDK のインストールに時間がかかる状況では、次の設定を使用します。
- name: Setup .NET with cache
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
cache: true
cache-dependency-path: '**/packages.lock.json'
actions/setup-dotnet@v4 の cache: true オプションを有効にすると、packages.lock.json をキャッシュキーとして組み込みの NuGet キャッシュを利用できます。
ビルド出力キャッシュ(.NET 9 以降)
.NET 9 では、MSBuild のビルドチェックキャッシュが導入されました。CI ビルドを段階的に実行するには、次の設定を使用します。
- name: Cache build output
uses: actions/cache@v4
with:
path: |
**/bin/
**/obj/
key: build-${{ runner.os }}-${{ hashFiles('**/*.csproj', '**/*.cs') }}
restore-keys: |
build-${{ runner.os }}-
ビルド出力キャッシュは慎重に使用してください。古いキャッシュによってビルドエラーが隠れることがあります。CI の速度向上には、NuGet キャッシュを主な最適化手段として使用することをおすすめします。
workflow_dispatch の入力
パラメーター付きの手動トリガー
on:
workflow_dispatch:
inputs:
environment:
description: 'Target deployment environment'
required: true
type: choice
options:
- staging
- production
default: staging
version:
description: 'Version to deploy (e.g., 1.2.3)'
required: true
type: string
dry-run:
description: 'Simulate deployment without applying changes'
required: false
type: boolean
default: false
jobs:
deploy:
runs-on: ubuntu-latest
environment: ${{ inputs.environment }}
steps:
- uses: actions/checkout@v4
with:
ref: v${{ inputs.version }}
- name: Deploy
env:
DRY_RUN: ${{ inputs.dry-run }}
run: |
set -euo pipefail
if [ "$DRY_RUN" = "true" ]; then
echo "DRY RUN: would deploy v${{ inputs.version }} to ${{ inputs.environment }}"
else
./deploy.sh --version ${{ inputs.version }}
fi
入力タイプ:string、boolean、choice、environment(設定済みの環境から選択します)。
エージェントが注意すべき点
- 同じイベントで
pathsとpaths-ignoreを併用しないでください — 両方を指定すると、paths-ignoreは警告なしに無視されます。どちらか一方を使用してください。 - マトリックスビルドでは
fail-fast: falseを設定してください — デフォルトのfail-fast: trueでは、1 つのジョブが失敗すると兄弟ジョブがキャンセルされ、ほかにどの組み合わせが失敗するか分からなくなります。 - すべての bash ステップで
set -euo pipefailを使用してください —pipefailがないと、パイプでつないだコマンド(例:script | tee)の終了コードが 0 以外でも、ステップは失敗しません。 - 再利用可能なワークフローの入力は、デフォルトで文字列です — ブール値と数値の型は、
workflow_callの入力でtype:を明示して宣言する必要があります。 - キャッシュキーには
runner.osを含めてください — NuGet パッケージは OS に依存します。Linux でビルドしたキャッシュを Windows で復元すると、復元に失敗します。 - ワークフローファイルに TFM をハードコードしないでください — ワークフローとプロジェクト設定の同期を保つため、マトリックス変数を使用するか、csproj から抽出してください。
secrets: inheritは呼び出し元のすべてのシークレットを渡します — セキュリティ上重要な再利用可能ワークフローでは、公開範囲を制限するためにシークレットを明示的に宣言してください。- デプロイ用の同時実行グループでは
cancel-in-progress: falseを使用してください — 実行中のデプロイをキャンセルすると、インフラストラクチャが不整合な状態になるおそれがあります。