mcpField
D
dotnet-ado-unique

dotnet-ado-unique

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

dotnet-ado-unique について

Azure DevOps Services を使う .NET チーム向けのスキルです。デプロイチェック、サービス接続、変数グループ、従来型リリースの移行など、Azure DevOps 固有の機能を扱います。

主な機能

  1. 01環境の承認とチェック
  2. 02デプロイグループと環境の選択・移行
  3. 03Azure、Docker Registry、NuGet のサービス接続
  4. 04従来型リリースから YAML への移行
  5. 05Key Vault 連携の変数グループとセキュアファイル
  6. 06組織全体のパイプラインデコレーター

活用シーン

  1. 01本番デプロイに承認と業務時間の制限を設定
  2. 02デプロイグループのワークロードを環境へ移行
  3. 03Azure、レジストリ、NuGet の認証を構成
  4. 04従来型リリースをマルチステージ YAML に変換

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-ado-unique

インストール後、Claude Code で/dotnet-ado-uniqueを入力して読み込まれたか確認します。

詳細

dotnet-ado-unique

GitHub Actions では利用できない Azure DevOps 固有の機能:承認とゲートを備えた環境(デプロイ前チェック、業務時間の制限)、デプロイグループと環境の使い分け、サービス接続(Azure Resource Manager、Docker Registry、NuGet)、クラシックリリースパイプライン(YAML へのレガシー移行ガイダンス)、変数グループとライブラリ(Azure Key Vault とのリンク)、組織全体のポリシーを適用するパイプラインデコレーター、Azure Artifacts ユニバーサルパッケージ。

バージョンの前提: Azure DevOps Services(クラウド)。複数ステージに対応した YAML パイプライン。クラシックリリースパイプラインはレガシー移行の文脈でのみ扱います。

対象範囲の境界: このスキルでは、GitHub Actions に直接相当する機能がない ADO 固有のプラットフォーム機能を扱います。組み合わせ可能な YAML パイプラインパターン(テンプレート、トリガー、複数ステージ)は [skill:dotnet-ado-patterns] で扱います。ビルド/テストのパイプライン構成は [skill:dotnet-ado-build-test] で扱います。公開パイプラインは [skill:dotnet-ado-publish] で扱います。スターター CI テンプレートは [skill:dotnet-add-ci] が担当します。

対象外: 組み合わせ可能なパイプラインパターン(テンプレート、トリガー)については [skill:dotnet-ado-patterns] を参照してください。ビルド/テストのパイプライン構成については [skill:dotnet-ado-build-test] を参照してください。公開パイプラインについては [skill:dotnet-ado-publish] を参照してください。スターター CI テンプレートについては [skill:dotnet-add-ci] を参照してください。GitHub Actions に相当する機能については [skill:dotnet-gha-patterns]、[skill:dotnet-gha-build-test]、[skill:dotnet-gha-publish]、[skill:dotnet-gha-deploy] を参照してください。CLI リリースパイプラインについては [skill:dotnet-cli-release-pipeline] を参照してください。

相互参照:[skill:dotnet-add-ci](スターター CI テンプレート)、[skill:dotnet-cli-release-pipeline](CLI 固有のリリース自動化)。


承認とゲートを備えた環境

YAML での環境の定義

環境は、デプロイ先の指定、承認ゲート、デプロイ履歴を提供する Azure DevOps の第一級リソースです。

stages:
  - stage: DeployStaging
    jobs:
      - deployment: DeployToStaging
        pool:
          vmImage: 'ubuntu-latest'
        environment: 'staging'
        strategy:
          runOnce:
            deploy:
              steps:
                - download: current
                  artifact: app
                - script: echo "Deploying to staging"

  - stage: DeployProduction
    dependsOn: DeployStaging
    jobs:
      - deployment: DeployToProduction
        pool:
          vmImage: 'ubuntu-latest'
        environment: 'production'
        strategy:
          runOnce:
            deploy:
              steps:
                - download: current
                  artifact: app
                - script: echo "Deploying to production"

環境は、初めて参照されたときに自動的に作成されます。承認とゲートは、Azure DevOps > Pipelines > Environments > (環境を選択) > Approvals and checks で構成します。

承認チェック
チェックの種類目的構成
承認デプロイ前の手動承認承認者のユーザー/グループを割り当てる
ブランチ制御デプロイを特定のブランチに制限するmain、release/* のみ許可する
業務時間許可された時間帯にのみデプロイする時間帯とタイムゾーンを定義する
テンプレートの検証特定のテンプレートを拡張するようパイプラインに要求する必須テンプレートのパスを指定する
Azure Function の呼び出しAzure Function によるカスタム検証Function の URL とキーを指定する
REST API の呼び出しHTTP エンドポイントによるカスタム検証URL と成功条件を指定する
必須テンプレートパイプラインの構造を適用する必須の extends テンプレートを指定する
承認チェックの構成

承認チェックは YAML ではなく、Azure DevOps の UI で構成します。YAML パイプラインから環境を参照すると、チェックが適用されます。

# Pipeline YAML -- environment reference triggers checks
- deployment: DeployToProduction
  environment: 'production'  # checks configured in UI
  strategy:
    runOnce:
      deploy:
        steps:
          - script: echo "This runs only after all checks pass"

承認の構成(UI):

  • Pipelines > Environments > production > Approvals and checks に移動します
  • 「Approvals」チェックを追加し、ユーザーまたはグループを割り当てます
  • 承認者の最小数を設定します(例:本番環境では 2 人)
  • 適切な場合にのみ、「allow approvers to approve their own runs」を有効にします
業務時間ゲート

リスクを軽減するため、デプロイを特定の時間帯に制限します。

  • Pipelines > Environments > production > Approvals and checks に移動します
  • 「Business Hours」チェックを追加します
  • 月曜日から金曜日、09:00~17:00(チームのタイムゾーン)に設定します
  • パイプラインはキューに入り、時間帯が始まるまで待機します
Azure Functions によるデプロイ前の検証
# The environment's "Invoke Azure Function" check calls:
# https://myvalidation.azurewebsites.net/api/pre-deploy
# with the pipeline context as payload.
# Returns 200 to approve, non-200 to reject.

- deployment: DeployToProduction
  environment: 'production'  # Azure Function check configured in UI
  strategy:
    runOnce:
      preDeploy:
        steps:
          - script: echo "Pre-deploy hook (in-pipeline)"
      deploy:
        steps:
          - script: echo "Deploying"
      routeTraffic:
        steps:
          - script: echo "Routing traffic"
      postRouteTraffic:
        steps:
          - script: echo "Post-route validation"

preDeploy、routeTraffic、postRouteTraffic のライフサイクルフックは、パイプライン内で実行されます。環境チェック(承認、Azure Function ゲート)は、デプロイジョブの開始前に実行されます。


デプロイグループと環境

各機能の使い分け
機能デプロイグループ環境
対象エージェントを配置した物理/仮想マシン任意の対象(VM、Kubernetes、クラウドサービス)
エージェントモデル対象マシン上のセルフホストエージェントエージェントプールまたは対象固有のリソース
パイプラインの種類クラシックリリースパイプライン(レガシー)YAML マルチステージパイプライン(最新)
承認クラシック UI のステージごと環境のチェックと承認
ローリングデプロイローリング戦略を標準搭載YAML の strategy: rolling
推奨レガシーワークロードのみすべての新規プロジェクト
デプロイグループの例(レガシー)

デプロイグループでは、各対象マシンにエージェントをインストールします。既存のオンプレミスデプロイでのみ使用してください。

# Classic release pipeline (not YAML) -- for reference only
# Deployment groups are configured in Project Settings > Deployment Groups
# Each target server runs the ADO agent registered to the group
Kubernetes リソースを含む環境
- deployment: DeployToK8s
  environment: 'production.my-k8s-namespace'
  strategy:
    runOnce:
      deploy:
        steps:
          - task: KubernetesManifest@1
            inputs:
              action: 'deploy'
              manifests: 'k8s/*.yml'
              containers: '$(ACR_LOGIN_SERVER)/myapp:$(Build.BuildId)'

環境では、Kubernetes クラスターと名前空間を対象にできます。Azure DevOps UI で、環境配下のリソースとしてクラスターを登録してください。

デプロイグループから環境への移行
  1. 既存のデプロイグループ名に対応する環境を作成します
  2. 環境の「承認とチェック」で同じ承認ゲートを設定します
  3. クラシックリリースパイプラインのステージを、新しい環境を対象とする YAML deployment ジョブに変換します
  4. デプロイグループと同等の段階的なデプロイを行うには、strategy: rolling を使用します

サービス接続

Azure Resource Manager(ARM)

サービス接続を使用すると、外部サービスに認証済みでアクセスできます。ARM 接続では Azure リソースをデプロイできます。

- task: AzureWebApp@1
  displayName: 'Deploy to Azure App Service'
  inputs:
    azureSubscription: 'MyAzureServiceConnection'
    appType: 'webAppLinux'
    appName: 'myapp-staging'
    package: '$(Pipeline.Workspace)/app'

ARM サービス接続の作成:

  • 「Project Settings」>「Service Connections」>「New service connection」>「Azure Resource Manager」に移動します
  • 自動的に資格情報を管理するには、「Service principal (automatic)」を選択します
  • サブスクリプションとリソースグループのスコープを選択します
  • ADO がアプリの登録を作成し、共同作成者ロールを割り当てます
ワークロード ID フェデレーション(推奨)

パスワードレスの Azure 認証には、ワークロード ID フェデレーションを使用します(クライアントシークレットは不要です)。

  • 「Project Settings」>「Service Connections」>「New service connection」>「Azure Resource Manager」に移動します
  • 「Workload Identity federation (automatic)」を選択します
  • Azure DevOps パイプラインのトークンを信頼するフェデレーション資格情報が作成されます
  • シークレットのローテーションは不要です。この資格情報では有効期間の短いパイプライントークンを使用します
Docker レジストリサービス接続
- task: Docker@2
  displayName: 'Login to ACR'
  inputs:
    command: 'login'
    containerRegistry: 'MyACRServiceConnection'

- task: Docker@2
  displayName: 'Build and push'
  inputs:
    command: 'buildAndPush'
    containerRegistry: 'MyACRServiceConnection'
    repository: 'myapp'
    dockerfile: 'src/MyApp/Dockerfile'

Docker レジストリ接続の作成:

  • 「Project Settings」>「Service Connections」>「New service connection」>「Docker Registry」
  • ACR の場合は、「Azure Container Registry」を選択してレジストリを指定します
  • DockerHub の場合は、ユーザー名とアクセストークンを入力します
NuGet サービス接続

外部 NuGet フィード(例:nuget.org)にプッシュする場合:

- task: NuGetCommand@2
  displayName: 'Push to nuget.org'
  inputs:
    command: 'push'
    packagesToPush: '$(Pipeline.Workspace)/nupkgs/*.nupkg'
    nuGetFeedType: 'external'
    publishFeedCredentials: 'NuGetOrgServiceConnection'

NuGet 接続の作成:

  • 「Project Settings」>「Service Connections」>「New service connection」>「NuGet」
  • フィード URL(https://api.nuget.org/v3/index.json)と API キーを入力します

クラシックリリースパイプライン(レガシーからの移行)

YAML に移行する理由

クラシックリリースパイプラインはビジュアルデザイナーを使用し、ソース管理に保存されません。以下の利点を得るため、YAML マルチステージパイプラインに移行してください。

  • ソース管理: パイプライン定義をコードと一緒に管理できます
  • コードレビュー: パイプラインの変更を PR レビューに通せます
  • ブランチごとのパイプライン: YAML パイプラインはブランチごとに変更できます
  • 再利用性: テンプレートと extends を使って、組み合わせ可能なパイプラインを作成できます
  • 最新の機能: 環境、デプロイ戦略、パイプラインデコレーターを利用できます
移行パターン

クラシックリリースの構成:

Build Pipeline -> Release Pipeline
                    Stage 1: Dev (auto-deploy)
                    Stage 2: Staging (manual approval)
                    Stage 3: Production (scheduled + approval)

同等の YAML マルチステージパイプライン:

trigger:
  branches:
    include:
      - main

stages:
  - stage: Build
    jobs:
      - job: BuildJob
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - task: DotNetCoreCLI@2
            inputs:
              command: 'publish'
              projects: 'src/MyApp/MyApp.csproj'
              arguments: '-c Release -o $(Build.ArtifactStagingDirectory)/app'
          - task: PublishPipelineArtifact@1
            inputs:
              targetPath: '$(Build.ArtifactStagingDirectory)/app'
              artifactName: 'app'

  - stage: DeployDev
    dependsOn: Build
    jobs:
      - deployment: DeployDev
        environment: 'development'
        strategy:
          runOnce:
            deploy:
              steps:
                - download: current
                  artifact: app
                - script: echo "Deploy to dev"

  - stage: DeployStaging
    dependsOn: DeployDev
    jobs:
      - deployment: DeployStaging
        environment: 'staging'  # approvals configured in UI
        strategy:
          runOnce:
            deploy:
              steps:
                - download: current
                  artifact: app
                - script: echo "Deploy to staging"

  - stage: DeployProduction
    dependsOn: DeployStaging
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
    jobs:
      - deployment: DeployProduction
        environment: 'production'  # approvals + business hours in UI
        strategy:
          runOnce:
            deploy:
              steps:
                - download: current
                  artifact: app
                - script: echo "Deploy to production"
移行チェックリスト
  1. 従来のリリースステージをすべて特定し、YAML ステージに対応付けます
  2. 環境変数を YAML の変数グループまたはテンプレートに変換します
  3. 従来の承認ゲートを環境チェックに置き換えます
  4. 成果物のソースを download: current またはパイプラインリソースに変換します
  5. タスクグループを YAML のステップまたはジョブのテンプレートに置き換えます
  6. 従来のリリースを廃止する前に、本番環境以外のブランチで YAML パイプラインをテストします

変数グループとライブラリ

Azure Key Vault にリンクされた変数グループ

変数グループは、パイプラインの実行時に Azure Key Vault からシークレットを直接取得できます。

variables:
  - group: 'kv-production-secrets'
  - group: 'build-settings'
  - name: buildConfiguration
    value: 'Release'

steps:
  - script: |
      echo "Building with configuration $(buildConfiguration)"
    displayName: 'Build'
    env:
      SQL_CONNECTION: $(sql-connection-string)  # from Key Vault
      API_KEY: $(api-key)                        # from Key Vault

Key Vault にリンクされた変数グループの設定方法:

  1. Pipelines > Library > Variable Groups > New variable group に移動します
  2. 「Link secrets from an Azure key vault as variables」を有効にします
  3. Azure サブスクリプション(サービス接続)と Key Vault を選択します
  4. 含めるシークレットを選択します
  5. シークレットはパイプラインの実行時に取得され、$(secret-name) として利用できます
変数グループの環境へのスコープ設定

パイプラインのステージに基づいて、条件付きで変数グループを参照します。

stages:
  - stage: DeployStaging
    variables:
      - group: 'staging-config'
      - group: 'kv-staging-secrets'
    jobs:
      - deployment: Deploy
        environment: 'staging'
        strategy:
          runOnce:
            deploy:
              steps:
                - script: echo "Deploying with staging config"
                  env:
                    CONNECTION_STRING: $(sql-connection-string)

  - stage: DeployProduction
    variables:
      - group: 'production-config'
      - group: 'kv-production-secrets'
    jobs:
      - deployment: Deploy
        environment: 'production'
        strategy:
          runOnce:
            deploy:
              steps:
                - script: echo "Deploying with production config"
                  env:
                    CONNECTION_STRING: $(sql-connection-string)
ライブラリ内のセキュアファイル

証明書、SSH キー、その他のバイナリ形式のシークレットを Pipelines Library に保存します。

- task: DownloadSecureFile@1
  displayName: 'Download signing certificate'
  name: signingCert
  inputs:
    secureFile: 'code-signing.pfx'

- script: |
    dotnet nuget sign ./nupkgs/*.nupkg \
      --certificate-path $(signingCert.secureFilePath) \
      --certificate-password $(CERT_PASSWORD) \
      --timestamper http://timestamp.digicert.com
  displayName: 'Sign NuGet packages'

パイプラインデコレーター

パイプラインデコレーターは、個々のパイプラインファイルを変更せずに、組織またはプロジェクト内のすべてのパイプラインにステップを挿入します。組織のポリシーを適用できます。

デコレーターのユースケース
ユースケース実装
必須のセキュリティスキャン各ジョブの前に認証情報スキャナーを挿入
コンプライアンス監査ログ各ジョブの後にテレメトリステップを挿入
必須のコード分析main ブランチのビルドで SonarQube 分析を挿入
ライセンスコンプライアンス依存関係のライセンススキャナーを挿入
デコレーターの定義

デコレーターは Azure DevOps 拡張機能としてパッケージ化されます。

# vss-extension.json (extension manifest)
{
  "contributions": [
    {
      "id": "required-security-scan",
      "type": "ms.azure-pipelines.pipeline-decorator",
      "targets": ["ms.azure-pipelines-agent-job"],
      "properties": {
        "template": "decorator.yml",
        "targetsExecutionOrder": "PreJob"
      }
    }
  ]
}
# decorator.yml
steps:
  - task: CredentialScanner@1
    displayName: '[Policy] Credential scan'
    condition: always()
デプロイの制限事項
  • デコレーターのインストールには、Azure DevOps 組織管理者の権限が必要です
  • 組織内(または選択したプロジェクト)のすべてのパイプラインに適用されます
  • パイプラインの作成者がデコレーターのステップを上書きしたり、スキップしたりすることはできません
  • デコレーターのステップは、パイプラインのエージェントプールとサービス接続のコンテキストで実行されます

Azure Artifacts Universal Packages

Universal Packages は、NuGet/npm/Maven 形式に限定されず、任意のファイル(バイナリ、ツール、データセット)を Azure Artifacts フィードに保存します。

Universal Package の発行
- task: UniversalPackages@0
  displayName: 'Publish universal package'
  inputs:
    command: 'publish'
    publishDirectory: '$(Build.ArtifactStagingDirectory)/tools'
    feedsToUsePublish: 'internal'
    vstsFeedPublish: 'MyProject/MyFeed'
    vstsFeedPackagePublish: 'my-dotnet-tool'
    versionOption: 'custom'
    versionPublish: '$(Build.BuildNumber)'
    packagePublishDescription: '.NET CLI tool binaries'
Universal Package のダウンロード
- task: UniversalPackages@0
  displayName: 'Download universal package'
  inputs:
    command: 'download'
    feedsToUse: 'internal'
    vstsFeed: 'MyProject/MyFeed'
    vstsFeedPackage: 'my-dotnet-tool'
    vstsPackageVersion: '*'
    downloadDirectory: '$(Pipeline.Workspace)/tools'
.NET プロジェクトでのユースケース
  • CLI ツールの配布: チーム間で利用する、自己完結型の .NET CLI ツールのバイナリを発行します
  • ビルドツールのキャッシュ: リポジトリ間で使用するカスタム MSBuild タスクやアナライザーを保存します
  • テストフィクスチャデータ: Git に保存すべきでない大規模なテストデータセットを発行します
  • AOT バイナリ: オンデマンドコンパイルが現実的でないプラットフォーム向けに、ビルド済みの Native AOT バイナリを配布します

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

  1. 環境チェック(承認、ゲート)は YAML ではなく UI で設定します -- YAML パイプラインでは環境名を参照します。すべてのチェックは Azure DevOps の Web UI で管理します。
  2. デプロイグループはレガシー機能です -- 新しいプロジェクトでは環境を使用してください。デプロイグループは、クラシックリリースパイプラインとの後方互換性のためだけに存在します。
  3. サービス接続のスコープが重要です -- リソースグループをスコープとする ARM 接続では、そのグループ外のリソースにデプロイできません。複数のリソースグループにまたがるデプロイには、サブスクリプションレベルのスコープを使用してください。
  4. サービスプリンシパルのシークレットより、ワークロード ID フェデレーションが推奨されます -- フェデレーション資格情報を使うとシークレットのローテーションが不要になります。新しい接続では自動フェデレーションを使用してください。
  5. Key Vault にリンクされた変数グループは、実行時にシークレットを取得します -- テンプレート式(${{ }})はコンパイル時に解決されるため、Key Vault のシークレットにアクセスできません。代わりに実行時式($())を使用してください。
  6. クラシックリリースパイプラインはソース管理に保存されません -- これが移行の主な動機です。YAML パイプラインを使うと、PR レビューやブランチごとの定義が可能になります。
  7. パイプラインデコレーターをパイプライン作成者が回避することはできません -- これはポリシーを適用するための意図的な仕様です。すべてのパイプラインを壊さないよう、別の組織またはプロジェクトでデコレーターの変更をテストしてください。
  8. ユニバーサルパッケージのファイルサイズ上限は 4 GiB です -- これより大きな成果物には、ファイルを分割するか、代わりに SAS トークンを使用して Azure Blob Storage を利用してください。

コメント