mcpField
D
dotnet-gha-patterns

dotnet-gha-patterns

github.com/wshaddixクラウド・DevOps8673 回インストール35 週間前に更新
リポジトリ

dotnet-gha-patterns について

.NET プロジェクト向けに、再利用可能な GitHub Actions ワークフローを設計するスキルです。基本的なビルド・テストテンプレートを超えた構成と CI/CD 制御を扱います。

主な機能

  1. 01workflow_call によるワークフロー再利用
  2. 02複合アクションによる手順共有
  3. 03複数 TFM・OS のマトリックスビルド
  4. 04パスベースのトリガーと同時実行制御
  5. 05環境保護ルールとシークレット
  6. 06NuGet・SDK キャッシュと手動入力

活用シーン

  1. 01複数リポジトリでビルドジョブを共有
  2. 02複数 OS で .NET バージョンをテスト
  3. 03無関係な変更時に CI をスキップ
  4. 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(設定済みの環境から選択します)。


エージェントが注意すべき点

  1. 同じイベントで paths と paths-ignore を併用しないでください — 両方を指定すると、paths-ignore は警告なしに無視されます。どちらか一方を使用してください。
  2. マトリックスビルドでは fail-fast: false を設定してください — デフォルトの fail-fast: true では、1 つのジョブが失敗すると兄弟ジョブがキャンセルされ、ほかにどの組み合わせが失敗するか分からなくなります。
  3. すべての bash ステップで set -euo pipefail を使用してください — pipefail がないと、パイプでつないだコマンド(例:script | tee)の終了コードが 0 以外でも、ステップは失敗しません。
  4. 再利用可能なワークフローの入力は、デフォルトで文字列です — ブール値と数値の型は、workflow_call の入力で type: を明示して宣言する必要があります。
  5. キャッシュキーには runner.os を含めてください — NuGet パッケージは OS に依存します。Linux でビルドしたキャッシュを Windows で復元すると、復元に失敗します。
  6. ワークフローファイルに TFM をハードコードしないでください — ワークフローとプロジェクト設定の同期を保つため、マトリックス変数を使用するか、csproj から抽出してください。
  7. secrets: inherit は呼び出し元のすべてのシークレットを渡します — セキュリティ上重要な再利用可能ワークフローでは、公開範囲を制限するためにシークレットを明示的に宣言してください。
  8. デプロイ用の同時実行グループでは cancel-in-progress: false を使用してください — 実行中のデプロイをキャンセルすると、インフラストラクチャが不整合な状態になるおそれがあります。

コメント