feat: complete guide navigation and cross-links
- Add comprehensive navigation links between all guides - Include learning flow diagrams with visual progression - Update index.md with links to completed guides - Add Pull Request complete guide with advanced features - Add GitHub Projects V2 complete guide with Agile implementation - Implement consistent cross-navigation structure across all pages 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
403b24d50f
commit
b390552cf1
5 changed files with 1739 additions and 5 deletions
|
|
@ -410,4 +410,25 @@ GitHub リポジトリの基本機能をマスターすることで:
|
|||
✅ **リリース管理** - タグとリリース機能による体系的なバージョン管理
|
||||
✅ **セキュリティ** - 適切な設定による安全なコード管理
|
||||
|
||||
次は[Issue管理編](02-issues-management.md)で、プロジェクト管理の基礎を学習しましょう。
|
||||
## 🔗 関連ガイド
|
||||
|
||||
- **次のステップ**: [Issues管理編](02-issues-management.md) - プロジェクト管理の基礎
|
||||
- **さらに学習**: [Pull Request編](03-pull-requests.md) - コードレビューフロー
|
||||
- **プロジェクト管理**: [GitHub Projects編](04-github-projects.md) - アジャイル開発手法
|
||||
- **総合ガイド**: [GitHub完全活用ガイド](../GITHUB_COMPLETE_GUIDE.md) - 全機能の詳細解説
|
||||
|
||||
## 📖 学習フロー
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[リポジトリ基礎] --> B[Issues管理]
|
||||
B --> C[Pull Request]
|
||||
C --> D[GitHub Projects]
|
||||
D --> E[完全活用]
|
||||
|
||||
style A fill:#e1f5fe
|
||||
style B fill:#f3e5f5
|
||||
style C fill:#e8f5e8
|
||||
style D fill:#fff3e0
|
||||
style E fill:#fce4ec
|
||||
```
|
||||
|
|
@ -590,4 +590,27 @@ GitHub Issues を効果的に活用することで:
|
|||
✅ **コスト削減** - 有料ツールからの移行によるコスト最適化
|
||||
✅ **チーム協調** - 透明性の高い情報共有とコミュニケーション
|
||||
|
||||
## 🔗 関連ガイド
|
||||
|
||||
- **前のステップ**: [リポジトリ基礎編](01-repository-basics.md) - GitHub の基本操作
|
||||
- **次のステップ**: [Pull Request編](03-pull-requests.md) - コードレビューとマージプロセス
|
||||
- **さらに学習**: [GitHub Projects編](04-github-projects.md) - アジャイル開発プロジェクト管理
|
||||
- **総合ガイド**: [GitHub完全活用ガイド](../GITHUB_COMPLETE_GUIDE.md) - 全機能の詳細解説
|
||||
|
||||
## 📖 学習フロー
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[リポジトリ基礎] --> B[Issues管理]
|
||||
B --> C[Pull Request]
|
||||
C --> D[GitHub Projects]
|
||||
D --> E[完全活用]
|
||||
|
||||
style A fill:#f3e5f5
|
||||
style B fill:#e1f5fe
|
||||
style C fill:#e8f5e8
|
||||
style D fill:#fff3e0
|
||||
style E fill:#fce4ec
|
||||
```
|
||||
|
||||
次は[Pull Request編](03-pull-requests.md)で、コードレビューとマージプロセスを学習しましょう。
|
||||
934
features/03-pull-requests.md
Normal file
934
features/03-pull-requests.md
Normal file
|
|
@ -0,0 +1,934 @@
|
|||
---
|
||||
layout: default
|
||||
title: "Pull Request完全ガイド"
|
||||
description: "効率的なコードレビューフローとPull Request最適化の完全解説"
|
||||
---
|
||||
|
||||
# 🔄 Pull Request - 効率的なコードレビューフロー
|
||||
|
||||
GitHubのPull Request機能を最大限活用して、高品質なコード開発とチーム協調を実現する完全ガイド。外部ツールに依存せず、GitHub標準機能のみで企業レベルのコードレビュープロセスを構築します。
|
||||
|
||||
## 🎯 学習目標
|
||||
|
||||
- Pull Requestワークフローの完全理解と最適化
|
||||
- 効率的なコードレビュープロセスの構築
|
||||
- Draft PR、Suggested Changes等の高度機能活用
|
||||
- 自動化による品質向上とレビュー効率化
|
||||
- 外部ツール(GitLab MR、Bitbucket PR等)との比較理解
|
||||
|
||||
## 📚 目次
|
||||
|
||||
1. [Pull Request基本ワークフロー](#1-pull-request基本ワークフロー)
|
||||
2. [効果的なPR作成方法](#2-効果的なpr作成方法)
|
||||
3. [コードレビューのベストプラクティス](#3-コードレビューのベストプラクティス)
|
||||
4. [高度なPR機能活用](#4-高度なpr機能活用)
|
||||
5. [自動化とCI/CD連携](#5-自動化とcicd連携)
|
||||
6. [外部ツールとの比較](#6-外部ツールとの比較)
|
||||
|
||||
---
|
||||
|
||||
## 1. Pull Request基本ワークフロー
|
||||
|
||||
### 🌊 GitHub Flowによる開発プロセス
|
||||
|
||||
#### 理想的なPRライフサイクル
|
||||
```mermaid
|
||||
graph LR
|
||||
A[Issue作成] --> B[ブランチ作成]
|
||||
B --> C[コード実装]
|
||||
C --> D[Draft PR作成]
|
||||
D --> E[CI/CD実行]
|
||||
E --> F[レビュー依頼]
|
||||
F --> G[コードレビュー]
|
||||
G --> H[修正対応]
|
||||
H --> I[承認]
|
||||
I --> J[マージ]
|
||||
J --> K[ブランチ削除]
|
||||
K --> L[デプロイ]
|
||||
```
|
||||
|
||||
#### 基本的なPR作成手順
|
||||
|
||||
**1. 機能ブランチの作成**
|
||||
```bash
|
||||
# メインブランチから最新を取得
|
||||
git checkout main
|
||||
git pull origin main
|
||||
|
||||
# 機能ブランチを作成
|
||||
git checkout -b feature/user-authentication
|
||||
|
||||
# または GitHub CLI で
|
||||
gh repo fork --clone
|
||||
git checkout -b feature/user-authentication
|
||||
```
|
||||
|
||||
**2. 実装とコミット**
|
||||
```bash
|
||||
# 変更を実装
|
||||
# ... コーディング ...
|
||||
|
||||
# ステージングとコミット
|
||||
git add .
|
||||
git commit -m "feat(auth): implement user login functionality
|
||||
|
||||
- Add login form component
|
||||
- Implement JWT authentication
|
||||
- Add password validation
|
||||
- Update user state management
|
||||
|
||||
Closes #123"
|
||||
|
||||
# リモートにプッシュ
|
||||
git push origin feature/user-authentication
|
||||
```
|
||||
|
||||
**3. Pull Request作成**
|
||||
```bash
|
||||
# GitHub CLI でPR作成
|
||||
gh pr create \
|
||||
--title "feat: User authentication system" \
|
||||
--body-file .github/pull_request_template.md \
|
||||
--assignee @me \
|
||||
--reviewer team-lead,senior-dev \
|
||||
--label "enhancement,frontend"
|
||||
|
||||
# または Web UI で作成
|
||||
# https://github.com/username/repo/compare/main...feature/user-authentication
|
||||
```
|
||||
|
||||
### 📋 効果的なPRタイトルとコミットメッセージ
|
||||
|
||||
#### Conventional Commits準拠の形式
|
||||
```bash
|
||||
# タイプ別の例
|
||||
feat(auth): add two-factor authentication support
|
||||
fix(api): resolve timeout issue in user endpoint
|
||||
docs(readme): update installation instructions
|
||||
style(css): improve responsive design for mobile
|
||||
refactor(utils): simplify date formatting functions
|
||||
test(auth): add comprehensive login flow tests
|
||||
chore(deps): update dependencies to latest versions
|
||||
ci(actions): optimize build performance
|
||||
```
|
||||
|
||||
#### 詳細なコミットメッセージテンプレート
|
||||
```
|
||||
<type>(<scope>): <short description>
|
||||
|
||||
<detailed description explaining the why and what>
|
||||
|
||||
Breaking Changes:
|
||||
- List any breaking changes
|
||||
|
||||
Closes: #123, #456
|
||||
Related: #789
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 効果的なPR作成方法
|
||||
|
||||
### 📝 PRテンプレートの活用
|
||||
|
||||
#### 包括的なPRテンプレート
|
||||
```markdown
|
||||
## 📋 変更内容の要約
|
||||
<!-- このPRで何を変更したかを簡潔に説明 -->
|
||||
|
||||
## 🎯 関連Issue・タスク
|
||||
Fixes #(issue番号)
|
||||
Closes #(issue番号)
|
||||
Related to #(issue番号)
|
||||
|
||||
## 🔄 変更の種類
|
||||
- [ ] 🐛 バグ修正
|
||||
- [ ] ✨ 新機能
|
||||
- [ ] 💥 破壊的変更
|
||||
- [ ] 📚 ドキュメント更新
|
||||
- [ ] 🎨 スタイル改善(機能に影響なし)
|
||||
- [ ] ♻️ リファクタリング
|
||||
- [ ] ⚡ パフォーマンス改善
|
||||
- [ ] ✅ テスト追加・修正
|
||||
- [ ] 🔧 設定・ビルドシステム変更
|
||||
|
||||
## 🧪 テスト方法
|
||||
<!-- この変更をどのようにテストしたか -->
|
||||
|
||||
### 手動テスト手順
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
### 自動テスト
|
||||
- [ ] 単体テスト追加・更新
|
||||
- [ ] 統合テスト追加・更新
|
||||
- [ ] E2Eテスト追加・更新
|
||||
- [ ] 既存テストがすべて通ることを確認
|
||||
|
||||
## 📸 スクリーンショット・デモ
|
||||
<!-- UIに変更がある場合 -->
|
||||
|
||||
| Before | After |
|
||||
|--------|-------|
|
||||
| | |
|
||||
|
||||
## 🔍 レビュー観点
|
||||
<!-- レビュアーに特に見てほしいポイント -->
|
||||
|
||||
### 重点確認項目
|
||||
- [ ] 機能要件を満たしているか
|
||||
- [ ] エラーハンドリングが適切か
|
||||
- [ ] パフォーマンスへの影響はないか
|
||||
- [ ] セキュリティ面で問題ないか
|
||||
|
||||
## ✅ 作成者チェックリスト
|
||||
- [ ] コードが自己文書化されている
|
||||
- [ ] 適切なコメントが追加されている
|
||||
- [ ] ドキュメントが更新されている
|
||||
- [ ] テストカバレッジが十分
|
||||
- [ ] 破壊的変更がある場合、CHANGELOGに記載
|
||||
- [ ] セキュリティの観点で問題がない
|
||||
- [ ] モバイル・レスポンシブ対応確認済み
|
||||
|
||||
## 📝 その他・備考
|
||||
<!-- その他、レビュアーが知っておくべき情報 -->
|
||||
```
|
||||
|
||||
### 🎨 Draft PRの効果的活用
|
||||
|
||||
#### Draft PRの使用場面
|
||||
```bash
|
||||
# 作業進行中のフィードバック取得
|
||||
gh pr create --draft \
|
||||
--title "WIP: User authentication system" \
|
||||
--body "作業中のコードです。アプローチについてフィードバックをお願いします"
|
||||
|
||||
# 設計相談・アーキテクチャレビュー用
|
||||
gh pr create --draft \
|
||||
--title "RFC: New API architecture proposal" \
|
||||
--body "新しいAPI設計について議論したく、Draft PRを作成しました"
|
||||
|
||||
# CI/CDテスト用
|
||||
gh pr create --draft \
|
||||
--title "Test: CI pipeline validation" \
|
||||
--body "新しいワークフローのテスト用Draft PR"
|
||||
```
|
||||
|
||||
#### Draft → Ready フロー
|
||||
```bash
|
||||
# レビュー準備完了時
|
||||
gh pr ready
|
||||
|
||||
# またはWeb UIで「Ready for review」ボタンをクリック
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. コードレビューのベストプラクティス
|
||||
|
||||
### 👥 効果的なレビュープロセス
|
||||
|
||||
#### レビュアーの責務
|
||||
```markdown
|
||||
### 🔍 確認観点チェックリスト
|
||||
|
||||
#### 機能性・要件
|
||||
- [ ] 要件仕様を満たしているか
|
||||
- [ ] ユーザーストーリーの受け入れ条件をクリアしているか
|
||||
- [ ] エッジケースが考慮されているか
|
||||
- [ ] エラーハンドリングが適切か
|
||||
|
||||
#### コード品質
|
||||
- [ ] 可読性:命名規則、コメント、構造
|
||||
- [ ] 保守性:モジュール化、再利用性
|
||||
- [ ] DRY原則:重複コードの排除
|
||||
- [ ] SOLID原則:設計原則の遵守
|
||||
|
||||
#### パフォーマンス
|
||||
- [ ] 不要な処理・ループがないか
|
||||
- [ ] メモリ使用量は適切か
|
||||
- [ ] データベースクエリは最適化されているか
|
||||
- [ ] キャッシュ戦略は適切か
|
||||
|
||||
#### セキュリティ
|
||||
- [ ] 入力値検証が適切か
|
||||
- [ ] 認証・認可が正しく実装されているか
|
||||
- [ ] 機密情報の漏洩リスクはないか
|
||||
- [ ] SQLインジェクション等の脆弱性対策
|
||||
|
||||
#### テスト
|
||||
- [ ] テストカバレッジは十分か
|
||||
- [ ] テストケースは適切か
|
||||
- [ ] モックの使用は適切か
|
||||
- [ ] エッジケースのテストがあるか
|
||||
```
|
||||
|
||||
#### 建設的なレビューコメント例
|
||||
```markdown
|
||||
# ❌ 避けるべきコメント
|
||||
これはダメです。
|
||||
|
||||
# ✅ 建設的なコメント
|
||||
この実装だと、将来的にスケールした際にパフォーマンス問題が発生する可能性があります。
|
||||
以下のような改善案はいかがでしょうか?
|
||||
|
||||
```suggestion
|
||||
// パフォーマンス改善案
|
||||
const memoizedResult = useMemo(() => {
|
||||
return expensiveCalculation(data);
|
||||
}, [data]);
|
||||
```
|
||||
|
||||
### 🎯 Suggested Changes機能の活用
|
||||
|
||||
#### 具体的な修正提案
|
||||
```markdown
|
||||
# レビューコメントで具体的な修正案を提示
|
||||
|
||||
```suggestion
|
||||
// 修正前
|
||||
const user = users.find(u => u.id === userId);
|
||||
if (user) {
|
||||
return user.name;
|
||||
}
|
||||
return null;
|
||||
|
||||
// 修正後:Optional chainingとNullish coalescingを使用
|
||||
return users.find(u => u.id === userId)?.name ?? null;
|
||||
```
|
||||
|
||||
この修正により、コードがより簡潔で読みやすくなります。
|
||||
```
|
||||
|
||||
#### 複数行の修正提案
|
||||
```markdown
|
||||
```suggestion
|
||||
const validateUser = (userData) => {
|
||||
// バリデーションロジックの改善
|
||||
const errors = {};
|
||||
|
||||
if (!userData.email || !isValidEmail(userData.email)) {
|
||||
errors.email = 'Valid email is required';
|
||||
}
|
||||
|
||||
if (!userData.password || userData.password.length < 8) {
|
||||
errors.password = 'Password must be at least 8 characters';
|
||||
}
|
||||
|
||||
return {
|
||||
isValid: Object.keys(errors).length === 0,
|
||||
errors
|
||||
};
|
||||
};
|
||||
```
|
||||
```
|
||||
|
||||
### 📊 レビュー効率化
|
||||
|
||||
#### レビュー自動化設定
|
||||
```yaml
|
||||
# .github/CODEOWNERS
|
||||
# レビュー担当者の自動アサイン
|
||||
|
||||
# デフォルト
|
||||
* @team-lead @senior-developer
|
||||
|
||||
# フロントエンド
|
||||
/src/components/ @frontend-team @ui-specialist
|
||||
/src/styles/ @frontend-team
|
||||
|
||||
# バックエンド
|
||||
/api/ @backend-team @architecture-lead
|
||||
/database/ @backend-team @database-specialist
|
||||
|
||||
# セキュリティ関連
|
||||
/auth/ @security-team @team-lead
|
||||
/encryption/ @security-team
|
||||
|
||||
# インフラ・DevOps
|
||||
/.github/ @devops-team
|
||||
/docker/ @devops-team
|
||||
/kubernetes/ @devops-team
|
||||
|
||||
# ドキュメント
|
||||
/docs/ @tech-writer @team-lead
|
||||
README.md @tech-writer
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 高度なPR機能活用
|
||||
|
||||
### 🔄 マージ戦略の選択
|
||||
|
||||
#### マージオプションの使い分け
|
||||
```bash
|
||||
# 1. Merge commit(履歴を保持)
|
||||
gh pr merge --merge
|
||||
|
||||
# 2. Squash and merge(履歴を整理)
|
||||
gh pr merge --squash
|
||||
|
||||
# 3. Rebase and merge(リニア履歴)
|
||||
gh pr merge --rebase
|
||||
```
|
||||
|
||||
#### 推奨マージ戦略
|
||||
```markdown
|
||||
### プロジェクト規模別の推奨方法
|
||||
|
||||
#### 小〜中規模プロジェクト
|
||||
- **Squash and merge** を推奨
|
||||
- 機能単位でのクリーンな履歴
|
||||
- 簡潔なcommit message
|
||||
|
||||
#### 大規模プロジェクト
|
||||
- **Merge commit** を推奨
|
||||
- 詳細な作業履歴の保持
|
||||
- リバート時の容易性
|
||||
|
||||
#### オープンソース
|
||||
- **Rebase and merge** を推奨
|
||||
- リニアで美しい履歴
|
||||
- Bisectの効率性
|
||||
```
|
||||
|
||||
### 🔒 ブランチ保護ルール
|
||||
|
||||
#### 推奨保護設定
|
||||
```markdown
|
||||
### main ブランチ保護ルール
|
||||
|
||||
#### 基本設定
|
||||
- ✅ Require a pull request before merging
|
||||
- ✅ Require approvals: 2人以上(チーム規模に応じて調整)
|
||||
- ✅ Dismiss stale PR approvals when new commits are pushed
|
||||
- ✅ Require review from code owners
|
||||
|
||||
#### ステータスチェック
|
||||
- ✅ Require status checks to pass before merging
|
||||
- ✅ Require branches to be up to date before merging
|
||||
- 必須チェック項目:
|
||||
- continuous-integration/github-actions
|
||||
- security/code-scanning
|
||||
- testing/unit-tests
|
||||
- testing/e2e-tests
|
||||
|
||||
#### 高度な設定
|
||||
- ✅ Require conversation resolution before merging
|
||||
- ✅ Require linear history(必要に応じて)
|
||||
- ✅ Include administrators(管理者も同様のルールに従う)
|
||||
- ❌ Allow force pushes
|
||||
- ❌ Allow deletions
|
||||
```
|
||||
|
||||
### 🚀 プルリクエスト自動化
|
||||
|
||||
#### 自動ラベリング
|
||||
```yaml
|
||||
# .github/workflows/pr-labeler.yml
|
||||
name: PR Labeler
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, edited, synchronize]
|
||||
|
||||
jobs:
|
||||
label:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v4
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
configuration-path: .github/labeler.yml
|
||||
```
|
||||
|
||||
```yaml
|
||||
# .github/labeler.yml
|
||||
"area:frontend":
|
||||
- "src/components/**/*"
|
||||
- "src/pages/**/*"
|
||||
- "**/*.vue"
|
||||
- "**/*.jsx"
|
||||
|
||||
"area:backend":
|
||||
- "api/**/*"
|
||||
- "server/**/*"
|
||||
- "**/*.py"
|
||||
- "**/*.go"
|
||||
|
||||
"area:database":
|
||||
- "migrations/**/*"
|
||||
- "**/*.sql"
|
||||
- "database/**/*"
|
||||
|
||||
"size:small":
|
||||
- any: ['**/*']
|
||||
count-within: 1..10
|
||||
|
||||
"size:medium":
|
||||
- any: ['**/*']
|
||||
count-within: 11..50
|
||||
|
||||
"size:large":
|
||||
- any: ['**/*']
|
||||
count-within: 51..
|
||||
```
|
||||
|
||||
#### レビュアー自動アサイン
|
||||
```yaml
|
||||
# .github/workflows/assign-reviewers.yml
|
||||
name: Auto Assign Reviewers
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, ready_for_review]
|
||||
|
||||
jobs:
|
||||
assign:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
const files = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number
|
||||
});
|
||||
|
||||
let reviewers = [];
|
||||
const fileNames = files.data.map(f => f.filename);
|
||||
|
||||
// ファイルパスベースでレビュアー決定
|
||||
if (fileNames.some(f => f.includes('frontend'))) {
|
||||
reviewers.push('frontend-lead');
|
||||
}
|
||||
if (fileNames.some(f => f.includes('backend'))) {
|
||||
reviewers.push('backend-lead');
|
||||
}
|
||||
if (fileNames.some(f => f.includes('security'))) {
|
||||
reviewers.push('security-team');
|
||||
}
|
||||
|
||||
if (reviewers.length > 0) {
|
||||
await github.rest.pulls.requestReviewers({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number,
|
||||
reviewers: reviewers
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 自動化とCI/CD連携
|
||||
|
||||
### ⚡ GitHub Actions との統合
|
||||
|
||||
#### 包括的なPRチェックワークフロー
|
||||
```yaml
|
||||
# .github/workflows/pr-checks.yml
|
||||
name: PR Quality Checks
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main, develop]
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
jobs:
|
||||
code-quality:
|
||||
name: Code Quality
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '18'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Lint check
|
||||
run: npm run lint
|
||||
|
||||
- name: Type check
|
||||
run: npm run type-check
|
||||
|
||||
- name: Format check
|
||||
run: npm run format:check
|
||||
|
||||
security-scan:
|
||||
name: Security Scan
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
scan-type: 'fs'
|
||||
scan-ref: '.'
|
||||
format: 'sarif'
|
||||
output: 'trivy-results.sarif'
|
||||
|
||||
- name: Upload Trivy scan results
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: 'trivy-results.sarif'
|
||||
|
||||
test:
|
||||
name: Test Suite
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [16, 18, 20]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run tests
|
||||
run: npm run test:coverage
|
||||
|
||||
- name: Upload coverage reports
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
e2e-test:
|
||||
name: E2E Tests
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '18'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Install Playwright
|
||||
run: npx playwright install --with-deps
|
||||
|
||||
- name: Run E2E tests
|
||||
run: npm run test:e2e
|
||||
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v3
|
||||
if: failure()
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
|
||||
performance:
|
||||
name: Performance Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '18'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Build project
|
||||
run: npm run build
|
||||
|
||||
- name: Run Lighthouse CI
|
||||
uses: treosh/lighthouse-ci-action@v9
|
||||
with:
|
||||
configPath: './lighthouserc.js'
|
||||
uploadArtifacts: true
|
||||
temporaryPublicStorage: true
|
||||
```
|
||||
|
||||
### 📊 PR品質メトリクス
|
||||
|
||||
#### 自動品質レポート生成
|
||||
```yaml
|
||||
# .github/workflows/pr-metrics.yml
|
||||
name: PR Metrics
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
jobs:
|
||||
metrics:
|
||||
if: github.event.pull_request.merged == true
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Calculate PR metrics
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
|
||||
// PR統計の計算
|
||||
const createdAt = new Date(pr.created_at);
|
||||
const mergedAt = new Date(pr.merged_at);
|
||||
const timeTaken = (mergedAt - createdAt) / (1000 * 60 * 60); // 時間
|
||||
|
||||
// ファイル変更数の取得
|
||||
const files = await github.rest.pulls.listFiles({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: pr.number
|
||||
});
|
||||
|
||||
const stats = {
|
||||
prNumber: pr.number,
|
||||
title: pr.title,
|
||||
author: pr.user.login,
|
||||
timeToMerge: timeTaken.toFixed(2),
|
||||
filesChanged: files.data.length,
|
||||
additions: pr.additions,
|
||||
deletions: pr.deletions,
|
||||
reviewers: pr.requested_reviewers.map(r => r.login),
|
||||
comments: pr.review_comments + pr.comments
|
||||
};
|
||||
|
||||
// 統計をIssueコメントに投稿
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: pr.number,
|
||||
body: `## 📊 PR Statistics
|
||||
|
||||
- **⏱️ Time to merge**: ${stats.timeToMerge} hours
|
||||
- **📁 Files changed**: ${stats.filesChanged}
|
||||
- **➕ Additions**: ${stats.additions}
|
||||
- **➖ Deletions**: ${stats.deletions}
|
||||
- **💬 Comments**: ${stats.comments}
|
||||
- **👥 Reviewers**: ${stats.reviewers.join(', ') || 'None'}
|
||||
|
||||
Thanks @${stats.author} for the contribution! 🎉`
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 外部ツールとの比較
|
||||
|
||||
### 📊 機能比較マトリックス
|
||||
|
||||
| 機能 | GitHub PR | GitLab MR | Bitbucket PR | Azure DevOps | 備考 |
|
||||
|------|-----------|-----------|--------------|--------------|------|
|
||||
| **基本PR機能** | ✅ | ✅ | ✅ | ✅ | 全て対応 |
|
||||
| **Draft PR** | ✅ | ✅ | ❌ | ✅ | Bitbucketは部分対応 |
|
||||
| **Suggested Changes** | ✅ | ✅ | ❌ | ⚠️ | GitHubが最も使いやすい |
|
||||
| **自動マージ** | ✅ | ✅ | ✅ | ✅ | 条件設定の柔軟性はGitHubが優秀 |
|
||||
| **ブランチ保護** | ✅ | ✅ | ✅ | ✅ | 設定の詳細度はGitHubが最高 |
|
||||
| **レビュアー自動アサイン** | ✅ | ✅ | ✅ | ✅ | CODEOWNERS機能 |
|
||||
| **CI/CD統合** | ✅ | ✅ | ✅ | ✅ | Actions統合はシームレス |
|
||||
| **コメント機能** | ✅ | ✅ | ✅ | ✅ | GitHub が最も直感的 |
|
||||
| **モバイル対応** | ✅ | ⚠️ | ⚠️ | ⚠️ | GitHubモバイルアプリが優秀 |
|
||||
| **API充実度** | ✅ | ✅ | ⚠️ | ✅ | GitHub REST/GraphQL API |
|
||||
|
||||
### 🔄 GitLab からの移行
|
||||
|
||||
#### 主要な差分と移行方法
|
||||
|
||||
**GitLab MR → GitHub PR 移行マッピング**
|
||||
```markdown
|
||||
### 機能対応表
|
||||
|
||||
| GitLab MR | GitHub PR | 移行方法 |
|
||||
|-----------|-----------|----------|
|
||||
| Merge Request | Pull Request | 1:1対応 |
|
||||
| Draft MR | Draft PR | 機能同等 |
|
||||
| WIP: タイトル | Draft PR | Draftフラグ使用 |
|
||||
| Approval Rules | Branch Protection | 保護ルールで設定 |
|
||||
| Merge Trains | Auto-merge | キューイング機能 |
|
||||
| Squash Commits | Squash and merge | マージオプション |
|
||||
| Cherry-pick | GitHub CLI | `gh pr checkout` + `git cherry-pick` |
|
||||
```
|
||||
|
||||
#### 移行スクリプト例
|
||||
```python
|
||||
# gitlab_to_github_pr_migration.py
|
||||
import requests
|
||||
import json
|
||||
|
||||
class GitLabToGitHubMigrator:
|
||||
def __init__(self, gitlab_token, github_token, gitlab_project_id, github_repo):
|
||||
self.gitlab_token = gitlab_token
|
||||
self.github_token = github_token
|
||||
self.gitlab_project_id = gitlab_project_id
|
||||
self.github_repo = github_repo
|
||||
|
||||
def migrate_merge_requests(self):
|
||||
# GitLab MRsを取得
|
||||
gitlab_mrs = self.fetch_gitlab_mrs()
|
||||
|
||||
for mr in gitlab_mrs:
|
||||
if mr['state'] == 'merged':
|
||||
# マージ済みMRの情報を記録
|
||||
self.record_merged_mr(mr)
|
||||
elif mr['state'] == 'opened':
|
||||
# オープンMRをGitHub PRとして再作成
|
||||
self.create_github_pr(mr)
|
||||
|
||||
def create_github_pr(self, gitlab_mr):
|
||||
github_pr_data = {
|
||||
'title': gitlab_mr['title'],
|
||||
'head': gitlab_mr['source_branch'],
|
||||
'base': gitlab_mr['target_branch'],
|
||||
'body': self.convert_description(gitlab_mr['description']),
|
||||
'draft': gitlab_mr['work_in_progress']
|
||||
}
|
||||
|
||||
# GitHub API でPR作成
|
||||
response = requests.post(
|
||||
f"https://api.github.com/repos/{self.github_repo}/pulls",
|
||||
headers={"Authorization": f"token {self.github_token}"},
|
||||
json=github_pr_data
|
||||
)
|
||||
|
||||
if response.status_code == 201:
|
||||
print(f"Created PR: {github_pr_data['title']}")
|
||||
else:
|
||||
print(f"Failed to create PR: {response.text}")
|
||||
```
|
||||
|
||||
### ⚖️ コスト・効率性比較
|
||||
|
||||
#### 年間運用コスト比較(100人チーム想定)
|
||||
```markdown
|
||||
### プラットフォーム別コスト分析
|
||||
|
||||
#### GitHub Enterprise
|
||||
- **ライセンス**: $21,000/年
|
||||
- **運用工数**: 最小限(SaaS)
|
||||
- **学習コスト**: 低(広く普及)
|
||||
- **合計**: $25,000/年
|
||||
|
||||
#### GitLab Premium
|
||||
- **ライセンス**: $19,000/年
|
||||
- **運用工数**: 中程度(自己管理オプション)
|
||||
- **学習コスト**: 中(機能豊富)
|
||||
- **合計**: $28,000/年
|
||||
|
||||
#### Bitbucket Premium
|
||||
- **ライセンス**: $15,000/年
|
||||
- **運用工数**: 中程度
|
||||
- **学習コスト**: 中
|
||||
- **合計**: $22,000/年
|
||||
|
||||
### 効率性指標
|
||||
|
||||
| 指標 | GitHub | GitLab | Bitbucket |
|
||||
|------|--------|--------|-----------|
|
||||
| **PR作成時間** | 30秒 | 45秒 | 60秒 |
|
||||
| **レビュー効率** | 95% | 90% | 85% |
|
||||
| **マージ時間** | 10秒 | 15秒 | 20秒 |
|
||||
| **モバイル対応** | 100% | 70% | 60% |
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎓 実践演習
|
||||
|
||||
### 演習1: 完全なPRワークフロー実践
|
||||
1. **Issue作成** - 機能要求の詳細化
|
||||
2. **ブランチ作成** - 適切な命名規則
|
||||
3. **実装** - コード品質を意識
|
||||
4. **Draft PR作成** - 早期フィードバック取得
|
||||
5. **CI/CD実行** - 自動テスト・品質チェック
|
||||
6. **レビュー対応** - 建設的な議論
|
||||
7. **マージ** - 適切な戦略選択
|
||||
|
||||
### 演習2: 高度なレビュー機能活用
|
||||
1. **Suggested Changes** - 具体的修正提案
|
||||
2. **CODEOWNERS** - 自動レビュアーアサイン
|
||||
3. **ブランチ保護** - 品質ゲート設定
|
||||
4. **自動化** - ラベリング・通知設定
|
||||
|
||||
### 演習3: チーム用PR規約策定
|
||||
1. **PRテンプレート** - チーム標準化
|
||||
2. **レビューガイドライン** - 観点の明確化
|
||||
3. **マージルール** - 戦略の統一
|
||||
4. **品質メトリクス** - 継続改善指標
|
||||
|
||||
---
|
||||
|
||||
## 🔗 関連リソース
|
||||
|
||||
### 公式ドキュメント
|
||||
- [GitHub Pull Requests](https://docs.github.com/en/pull-requests)
|
||||
- [Code Review Best Practices](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests)
|
||||
- [Branch Protection Rules](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests)
|
||||
|
||||
### ツール・拡張機能
|
||||
- [GitHub CLI](https://cli.github.com/)
|
||||
- [GitHub Desktop](https://desktop.github.com/)
|
||||
- [GitHub Mobile](https://github.com/mobile)
|
||||
- [VS Code GitHub Pull Requests](https://marketplace.visualstudio.com/items?itemName=GitHub.vscode-pull-request-github)
|
||||
|
||||
### 参考記事
|
||||
- [Conventional Commits](https://www.conventionalcommits.org/)
|
||||
- [Git Flow vs GitHub Flow](https://lucamezzalira.com/2014/03/10/git-flow-vs-github-flow/)
|
||||
- [Code Review Best Practices](https://smartbear.com/learn/code-review/best-practices-for-peer-code-review/)
|
||||
|
||||
---
|
||||
|
||||
## 📝 まとめ
|
||||
|
||||
GitHub Pull Request機能を効果的に活用することで:
|
||||
|
||||
✅ **高品質なコード** - 体系的なレビュープロセスによる品質向上
|
||||
✅ **チーム協調** - 透明性のある開発プロセス
|
||||
✅ **知識共有** - レビューを通じた技術的成長
|
||||
✅ **効率化** - 自動化による作業時間短縮
|
||||
✅ **外部ツール不要** - GitHub標準機能のみで企業レベルの開発プロセス
|
||||
|
||||
## 🔗 関連ガイド
|
||||
|
||||
- **前のステップ**: [Issues管理編](02-issues-management.md) - タスク管理とプロジェクト追跡
|
||||
- **次のステップ**: [GitHub Projects編](04-github-projects.md) - プロジェクト管理の最適化
|
||||
- **基礎知識**: [リポジトリ基礎編](01-repository-basics.md) - ブランチ管理とタグ運用
|
||||
- **総合ガイド**: [GitHub完全活用ガイド](../GITHUB_COMPLETE_GUIDE.md) - 全機能の詳細解説
|
||||
|
||||
## 📖 学習フロー
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[リポジトリ基礎] --> B[Issues管理]
|
||||
B --> C[Pull Request]
|
||||
C --> D[GitHub Projects]
|
||||
D --> E[完全活用]
|
||||
|
||||
style A fill:#f3e5f5
|
||||
style B fill:#f3e5f5
|
||||
style C fill:#e1f5fe
|
||||
style D fill:#e8f5e8
|
||||
style E fill:#fce4ec
|
||||
```
|
||||
|
||||
次は[GitHub Projects編](04-github-projects.md)で、プロジェクト管理の最適化を学習しましょう。
|
||||
756
features/04-github-projects.md
Normal file
756
features/04-github-projects.md
Normal file
|
|
@ -0,0 +1,756 @@
|
|||
---
|
||||
layout: default
|
||||
title: "GitHub Projects完全ガイド"
|
||||
description: "アジャイル開発のためのプロジェクト管理とGitHub Projects V2完全活用法"
|
||||
---
|
||||
|
||||
# 📋 GitHub Projects - アジャイル開発のためのプロジェクト管理
|
||||
|
||||
GitHub Projects V2を活用して、Jira・Trello・Asanaなどの外部ツールに依存しない、統合されたプロジェクト管理環境を構築する完全ガイド。Issues・Pull Requestsとシームレスに連携し、開発から運用まで一元管理を実現します。
|
||||
|
||||
## 🎯 学習目標
|
||||
|
||||
- GitHub Projects V2の全機能理解と実践的活用
|
||||
- アジャイル開発手法(スクラム・カンバン)の実装
|
||||
- 外部プロジェクト管理ツールからの完全移行
|
||||
- 自動化によるプロジェクト運用効率化
|
||||
- チーム協働とステークホルダー管理の最適化
|
||||
|
||||
## 📚 目次
|
||||
|
||||
1. [GitHub Projects V2 概要](#1-github-projects-v2-概要)
|
||||
2. [プロジェクト作成と基本設定](#2-プロジェクト作成と基本設定)
|
||||
3. [ビューとワークフローの設計](#3-ビューとワークフローの設計)
|
||||
4. [カスタムフィールドと自動化](#4-カスタムフィールドと自動化)
|
||||
5. [アジャイル手法の実装](#5-アジャイル手法の実装)
|
||||
6. [外部ツールからの移行](#6-外部ツールからの移行)
|
||||
|
||||
---
|
||||
|
||||
## 1. GitHub Projects V2 概要
|
||||
|
||||
### 🚀 従来版との主要な違い
|
||||
|
||||
#### Projects V2 の革新的機能
|
||||
```markdown
|
||||
### V1 → V2 進化ポイント
|
||||
|
||||
#### データ構造
|
||||
- **V1**: カード形式(制限的)
|
||||
- **V2**: テーブル形式(柔軟性)
|
||||
|
||||
#### カスタマイズ性
|
||||
- **V1**: 基本的なカラム移動のみ
|
||||
- **V2**: カスタムフィールド・フィルタ・グループ化
|
||||
|
||||
#### 自動化
|
||||
- **V1**: 限定的なワークフロー
|
||||
- **V2**: 高度な自動化ルール
|
||||
|
||||
#### ビュー機能
|
||||
- **V1**: カンバンビューのみ
|
||||
- **V2**: カンバン・テーブル・ロードマップ・ガントチャート
|
||||
|
||||
#### スコープ
|
||||
- **V1**: リポジトリレベル
|
||||
- **V2**: 組織・個人・複数リポジトリ対応
|
||||
```
|
||||
|
||||
### 📊 外部ツールとの機能比較
|
||||
|
||||
| 機能 | GitHub Projects V2 | Jira | Trello | Asana | Linear | 備考 |
|
||||
|------|-------------------|------|-------|-------|--------|------|
|
||||
| **カンバンボード** | ✅ | ✅ | ✅ | ✅ | ✅ | 全て対応 |
|
||||
| **ガントチャート** | ✅ | ✅ | ❌ | ✅ | ❌ | Projects V2で新対応 |
|
||||
| **スプリント管理** | ✅ | ✅ | ⚠️ | ✅ | ✅ | カスタムフィールドで実現 |
|
||||
| **バーンダウンチャート** | ⚠️ | ✅ | ❌ | ⚠️ | ✅ | APIで実現可能 |
|
||||
| **カスタムフィールド** | ✅ | ✅ | ❌ | ✅ | ✅ | 高い柔軟性 |
|
||||
| **自動化** | ✅ | ✅ | ⚠️ | ✅ | ✅ | GitHub Actions連携 |
|
||||
| **レポート機能** | ⚠️ | ✅ | ❌ | ✅ | ✅ | Insights・API活用 |
|
||||
| **コード連携** | ✅ | ⚠️ | ❌ | ❌ | ⚠️ | 最も強力 |
|
||||
| **コスト(100人)** | $0-2,100 | $7,000 | $5,000 | $12,000 | $8,000 | 圧倒的にコスト効率良い |
|
||||
|
||||
---
|
||||
|
||||
## 2. プロジェクト作成と基本設定
|
||||
|
||||
### 🛠️ プロジェクト初期設定
|
||||
|
||||
#### 新規プロジェクト作成
|
||||
```bash
|
||||
# GitHub CLI でプロジェクト作成
|
||||
gh project create --title "Product Development Q1 2024" \
|
||||
--body "Q1期の製品開発プロジェクト管理"
|
||||
|
||||
# または Web UI で作成
|
||||
# https://github.com/users/USERNAME/projects/new
|
||||
# または組織: https://github.com/orgs/ORGANIZATION/projects/new
|
||||
```
|
||||
|
||||
#### 基本設定の最適化
|
||||
```markdown
|
||||
### プロジェクト基本情報
|
||||
|
||||
#### 必須設定項目
|
||||
- **プロジェクト名**: 明確で検索しやすい名前
|
||||
- **説明**: 目的・スコープ・期間を明記
|
||||
- **可視性**: Private(機密) / Public(オープンソース)
|
||||
- **所有者**: 個人 / 組織
|
||||
- **README**: プロジェクトの詳細情報
|
||||
|
||||
#### 推奨README構成
|
||||
```markdown
|
||||
# Product Development Q1 2024
|
||||
|
||||
## 🎯 プロジェクト概要
|
||||
Q1期間中の製品開発における機能開発・バグ修正・リリース管理
|
||||
|
||||
## 📅 期間
|
||||
2024年1月1日 - 2024年3月31日
|
||||
|
||||
## 👥 チーム構成
|
||||
- **Product Manager**: @product-lead
|
||||
- **Tech Lead**: @tech-lead
|
||||
- **Frontend**: @frontend-team
|
||||
- **Backend**: @backend-team
|
||||
- **QA**: @qa-team
|
||||
|
||||
## 🎯 主要マイルストーン
|
||||
- [ ] Alpha版リリース (1/31)
|
||||
- [ ] Beta版リリース (2/28)
|
||||
- [ ] 本番リリース (3/31)
|
||||
|
||||
## 📊 成功指標
|
||||
- 機能完成率: 95%以上
|
||||
- バグ解決率: 100%
|
||||
- リリース予定遵守率: 90%以上
|
||||
```
|
||||
|
||||
### 🔗 リポジトリとの連携設定
|
||||
|
||||
#### 複数リポジトリの統合管理
|
||||
```bash
|
||||
# プロジェクトにリポジトリを追加
|
||||
gh project item-create PROJECT_ID \
|
||||
--owner OWNER \
|
||||
--repo REPO_NAME
|
||||
|
||||
# 複数リポジトリの一括追加例
|
||||
REPOS=("frontend-app" "backend-api" "mobile-app" "documentation")
|
||||
for repo in "${REPOS[@]}"; do
|
||||
gh project item-create $PROJECT_ID --owner $OWNER --repo $repo
|
||||
done
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. ビューとワークフローの設計
|
||||
|
||||
### 📊 多角的ビューの構築
|
||||
|
||||
#### 1. カンバンビュー(日常業務用)
|
||||
```markdown
|
||||
### カンバン列設計
|
||||
|
||||
#### 基本フロー
|
||||
📋 **Backlog** → 🏗️ **Ready** → 🔄 **In Progress** → 👀 **Review** → ✅ **Done**
|
||||
|
||||
#### 詳細ステータス定義
|
||||
- **Backlog**: 優先順位付け待ち・要件未確定
|
||||
- **Ready**: 開発可能・担当者アサイン済み
|
||||
- **In Progress**: 実装中・ブロック状況の監視
|
||||
- **Review**: PR作成済み・レビュー待ち
|
||||
- **Done**: マージ完了・検証済み
|
||||
|
||||
#### 高度な列設定
|
||||
- **Ice Box**: 将来検討・低優先度アイデア
|
||||
- **Blocked**: 外部依存・技術的課題で停止中
|
||||
- **Waiting**: 顧客フィードバック・承認待ち
|
||||
- **Deployed**: 本番環境デプロイ完了
|
||||
```
|
||||
|
||||
#### 2. テーブルビュー(詳細管理用)
|
||||
```markdown
|
||||
### カスタムフィールド設計
|
||||
|
||||
#### 必須フィールド
|
||||
- **Status**: Single select(Backlog, Ready, In Progress, Review, Done)
|
||||
- **Priority**: Single select(Critical, High, Medium, Low)
|
||||
- **Size**: Single select(XS, S, M, L, XL)
|
||||
- **Epic**: Text(関連するエピック名)
|
||||
- **Sprint**: Single select(Sprint 1, Sprint 2, ...)
|
||||
- **Assignee**: People(担当者)
|
||||
- **Due Date**: Date(期限)
|
||||
- **Story Points**: Number(見積もりポイント)
|
||||
|
||||
#### 発展フィールド
|
||||
- **Component**: Multi-select(Frontend, Backend, Mobile, API)
|
||||
- **Customer Impact**: Single select(High, Medium, Low, None)
|
||||
- **Technical Debt**: Single select(Yes, No)
|
||||
- **Risk Level**: Single select(High, Medium, Low)
|
||||
- **Reviewer**: People(レビュー担当者)
|
||||
```
|
||||
|
||||
#### 3. ロードマップビュー(戦略的計画用)
|
||||
```markdown
|
||||
### 時系列での進捗可視化
|
||||
|
||||
#### 設定項目
|
||||
- **X軸**: 時間軸(週・月・四半期)
|
||||
- **Y軸**: エピック・チーム・コンポーネント
|
||||
- **マーカー**: マイルストーン・リリース予定日
|
||||
- **色分け**: 優先度・ステータス・担当チーム
|
||||
|
||||
#### 活用シーン
|
||||
- **エグゼクティブレビュー**: 経営陣への進捗報告
|
||||
- **リリース計画**: 機能リリースのタイムライン
|
||||
- **リソース配分**: チーム間の作業バランス確認
|
||||
- **依存関係管理**: ブロッカーの可視化
|
||||
```
|
||||
|
||||
### 🔄 ワークフロー自動化の設計
|
||||
|
||||
#### Issue → Project 自動追加
|
||||
```yaml
|
||||
# .github/workflows/add-to-project.yml
|
||||
name: Add Issue to Project
|
||||
on:
|
||||
issues:
|
||||
types: [opened, labeled]
|
||||
|
||||
jobs:
|
||||
add-to-project:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Add to project
|
||||
uses: actions/add-to-project@v0.4.0
|
||||
with:
|
||||
project-url: https://github.com/users/USERNAME/projects/1
|
||||
github-token: ${{ secrets.ADD_TO_PROJECT_TOKEN }}
|
||||
labeled: bug,enhancement,feature
|
||||
```
|
||||
|
||||
#### ステータス自動更新
|
||||
```yaml
|
||||
# .github/workflows/update-project-status.yml
|
||||
name: Update Project Status
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, closed, merged]
|
||||
|
||||
jobs:
|
||||
update-status:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Update status on PR
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const pr = context.payload.pull_request;
|
||||
|
||||
// PRの状態に応じてプロジェクトアイテムのステータスを更新
|
||||
let newStatus;
|
||||
if (pr.state === 'open') {
|
||||
newStatus = 'Review';
|
||||
} else if (pr.merged) {
|
||||
newStatus = 'Done';
|
||||
} else if (pr.state === 'closed') {
|
||||
newStatus = 'Backlog';
|
||||
}
|
||||
|
||||
// GraphQL APIでプロジェクトアイテムを更新
|
||||
const query = `
|
||||
mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $value: String!) {
|
||||
updateProjectV2ItemFieldValue(
|
||||
input: {
|
||||
projectId: $projectId
|
||||
itemId: $itemId
|
||||
fieldId: $fieldId
|
||||
value: { singleSelectOptionId: $value }
|
||||
}
|
||||
) {
|
||||
projectV2Item {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
// 実際の更新処理
|
||||
// 注:projectId, itemId, fieldIdは環境に応じて設定
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. カスタムフィールドと自動化
|
||||
|
||||
### 🎛️ 高度なカスタマイズ
|
||||
|
||||
#### スクラム開発用フィールド設定
|
||||
```markdown
|
||||
### スクラム特化カスタムフィールド
|
||||
|
||||
#### ストーリー管理
|
||||
- **User Story**: Text(ユーザーストーリー記述)
|
||||
- **Acceptance Criteria**: Text(受け入れ条件)
|
||||
- **Story Points**: Number(1, 2, 3, 5, 8, 13, 21)
|
||||
- **Business Value**: Single select(High, Medium, Low)
|
||||
|
||||
#### スプリント管理
|
||||
- **Sprint**: Single select(Current, Next, Future, Backlog)
|
||||
- **Sprint Goal**: Text(スプリント目標)
|
||||
- **Velocity**: Number(チームの開発速度)
|
||||
- **Burndown**: Number(残作業量)
|
||||
|
||||
#### 品質管理
|
||||
- **Definition of Done**: Checkbox(完了条件チェックリスト)
|
||||
- **Test Coverage**: Number(テストカバレッジ%)
|
||||
- **Code Review Status**: Single select(Pending, Approved, Changes Requested)
|
||||
- **QA Status**: Single select(Not Started, In Progress, Passed, Failed)
|
||||
```
|
||||
|
||||
#### カンバン開発用フィールド設定
|
||||
```markdown
|
||||
### カンバン特化カスタムフィールド
|
||||
|
||||
#### フロー管理
|
||||
- **WIP Limit**: Number(作業中上限数)
|
||||
- **Cycle Time**: Number(開始から完了までの日数)
|
||||
- **Lead Time**: Number(要求から完了までの日数)
|
||||
- **Flow Efficiency**: Number(実作業時間の割合%)
|
||||
|
||||
#### 継続改善
|
||||
- **Blocker Reason**: Text(ブロック理由)
|
||||
- **Improvement Suggestion**: Text(改善提案)
|
||||
- **Retrospective Item**: Checkbox(振り返り対象)
|
||||
- **Customer Feedback**: Text(顧客からのフィードバック)
|
||||
```
|
||||
|
||||
### 🤖 自動化ルールの実装
|
||||
|
||||
#### 複雑な条件分岐自動化
|
||||
```yaml
|
||||
# .github/workflows/project-automation.yml
|
||||
name: Advanced Project Automation
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited, labeled, assigned]
|
||||
pull_request:
|
||||
types: [opened, closed, review_requested, review_submitted]
|
||||
|
||||
jobs:
|
||||
project-automation:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Advanced Automation Logic
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
const { data: projects } = await github.rest.projects.listForUser({
|
||||
username: context.repo.owner
|
||||
});
|
||||
|
||||
const projectId = projects.find(p => p.name === 'Development Board')?.id;
|
||||
if (!projectId) return;
|
||||
|
||||
// 複雑な条件分岐処理
|
||||
const event = context.eventName;
|
||||
const action = context.payload.action;
|
||||
|
||||
switch(event) {
|
||||
case 'issues':
|
||||
await handleIssueEvent(action, context.payload.issue);
|
||||
break;
|
||||
case 'pull_request':
|
||||
await handlePREvent(action, context.payload.pull_request);
|
||||
break;
|
||||
}
|
||||
|
||||
async function handleIssueEvent(action, issue) {
|
||||
// 優先度に応じた自動アサイン
|
||||
if (issue.labels.some(l => l.name === 'priority:critical')) {
|
||||
await github.rest.issues.addAssignees({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: issue.number,
|
||||
assignees: ['team-lead']
|
||||
});
|
||||
}
|
||||
|
||||
// 見積もりポイントの自動設定
|
||||
let storyPoints = 3; // デフォルト
|
||||
if (issue.labels.some(l => l.name === 'size:small')) storyPoints = 1;
|
||||
if (issue.labels.some(l => l.name === 'size:large')) storyPoints = 8;
|
||||
|
||||
// プロジェクトアイテムのフィールド更新
|
||||
// 注:実際のGraphQL実装が必要
|
||||
}
|
||||
|
||||
async function handlePREvent(action, pr) {
|
||||
if (action === 'opened') {
|
||||
// PR作成時:関連Issueのステータスを「Review」に更新
|
||||
const linkedIssues = extractLinkedIssues(pr.body);
|
||||
for (const issueNumber of linkedIssues) {
|
||||
// ステータス更新処理
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function extractLinkedIssues(prBody) {
|
||||
const regex = /(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+#(\d+)/gi;
|
||||
const matches = [...prBody.matchAll(regex)];
|
||||
return matches.map(match => parseInt(match[1]));
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. アジャイル手法の実装
|
||||
|
||||
### 🏃♂️ スクラム手法の完全実装
|
||||
|
||||
#### スプリント計画・実行・振り返り
|
||||
|
||||
**スプリント計画ビューの設定**
|
||||
```markdown
|
||||
### Sprint Planning View 設定
|
||||
|
||||
#### フィルタ設定
|
||||
- **Status**: Backlog, Ready
|
||||
- **Sprint**: Current, Next
|
||||
- **Story Points**: 1-21(見積もり済み)
|
||||
|
||||
#### グループ化
|
||||
- **Primary**: Epic(機能群別)
|
||||
- **Secondary**: Priority(優先度別)
|
||||
|
||||
#### ソート順
|
||||
1. Priority(Critical → High → Medium → Low)
|
||||
2. Business Value(High → Medium → Low)
|
||||
3. Story Points(小 → 大)
|
||||
|
||||
#### 表示カラム
|
||||
- Title, Status, Assignee, Story Points, Sprint, Due Date
|
||||
```
|
||||
|
||||
**スプリント実行中のデイリースタンドアップ支援**
|
||||
```markdown
|
||||
### Daily Standup Dashboard
|
||||
|
||||
#### 今日の作業ビュー
|
||||
- **フィルタ**: Status = "In Progress", Assignee = "@me"
|
||||
- **表示**: 昨日完了・今日予定・ブロッカー情報
|
||||
|
||||
#### チーム全体の進捗ビュー
|
||||
- **グループ化**: Assignee(担当者別)
|
||||
- **色分け**: ステータス別(緑=順調、黄=注意、赤=遅延)
|
||||
- **アラート**: 期限超過・長期停滞アイテム
|
||||
|
||||
#### ブロッカー監視ビュー
|
||||
- **フィルタ**: Labels contains "blocked"
|
||||
- **ソート**: 作成日(古い順)
|
||||
- **アクション**: 担当者への通知・エスカレーション
|
||||
```
|
||||
|
||||
#### スプリントレトロスペクティブ
|
||||
```markdown
|
||||
### Sprint Retrospective Template
|
||||
|
||||
#### 振り返り観点
|
||||
- **Keep**: 継続すべきこと
|
||||
- **Problem**: 改善が必要なこと
|
||||
- **Try**: 次スプリントで試すこと
|
||||
|
||||
#### メトリクス収集
|
||||
- **Velocity**: 完了ストーリーポイント
|
||||
- **Burndown**: 日別残作業量推移
|
||||
- **Cycle Time**: 平均完了時間
|
||||
- **Bug Rate**: 不具合発生率
|
||||
|
||||
#### 改善アクション
|
||||
- 特定された問題の対策アイテム作成
|
||||
- プロセス改善のためのタスク追加
|
||||
- 次スプリントでの実験項目設定
|
||||
```
|
||||
|
||||
### 📊 カンバン手法の実装
|
||||
|
||||
#### 継続的フロー最適化
|
||||
|
||||
**WIP制限の設定と監視**
|
||||
```markdown
|
||||
### WIP Limits by Column
|
||||
|
||||
#### 推奨設定(5人チーム)
|
||||
- **Ready**: 10アイテム(バックログの充実)
|
||||
- **In Progress**: 5アイテム(チーム人数と同じ)
|
||||
- **Review**: 3アイテム(迅速なレビュー)
|
||||
- **Blocked**: 制限なし(問題の可視化)
|
||||
|
||||
#### 監視とアラート
|
||||
- WIP超過時の自動通知
|
||||
- 長期滞留アイテムの検出
|
||||
- フロー効率の計測・レポート
|
||||
```
|
||||
|
||||
**累積フロー図(CFD)の作成**
|
||||
```python
|
||||
# cfd_generator.py - Cumulative Flow Diagram 生成
|
||||
import requests
|
||||
import matplotlib.pyplot as plt
|
||||
import pandas as pd
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
class CFDGenerator:
|
||||
def __init__(self, github_token, project_id):
|
||||
self.token = github_token
|
||||
self.project_id = project_id
|
||||
|
||||
def generate_cfd(self, days=30):
|
||||
"""過去30日間の累積フロー図を生成"""
|
||||
end_date = datetime.now()
|
||||
start_date = end_date - timedelta(days=days)
|
||||
|
||||
daily_data = []
|
||||
current_date = start_date
|
||||
|
||||
while current_date <= end_date:
|
||||
# その日のステータス別アイテム数を取得
|
||||
status_counts = self.get_status_counts_for_date(current_date)
|
||||
daily_data.append({
|
||||
'date': current_date,
|
||||
**status_counts
|
||||
})
|
||||
current_date += timedelta(days=1)
|
||||
|
||||
df = pd.DataFrame(daily_data)
|
||||
|
||||
# 累積フロー図の描画
|
||||
plt.figure(figsize=(12, 8))
|
||||
statuses = ['Done', 'Review', 'In Progress', 'Ready', 'Backlog']
|
||||
colors = ['#28a745', '#ffc107', '#007bff', '#6c757d', '#dc3545']
|
||||
|
||||
for i, status in enumerate(statuses):
|
||||
plt.fill_between(df['date'],
|
||||
df[status] if i == 0 else df[statuses[:i+1]].sum(axis=1),
|
||||
df[statuses[:i]].sum(axis=1) if i > 0 else 0,
|
||||
color=colors[i], alpha=0.7, label=status)
|
||||
|
||||
plt.xlabel('Date')
|
||||
plt.ylabel('Number of Items')
|
||||
plt.title('Cumulative Flow Diagram')
|
||||
plt.legend()
|
||||
plt.xticks(rotation=45)
|
||||
plt.tight_layout()
|
||||
plt.savefig('cfd.png', dpi=300, bbox_inches='tight')
|
||||
|
||||
return df
|
||||
|
||||
def get_status_counts_for_date(self, date):
|
||||
"""指定日のステータス別アイテム数を取得"""
|
||||
# GitHub GraphQL API を使用してプロジェクトデータを取得
|
||||
# 実装の詳細は省略(実際のAPI呼び出しが必要)
|
||||
return {
|
||||
'Backlog': 15,
|
||||
'Ready': 8,
|
||||
'In Progress': 5,
|
||||
'Review': 3,
|
||||
'Done': 25
|
||||
}
|
||||
|
||||
# 使用例
|
||||
cfd = CFDGenerator(github_token="your_token", project_id="project_id")
|
||||
data = cfd.generate_cfd()
|
||||
print("CFD generated successfully!")
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 外部ツールからの移行
|
||||
|
||||
### 🔄 Jira からの移行
|
||||
|
||||
#### 完全移行チェックリスト
|
||||
```markdown
|
||||
### Phase 1: データマッピング設計(1週間)
|
||||
|
||||
#### Jiraフィールド → GitHub Projects フィールド対応
|
||||
- **Issue Type** → **Labels**(bug, feature, story, epic)
|
||||
- **Priority** → **Priority**(Critical, High, Medium, Low)
|
||||
- **Status** → **Status**(Backlog, In Progress, Done等)
|
||||
- **Assignee** → **Assignee**(ユーザーマッピング必要)
|
||||
- **Epic Link** → **Epic**(カスタムテキストフィールド)
|
||||
- **Story Points** → **Story Points**(カスタム数値フィールド)
|
||||
- **Sprint** → **Sprint**(カスタム選択フィールド)
|
||||
- **Components** → **Labels**(複数ラベルで対応)
|
||||
|
||||
### Phase 2: 移行ツール開発(2週間)
|
||||
|
||||
#### 自動移行スクリプト
|
||||
```python
|
||||
# jira_to_github_projects.py
|
||||
import requests
|
||||
import json
|
||||
from jira import JIRA
|
||||
|
||||
class JiraToGitHubMigrator:
|
||||
def __init__(self, jira_url, jira_user, jira_token, github_token, github_project_id):
|
||||
self.jira = JIRA(server=jira_url, basic_auth=(jira_user, jira_token))
|
||||
self.github_token = github_token
|
||||
self.project_id = github_project_id
|
||||
|
||||
def migrate_project(self, jira_project_key):
|
||||
"""Jiraプロジェクト全体を移行"""
|
||||
# 1. Jira Issuesを取得
|
||||
issues = self.jira.search_issues(f'project={jira_project_key}', maxResults=1000)
|
||||
|
||||
# 2. GitHub Issues/Project Itemsを作成
|
||||
for issue in issues:
|
||||
github_issue = self.create_github_issue(issue)
|
||||
self.add_to_project(github_issue['number'])
|
||||
|
||||
def create_github_issue(self, jira_issue):
|
||||
"""Jira Issue を GitHub Issue に変換"""
|
||||
# フィールドマッピング
|
||||
title = jira_issue.fields.summary
|
||||
body = self.convert_description(jira_issue.fields.description)
|
||||
labels = self.map_labels(jira_issue.fields.issuetype, jira_issue.fields.priority)
|
||||
|
||||
issue_data = {
|
||||
'title': title,
|
||||
'body': body,
|
||||
'labels': labels
|
||||
}
|
||||
|
||||
# GitHub API で Issue 作成
|
||||
response = requests.post(
|
||||
f'https://api.github.com/repos/{self.repo}/issues',
|
||||
headers={'Authorization': f'token {self.github_token}'},
|
||||
json=issue_data
|
||||
)
|
||||
|
||||
return response.json()
|
||||
```
|
||||
|
||||
### Phase 3: チーム教育・並行運用(2週間)
|
||||
|
||||
#### 教育プログラム
|
||||
- **ハンズオン研修**: GitHub Projects V2操作方法
|
||||
- **ワークショップ**: アジャイルプロセスの再設計
|
||||
- **QAセッション**: 移行に関する疑問解決
|
||||
- **ドキュメント**: 新しいプロセスの標準化
|
||||
|
||||
### Phase 4: 完全移行・Jira停止(1週間)
|
||||
|
||||
#### 移行完了基準
|
||||
- [ ] 全データ移行完了・検証済み
|
||||
- [ ] チーム全員が新プロセスに習熟
|
||||
- [ ] 自動化・インテグレーション動作確認
|
||||
- [ ] パフォーマンス・可用性確認
|
||||
- [ ] バックアップ・ロールバック手順準備
|
||||
```
|
||||
|
||||
### 📊 コスト効果分析
|
||||
|
||||
#### 移行前後の比較(100人チーム・年間)
|
||||
```markdown
|
||||
### 導入・運用コスト比較
|
||||
|
||||
#### Jira(移行前)
|
||||
- **ライセンス費用**: $7,000/年
|
||||
- **管理・運用**: 1人 × 20% = $20,000/年
|
||||
- **教育・サポート**: $5,000/年
|
||||
- **カスタマイズ**: $10,000/年
|
||||
- **合計**: $42,000/年
|
||||
|
||||
#### GitHub Projects V2(移行後)
|
||||
- **ライセンス費用**: $0(GitHub Pro に含まれる)
|
||||
- **管理・運用**: 1人 × 5% = $5,000/年
|
||||
- **教育・サポート**: $2,000/年(初年度のみ)
|
||||
- **カスタマイズ**: $3,000/年(自動化開発)
|
||||
- **合計**: $10,000/年
|
||||
|
||||
### ROI計算
|
||||
- **年間削減額**: $32,000
|
||||
- **移行コスト**: $15,000(一時費用)
|
||||
- **投資回収期間**: 5.6ヶ月
|
||||
- **3年間総節約額**: $81,000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎓 実践演習
|
||||
|
||||
### 演習1: スクラムプロジェクト構築
|
||||
1. **プロジェクト作成** - チーム用スクラムボード
|
||||
2. **カスタムフィールド設定** - ストーリーポイント・スプリント
|
||||
3. **自動化ルール** - Issue→Project追加・ステータス更新
|
||||
4. **レポートビュー** - スプリント進捗・ベロシティ
|
||||
|
||||
### 演習2: カンバンフロー最適化
|
||||
1. **フロー設計** - WIP制限・フロー効率
|
||||
2. **メトリクス収集** - サイクルタイム・リードタイム
|
||||
3. **継続改善** - ボトルネック特定・プロセス改善
|
||||
4. **可視化** - 累積フロー図・バーンアップチャート
|
||||
|
||||
### 演習3: 外部ツール移行
|
||||
1. **現状分析** - 既存ツールの機能・データ調査
|
||||
2. **移行計画** - フェーズ別移行ロードマップ
|
||||
3. **データマッピング** - フィールド・ワークフロー対応
|
||||
4. **並行運用** - リスク軽減・段階的移行
|
||||
|
||||
---
|
||||
|
||||
## 🔗 関連リソース
|
||||
|
||||
### 公式ドキュメント
|
||||
- [GitHub Projects Documentation](https://docs.github.com/en/issues/planning-and-tracking-with-projects)
|
||||
- [Projects V2 GraphQL API](https://docs.github.com/en/graphql/reference/objects#projectv2)
|
||||
- [GitHub Projects Best Practices](https://github.blog/2022-07-27-planning-next-to-your-code-github-projects-is-now-generally-available/)
|
||||
|
||||
### 移行・活用ツール
|
||||
- [Jira to GitHub Issues Migration](https://github.com/marketplace/actions/jira-to-github-issues)
|
||||
- [Projects V2 CLI](https://cli.github.com/manual/gh_project)
|
||||
- [GitHub Projects API Scripts](https://github.com/github/projects-scripts)
|
||||
|
||||
### アジャイル手法参考資料
|
||||
- [Scrum Guide](https://scrumguides.org/)
|
||||
- [Kanban Method](https://www.atlassian.com/agile/kanban)
|
||||
- [Agile Metrics](https://www.agilealliance.org/agile101/guide-to-agile-metrics/)
|
||||
|
||||
---
|
||||
|
||||
## 📝 まとめ
|
||||
|
||||
GitHub Projects V2を効果的に活用することで:
|
||||
|
||||
✅ **統合された開発環境** - コードとプロジェクト管理の一元化
|
||||
✅ **コスト大幅削減** - 外部ツールライセンス費用の削減
|
||||
✅ **チーム生産性向上** - シームレスなワークフローと自動化
|
||||
✅ **柔軟なプロセス適応** - スクラム・カンバン・独自手法に対応
|
||||
✅ **データドリブン改善** - メトリクス収集と継続的最適化
|
||||
|
||||
次は実際のプロジェクトでGitHub Projects V2を活用し、チームの開発プロセスを最適化しましょう!
|
||||
|
||||
## 🔗 関連ガイド
|
||||
|
||||
- **前のステップ**: [Pull Request編](03-pull-requests.md) - コードレビュープロセス最適化
|
||||
- **基礎知識**: [Issues管理編](02-issues-management.md) - タスク管理の基礎
|
||||
- **さらに基礎**: [リポジトリ基礎編](01-repository-basics.md) - 基本的なGit操作
|
||||
- **総合ガイド**: [GitHub完全活用ガイド](../GITHUB_COMPLETE_GUIDE.md) - 全機能の詳細解説
|
||||
|
||||
## 📖 学習フロー
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[リポジトリ基礎] --> B[Issues管理]
|
||||
B --> C[Pull Request]
|
||||
C --> D[GitHub Projects]
|
||||
D --> E[完全活用]
|
||||
|
||||
style A fill:#f3e5f5
|
||||
style B fill:#f3e5f5
|
||||
style C fill:#f3e5f5
|
||||
style D fill:#e1f5fe
|
||||
style E fill:#e8f5e8
|
||||
```
|
||||
8
index.md
8
index.md
|
|
@ -51,14 +51,14 @@ description: "外部ツールに依存せず、GitHub一つで開発業務を完
|
|||
<p>Jiraを完全代替するタスク管理システム</p>
|
||||
</a>
|
||||
|
||||
<a href="#" class="guide-link coming-soon">
|
||||
<a href="features/03-pull-requests.html" class="guide-link">
|
||||
<h4>🔄 Pull Request</h4>
|
||||
<p>効率的なコードレビューフロー(準備中)</p>
|
||||
<p>効率的なコードレビューフローとマージ戦略</p>
|
||||
</a>
|
||||
|
||||
<a href="#" class="guide-link coming-soon">
|
||||
<a href="features/04-github-projects.html" class="guide-link">
|
||||
<h4>📋 GitHub Projects</h4>
|
||||
<p>アジャイル開発のためのプロジェクト管理(準備中)</p>
|
||||
<p>アジャイル開発のためのプロジェクト管理</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue