Azure DevOps

バージョン管理DevOpsMicrosoftGitTFVCCI/CDプロジェクト管理統合プラットフォーム

バージョン管理ツール

Azure DevOps

概要

Azure DevOpsは、Microsoftが提供する包括的なDevOpsプラットフォームで、バージョン管理からプロジェクト管理、CI/CD、テスト管理まで統合された開発ライフサイクル管理を実現します。旧称Visual Studio Team Services(VSTS)として知られ、GitとTeam Foundation Version Control(TFVC)の両方に対応。Microsoft エコシステム(Visual Studio、Office 365、Azure)との深い統合により、企業での.NET開発やWindows環境に最適化されています。クラウド版のAzure DevOps ServicesとオンプレミスのAzure DevOps Serverの両方を提供し、セキュリティと統制を重視する企業環境での採用が拡大しています。

詳細

Azure DevOps 2025年版は、3%のマーケットシェアでMicrosoft エコシステムの中核として重要な位置を占めています。旧Team Foundation Server(TFS)から進化し、現在ではクラウドファーストながらハイブリッド展開も可能な柔軟性を提供。Azure Repos(Git/TFVC)、Azure Pipelines(CI/CD)、Azure Boards(作業項目管理)、Azure Test Plans(テスト管理)、Azure Artifacts(パッケージ管理)の5つのサービスで構成されています。Microsoft Graph API統合によりOffice 365やTeamsとシームレス連携し、Azure Active Directory認証でエンタープライズセキュリティを確保します。

主な特徴

  • 統合DevOpsプラットフォーム: 企画からリリースまでの完全なライフサイクル管理
  • Git と TFVC 対応: 分散型と集中型両方のバージョン管理システム
  • Microsoft エコシステム統合: Visual Studio、Azure、Office 365との深い連携
  • 柔軟な展開オプション: クラウド、オンプレミス、ハイブリッド対応
  • エンタープライズセキュリティ: Azure AD認証と詳細なアクセス制御
  • 豊富なマーケットプレイス: サードパーティ拡張機能エコシステム

メリット・デメリット

メリット

  • 3%のマーケットシェアでMicrosoft エコシステムの中核として拡大
  • Office 365連携とAzure統合により企業での採用拡大
  • 統合プラットフォームによるツール切り替えコストの削減
  • Visual Studio、.NET開発環境との優れた親和性
  • エンタープライズレベルのセキュリティと コンプライアンス機能
  • 無料枠でも最大5ユーザーまでの充実した機能提供

デメリット

  • Microsoft 技術スタック以外での統合がサードパーティ依存
  • GitHub や GitLab と比較して GitHub Actions などの機能で後塵
  • オープンソースコミュニティでの採用は限定的
  • TFVC は新規投資が少なく Gitへの移行が推奨される状況
  • UI/UX がエンタープライズ向けで学習コストが高い
  • クラウド版での地理的制約やデータ主権の課題

参考ページ

書き方の例

Azure DevOps 初期設定とOrganization作成

# Azure DevOps CLI のインストール
# Windows (Chocolatey)
choco install azure-cli
az extension add --name azure-devops

# macOS (Homebrew)
brew install azure-cli
az extension add --name azure-devops

# Azure にログイン
az login

# DevOps Organization の設定
az devops configure --defaults organization=https://dev.azure.com/your-org
az devops configure --defaults project=your-project

# プロジェクトの作成
az devops project create --name "GameProject" --description "AAA Game Development"

# プロジェクト一覧
az devops project list

Git リポジトリ管理(Azure Repos)

# 新しいリポジトリの作成
az repos create --name "game-engine" --project GameProject

# リポジトリのクローン
git clone https://[email protected]/your-org/GameProject/_git/game-engine
cd game-engine

# Azure DevOps Git 認証設定
git config credential.helper manager
git config user.name "Developer Name"
git config user.email "[email protected]"

# Personal Access Token を使用した認証
# https://dev.azure.com/your-org/_usersSettings/tokens

# 基本的な Git ワークフロー
echo "# Game Engine" > README.md
git add README.md
git commit -m "Initial commit"
git push origin main

# ブランチ作成とプッシュ
git checkout -b feature/player-movement
echo "Player movement implementation" > PlayerController.cs
git add PlayerController.cs
git commit -m "Add player movement controller"
git push -u origin feature/player-movement

Pull Request とコードレビュー

# Pull Request の作成(CLI)
az repos pr create \
  --source-branch feature/player-movement \
  --target-branch main \
  --title "Implement player movement system" \
  --description "
## Overview
Implement basic player movement system with keyboard input

## Changes
- Add PlayerController class
- Implement movement input handling
- Add collision detection

## Testing
- Unit tests added for movement logic
- Manual testing on Windows and Mac
"

# Pull Request のリスト表示
az repos pr list --project GameProject

# Pull Request のレビュアー追加
az repos pr reviewer add --id 123 --reviewers "[email protected]"

# Pull Request の承認
az repos pr set-vote --id 123 --vote approve

# Pull Request の完了(マージ)
az repos pr update --id 123 --status completed

# ブランチポリシーの設定
az repos policy build create \
  --project GameProject \
  --repository-id $(az repos show --repository game-engine --query id -o tsv) \
  --branch main \
  --build-definition-id 1 \
  --display-name "Build validation" \
  --is-enabled true \
  --is-blocking true

CI/CD パイプライン(Azure Pipelines)

# azure-pipelines.yml - Unity ゲームプロジェクト
trigger:
  branches:
    include:
    - main
    - develop
    - feature/*

pool:
  vmImage: 'windows-latest'

variables:
  buildConfiguration: 'Release'
  unityVersion: '2023.2.5f1'

stages:
- stage: Build
  displayName: 'Build Stage'
  jobs:
  - job: BuildGame
    displayName: 'Build Unity Game'
    steps:
    - task: UnityGetProjectVersionV1@1
      displayName: 'Get Unity Version'

    - task: UnityActivateLicenseV1@1
      displayName: 'Activate Unity License'
      inputs:
        username: '$(UNITY_USERNAME)'
        password: '$(UNITY_PASSWORD)'
        serial: '$(UNITY_SERIAL)'

    - task: UnityBuildV1@3
      displayName: 'Build Unity Project'
      inputs:
        buildTarget: 'StandaloneWindows64'
        unityProjectPath: '$(Build.SourcesDirectory)'
        outputPath: '$(Build.ArtifactStagingDirectory)/Builds'

    - task: PublishBuildArtifacts@1
      displayName: 'Publish Build Artifacts'
      inputs:
        pathToPublish: '$(Build.ArtifactStagingDirectory)/Builds'
        artifactName: 'GameBuilds'

- stage: Test
  displayName: 'Test Stage'
  dependsOn: Build
  jobs:
  - job: UnitTests
    displayName: 'Run Unit Tests'
    steps:
    - task: UnityTestV1@2
      displayName: 'Run Unity Tests'
      inputs:
        testMode: 'EditMode'
        unityProjectPath: '$(Build.SourcesDirectory)'

    - task: PublishTestResults@2
      displayName: 'Publish Test Results'
      inputs:
        testResultsFormat: 'NUnit'
        testResultsFiles: '$(Build.SourcesDirectory)/TestResults/*.xml'

- stage: Deploy
  displayName: 'Deploy Stage'
  dependsOn: Test
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  jobs:
  - deployment: DeployToSteam
    displayName: 'Deploy to Steam'
    environment: 'Production'
    strategy:
      runOnce:
        deploy:
          steps:
          - task: DownloadBuildArtifacts@0
            inputs:
              buildType: 'current'
              downloadType: 'single'
              artifactName: 'GameBuilds'

          - task: SteamUpload@1
            displayName: 'Upload to Steam'
            inputs:
              steamUsername: '$(STEAM_USERNAME)'
              steamPassword: '$(STEAM_PASSWORD)'
              buildPath: '$(Pipeline.Workspace)/GameBuilds'
              appId: '$(STEAM_APP_ID)'

Azure Boards による作業項目管理

# Work Item の作成
az boards work-item create \
  --title "Implement character inventory system" \
  --type "User Story" \
  --description "As a player, I want to manage my character's inventory so that I can collect and use items." \
  --assigned-to "[email protected]" \
  --area-path "GameProject\Gameplay" \
  --iteration-path "GameProject\Sprint 1"

# バックログの確認
az boards work-item show --id 1234

# Work Item の更新
az boards work-item update --id 1234 --state "In Progress"

# クエリの実行
az boards query \
  --wiql "SELECT [System.Id], [System.Title], [System.State] FROM WorkItems WHERE [System.TeamProject] = 'GameProject' AND [System.State] = 'Active'"

# スプリントの管理
az boards iteration project list --project GameProject

Team Foundation Version Control (TFVC)

# TFVC ワークスペースの作成
tf workspace -new -collection:https://dev.azure.com/your-org -comment:"Development workspace" DevWorkspace

# ワークスペース設定
tf workfold -map "$/GameProject" "C:\Development\GameProject" -workspace:DevWorkspace

# ソースの取得
tf get C:\Development\GameProject -recursive

# ファイルのチェックアウト
tf checkout Assets/Scripts/PlayerController.cs

# 新しいファイルの追加
tf add Assets/Scripts/NewScript.cs

# 変更のチェックイン
tf checkin /comment:"Implement player movement system"

# 履歴の確認
tf history Assets/Scripts/PlayerController.cs -recursive

# ブランチの作成
tf branch $/GameProject/Main $/GameProject/Branches/Feature1

# マージ操作
tf merge $/GameProject/Branches/Feature1 $/GameProject/Main -recursive

Azure Test Plans によるテスト管理

# テストプランの作成
az boards work-item create \
  --title "Game Alpha Test Plan" \
  --type "Test Plan" \
  --description "Comprehensive testing for game alpha release"

# テストケースの作成
az boards work-item create \
  --title "Player Movement Test" \
  --type "Test Case" \
  --description "Verify player can move in all directions using WASD keys"

# テスト実行の作成
az test run create \
  --name "Alpha Build Test Run" \
  --plan-id 1001 \
  --build-id 20231201.1

Azure Artifacts によるパッケージ管理

# フィードの作成
az artifacts feed create --name "GameDevelopmentFeed" --description "Packages for game development"

# NuGet パッケージのアップロード
dotnet nuget push package.nupkg --source "GameDevelopmentFeed" --api-key $(System.AccessToken)

# npm パッケージのセットアップ
npm config set registry https://pkgs.dev.azure.com/your-org/_packaging/GameDevelopmentFeed/npm/registry/
npm config set //pkgs.dev.azure.com/your-org/_packaging/GameDevelopmentFeed/npm/registry/:_authToken $(System.AccessToken)

# パッケージのインストール
npm install @your-org/game-utilities

PowerShell による自動化

# Azure DevOps PowerShell モジュールのインストール
Install-Module -Name VSTeam -Force

# 接続設定
Set-VSTeamAccount -Account "https://dev.azure.com/your-org" -PersonalAccessToken $env:AZURE_DEVOPS_TOKEN

# プロジェクト情報の取得
Get-VSTeamProject

# ビルド定義の取得と実行
Get-VSTeamBuildDefinition -ProjectName "GameProject"
Add-VSTeamBuild -ProjectName "GameProject" -BuildDefinitionId 1

# Work Item のバルク操作
$workItems = Get-VSTeamWorkItem -Id 1,2,3,4,5
foreach ($item in $workItems) {
    Update-VSTeamWorkItem -Id $item.id -State "Closed"
}

# レポート生成
$builds = Get-VSTeamBuild -ProjectName "GameProject" -Top 10
$builds | Select-Object Id, BuildNumber, Status, QueueTime | Export-Csv -Path "build-report.csv"

API を使用した高度な統合

// C# での Azure DevOps REST API 使用例
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.WebApi;

public class AzureDevOpsClient
{
    private readonly WorkItemTrackingHttpClient _workItemClient;

    public AzureDevOpsClient(string organizationUrl, string personalAccessToken)
    {
        var connection = new VssConnection(
            new Uri(organizationUrl),
            new VssBasicCredential(string.Empty, personalAccessToken));
        
        _workItemClient = connection.GetClient<WorkItemTrackingHttpClient>();
    }

    public async Task<WorkItem> CreateBugAsync(string title, string description)
    {
        var document = new JsonPatchDocument
        {
            new JsonPatchOperation
            {
                Operation = Operation.Add,
                Path = "/fields/System.Title",
                Value = title
            },
            new JsonPatchOperation
            {
                Operation = Operation.Add,
                Path = "/fields/System.Description",
                Value = description
            }
        };

        return await _workItemClient.CreateWorkItemAsync(document, "GameProject", "Bug");
    }

    public async Task<List<WorkItem>> GetActiveUserStoriesAsync()
    {
        var wiql = new Wiql
        {
            Query = @"
                SELECT [System.Id], [System.Title], [System.State], [System.AssignedTo] 
                FROM WorkItems 
                WHERE [System.TeamProject] = 'GameProject' 
                AND [System.WorkItemType] = 'User Story' 
                AND [System.State] = 'Active'"
        };

        var result = await _workItemClient.QueryByWiqlAsync(wiql);
        var workItemIds = result.WorkItems.Select(wi => wi.Id).ToArray();
        
        return await _workItemClient.GetWorkItemsAsync(workItemIds);
    }
}

環境設定とベストプラクティス

# 開発環境の標準設定
# .gitconfig
[credential "https://dev.azure.com"]
    helper = manager

[user]
    name = Developer Name
    email = [email protected]

# Azure DevOps 拡張機能のインストール (Visual Studio Code)
code --install-extension ms-vscode.azure-account
code --install-extension ms-azure-devops.azure-pipelines

# チーム設定テンプレート (.azuredevops/team-settings.json)
{
  "workItemTypes": {
    "epic": { "color": "#FF7B00", "icon": "epic" },
    "feature": { "color": "#773B93", "icon": "feature" },
    "userStory": { "color": "#009CCC", "icon": "user-story" },
    "task": { "color": "#F2CB1D", "icon": "task" },
    "bug": { "color": "#CC293D", "icon": "bug" }
  },
  "boardSettings": {
    "columns": ["New", "Active", "Resolved", "Closed"],
    "swimlanes": ["Expedite", "Normal"],
    "cardFields": ["Assigned To", "Tags", "Effort"]
  }
}