dotnet-ado-unique について
Azure DevOps Services を使う .NET チーム向けのスキルです。デプロイチェック、サービス接続、変数グループ、従来型リリースの移行など、Azure DevOps 固有の機能を扱います。
主な機能
- 01環境の承認とチェック
- 02デプロイグループと環境の選択・移行
- 03Azure、Docker Registry、NuGet のサービス接続
- 04従来型リリースから YAML への移行
- 05Key Vault 連携の変数グループとセキュアファイル
- 06組織全体のパイプラインデコレーター
活用シーン
- 01本番デプロイに承認と業務時間の制限を設定
- 02デプロイグループのワークロードを環境へ移行
- 03Azure、レジストリ、NuGet の認証を構成
- 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 で、環境配下のリソースとしてクラスターを登録してください。
デプロイグループから環境への移行
- 既存のデプロイグループ名に対応する環境を作成します
- 環境の「承認とチェック」で同じ承認ゲートを設定します
- クラシックリリースパイプラインのステージを、新しい環境を対象とする YAML
deploymentジョブに変換します - デプロイグループと同等の段階的なデプロイを行うには、
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"
移行チェックリスト
- 従来のリリースステージをすべて特定し、YAML ステージに対応付けます
- 環境変数を YAML の変数グループまたはテンプレートに変換します
- 従来の承認ゲートを環境チェックに置き換えます
- 成果物のソースを
download: currentまたはパイプラインリソースに変換します - タスクグループを YAML のステップまたはジョブのテンプレートに置き換えます
- 従来のリリースを廃止する前に、本番環境以外のブランチで 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 にリンクされた変数グループの設定方法:
- Pipelines > Library > Variable Groups > New variable group に移動します
- 「Link secrets from an Azure key vault as variables」を有効にします
- Azure サブスクリプション(サービス接続)と Key Vault を選択します
- 含めるシークレットを選択します
- シークレットはパイプラインの実行時に取得され、
$(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 バイナリを配布します
エージェントが注意すべき点
- 環境チェック(承認、ゲート)は YAML ではなく UI で設定します -- YAML パイプラインでは環境名を参照します。すべてのチェックは Azure DevOps の Web UI で管理します。
- デプロイグループはレガシー機能です -- 新しいプロジェクトでは環境を使用してください。デプロイグループは、クラシックリリースパイプラインとの後方互換性のためだけに存在します。
- サービス接続のスコープが重要です -- リソースグループをスコープとする ARM 接続では、そのグループ外のリソースにデプロイできません。複数のリソースグループにまたがるデプロイには、サブスクリプションレベルのスコープを使用してください。
- サービスプリンシパルのシークレットより、ワークロード ID フェデレーションが推奨されます -- フェデレーション資格情報を使うとシークレットのローテーションが不要になります。新しい接続では自動フェデレーションを使用してください。
- Key Vault にリンクされた変数グループは、実行時にシークレットを取得します -- テンプレート式(
${{ }})はコンパイル時に解決されるため、Key Vault のシークレットにアクセスできません。代わりに実行時式($())を使用してください。 - クラシックリリースパイプラインはソース管理に保存されません -- これが移行の主な動機です。YAML パイプラインを使うと、PR レビューやブランチごとの定義が可能になります。
- パイプラインデコレーターをパイプライン作成者が回避することはできません -- これはポリシーを適用するための意図的な仕様です。すべてのパイプラインを壊さないよう、別の組織またはプロジェクトでデコレーターの変更をテストしてください。
- ユニバーサルパッケージのファイルサイズ上限は 4 GiB です -- これより大きな成果物には、ファイルを分割するか、代わりに SAS トークンを使用して Azure Blob Storage を利用してください。