YouTrack

イシュー追跡プロジェクト管理チケット管理JetBrainsアジャイル開発DevOps

チケット管理ツール

YouTrack

概要

YouTrackは、JetBrains社が開発したエンタープライズレベルのプロジェクト管理・イシュー追跡ツールです。強力で柔軟なタスク管理コアを中心に、プロジェクトの進捗管理、チーム連携、ナレッジベース構築、顧客サポートまでを統合的に支援します。アジャイル開発チームはもちろん、HR、マーケティング、運用チームなど、様々な部門で活用されており、世界100,000社以上の企業で導入されています。

詳細

YouTrackは、複雑なプロジェクト管理ニーズに応えるため、高度な柔軟性とカスタマイズ性を提供する設計が特徴です。

主要な特徴

  • 強力なイシュー管理: 膨大な数のイシューと添付ファイルを効率的に処理
  • 高度なカスタマイズ: カスタムフィールド、ワークフロー、権限設定の柔軟な構成
  • アジャイル対応: Scrum、Kanbanボードプリセット、カスタムボード作成機能
  • 統合ナレッジベース: プロジェクト文書化、FAQ、技術仕様の一元管理
  • 詳細レポート機能: 20種類の設定可能レポートとパフォーマンス分析

技術仕様

  • アーキテクチャ: クラウド・オンプレミス両対応、スケーラブル設計
  • セキュリティ: エンタープライズグレードセキュリティ、LDAP/SSO統合
  • パフォーマンス: 大容量データ処理対応、高速検索エンジン
  • 拡張性: JetBrains Marketplace、REST API、カスタム統合

メリット・デメリット

メリット

  1. 優れたコストパフォーマンス

    • 10ユーザーまで完全無料
    • 有料プランも競合他社より割安(月額4.40ユーロ~)
  2. エンタープライズグレードの機能性

    • 大規模プロジェクト・チーム対応
    • 詳細な権限管理と監査機能
  3. 開発チーム特化の設計

    • JetBrains IDEとの深い統合
    • 開発ワークフローに最適化された機能
  4. 高度なクエリとフィルタリング

    • 強力な検索言語とカスタムクエリ
    • 複雑な条件での課題抽出

デメリット

  1. ユーザーインターフェースの課題

    • やや古いデザインと操作感
    • モダンなUIに慣れたユーザーには不親切
  2. 学習コストの高さ

    • 豊富な機能ゆえの複雑性
    • 初期設定とカスタマイズに専門知識が必要
  3. 限定的なモバイル対応

    • モバイルアプリの機能制約
    • レスポンシブデザインの改善余地

参考ページ

基本的な使い方

1. プロジェクト設定と初期構成

// YouTrack REST API を使用したプロジェクト作成
const createProject = async (projectData) => {
  const response = await fetch(`${YOUTRACK_URL}/api/admin/projects`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`,
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    },
    body: JSON.stringify({
      shortName: projectData.key,
      name: projectData.name,
      description: projectData.description,
      leader: {
        login: projectData.leadLogin
      },
      startingNumber: 1,
      template: {
        id: projectData.templateId || 'scrum-template'
      }
    })
  });
  
  const project = await response.json();
  
  // カスタムフィールド設定
  await setupCustomFields(project.shortName, projectData.customFields);
  
  return project;
};

const setupCustomFields = async (projectKey, customFields) => {
  for (const field of customFields) {
    await fetch(`${YOUTRACK_URL}/api/admin/projects/${projectKey}/customFields`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_TOKEN}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        field: {
          name: field.name,
          fieldType: {
            id: field.type // 'string', 'integer', 'date', 'enum[1]', etc.
          }
        },
        emptyFieldText: field.placeholder,
        canBeEmpty: field.optional || false,
        isPublic: field.public || true
      })
    });
  }
};

2. イシュー管理とワークフロー

// イシュー作成と詳細設定
const createIssue = async (projectKey, issueData) => {
  const issue = await fetch(`${YOUTRACK_URL}/api/issues`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      summary: issueData.title,
      description: issueData.description,
      project: { shortName: projectKey },
      customFields: [
        {
          name: 'Priority',
          value: { name: issueData.priority || 'Normal' }
        },
        {
          name: 'Type',
          value: { name: issueData.type || 'Task' }
        },
        {
          name: 'State',
          value: { name: issueData.status || 'Open' }
        },
        {
          name: 'Assignee',
          value: { login: issueData.assignee }
        },
        {
          name: 'Fix versions',
          value: [{ name: issueData.fixVersion }]
        }
      ]
    })
  });
  
  const createdIssue = await issue.json();
  
  // タグとラベル追加
  if (issueData.tags) {
    await addTags(createdIssue.idReadable, issueData.tags);
  }
  
  // 作業時間の見積もり設定
  if (issueData.estimation) {
    await setTimeEstimation(createdIssue.idReadable, issueData.estimation);
  }
  
  return createdIssue;
};

const addTags = async (issueId, tags) => {
  for (const tag of tags) {
    await fetch(`${YOUTRACK_URL}/api/issues/${issueId}/tags`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_TOKEN}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name: tag,
        color: { id: 0 } // デフォルト色
      })
    });
  }
};

3. アジャイルボードとスプリント管理

// Scrumボード設定とスプリント管理
const setupScrumBoard = async (projectKey, boardConfig) => {
  // アジャイルボード作成
  const board = await fetch(`${YOUTRACK_URL}/api/agiles`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: boardConfig.name,
      projects: [{ shortName: projectKey }],
      columnSettings: {
        columns: [
          { fieldValues: [{ name: 'Open' }], isResolved: false },
          { fieldValues: [{ name: 'In Progress' }], isResolved: false },
          { fieldValues: [{ name: 'In Review' }], isResolved: false },
          { fieldValues: [{ name: 'Done' }], isResolved: true }
        ]
      },
      sprintsSettings: {
        disableSprints: false,
        defaultSprint: null,
        explicitQuery: `project: ${projectKey} #Unresolved`,
        hideOrphansSwimlane: false
      }
    })
  });
  
  const createdBoard = await board.json();
  
  // スプリント作成
  const sprint = await createSprint(createdBoard.id, {
    name: boardConfig.sprintName,
    start: new Date().toISOString(),
    finish: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000).toISOString() // 2週間後
  });
  
  return { board: createdBoard, sprint };
};

const createSprint = async (boardId, sprintData) => {
  return await fetch(`${YOUTRACK_URL}/api/agiles/${boardId}/sprints`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      name: sprintData.name,
      start: sprintData.start,
      finish: sprintData.finish,
      goal: sprintData.goal || ''
    })
  });
};

4. レポートと分析機能

// バーンダウンチャートとベロシティレポート
const generateSprintReports = async (projectKey, sprintId) => {
  // バーンダウンデータ取得
  const burndownData = await fetch(
    `${YOUTRACK_URL}/api/reports/burndown?projects=${projectKey}&sprint=${sprintId}`,
    {
      headers: { 'Authorization': `Bearer ${API_TOKEN}` }
    }
  );
  
  // チームベロシティ計算
  const velocityData = await fetch(
    `${YOUTRACK_URL}/api/reports/timesheet?projects=${projectKey}&range=last-3-sprints`,
    {
      headers: { 'Authorization': `Bearer ${API_TOKEN}` }
    }
  );
  
  // カスタムレポート生成
  const customReport = await generateCustomReport(projectKey, {
    groupBy: 'Assignee',
    dateRange: 'current-sprint',
    fields: ['State', 'Priority', 'Type', 'Estimation']
  });
  
  return {
    burndown: await burndownData.json(),
    velocity: await velocityData.json(),
    customReport
  };
};

const generateCustomReport = async (projectKey, reportConfig) => {
  const query = `project: ${projectKey} #Unresolved`;
  
  const issues = await fetch(
    `${YOUTRACK_URL}/api/issues?query=${encodeURIComponent(query)}&fields=id,summary,customFields(name,value)`,
    {
      headers: { 'Authorization': `Bearer ${API_TOKEN}` }
    }
  );
  
  const issuesData = await issues.json();
  
  // レポートデータ集計
  const report = {
    totalIssues: issuesData.length,
    byAssignee: {},
    byPriority: {},
    totalEstimation: 0
  };
  
  issuesData.forEach(issue => {
    const assignee = issue.customFields.find(f => f.name === 'Assignee')?.value?.fullName || 'Unassigned';
    const priority = issue.customFields.find(f => f.name === 'Priority')?.value?.name || 'Normal';
    const estimation = issue.customFields.find(f => f.name === 'Estimation')?.value || 0;
    
    report.byAssignee[assignee] = (report.byAssignee[assignee] || 0) + 1;
    report.byPriority[priority] = (report.byPriority[priority] || 0) + 1;
    report.totalEstimation += estimation;
  });
  
  return report;
};

5. ナレッジベースと文書管理

// プロジェクトWikiとナレッジベース管理
const manageProjectWiki = async (projectKey, wikiData) => {
  // Wiki記事作成
  const createWikiArticle = async (articleData) => {
    return await fetch(`${YOUTRACK_URL}/api/articles`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_TOKEN}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        summary: articleData.title,
        content: articleData.content,
        project: { shortName: projectKey },
        parentArticle: articleData.parentId ? { id: articleData.parentId } : null,
        attachments: articleData.attachments || []
      })
    });
  };
  
  // FAQ記事作成
  const createFAQStructure = async () => {
    const faqRoot = await createWikiArticle({
      title: 'プロジェクト FAQ',
      content: '# よくある質問\n\nプロジェクトに関するよくある質問と回答をまとめています。'
    });
    
    const faqSections = [
      {
        title: '開発環境について',
        content: '## 開発環境セットアップ\n\n開発環境の構築手順と注意点について説明します。'
      },
      {
        title: 'デプロイメント手順',
        content: '## デプロイメント\n\n本番環境へのデプロイ手順とチェックリストです。'
      }
    ];
    
    for (const section of faqSections) {
      await createWikiArticle({
        ...section,
        parentId: faqRoot.id
      });
    }
    
    return faqRoot;
  };
  
  return {
    createWikiArticle,
    createFAQStructure
  };
};

6. 統合とワークフロー自動化

// JetBrains IDE統合とGit連携
const setupIntegrations = async (projectKey, integrationConfig) => {
  // Git統合設定
  const setupGitIntegration = async (repoConfig) => {
    return await fetch(`${YOUTRACK_URL}/api/admin/projects/${projectKey}/vcs`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_TOKEN}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name: repoConfig.name,
        url: repoConfig.url,
        defaultBranch: repoConfig.defaultBranch || 'main',
        usernameStyle: 'author_name',
        maxCommits: 200,
        commitMessageIssueIdPattern: repoConfig.pattern || '#${id}'
      })
    });
  };
  
  // Slack通知設定
  const setupSlackNotifications = async (webhookUrl) => {
    return await fetch(`${YOUTRACK_URL}/api/admin/projects/${projectKey}/notifications`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${API_TOKEN}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        name: 'Slack Notifications',
        type: 'webhook',
        url: webhookUrl,
        events: ['issue.created', 'issue.updated', 'issue.resolved'],
        filter: 'project: ' + projectKey,
        template: {
          message: 'Issue {{issue.id}}: {{issue.summary}} - {{issue.state}}'
        }
      })
    });
  };
  
  // カスタムワークフロー設定
  const setupCustomWorkflow = async (workflowRules) => {
    for (const rule of workflowRules) {
      await fetch(`${YOUTRACK_URL}/api/admin/projects/${projectKey}/workflow`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${API_TOKEN}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          name: rule.name,
          description: rule.description,
          trigger: rule.trigger,
          conditions: rule.conditions,
          actions: rule.actions,
          isEnabled: true
        })
      });
    }
  };
  
  return {
    setupGitIntegration,
    setupSlackNotifications,
    setupCustomWorkflow
  };
};

YouTrackは、特に開発チームのプロジェクト管理とイシュー追跡に特化した強力なツールです。JetBrains製品との深い統合により、開発ワークフローを効率化し、チーム全体の生産性向上を実現します。