「手動デプロイでミスが多発する」「テストを手で回すので時間がかかる」「リリースのたびに休日出勤になる」――こうした課題を解決するのがCI/CD(継続的インテグレーション/継続的デリバリー)です。
この記事では、Azure DevOpsを使ってCI/CDパイプラインを構築する方法を実践的に解説します。Pipelines、Repos、Artifactsの各サービスの使い方からYAMLによるパイプライン定義、本番環境へのデプロイ戦略までをカバーします。
Azure DevOpsとは?開発チームのためのオールインワンプラットフォーム
Azure DevOpsは、ソフトウェアの開発からデプロイ、運用までを一貫して管理できるMicrosoftのクラウドサービスです。複数の独立したサービスで構成されており、必要なものだけを選んで利用できます。
Azure DevOpsの主要サービス
- Azure Repos:GitベースのソースコードリポジトリとTFVC(集中管理型)のリポジトリ
- Azure Pipelines:ビルド、テスト、デプロイの自動化パイプライン
- Azure Boards:アジャイル開発のタスク管理・スプリント計画
- Azure Artifacts:NuGet、npm、Mavenなどのパッケージ管理フィード
- Azure Test Plans:手動テストと自動テストの管理
本記事では、CI/CDの中核となるPipelines、Repos、Artifactsに焦点を当てます。
CI/CDの基本概念
CI(継続的インテグレーション)は、開発者がコードをリポジトリにプッシュするたびに自動でビルドとテストを実行する仕組みです。バグを早期に発見し、統合の問題を防ぎます。
CD(継続的デリバリー/デプロイ)は、CIで検証されたコードを自動的にステージング環境や本番環境にデプロイする仕組みです。手動作業を排除し、リリースの頻度と品質を向上させます。
CI/CDを導入することで、「コードの変更からデプロイまで」の時間が数日から数分に短縮されます。
Azure Reposでソースコード管理を始める
CI/CDパイプラインの起点はソースコード管理です。Azure Reposは、Gitベースの信頼性の高いリポジトリサービスを提供します。
リポジトリの作成と基本操作
Azure DevOpsポータルでプロジェクトを作成すると、自動的にGitリポジトリが1つ作成されます。追加のリポジトリも自由に作成可能です。
基本的なGitワークフローは以下のとおりです。
1. リポジトリのクローン
git clone https://dev.azure.com/{組織名}/{プロジェクト名}/_git/{リポジトリ名}
2. ブランチの作成と開発
git checkout -b feature/add-login-api
# コードの変更
git add .
git commit -m "ログインAPIの実装"
git push origin feature/add-login-api
3. プルリクエストの作成
Azure DevOpsポータルからプルリクエストを作成し、コードレビューを実施します。
ブランチポリシーの設定
mainブランチを保護するために、ブランチポリシーを設定しましょう。重要な設定項目は以下のとおりです。
- 最小レビュアー数:プルリクエストに必要なレビュー承認数(推奨:1名以上)
- ビルド検証:プルリクエスト作成時にCIパイプラインを自動実行し、成功を必須とする
- コメント解決:すべてのレビューコメントが解決されるまでマージを禁止
- マージ戦略:Squash merge(コミットを1つにまとめる)を推奨
これらのポリシーにより、品質が担保されたコードのみがmainブランチに統合されます。
Azure PipelinesでCIパイプラインを構築する
Azure Pipelinesの核心部分です。YAML形式でパイプラインを定義し、コードとしてバージョン管理します。
YAMLパイプラインの基本構造
パイプラインの定義ファイル(azure-pipelines.yml)の基本構造を示します。
# azure-pipelines.yml
trigger:
branches:
include:
- main
- develop
pool:
vmImage: 'ubuntu-latest'
variables:
buildConfiguration: 'Release'
stages:
- stage: Build
displayName: 'ビルドとテスト'
jobs:
- job: BuildJob
steps:
- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '8.0.x'
- script: dotnet restore
displayName: 'パッケージの復元'
- script: dotnet build --configuration $(buildConfiguration)
displayName: 'ビルドの実行'
- script: dotnet test --configuration $(buildConfiguration) --logger trx
displayName: 'テストの実行'
- task: PublishTestResults@2
inputs:
testResultsFormat: 'VSTest'
testResultsFiles: '**/*.trx'
- task: PublishBuildArtifacts@1
inputs:
pathToPublish: '$(Build.ArtifactStagingDirectory)'
artifactName: 'drop'
この定義では、mainまたはdevelopブランチへのプッシュをトリガーに、ビルド→テスト→成果物の公開が自動実行されます。
主要なパイプライン要素
trigger:パイプラインの実行条件を定義します。ブランチ名、パス、タグによるフィルタリングが可能です。
pool:パイプラインを実行するエージェントプールを指定します。Microsoftホステッドエージェント(ubuntu-latest、windows-latest、macos-latest)を使うのが手軽です。
stages:パイプラインの大きな区切り。ビルド→テスト→デプロイのように段階を分けます。
jobs:ステージ内の実行単位。並列実行も可能です。
steps:ジョブ内の具体的な処理。タスク(task)またはスクリプト(script)で記述します。
変数とシークレット管理
パイプライン内で使用する変数は複数の方法で管理できます。
- YAMLファイル内の変数:バージョン管理対象。機密情報以外の設定値に使用
- パイプライン変数:Azure DevOpsポータルから設定。シークレットとしてマスク可能
- 変数グループ:複数のパイプラインで共有する変数セット。Azure Key Vaultとの連携も可能
データベースの接続文字列やAPIキーなどの機密情報は、必ずシークレット変数またはKey Vault連携を使用しましょう。YAMLファイルにハードコードするのは厳禁です。
CDパイプラインで自動デプロイを実現する
CIで検証されたアーティファクトを、ステージング環境や本番環境に自動デプロイするCDパイプラインを構築します。
マルチステージパイプラインの定義
ビルドからデプロイまでを一つのYAMLファイルで定義する例です。
stages:
- stage: Build
displayName: 'ビルド'
jobs:
- job: BuildJob
steps:
# ビルド処理(省略)
- stage: DeployStaging
displayName: 'ステージング環境へデプロイ'
dependsOn: Build
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: DeployToStaging
environment: 'staging'
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
inputs:
azureSubscription: 'MyAzureConnection'
appName: 'myapp-staging'
package: '$(Pipeline.Workspace)/drop/*.zip'
- stage: DeployProduction
displayName: '本番環境へデプロイ'
dependsOn: DeployStaging
condition: succeeded()
jobs:
- deployment: DeployToProduction
environment: 'production'
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
inputs:
azureSubscription: 'MyAzureConnection'
appName: 'myapp-production'
package: '$(Pipeline.Workspace)/drop/*.zip'
環境と承認ゲート
環境(Environments)は、デプロイ先を抽象化したリソースです。各環境に承認ゲートやチェックを設定することで、デプロイの安全性を高めます。
本番環境に設定すべきチェック:
- 手動承認:指定した承認者がAzure DevOpsポータルで承認するまでデプロイを待機
- ビジネスアワーチェック:営業時間内のみデプロイを許可
- ブランチ制御:mainブランチからのデプロイのみ許可
- 排他ロック:同時に複数のデプロイが実行されないように制御
ステージング環境では自動デプロイ、本番環境では手動承認後にデプロイ、という構成が多くの現場で採用されています。
デプロイ戦略
Azure Pipelinesでは以下のデプロイ戦略をサポートしています。
- runOnce:すべてのインスタンスに一括デプロイ。シンプルだがリスクが高い
- rolling:インスタンスを段階的に更新。VM環境で有効
- canary:一部のインスタンスにのみ先行デプロイし、問題がなければ全体に展開
App Serviceのデプロイスロットを活用すると、スワップ方式のブルーグリーンデプロイメントも実現できます。本番スロットに影響を与えず、ステージングスロットにデプロイしてから切り替える方法です。
Azure Artifactsでパッケージを管理する
Azure Artifactsは、チーム内で共有するパッケージ(ライブラリ)のプライベートフィードを提供するサービスです。
Artifactsの活用シーン
- 社内共通ライブラリの配布:複数プロジェクトで使用する共通コンポーネントをパッケージ化して共有
- バージョン管理:パッケージのバージョニングにより、依存関係の管理を正確に行う
- 上流ソースのキャッシュ:npmやNuGetの公式レジストリへのリクエストをキャッシュし、ビルド速度を向上
フィードの作成とパッケージの発行
フィードの作成はAzure DevOpsポータルのArtifactsセクションから行います。フィードのスコープはプロジェクト単位または組織単位で設定できます。
パイプラインからNuGetパッケージを発行する例です。
- task: NuGetCommand@2
inputs:
command: 'pack'
packagesToPack: '**/*.csproj'
versioningScheme: 'byBuildNumber'
- task: NuGetCommand@2
inputs:
command: 'push'
publishVstsFeed: 'MyProjectFeed'
allowPackageConflicts: true
npmパッケージの場合は以下のように記述します。
- task: Npm@1
inputs:
command: 'publish'
workingDir: '$(Build.SourcesDirectory)/packages/shared-lib'
publishRegistry: 'useFeed'
publishFeed: 'MyProjectFeed'
Artifactsフィードにはアップストリームソースを設定できます。これにより、npmjs.comやnuget.orgの公開パッケージとプライベートパッケージを単一のフィードから取得可能になります。
テスト自動化とコード品質の確保
CI/CDパイプラインの価値は、テスト自動化によるフィードバックの速さにあります。パイプライン内で様々なテストを実行し、品質を継続的に検証しましょう。
テストの種類とパイプラインでの実行
単体テスト(Unit Tests):
最も基本的なテストレイヤーです。CIパイプラインのビルドステージで毎回実行します。実行時間が短いため、フィードバックが速いのが特徴です。
統合テスト(Integration Tests):
データベースや外部APIとの連携を含むテストです。テスト用のデータベースをパイプライン内で立ち上げて実行します。Docker Composeとの組み合わせが効果的です。
E2Eテスト(End-to-End Tests):
ブラウザ操作を含むエンドツーエンドのテストです。PlaywrightやSeleniumを使用し、ステージング環境へのデプロイ後に実行します。
コード品質チェックの統合
テストに加え、以下の品質チェックもパイプラインに組み込みましょう。
- 静的コード分析:SonarCloudやSonarQubeとの連携で、コードの品質指標を自動計測
- セキュリティスキャン:依存パッケージの脆弱性チェック(npm audit、dotnet list package --vulnerable)
- コードカバレッジ:テストのカバレッジレポートを生成し、しきい値を下回ったらビルドを失敗させる
- リンターの実行:コーディング規約の自動チェック
これらの品質ゲートをプルリクエストのブランチポリシーと連携させることで、品質基準を満たさないコードのマージを自動的に防止できます。
CI/CDパイプラインの運用と最適化
パイプラインを構築した後は、継続的な運用改善が重要です。
パイプラインの実行時間の最適化
パイプラインの実行が遅いと、開発者のフィードバックループが長くなり、生産性が低下します。以下の手法で高速化しましょう。
- キャッシュの活用:パッケージの復元結果やビルド成果物をキャッシュして再利用する
- 並列実行:独立したテストスイートを複数のジョブに分割して並列実行する
- 条件付き実行:変更されたファイルに基づいて、影響のあるテストのみを実行する
- セルフホステッドエージェント:高スペックのマシンでビルドを実行する
キャッシュタスクの設定例です。
- task: Cache@2
inputs:
key: 'nuget | "$(Agent.OS)" | **/packages.lock.json'
restoreKeys: |
nuget | "$(Agent.OS)"
path: $(NUGET_PACKAGES)
displayName: 'NuGetパッケージキャッシュの復元'
テンプレートによるパイプラインの再利用
複数のプロジェクトで同じパイプライン構成を使う場合は、テンプレートを活用します。共通の処理をテンプレートファイルに切り出し、各プロジェクトのパイプラインから参照します。
# templates/dotnet-build.yml
parameters:
- name: buildConfiguration
default: 'Release'
steps:
- script: dotnet restore
displayName: 'パッケージの復元'
- script: dotnet build --configuration ${{ parameters.buildConfiguration }}
displayName: 'ビルドの実行'
- script: dotnet test --configuration ${{ parameters.buildConfiguration }}
displayName: 'テストの実行'
# azure-pipelines.yml(各プロジェクト)
stages:
- stage: Build
jobs:
- job: BuildJob
steps:
- template: templates/dotnet-build.yml
parameters:
buildConfiguration: 'Release'
監視とトラブルシューティング
パイプラインの健全性を維持するために、以下の点を定期的に確認しましょう。
- 成功率:パイプラインの成功率が低下していないか。目標は95%以上
- 実行時間:ビルド時間が徐々に長くなっていないか
- フレーキーテスト:結果が不安定なテスト(flaky tests)がないか
- エージェントの空き状況:キュー待ちが発生していないか
パイプラインの実行結果はAzure Monitorと連携して監視できます。デプロイ頻度やリードタイムをメトリクスとして追跡し、開発チームのパフォーマンスを可視化することも有効です。
CI/CDはAzure Well-Architected Frameworkの運用性における重要な柱です。インフラのコード化と合わせて導入することで、インフラからアプリケーションまで一貫した自動化が実現します。
関連記事
AWS CloudFrontでサイト高速化|CDN設定からキャッシュ戦略まで実践解説
AWS CloudWatchで監視・アラート設定|運用担当者のための実践ガイド
AWS CodePipelineでCI/CD構築|コード変更から本番デプロイまでの自動化
AWS Cost Explorerでコスト可視化|ムダを見つけて月額費用を削減する実践術
AWS ECS/Fargateでコンテナ運用|Docker→本番デプロイの実践ガイド
AWS IAMのベストプラクティス|最小権限の原則を実務で実装する方法
AWS RDSの実務ガイド|データベース構築・バックアップ・パフォーマンスチューニング
AWS S3の実務活用ガイド|バケット設計・アクセス制御・コスト最適化の実践