soba-cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.claude/commands/osoba/add-backlog.md +173 -0
  3. data/.claude/commands/osoba/implement.md +151 -0
  4. data/.claude/commands/osoba/plan.md +217 -0
  5. data/.claude/commands/osoba/review.md +133 -0
  6. data/.claude/commands/osoba/revise.md +176 -0
  7. data/.claude/commands/soba/implement.md +88 -0
  8. data/.claude/commands/soba/plan.md +93 -0
  9. data/.claude/commands/soba/review.md +91 -0
  10. data/.claude/commands/soba/revise.md +76 -0
  11. data/.devcontainer/.env +2 -0
  12. data/.devcontainer/Dockerfile +3 -0
  13. data/.devcontainer/LICENSE +21 -0
  14. data/.devcontainer/README.md +85 -0
  15. data/.devcontainer/bin/devcontainer-common.sh +50 -0
  16. data/.devcontainer/bin/down +35 -0
  17. data/.devcontainer/bin/rebuild +10 -0
  18. data/.devcontainer/bin/up +11 -0
  19. data/.devcontainer/compose.yaml +28 -0
  20. data/.devcontainer/devcontainer.json +53 -0
  21. data/.devcontainer/post-attach.sh +29 -0
  22. data/.devcontainer/post-create.sh +62 -0
  23. data/.devcontainer/setup/01-os-package.sh +19 -0
  24. data/.devcontainer/setup/02-npm-package.sh +22 -0
  25. data/.devcontainer/setup/03-mcp-server.sh +33 -0
  26. data/.devcontainer/setup/04-tool.sh +17 -0
  27. data/.devcontainer/setup/05-soba-setup.sh +66 -0
  28. data/.devcontainer/setup/scripts/functions/install_apt.sh +77 -0
  29. data/.devcontainer/setup/scripts/functions/install_npm.sh +71 -0
  30. data/.devcontainer/setup/scripts/functions/mcp_config.sh +14 -0
  31. data/.devcontainer/setup/scripts/functions/print_message.sh +59 -0
  32. data/.devcontainer/setup/scripts/setup/mcp-markdownify.sh +39 -0
  33. data/.devcontainer/sync-envs.sh +58 -0
  34. data/.envrc.sample +7 -0
  35. data/.rspec +4 -0
  36. data/.rubocop.yml +70 -0
  37. data/.rubocop_airbnb.yml +2 -0
  38. data/.rubocop_todo.yml +74 -0
  39. data/.tool-versions +1 -0
  40. data/CLAUDE.md +20 -0
  41. data/LICENSE +21 -0
  42. data/README.md +384 -0
  43. data/README_ja.md +384 -0
  44. data/Rakefile +18 -0
  45. data/bin/soba +120 -0
  46. data/config/config.yml.example +36 -0
  47. data/docs/business/INDEX.md +6 -0
  48. data/docs/business/overview.md +42 -0
  49. data/docs/business/workflow.md +143 -0
  50. data/docs/development/INDEX.md +10 -0
  51. data/docs/development/architecture.md +69 -0
  52. data/docs/development/coding-standards.md +152 -0
  53. data/docs/development/distribution.md +26 -0
  54. data/docs/development/implementation-guide.md +103 -0
  55. data/docs/development/testing-strategy.md +128 -0
  56. data/docs/development/tmux-management.md +253 -0
  57. data/docs/document_system.md +58 -0
  58. data/lib/soba/commands/config/show.rb +63 -0
  59. data/lib/soba/commands/init.rb +778 -0
  60. data/lib/soba/commands/open.rb +144 -0
  61. data/lib/soba/commands/start.rb +442 -0
  62. data/lib/soba/commands/status.rb +175 -0
  63. data/lib/soba/commands/stop.rb +147 -0
  64. data/lib/soba/config_loader.rb +32 -0
  65. data/lib/soba/configuration.rb +268 -0
  66. data/lib/soba/container.rb +48 -0
  67. data/lib/soba/domain/issue.rb +38 -0
  68. data/lib/soba/domain/phase_strategy.rb +74 -0
  69. data/lib/soba/infrastructure/errors.rb +23 -0
  70. data/lib/soba/infrastructure/github_client.rb +399 -0
  71. data/lib/soba/infrastructure/lock_manager.rb +129 -0
  72. data/lib/soba/infrastructure/tmux_client.rb +331 -0
  73. data/lib/soba/services/ansi_processor.rb +92 -0
  74. data/lib/soba/services/auto_merge_service.rb +133 -0
  75. data/lib/soba/services/closed_issue_window_cleaner.rb +96 -0
  76. data/lib/soba/services/daemon_service.rb +83 -0
  77. data/lib/soba/services/git_workspace_manager.rb +102 -0
  78. data/lib/soba/services/issue_monitor.rb +29 -0
  79. data/lib/soba/services/issue_processor.rb +215 -0
  80. data/lib/soba/services/issue_watcher.rb +193 -0
  81. data/lib/soba/services/pid_manager.rb +87 -0
  82. data/lib/soba/services/process_info.rb +58 -0
  83. data/lib/soba/services/queueing_service.rb +98 -0
  84. data/lib/soba/services/session_logger.rb +111 -0
  85. data/lib/soba/services/session_resolver.rb +72 -0
  86. data/lib/soba/services/slack_notifier.rb +121 -0
  87. data/lib/soba/services/status_manager.rb +74 -0
  88. data/lib/soba/services/test_process_manager.rb +84 -0
  89. data/lib/soba/services/tmux_session_manager.rb +251 -0
  90. data/lib/soba/services/workflow_blocking_checker.rb +73 -0
  91. data/lib/soba/services/workflow_executor.rb +256 -0
  92. data/lib/soba/services/workflow_integrity_checker.rb +151 -0
  93. data/lib/soba/templates/claude_commands/implement.md +88 -0
  94. data/lib/soba/templates/claude_commands/plan.md +93 -0
  95. data/lib/soba/templates/claude_commands/review.md +91 -0
  96. data/lib/soba/templates/claude_commands/revise.md +76 -0
  97. data/lib/soba/version.rb +5 -0
  98. data/lib/soba.rb +44 -0
  99. data/lib/tasks/gem.rake +75 -0
  100. data/soba-cli.gemspec +59 -0
  101. metadata +430 -0
@@ -0,0 +1,143 @@
1
+ # soba 自動ワークフロー
2
+
3
+ ## 概要
4
+
5
+ sobaは、GitHub Issueを起点とした自律的な開発ワークフローを実現します。Issue のラベルに基づいて自動的に計画と実装のサイクルを実行します。
6
+
7
+ ## ワークフローの流れ
8
+
9
+ ```mermaid
10
+ graph TD
11
+ A[複数のsoba:todo] -->|soba: 優先度判定| B[1つをsoba:queued]
12
+ B -->|soba: 即座に| C[soba:planning]
13
+ C -->|Claude: 計画策定| D[soba:ready]
14
+ D -->|soba: 自動検出| E[soba:doing]
15
+ E -->|Claude: 実装・PR作成| F[soba:review-requested]
16
+ F -->|soba: 自動検出| G[soba:reviewing]
17
+ G -->|Claude: レビュー承認| H[soba:done + PR:soba:lgtm]
18
+ G -->|Claude: 修正要求| I[soba:requires-changes]
19
+ I -->|soba: 自動検出| K[soba:revising]
20
+ K -->|Claude: 修正対応| F
21
+ H -->|soba: 自動マージ| J[soba:merged]
22
+ J -->|次のキューイング| A
23
+ ```
24
+
25
+ ## 計画フェーズ
26
+
27
+ ### 1. Issue検出
28
+ - **対象ラベル**: `soba:todo`
29
+ - **検出方法**: 定期的なGitHub Issue監視
30
+ - **選定基準**: Issue番号が最も若いものを1件抽出
31
+ - **実行主体**: **soba CLI**
32
+
33
+ ### 2. キューイング・計画策定
34
+ - **【soba】** 複数の `soba:todo` から Issue番号が最も若いものを選択
35
+ - **【soba】** ラベルを `soba:todo` → `soba:queued` → `soba:planning` に変更
36
+ - **【soba】** Claude Codeプロセスを起動
37
+ - **【Claude】** Issueの内容を分析し、実装計画を策定
38
+ - **【Claude】** 策定完了後、ラベルを `soba:planning` → `soba:ready` に変更
39
+
40
+ ## 実装フェーズ
41
+
42
+ ### 1. Issue検出
43
+ - **対象ラベル**: `soba:ready`
44
+ - **検出方法**: 定期的なGitHub Issue監視
45
+ - **選定基準**: Issue番号が最も若いものを1件抽出
46
+ - **実行主体**: **soba CLI**
47
+
48
+ ### 2. 実装作業
49
+ - **【soba】** ラベルを `soba:ready` → `soba:doing` に変更
50
+ - **【soba】** Claude Codeプロセスを起動
51
+ - **【Claude】** 以下を自動実行:
52
+ - Issueの実装
53
+ - セルフレビュー
54
+ - Pull Request作成
55
+ - **【Claude】** 完了後、ラベルを `soba:doing` → `soba:review-requested` に変更
56
+
57
+ ## レビューフェーズ
58
+
59
+ ### 1. Issue検出
60
+ - **対象ラベル**: `soba:review-requested`
61
+ - **検出方法**: 定期的なGitHub Issue監視
62
+ - **選定基準**: Issue番号が最も若いものを1件抽出
63
+ - **実行主体**: **soba CLI**
64
+
65
+ ### 2. レビュー実施
66
+ - **【soba】** ラベルを `soba:review-requested` → `soba:reviewing` に変更
67
+ - **【soba】** Claude Codeプロセスを起動
68
+ - **【Claude】** PRの内容をレビューし、以下を実行:
69
+ - コード品質のチェック
70
+ - テスト実行状況の確認
71
+ - セキュリティ観点でのチェック
72
+ - レビューコメントの投稿
73
+ - **【Claude】** レビュー結果に応じてラベルを変更:
74
+ - 承認: Issueラベル `soba:reviewing` → `soba:done`、PRに `soba:lgtm` ラベル付与
75
+ - 修正要求: Issueラベル `soba:reviewing` → `soba:requires-changes`
76
+
77
+ ## 修正フェーズ
78
+
79
+ ### 1. Issue検出
80
+ - **対象ラベル**: `soba:requires-changes`
81
+ - **検出方法**: 定期的なGitHub Issue監視
82
+ - **選定基準**: Issue番号が最も若いものを1件抽出
83
+ - **実行主体**: **soba CLI**
84
+
85
+ ### 2. 修正対応
86
+ - **【soba】** ラベルを `soba:requires-changes` → `soba:revising` に変更
87
+ - **【soba】** Claude Codeプロセスを起動
88
+ - **【Claude】** レビューコメントを確認し、以下を実行:
89
+ - 指摘事項への対応実施
90
+ - テストの修正・追加
91
+ - コードの改善
92
+ - **【Claude】** 修正完了後、ラベルを `soba:revising` → `soba:review-requested` に変更
93
+
94
+ ## マージフェーズ
95
+
96
+ ### 1. PR検出
97
+ - **対象ラベル**: PRの `soba:lgtm` ラベル
98
+ - **検出方法**: 定期的なGitHub PR監視
99
+ - **選定基準**: `soba:lgtm` ラベルが付いた全てのPR
100
+ - **実行主体**: **soba CLI**
101
+
102
+ ### 2. 自動マージ実施
103
+ - **【soba】** PRのマージ可能状態を確認:
104
+ - CIが全てパス
105
+ - コンフリクトなし
106
+ - マージ可能状態
107
+ - **【soba】** 条件を満たすPRを自動的にマージ(squash merge)
108
+ - **【soba】** マージ後の処理:
109
+ - 関連するIssueを自動クローズ
110
+ - Issueに `soba:merged` ラベルを付与
111
+ - 作業ブランチを削除
112
+
113
+ ## ラベル定義
114
+
115
+ ### Issueラベル(状態管理)
116
+
117
+ | ラベル | 状態 | 説明 | 変更主体 |
118
+ |--------|------|------|----------|
119
+ | `soba:todo` | 待機 | 新規Issue、計画待ち(複数設定可) | - |
120
+ | `soba:queued` | キュー選択 | 優先度判定で選択済み(1つのみ) | soba → |
121
+ | `soba:planning` | 計画中 | Claude Codeが計画策定中(1つのみ) | soba → |
122
+ | `soba:ready` | 準備完了 | 計画策定済み、実装待ち | Claude → |
123
+ | `soba:doing` | 実装中 | Claude Codeが実装作業中(1つのみ) | soba → |
124
+ | `soba:review-requested` | レビュー待ち | PR作成済み、レビュー待ち | Claude → |
125
+ | `soba:reviewing` | レビュー中 | Claude Codeがレビュー実施中(1つのみ) | soba → |
126
+ | `soba:done` | 完了 | レビュー承認、マージ可能 | Claude → |
127
+ | `soba:requires-changes` | 修正要求 | レビューで修正が必要と判断 | Claude → |
128
+ | `soba:revising` | 修正中 | Claude Codeが修正対応中(1つのみ) | soba → |
129
+ | `soba:merged` | マージ済み | PRがマージされ、Issueクローズ済み | soba → |
130
+
131
+ ### PRラベル(マージ判定)
132
+
133
+ | ラベル | 状態 | 説明 | 変更主体 |
134
+ |--------|------|------|----------|
135
+ | `soba:lgtm` | 承認済み | レビュー承認、自動マージ対象 | Claude → |
136
+
137
+ ## 自動化のメリット
138
+
139
+ 1. **継続的な進捗**: Issueが自動的に処理され、開発が停滞しない
140
+ 2. **一貫性**: 同じプロセスで全てのIssueを処理
141
+ 3. **効率化**: 手動でのラベル変更やプロセス起動が不要
142
+ 4. **優先順位管理**: Issue番号順による明確な処理順序
143
+ 5. **厳密な排他制御**: 常に1つのIssueのみがアクティブ処理される
@@ -0,0 +1,10 @@
1
+ # Development Documents
2
+
3
+ ## ドキュメント一覧
4
+
5
+ - `architecture.md`: soba CLIのアーキテクチャ設計書(レイヤー構成、コンポーネント設計、ディレクトリ構造)
6
+ - `implementation-guide.md`: 実装ガイド(段階的な実装手順、ベストプラクティス、サンプルコード)
7
+ - `coding-standards.md`: コーディング規約(命名規則、スタイルガイド、Rubocop設定、レビューチェックリスト)
8
+ - `testing-strategy.md`: テスト戦略(テストピラミッド、各種テストの実装方法、カバレッジ目標)
9
+ - `distribution.md`: 配布戦略(配布方法は検討中)
10
+ - `tmux-management.md`: tmux管理機能(セッション管理、ペイン操作、自動クリーンアップ)
@@ -0,0 +1,69 @@
1
+ # soba CLI アーキテクチャ設計書
2
+
3
+ ## 概要
4
+
5
+ GitHub IssueとClaude Codeを連携させる自律的ワークフロー実行ツールのアーキテクチャ。
6
+
7
+ ## レイヤー構成
8
+
9
+ ```
10
+ ┌─────────────────────────────────────┐
11
+ │ CLI (GLI) │ → コマンドインターフェース
12
+ ├─────────────────────────────────────┤
13
+ │ Commands │ → コマンド処理
14
+ ├─────────────────────────────────────┤
15
+ │ Services │ → ビジネスロジック
16
+ ├─────────────────────────────────────┤
17
+ │ Domain │ → ドメインモデル
18
+ ├─────────────────────────────────────┤
19
+ │ Infrastructure │ → 外部連携
20
+ └─────────────────────────────────────┘
21
+ ```
22
+
23
+ ## ディレクトリ構造
24
+
25
+ ```
26
+ soba/
27
+ ├── bin/soba # 実行ファイル
28
+ ├── lib/soba/
29
+ │ ├── cli/ # CLIコマンド定義
30
+ │ ├── commands/ # コマンド実装
31
+ │ ├── services/ # ビジネスロジック
32
+ │ ├── domain/ # エンティティ、値オブジェクト
33
+ │ └── infrastructure/ # GitHub/Claude API連携
34
+ ├── spec/ # テスト
35
+ └── config/ # 設定ファイル
36
+ ```
37
+
38
+ ## 主要コンポーネント
39
+
40
+ | コンポーネント | ライブラリ | 用途 |
41
+ |-------------|----------|------|
42
+ | CLI | GLI | コマンドライン処理 |
43
+ | DI | dry-container | 依存性注入 |
44
+ | HTTP | Faraday + Octokit | API通信 |
45
+ | 非同期 | concurrent-ruby | 並行処理 |
46
+ | ログ | semantic_logger | ログ出力 |
47
+
48
+ ## データフロー
49
+
50
+ ```
51
+ User → CLI → Command → Service → Domain
52
+
53
+ Infrastructure → External API
54
+ ```
55
+
56
+ ## 設定ファイル
57
+
58
+ ```yaml
59
+ # ~/.soba/config.yml
60
+ github:
61
+ token: ${GITHUB_TOKEN}
62
+ repository: owner/repo
63
+
64
+ claude:
65
+ api_key: ${CLAUDE_API_KEY}
66
+
67
+ workflow:
68
+ interval: 60
69
+ ```
@@ -0,0 +1,152 @@
1
+ # soba CLI コーディング規約
2
+
3
+ ## 基本原則
4
+
5
+ 1. **可読性優先** - シンプルで理解しやすいコード
6
+ 2. **Ruby Way** - Rubyの慣習に従う
7
+ 3. **一貫性** - プロジェクト全体で統一
8
+
9
+ ## 命名規則
10
+
11
+ | 種類 | 規則 | 例 |
12
+ |-----|------|-----|
13
+ | ファイル | snake_case | `issue_monitor.rb` |
14
+ | クラス | PascalCase | `IssueMonitor` |
15
+ | メソッド | snake_case | `fetch_issues` |
16
+ | 定数 | SCREAMING_SNAKE | `MAX_RETRIES` |
17
+ | 述語メソッド | 疑問符付き | `valid?` |
18
+
19
+ ## ファイル構造
20
+
21
+ ```ruby
22
+ # frozen_string_literal: true
23
+
24
+ require 'standard_library'
25
+ require_relative '../domain/issue'
26
+
27
+ module Soba
28
+ class IssueMonitor
29
+ # クラス実装
30
+ end
31
+ end
32
+ ```
33
+
34
+ ### require規則
35
+
36
+ - **相対パス**: 同一プロジェクト内のファイルは`require_relative`を使用
37
+ - **絶対パス禁止**: `require 'soba/services/foo'`は使わない(パスエラーの原因)
38
+ - **外部gem**: `require 'gem_name'`を使用
39
+
40
+ ### GLIコマンド構造
41
+
42
+ ```ruby
43
+ # bin/soba
44
+ #!/usr/bin/env ruby
45
+ require 'gli'
46
+
47
+ include GLI::App
48
+
49
+ desc 'Global option'
50
+ flag [:c, :config]
51
+
52
+ command :issue do |c|
53
+ c.action do |global, options, args|
54
+ # コマンド実装
55
+ end
56
+ end
57
+
58
+ exit run(ARGV)
59
+ ```
60
+
61
+ ## クラス設計
62
+
63
+ ```ruby
64
+ class IssueMonitor
65
+ attr_reader :client
66
+
67
+ def initialize(client)
68
+ @client = client
69
+ end
70
+
71
+ def start
72
+ validate!
73
+ monitor_loop
74
+ end
75
+
76
+ private
77
+
78
+ def validate!
79
+ raise ConfigError unless valid?
80
+ end
81
+ end
82
+ ```
83
+
84
+ ## メソッド設計
85
+
86
+ - 10行以内を目安
87
+ - 引数は3個まで(オプションハッシュ推奨)
88
+ - ガード節で早期リターン
89
+
90
+ ```ruby
91
+ def process(issue)
92
+ return unless issue.valid?
93
+ return if issue.closed?
94
+
95
+ perform_processing(issue)
96
+ end
97
+ ```
98
+
99
+ ## エラーハンドリング
100
+
101
+ ```ruby
102
+ module Soba
103
+ class Error < StandardError; end
104
+ class ConfigError < Error; end
105
+ end
106
+
107
+ def fetch_issue(id)
108
+ client.issue(id)
109
+ rescue Octokit::NotFound
110
+ nil
111
+ end
112
+ ```
113
+
114
+ ## Rubocop設定(主要項目)
115
+
116
+ ```yaml
117
+ AllCops:
118
+ TargetRubyVersion: 3.2
119
+
120
+ Layout/LineLength:
121
+ Max: 100
122
+
123
+ Metrics/MethodLength:
124
+ Max: 15
125
+
126
+ Style/StringLiterals:
127
+ EnforcedStyle: double_quotes
128
+ ```
129
+
130
+ ## テストコード
131
+
132
+ ```ruby
133
+ RSpec.describe IssueMonitor do
134
+ let(:monitor) { described_class.new(client) }
135
+
136
+ describe '#start' do
137
+ context 'when valid' do
138
+ it 'starts monitoring' do
139
+ expect(monitor).to receive(:monitor_loop)
140
+ monitor.start
141
+ end
142
+ end
143
+ end
144
+ end
145
+ ```
146
+
147
+ ## コードレビューチェックリスト
148
+
149
+ - [ ] 命名規則に従っているか
150
+ - [ ] 単一責任の原則を守っているか
151
+ - [ ] テストが書かれているか
152
+ - [ ] エラーハンドリングが適切か
@@ -0,0 +1,26 @@
1
+ # soba CLI 配布戦略
2
+
3
+ ## 概要
4
+
5
+ soba CLIの配布方法は現在検討中です。
6
+
7
+ ## 配布方法(検討中)
8
+
9
+ 現在、以下の配布方法を検討しています:
10
+
11
+ 1. **gem配布**
12
+ - RubyGemsによる標準的な配布
13
+ - `gem install soba`でインストール可能
14
+
15
+ 2. **スタンドアロンバイナリ**
16
+ - Ruby環境不要の単一実行ファイル
17
+ - 各プラットフォーム向けに最適化
18
+
19
+ 3. **パッケージマネージャ**
20
+ - Homebrew(macOS/Linux)
21
+ - Scoop/Chocolatey(Windows)
22
+ - APT/YUM(Linux)
23
+
24
+ ## 今後の計画
25
+
26
+ 配布戦略の詳細は、プロジェクトの成熟度とユーザーのニーズに応じて決定される予定です。
@@ -0,0 +1,103 @@
1
+ # soba CLI 実装ガイド
2
+
3
+ ## 実装フェーズ
4
+
5
+ ### Phase 1: 基盤構築(1週目)
6
+
7
+ ```bash
8
+ # Gemfile作成
9
+ bundle init
10
+ bundle add gli dry-container dry-auto_inject faraday octokit
11
+ bundle add --group development,test rspec webmock rubocop
12
+ ```
13
+
14
+ 基本ファイル:
15
+ - `bin/soba` - 実行ファイル
16
+ - `lib/soba.rb` - エントリポイント
17
+ - `lib/soba/container/container.rb` - DI設定
18
+
19
+ ### Phase 2: CLIコマンド(2週目)
20
+
21
+ ```ruby
22
+ # bin/soba
23
+ #!/usr/bin/env ruby
24
+ require 'gli'
25
+ require 'soba'
26
+
27
+ include GLI::App
28
+
29
+ program_desc 'GitHub Issue to Claude Code workflow automation'
30
+ version Soba::VERSION
31
+
32
+ desc 'Manage issues'
33
+ command :issue do |c|
34
+ c.desc 'List issues'
35
+ c.command :list do |list|
36
+ list.action do |global_options, options, args|
37
+ Soba::Commands::Issue::List.new.execute(args[0])
38
+ end
39
+ end
40
+ end
41
+
42
+ exit run(ARGV)
43
+ ```
44
+
45
+ 実装順序:
46
+ 1. `config` - 設定確認
47
+ 2. `issue list` - 一覧取得
48
+ 3. `issue watch` - 監視機能
49
+
50
+ ### Phase 3: ドメインモデル(3週目)
51
+
52
+ ```ruby
53
+ # lib/soba/domain/entities/issue.rb
54
+ module Soba
55
+ class Issue
56
+ attr_reader :id, :title, :state
57
+
58
+ def open?
59
+ state == 'open'
60
+ end
61
+ end
62
+ end
63
+ ```
64
+
65
+ ### Phase 4: 外部連携(4週目)
66
+
67
+ ```ruby
68
+ # lib/soba/infrastructure/github/client.rb
69
+ module Soba
70
+ class GitHubClient
71
+ def initialize(token:)
72
+ @octokit = Octokit::Client.new(access_token: token)
73
+ end
74
+
75
+ def issues(repo)
76
+ @octokit.issues(repo)
77
+ end
78
+ end
79
+ end
80
+ ```
81
+
82
+ ## Gem構成
83
+
84
+ ```ruby
85
+ # soba.gemspec
86
+ Gem::Specification.new do |spec|
87
+ spec.name = "soba"
88
+ spec.version = "0.1.0"
89
+ spec.files = Dir["lib/**/*", "bin/*"]
90
+ spec.executables = ["soba"]
91
+ spec.add_dependency "gli", "~> 2.21"
92
+ end
93
+ ```
94
+
95
+ ## Docker化
96
+
97
+ ```dockerfile
98
+ FROM ruby:3.2-slim
99
+ WORKDIR /app
100
+ COPY . .
101
+ RUN bundle install
102
+ ENTRYPOINT ["bin/soba"]
103
+ ```
@@ -0,0 +1,128 @@
1
+ # soba CLI テスト戦略
2
+
3
+ ## テストピラミッド
4
+
5
+ ```
6
+ /\
7
+ / \ E2E (5%)
8
+ /────\ 統合テスト (20%)
9
+ /──────\
10
+ /────────\ ユニットテスト (75%)
11
+ ```
12
+
13
+ ## テストレベル
14
+
15
+ ### 1. ユニットテスト
16
+
17
+ 個別クラス・メソッドの動作検証。実実装を使用して正確性を確保。
18
+
19
+ ```ruby
20
+ RSpec.describe Issue do
21
+ describe '#priority' do
22
+ let(:issue) { described_class.new(labels: ['critical']) }
23
+
24
+ it 'returns high for critical issues' do
25
+ expect(issue.priority).to eq(:high)
26
+ end
27
+ end
28
+ end
29
+ ```
30
+
31
+ ### 2. 統合テスト
32
+
33
+ コンポーネント間連携とAPI連携の検証。VCRでHTTP記録。
34
+
35
+ ```ruby
36
+ RSpec.describe GitHubClient, :vcr do
37
+ it 'fetches issues from repository' do
38
+ issues = client.fetch_issues('owner/repo')
39
+ expect(issues).to be_an(Array)
40
+ end
41
+ end
42
+ ```
43
+
44
+ ### 3. E2Eテスト
45
+
46
+ CLIコマンド全体の動作確認。
47
+
48
+ ```ruby
49
+ RSpec.describe 'CLI', type: :e2e do
50
+ it 'lists issues' do
51
+ output = `bin/soba issue list owner/repo`
52
+ expect($?).to be_success
53
+ expect(output).to include('Issues')
54
+ end
55
+ end
56
+ ```
57
+
58
+ ## テスト構成
59
+
60
+ ```ruby
61
+ # spec/spec_helper.rb
62
+ require 'simplecov'
63
+ SimpleCov.start { minimum_coverage 90 }
64
+
65
+ RSpec.configure do |config|
66
+ config.include FactoryBot::Syntax::Methods
67
+ config.order = :random
68
+ end
69
+ ```
70
+
71
+ ## モック戦略
72
+
73
+ **重要: モックの利用は外部のAPI連携のみに限定する。それ以外のテスト時は必ず実実装を利用する。**
74
+
75
+ ```ruby
76
+ # 外部API連携のみモック化
77
+ module MockHelpers
78
+ def stub_github_api_response
79
+ stub_request(:get, /api.github.com/).
80
+ to_return(status: 200, body: '[]', headers: {})
81
+ end
82
+ end
83
+ ```
84
+
85
+ ## VCR設定
86
+
87
+ ```ruby
88
+ VCR.configure do |config|
89
+ config.cassette_library_dir = 'spec/fixtures/vcr'
90
+ config.hook_into :webmock
91
+ config.filter_sensitive_data('<TOKEN>') { ENV['GITHUB_TOKEN'] }
92
+ end
93
+ ```
94
+
95
+ ## CI/CD
96
+
97
+ ```yaml
98
+ # .github/workflows/test.yml
99
+ name: Test
100
+ on: [push, pull_request]
101
+
102
+ jobs:
103
+ test:
104
+ runs-on: ubuntu-latest
105
+ steps:
106
+ - uses: actions/checkout@v3
107
+ - uses: ruby/setup-ruby@v1
108
+ with:
109
+ bundler-cache: true
110
+ - run: bundle exec rspec
111
+ ```
112
+
113
+ ## カバレッジ目標
114
+
115
+ | レイヤー | 目標 |
116
+ |---------|------|
117
+ | Domain | 95%+ |
118
+ | Services | 90%+ |
119
+ | Infrastructure | 85%+ |
120
+ | CLI | 80%+ |
121
+
122
+ ## ベストプラクティス
123
+
124
+ - AAAパターン(Arrange, Act, Assert)
125
+ - 1テスト1アサーション
126
+ - テストの独立性確保
127
+ - 明確なテスト名
128
+ - 実実装の利用(外部API以外はモック化禁止)