@sk8metal/michi-cli 0.0.8 → 0.0.9
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.
- package/CHANGELOG.md +33 -0
- package/README.md +202 -9
- package/dist/scripts/__tests__/setup-existing-project.test.js +67 -5
- package/dist/scripts/__tests__/setup-existing-project.test.js.map +1 -1
- package/dist/scripts/constants/__tests__/environments.test.d.ts +2 -0
- package/dist/scripts/constants/__tests__/environments.test.d.ts.map +1 -0
- package/dist/scripts/constants/__tests__/environments.test.js +91 -0
- package/dist/scripts/constants/__tests__/environments.test.js.map +1 -0
- package/dist/scripts/constants/__tests__/languages.test.d.ts +2 -0
- package/dist/scripts/constants/__tests__/languages.test.d.ts.map +1 -0
- package/dist/scripts/constants/__tests__/languages.test.js +82 -0
- package/dist/scripts/constants/__tests__/languages.test.js.map +1 -0
- package/dist/scripts/constants/environments.d.ts +33 -0
- package/dist/scripts/constants/environments.d.ts.map +1 -0
- package/dist/scripts/constants/environments.js +49 -0
- package/dist/scripts/constants/environments.js.map +1 -0
- package/dist/scripts/constants/languages.d.ts +23 -0
- package/dist/scripts/constants/languages.d.ts.map +1 -0
- package/dist/scripts/constants/languages.js +53 -0
- package/dist/scripts/constants/languages.js.map +1 -0
- package/dist/scripts/create-project.d.ts +4 -0
- package/dist/scripts/create-project.d.ts.map +1 -1
- package/dist/scripts/create-project.js +51 -22
- package/dist/scripts/create-project.js.map +1 -1
- package/dist/scripts/setup-existing-project.d.ts +3 -1
- package/dist/scripts/setup-existing-project.d.ts.map +1 -1
- package/dist/scripts/setup-existing-project.js +110 -55
- package/dist/scripts/setup-existing-project.js.map +1 -1
- package/dist/scripts/template/__tests__/renderer.test.d.ts +2 -0
- package/dist/scripts/template/__tests__/renderer.test.d.ts.map +1 -0
- package/dist/scripts/template/__tests__/renderer.test.js +165 -0
- package/dist/scripts/template/__tests__/renderer.test.js.map +1 -0
- package/dist/scripts/template/renderer.d.ts +70 -0
- package/dist/scripts/template/renderer.d.ts.map +1 -0
- package/dist/scripts/template/renderer.js +99 -0
- package/dist/scripts/template/renderer.js.map +1 -0
- package/dist/scripts/utils/template-finder.d.ts +37 -0
- package/dist/scripts/utils/template-finder.d.ts.map +1 -0
- package/dist/scripts/utils/template-finder.js +63 -0
- package/dist/scripts/utils/template-finder.js.map +1 -0
- package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts +5 -0
- package/dist/src/__tests__/integration/setup/claude-agent.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/claude-agent.test.js +125 -0
- package/dist/src/__tests__/integration/setup/claude-agent.test.js.map +1 -0
- package/dist/src/__tests__/integration/setup/claude.test.d.ts +5 -0
- package/dist/src/__tests__/integration/setup/claude.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/claude.test.js +111 -0
- package/dist/src/__tests__/integration/setup/claude.test.js.map +1 -0
- package/dist/src/__tests__/integration/setup/cursor.test.d.ts +5 -0
- package/dist/src/__tests__/integration/setup/cursor.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/cursor.test.js +162 -0
- package/dist/src/__tests__/integration/setup/cursor.test.js.map +1 -0
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts +32 -0
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js +72 -0
- package/dist/src/__tests__/integration/setup/helpers/fs-assertions.js.map +1 -0
- package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts +38 -0
- package/dist/src/__tests__/integration/setup/helpers/test-project.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/helpers/test-project.js +83 -0
- package/dist/src/__tests__/integration/setup/helpers/test-project.js.map +1 -0
- package/dist/src/__tests__/integration/setup/validation.test.d.ts +5 -0
- package/dist/src/__tests__/integration/setup/validation.test.d.ts.map +1 -0
- package/dist/src/__tests__/integration/setup/validation.test.js +318 -0
- package/dist/src/__tests__/integration/setup/validation.test.js.map +1 -0
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +20 -0
- package/dist/src/cli.js.map +1 -1
- package/dist/src/commands/setup-existing.d.ts +22 -0
- package/dist/src/commands/setup-existing.d.ts.map +1 -0
- package/dist/src/commands/setup-existing.js +408 -0
- package/dist/src/commands/setup-existing.js.map +1 -0
- package/dist/vitest.config.d.ts.map +1 -1
- package/dist/vitest.config.js +4 -3
- package/dist/vitest.config.js.map +1 -1
- package/docs/getting-started/new-repository-setup.md +108 -28
- package/docs/getting-started/quick-start.md +57 -6
- package/docs/getting-started/setup.md +250 -2
- package/docs/guides/customization.md +3 -3
- package/docs/guides/multi-project.md +1 -1
- package/docs/reference/quick-reference.md +25 -16
- package/docs/testing/integration-tests.md +297 -0
- package/package.json +7 -2
- package/scripts/__tests__/setup-existing-project.test.ts +73 -5
- package/scripts/constants/__tests__/environments.test.ts +110 -0
- package/scripts/constants/__tests__/languages.test.ts +100 -0
- package/scripts/constants/environments.ts +61 -0
- package/scripts/constants/languages.ts +70 -0
- package/scripts/create-project.ts +52 -22
- package/scripts/setup-existing-project.ts +136 -57
- package/scripts/setup-existing.sh +130 -3
- package/scripts/template/__tests__/renderer.test.ts +207 -0
- package/scripts/template/renderer.ts +133 -0
- package/scripts/utils/template-finder.ts +75 -0
- package/templates/claude/commands/michi/confluence-sync.md +38 -0
- package/templates/claude/commands/michi/project-switch.md +36 -0
- package/templates/claude/rules/atlassian-integration.md +35 -0
- package/templates/claude/rules/michi-core.md +54 -0
- package/templates/claude-agent/README.md +25 -0
- package/templates/cursor/commands/michi/confluence-sync.md +76 -0
- package/templates/cursor/commands/michi/project-switch.md +69 -0
- package/templates/cursor/rules/atlassian-mcp.mdc +188 -0
- package/templates/cursor/rules/github-ssot.mdc +151 -0
- package/templates/cursor/rules/multi-project.mdc +81 -0
- package/scripts/setup-env.sh +0 -52
|
@@ -4,17 +4,25 @@
|
|
|
4
4
|
|
|
5
5
|
## 新規プロジェクト作成
|
|
6
6
|
|
|
7
|
-
### パターンA: 既存リポジトリにMichi
|
|
7
|
+
### パターンA: 既存リポジトリにMichi共通ルール・コマンドを追加(最も簡単 ⭐)
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
# 既存プロジェクトに移動
|
|
11
11
|
cd /path/to/existing-repo
|
|
12
12
|
|
|
13
|
-
#
|
|
13
|
+
# Michiの共通ルール・コマンド・テンプレートをコピー
|
|
14
14
|
bash /path/to/michi/scripts/setup-existing.sh
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
このスクリプトが自動的に:
|
|
18
|
+
- 共通ルール(`.cursor/rules/`)をコピー
|
|
19
|
+
- カスタムコマンド(`.cursor/commands/kiro/`)をコピー
|
|
20
|
+
- Steeringテンプレート(`.kiro/steering/`)をコピー
|
|
21
|
+
- Specテンプレート(`.kiro/settings/templates/`)をコピー
|
|
22
|
+
|
|
23
|
+
**次のステップ**:
|
|
24
|
+
1. cc-sddを導入: `npx cc-sdd@latest --lang ja --cursor`
|
|
25
|
+
2. 設定を対話的に作成: `npm run setup:interactive`
|
|
18
26
|
|
|
19
27
|
### パターンB: 新規リポジトリを作成してセットアップ
|
|
20
28
|
|
|
@@ -64,11 +72,12 @@ cat > .kiro/project.json << 'EOF'
|
|
|
64
72
|
}
|
|
65
73
|
EOF
|
|
66
74
|
|
|
67
|
-
# 4. Michi
|
|
75
|
+
# 4. Michiから共通ルール・コマンド・テンプレートをコピー(自動スクリプト推奨)
|
|
76
|
+
bash /path/to/michi/scripts/setup-existing.sh
|
|
77
|
+
|
|
78
|
+
# または直接実行
|
|
68
79
|
npx tsx /path/to/michi/scripts/setup-existing-project.ts \
|
|
69
|
-
--michi-path /path/to/michi
|
|
70
|
-
--project-name "プロジェクト名" \
|
|
71
|
-
--jira-key "PRJX"
|
|
80
|
+
--michi-path /path/to/michi
|
|
72
81
|
|
|
73
82
|
# 5. npm install
|
|
74
83
|
# 6. 初期コミット
|
|
@@ -87,21 +96,21 @@ npx tsx /path/to/michi/scripts/setup-existing-project.ts \
|
|
|
87
96
|
/kiro:spec-init <機能説明>
|
|
88
97
|
/kiro:spec-requirements <feature>
|
|
89
98
|
jj commit -m "docs: 要件定義" && jj git push
|
|
90
|
-
npx @michi
|
|
99
|
+
npx @sk8metal/michi-cli phase:run <feature> requirements
|
|
91
100
|
```
|
|
92
101
|
|
|
93
102
|
**設計**:
|
|
94
103
|
```bash
|
|
95
104
|
/kiro:spec-design <feature>
|
|
96
105
|
jj commit -m "docs: 設計" && jj git push
|
|
97
|
-
npx @michi
|
|
106
|
+
npx @sk8metal/michi-cli phase:run <feature> design
|
|
98
107
|
```
|
|
99
108
|
|
|
100
109
|
**タスク分割**:
|
|
101
110
|
```bash
|
|
102
111
|
/kiro:spec-tasks <feature>
|
|
103
112
|
jj commit -m "docs: タスク分割" && jj git push
|
|
104
|
-
npx @michi
|
|
113
|
+
npx @sk8metal/michi-cli phase:run <feature> tasks
|
|
105
114
|
```
|
|
106
115
|
|
|
107
116
|
**実装**:
|
|
@@ -110,7 +119,7 @@ npx @michi/cli phase:run <feature> tasks
|
|
|
110
119
|
jj commit -m "feat: 実装 [<jira-key>-XXX]"
|
|
111
120
|
jj bookmark create <project-id>/feature/<feature> -r '@-'
|
|
112
121
|
jj git push --bookmark <project-id>/feature/<feature> --allow-new
|
|
113
|
-
gh pr create --head <project-id>/feature/<feature> --base
|
|
122
|
+
gh pr create --head <project-id>/feature/<feature> --base main
|
|
114
123
|
```
|
|
115
124
|
|
|
116
125
|
## コマンド一覧
|
|
@@ -132,7 +141,7 @@ gh pr create --head <project-id>/feature/<feature> --base init
|
|
|
132
141
|
|
|
133
142
|
## Michi CLIコマンド一覧
|
|
134
143
|
|
|
135
|
-
**使用方法**: `npx @michi
|
|
144
|
+
**使用方法**: `npx @sk8metal/michi-cli <command>` または `michi <command>`(グローバルインストール後)
|
|
136
145
|
|
|
137
146
|
| コマンド | 説明 |
|
|
138
147
|
|---------|------|
|
|
@@ -150,8 +159,8 @@ gh pr create --head <project-id>/feature/<feature> --base init
|
|
|
150
159
|
| `michi --version` | バージョン表示 |
|
|
151
160
|
|
|
152
161
|
**インストール方法**:
|
|
153
|
-
- **npx実行(推奨)**: `npx @michi
|
|
154
|
-
- **グローバルインストール**: `npm install -g @michi
|
|
162
|
+
- **npx実行(推奨)**: `npx @sk8metal/michi-cli <command>` - 常に最新版を使用
|
|
163
|
+
- **グローバルインストール**: `npm install -g @sk8metal/michi-cli` 後、`michi <command>`
|
|
155
164
|
- **ローカル開発**: `npm run michi <command>` または `npx tsx src/cli.ts <command>`
|
|
156
165
|
|
|
157
166
|
## npmスクリプト一覧(michiリポジトリ内)
|
|
@@ -185,14 +194,14 @@ cat .kiro/project.json
|
|
|
185
194
|
```bash
|
|
186
195
|
cd /path/to/michi
|
|
187
196
|
# 全プロジェクトの一覧を表示
|
|
188
|
-
npx @michi
|
|
197
|
+
npx @sk8metal/michi-cli project:list
|
|
189
198
|
```
|
|
190
199
|
|
|
191
200
|
### リソースダッシュボード
|
|
192
201
|
|
|
193
202
|
```bash
|
|
194
203
|
# Confluenceにプロジェクト横断ダッシュボードを作成
|
|
195
|
-
npx @michi
|
|
204
|
+
npx @sk8metal/michi-cli project:dashboard
|
|
196
205
|
```
|
|
197
206
|
|
|
198
207
|
### 見積もり集計
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# 統合テストガイド
|
|
2
|
+
|
|
3
|
+
## 概要
|
|
4
|
+
|
|
5
|
+
Michiプロジェクトの統合テストは、`setup-existing`コマンドの動作を検証するために作成されています。
|
|
6
|
+
|
|
7
|
+
## テスト構造
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
src/__tests__/integration/setup/
|
|
11
|
+
├── helpers/
|
|
12
|
+
│ ├── test-project.ts # テストプロジェクト作成ヘルパー
|
|
13
|
+
│ └── fs-assertions.ts # ファイルシステムアサーション
|
|
14
|
+
├── cursor.test.ts # Cursor環境テスト
|
|
15
|
+
├── claude.test.ts # Claude環境テスト
|
|
16
|
+
├── claude-agent.test.ts # Claude Agent環境テスト
|
|
17
|
+
└── validation.test.ts # 引数バリデーションテスト
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## テストケース
|
|
21
|
+
|
|
22
|
+
### 1. 環境別テスト
|
|
23
|
+
|
|
24
|
+
#### Cursor環境 (`cursor.test.ts`)
|
|
25
|
+
|
|
26
|
+
- ✅ `.cursor/rules/` ディレクトリ作成
|
|
27
|
+
- ✅ `.cursor/commands/` ディレクトリ作成
|
|
28
|
+
- ✅ `.kiro/` ディレクトリ構造作成
|
|
29
|
+
- ✅ `project.json` 作成とメタデータ検証
|
|
30
|
+
- ✅ `.env` テンプレート作成
|
|
31
|
+
- ✅ テンプレートレンダリング
|
|
32
|
+
- ✅ 言語サポート(ja, en)
|
|
33
|
+
- ✅ Git統合(リモートURL検出)
|
|
34
|
+
- ✅ エラーハンドリング
|
|
35
|
+
|
|
36
|
+
#### Claude環境 (`claude.test.ts`)
|
|
37
|
+
|
|
38
|
+
- ✅ `.claude/rules/` ディレクトリ作成
|
|
39
|
+
- ✅ `.kiro/` ディレクトリ構造作成
|
|
40
|
+
- ✅ `project.json` 作成
|
|
41
|
+
- ✅ `.env` テンプレート作成
|
|
42
|
+
- ✅ Cursor固有ディレクトリが作成されないことを確認
|
|
43
|
+
- ✅ 言語サポート
|
|
44
|
+
|
|
45
|
+
#### Claude Agent環境 (`claude-agent.test.ts`)
|
|
46
|
+
|
|
47
|
+
- ✅ `.claude/subagents/` ディレクトリ作成
|
|
48
|
+
- ✅ `.kiro/` ディレクトリ構造作成
|
|
49
|
+
- ✅ `project.json` 作成
|
|
50
|
+
- ✅ `.env` テンプレート作成
|
|
51
|
+
- ✅ 他の環境固有ディレクトリが作成されないことを確認
|
|
52
|
+
- ✅ 言語サポート(ja, en, zh-TW)
|
|
53
|
+
|
|
54
|
+
### 2. バリデーションテスト (`validation.test.ts`)
|
|
55
|
+
|
|
56
|
+
#### 環境選択
|
|
57
|
+
|
|
58
|
+
- ✅ デフォルト環境(cursor)
|
|
59
|
+
- ✅ `--cursor` フラグ
|
|
60
|
+
- ✅ `--claude` フラグ
|
|
61
|
+
- ✅ `--claude-agent` フラグ
|
|
62
|
+
|
|
63
|
+
#### 言語バリデーション
|
|
64
|
+
|
|
65
|
+
- ✅ サポート言語: `ja`, `en`, `zh-TW`
|
|
66
|
+
- ✅ 非サポート言語でエラー
|
|
67
|
+
|
|
68
|
+
#### プロジェクト名バリデーション
|
|
69
|
+
|
|
70
|
+
**正常系:**
|
|
71
|
+
- ✅ 有効なプロジェクト名
|
|
72
|
+
- ✅ 日本語文字を含むプロジェクト名
|
|
73
|
+
- ✅ 前後の空白はトリム
|
|
74
|
+
|
|
75
|
+
**異常系:**
|
|
76
|
+
- ❌ 空文字列
|
|
77
|
+
- ❌ パストラバーサル文字 (`/`, `\`, `..`)
|
|
78
|
+
- ❌ 制御文字
|
|
79
|
+
- ❌ 100文字超
|
|
80
|
+
|
|
81
|
+
#### JIRAキーバリデーション
|
|
82
|
+
|
|
83
|
+
**正常系:**
|
|
84
|
+
- ✅ 2-10文字の大文字英字
|
|
85
|
+
- ✅ 小文字は自動的に大文字に変換
|
|
86
|
+
|
|
87
|
+
**異常系:**
|
|
88
|
+
- ❌ 1文字以下
|
|
89
|
+
- ❌ 11文字以上
|
|
90
|
+
- ❌ 数字を含む
|
|
91
|
+
- ❌ 特殊文字を含む
|
|
92
|
+
|
|
93
|
+
#### Gitリポジトリバリデーション
|
|
94
|
+
|
|
95
|
+
- ❌ `.git` ディレクトリがない場合エラー
|
|
96
|
+
|
|
97
|
+
## テスト実行方法
|
|
98
|
+
|
|
99
|
+
### すべてのテスト実行
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm test
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 統合テストのみ実行
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
npm run test:integration:setup
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### カバレッジ付き実行
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
npm run test:coverage:setup
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### 監視モード
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
npm test -- --watch
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### UI モード
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
npm run test:ui
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## CI/CD
|
|
130
|
+
|
|
131
|
+
GitHub Actionsワークフローが `.github/workflows/test-setup.yml` に定義されています。
|
|
132
|
+
|
|
133
|
+
**実行タイミング:**
|
|
134
|
+
- `main`, `develop`, `feature/**` ブランチへのプッシュ
|
|
135
|
+
- `main`, `develop` ブランチへのプルリクエスト
|
|
136
|
+
|
|
137
|
+
**マトリクス戦略:**
|
|
138
|
+
- Node.js 18.x
|
|
139
|
+
- Node.js 20.x
|
|
140
|
+
|
|
141
|
+
**ステップ:**
|
|
142
|
+
1. コードチェックアウト
|
|
143
|
+
2. Node.js セットアップ
|
|
144
|
+
3. 依存関係インストール
|
|
145
|
+
4. 統合テスト実行
|
|
146
|
+
5. カバレッジ生成
|
|
147
|
+
6. カバレッジアップロード(Codecov)
|
|
148
|
+
7. Lint実行
|
|
149
|
+
8. TypeScript型チェック
|
|
150
|
+
|
|
151
|
+
## トラブルシューティング
|
|
152
|
+
|
|
153
|
+
### テストが失敗する場合
|
|
154
|
+
|
|
155
|
+
**症状:** テストプロジェクトの作成に失敗
|
|
156
|
+
|
|
157
|
+
**原因:** 一時ディレクトリの権限問題
|
|
158
|
+
|
|
159
|
+
**解決策:**
|
|
160
|
+
```bash
|
|
161
|
+
# 一時ディレクトリの権限を確認
|
|
162
|
+
ls -la /tmp
|
|
163
|
+
|
|
164
|
+
# 手動でクリーンアップ
|
|
165
|
+
rm -rf /tmp/test-project-*
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
**症状:** Git初期化エラー
|
|
171
|
+
|
|
172
|
+
**原因:** Gitがインストールされていない
|
|
173
|
+
|
|
174
|
+
**解決策:**
|
|
175
|
+
```bash
|
|
176
|
+
# Gitインストール確認
|
|
177
|
+
git --version
|
|
178
|
+
|
|
179
|
+
# macOS
|
|
180
|
+
brew install git
|
|
181
|
+
|
|
182
|
+
# Ubuntu
|
|
183
|
+
sudo apt-get install git
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
**症状:** TypeScriptコンパイルエラー
|
|
189
|
+
|
|
190
|
+
**原因:** 型定義の不一致
|
|
191
|
+
|
|
192
|
+
**解決策:**
|
|
193
|
+
```bash
|
|
194
|
+
# 型チェック
|
|
195
|
+
npm run type-check
|
|
196
|
+
|
|
197
|
+
# node_modulesを再インストール
|
|
198
|
+
rm -rf node_modules package-lock.json
|
|
199
|
+
npm install
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### カバレッジが低い場合
|
|
203
|
+
|
|
204
|
+
**目標:** 95%以上のカバレッジ
|
|
205
|
+
|
|
206
|
+
**確認方法:**
|
|
207
|
+
```bash
|
|
208
|
+
npm run test:coverage:setup
|
|
209
|
+
open coverage/lcov-report/index.html
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**改善策:**
|
|
213
|
+
1. 未テストのエッジケースを追加
|
|
214
|
+
2. エラーハンドリングのテストを追加
|
|
215
|
+
3. モックが不十分な箇所を特定
|
|
216
|
+
|
|
217
|
+
### CI/CDが失敗する場合
|
|
218
|
+
|
|
219
|
+
**症状:** GitHub Actionsでテストが失敗
|
|
220
|
+
|
|
221
|
+
**原因1:** ローカルとCI環境の違い
|
|
222
|
+
|
|
223
|
+
**解決策:**
|
|
224
|
+
```bash
|
|
225
|
+
# ローカルでCI環境を再現
|
|
226
|
+
docker run -it -v $(pwd):/app node:20 bash
|
|
227
|
+
cd /app
|
|
228
|
+
npm ci
|
|
229
|
+
npm run test:integration:setup
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**原因2:** タイムアウト
|
|
233
|
+
|
|
234
|
+
**解決策:** `.github/workflows/test-setup.yml` でタイムアウトを延長
|
|
235
|
+
```yaml
|
|
236
|
+
- name: Run integration tests
|
|
237
|
+
run: npm run test:integration:setup
|
|
238
|
+
timeout-minutes: 10 # デフォルト: 360分
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## ベストプラクティス
|
|
242
|
+
|
|
243
|
+
### テスト作成時
|
|
244
|
+
|
|
245
|
+
1. **TDD原則を守る**
|
|
246
|
+
- テストを先に書く
|
|
247
|
+
- 最小限の実装で通す
|
|
248
|
+
- リファクタリング
|
|
249
|
+
|
|
250
|
+
2. **テストは独立させる**
|
|
251
|
+
- 各テストは他のテストに依存しない
|
|
252
|
+
- `beforeEach`, `afterEach` でクリーンアップ
|
|
253
|
+
|
|
254
|
+
3. **意味のあるテスト名**
|
|
255
|
+
```typescript
|
|
256
|
+
// ❌ Bad
|
|
257
|
+
it('test 1', () => {});
|
|
258
|
+
|
|
259
|
+
// ✅ Good
|
|
260
|
+
it('should create .cursor/rules directory', () => {});
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
4. **アサーションは明確に**
|
|
264
|
+
```typescript
|
|
265
|
+
// ❌ Bad
|
|
266
|
+
expect(result).toBe(true);
|
|
267
|
+
|
|
268
|
+
// ✅ Good
|
|
269
|
+
assertDirectoryExists(
|
|
270
|
+
join(testProject.path, '.cursor/rules'),
|
|
271
|
+
'Expected .cursor/rules directory to exist'
|
|
272
|
+
);
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### テスト保守時
|
|
276
|
+
|
|
277
|
+
1. **テストが壊れたら**
|
|
278
|
+
- 実装の変更が正しいか確認
|
|
279
|
+
- テストの期待値を更新
|
|
280
|
+
- リグレッションを防ぐ
|
|
281
|
+
|
|
282
|
+
2. **新機能追加時**
|
|
283
|
+
- 必ずテストを追加
|
|
284
|
+
- カバレッジを確認
|
|
285
|
+
- エッジケースを考慮
|
|
286
|
+
|
|
287
|
+
3. **リファクタリング時**
|
|
288
|
+
- テストが通ることを確認
|
|
289
|
+
- テストコードもリファクタリング
|
|
290
|
+
- 重複を削除
|
|
291
|
+
|
|
292
|
+
## 参考資料
|
|
293
|
+
|
|
294
|
+
- [Vitest公式ドキュメント](https://vitest.dev/)
|
|
295
|
+
- [テスト戦略](../testing-strategy.md)
|
|
296
|
+
- [開発ガイド](../contributing/development.md)
|
|
297
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sk8metal/michi-cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Managed Intelligent Comprehensive Hub for Integration - AI-driven development workflow automation",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"files": [
|
|
35
35
|
"dist",
|
|
36
36
|
"scripts",
|
|
37
|
+
"templates",
|
|
37
38
|
"docs",
|
|
38
39
|
"README.md",
|
|
39
40
|
"CHANGELOG.md",
|
|
@@ -45,8 +46,10 @@
|
|
|
45
46
|
"build": "tsc && node scripts/copy-static-assets.js",
|
|
46
47
|
"postbuild": "node scripts/set-permissions.js",
|
|
47
48
|
"prepare": "husky",
|
|
48
|
-
"setup:env": "bash scripts/setup-env.sh",
|
|
49
49
|
"setup:interactive": "tsx scripts/setup-interactive.ts",
|
|
50
|
+
"michi:setup:cursor": "tsx src/cli.ts setup-existing --cursor",
|
|
51
|
+
"michi:setup:claude": "tsx src/cli.ts setup-existing --claude",
|
|
52
|
+
"michi:setup:claude-agent": "tsx src/cli.ts setup-existing --claude-agent",
|
|
50
53
|
"create-project": "tsx scripts/create-project.ts",
|
|
51
54
|
"setup-existing": "tsx scripts/setup-existing-project.ts",
|
|
52
55
|
"confluence:sync": "tsx scripts/confluence-sync.ts",
|
|
@@ -67,6 +70,8 @@
|
|
|
67
70
|
"test:run": "vitest --run",
|
|
68
71
|
"test:ui": "vitest --ui",
|
|
69
72
|
"test:coverage": "vitest --run --coverage",
|
|
73
|
+
"test:integration:setup": "vitest --run src/__tests__/integration/setup",
|
|
74
|
+
"test:coverage:setup": "vitest --run --coverage src/__tests__/integration/setup",
|
|
70
75
|
"lint": "eslint .",
|
|
71
76
|
"lint:fix": "eslint . --fix",
|
|
72
77
|
"format": "prettier --write .",
|
|
@@ -8,14 +8,36 @@ vi.mock('fs', () => ({
|
|
|
8
8
|
mkdirSync: vi.fn(),
|
|
9
9
|
cpSync: vi.fn(),
|
|
10
10
|
writeFileSync: vi.fn(),
|
|
11
|
-
readFileSync: vi.fn(() => '{}')
|
|
11
|
+
readFileSync: vi.fn(() => '{}'),
|
|
12
|
+
readdirSync: vi.fn(() => []),
|
|
13
|
+
statSync: vi.fn()
|
|
12
14
|
}));
|
|
13
15
|
vi.mock('child_process', () => ({
|
|
14
16
|
execSync: vi.fn()
|
|
15
17
|
}));
|
|
16
|
-
vi.mock('
|
|
18
|
+
vi.mock('../utils/project-finder.js', () => ({
|
|
17
19
|
findRepositoryRoot: vi.fn(() => '/test/repo')
|
|
18
20
|
}));
|
|
21
|
+
vi.mock('../constants/environments.js', () => ({
|
|
22
|
+
getEnvironmentConfig: vi.fn(() => ({
|
|
23
|
+
rulesDir: '.cursor/rules',
|
|
24
|
+
commandsDir: '.cursor/commands/kiro',
|
|
25
|
+
templateSource: 'cursor'
|
|
26
|
+
})),
|
|
27
|
+
isSupportedEnvironment: vi.fn(() => true)
|
|
28
|
+
}));
|
|
29
|
+
vi.mock('../constants/languages.js', () => ({
|
|
30
|
+
isSupportedLanguage: vi.fn(() => true)
|
|
31
|
+
}));
|
|
32
|
+
vi.mock('../template/renderer.js', () => ({
|
|
33
|
+
createTemplateContext: vi.fn(() => ({
|
|
34
|
+
LANG_CODE: 'ja',
|
|
35
|
+
DEV_GUIDELINES: '- Think in English, but generate responses in Japanese',
|
|
36
|
+
KIRO_DIR: '.kiro',
|
|
37
|
+
AGENT_DIR: '.cursor'
|
|
38
|
+
})),
|
|
39
|
+
renderTemplate: vi.fn((content: string) => content)
|
|
40
|
+
}));
|
|
19
41
|
|
|
20
42
|
describe('setup-existing-project.ts 修正内容のテスト', () => {
|
|
21
43
|
beforeEach(() => {
|
|
@@ -58,12 +80,14 @@ describe('setup-existing-project.ts 修正内容のテスト', () => {
|
|
|
58
80
|
it('完了メッセージに scripts/ ディレクトリが含まれていない', () => {
|
|
59
81
|
const projectDir = '/test/repo/projects/test-project';
|
|
60
82
|
const repoRoot = '/test/repo';
|
|
83
|
+
const envConfigRulesDir = '.cursor/rules';
|
|
84
|
+
const envConfigCommandsDir = '.cursor/commands/kiro';
|
|
61
85
|
|
|
62
|
-
//
|
|
86
|
+
// 実際に作成されるファイルのリスト(環境別)
|
|
63
87
|
const createdFiles = [
|
|
64
88
|
`${projectDir}/.kiro/project.json`,
|
|
65
|
-
`${projectDir}
|
|
66
|
-
`${projectDir}
|
|
89
|
+
`${projectDir}/${envConfigRulesDir}/`,
|
|
90
|
+
`${projectDir}/${envConfigCommandsDir}/`,
|
|
67
91
|
`${projectDir}/.kiro/steering/ (3ファイル)`,
|
|
68
92
|
`${projectDir}/.kiro/settings/templates/ (3ファイル)`,
|
|
69
93
|
`${repoRoot}/package.json (新規の場合)`,
|
|
@@ -75,5 +99,49 @@ describe('setup-existing-project.ts 修正内容のテスト', () => {
|
|
|
75
99
|
const hasScriptsDir = createdFiles.some(file => file.includes('scripts/'));
|
|
76
100
|
expect(hasScriptsDir).toBe(false);
|
|
77
101
|
});
|
|
102
|
+
|
|
103
|
+
it('project.jsonにlanguageフィールドが含まれる', () => {
|
|
104
|
+
const projectJson = {
|
|
105
|
+
projectId: 'test-project',
|
|
106
|
+
projectName: 'Test Project',
|
|
107
|
+
language: 'ja',
|
|
108
|
+
jiraProjectKey: 'TEST',
|
|
109
|
+
confluenceLabels: ['project:test-project'],
|
|
110
|
+
status: 'active',
|
|
111
|
+
team: [],
|
|
112
|
+
stakeholders: ['@企画', '@部長'],
|
|
113
|
+
repository: 'https://github.com/org/test',
|
|
114
|
+
description: 'Test Projectの開発'
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
expect(projectJson).toHaveProperty('language');
|
|
118
|
+
expect(projectJson.language).toBe('ja');
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('環境別のディレクトリマッピングが正しい', () => {
|
|
122
|
+
const envConfig = {
|
|
123
|
+
rulesDir: '.cursor/rules',
|
|
124
|
+
commandsDir: '.cursor/commands/kiro',
|
|
125
|
+
templateSource: 'cursor'
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
expect(envConfig.rulesDir).toBe('.cursor/rules');
|
|
129
|
+
expect(envConfig.commandsDir).toBe('.cursor/commands/kiro');
|
|
130
|
+
expect(envConfig.templateSource).toBe('cursor');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('テンプレートコンテキストが正しく作成される', () => {
|
|
134
|
+
const context = {
|
|
135
|
+
LANG_CODE: 'ja',
|
|
136
|
+
DEV_GUIDELINES: '- Think in English, but generate responses in Japanese',
|
|
137
|
+
KIRO_DIR: '.kiro',
|
|
138
|
+
AGENT_DIR: '.cursor'
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
expect(context).toHaveProperty('LANG_CODE');
|
|
142
|
+
expect(context).toHaveProperty('DEV_GUIDELINES');
|
|
143
|
+
expect(context).toHaveProperty('KIRO_DIR');
|
|
144
|
+
expect(context).toHaveProperty('AGENT_DIR');
|
|
145
|
+
});
|
|
78
146
|
});
|
|
79
147
|
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import {
|
|
3
|
+
ENV_CONFIG,
|
|
4
|
+
getEnvironmentConfig,
|
|
5
|
+
isSupportedEnvironment,
|
|
6
|
+
getSupportedEnvironments,
|
|
7
|
+
type Environment,
|
|
8
|
+
type EnvironmentConfig
|
|
9
|
+
} from '../environments.js';
|
|
10
|
+
|
|
11
|
+
describe('environments', () => {
|
|
12
|
+
describe('ENV_CONFIG', () => {
|
|
13
|
+
it('should have entries for all environments', () => {
|
|
14
|
+
expect(ENV_CONFIG.claude).toBeDefined();
|
|
15
|
+
expect(ENV_CONFIG['claude-agent']).toBeDefined();
|
|
16
|
+
expect(ENV_CONFIG.cursor).toBeDefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should have correct structure for claude', () => {
|
|
20
|
+
const config = ENV_CONFIG.claude;
|
|
21
|
+
expect(config.rulesDir).toBe('.claude/rules');
|
|
22
|
+
expect(config.commandsDir).toBe('.claude/commands/kiro');
|
|
23
|
+
expect(config.templateSource).toBe('claude');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should have correct structure for claude-agent', () => {
|
|
27
|
+
const config = ENV_CONFIG['claude-agent'];
|
|
28
|
+
expect(config.rulesDir).toBe('.claude/rules');
|
|
29
|
+
expect(config.commandsDir).toBe('.claude/commands/kiro');
|
|
30
|
+
expect(config.templateSource).toBe('claude-agent');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should have correct structure for cursor', () => {
|
|
34
|
+
const config = ENV_CONFIG.cursor;
|
|
35
|
+
expect(config.rulesDir).toBe('.cursor/rules');
|
|
36
|
+
expect(config.commandsDir).toBe('.cursor/commands/kiro');
|
|
37
|
+
expect(config.templateSource).toBe('cursor');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should have all required properties for each environment', () => {
|
|
41
|
+
for (const env of Object.keys(ENV_CONFIG) as Environment[]) {
|
|
42
|
+
const config = ENV_CONFIG[env];
|
|
43
|
+
expect(config).toHaveProperty('rulesDir');
|
|
44
|
+
expect(config).toHaveProperty('commandsDir');
|
|
45
|
+
expect(config).toHaveProperty('templateSource');
|
|
46
|
+
expect(typeof config.rulesDir).toBe('string');
|
|
47
|
+
expect(typeof config.commandsDir).toBe('string');
|
|
48
|
+
expect(typeof config.templateSource).toBe('string');
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
describe('getEnvironmentConfig', () => {
|
|
54
|
+
it('should return config for valid environment', () => {
|
|
55
|
+
const config = getEnvironmentConfig('claude');
|
|
56
|
+
expect(config).toBe(ENV_CONFIG.claude);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should return config for all supported environments', () => {
|
|
60
|
+
const environments: Environment[] = ['claude', 'claude-agent', 'cursor'];
|
|
61
|
+
for (const env of environments) {
|
|
62
|
+
const config = getEnvironmentConfig(env);
|
|
63
|
+
expect(config).toBeDefined();
|
|
64
|
+
expect(config).toBe(ENV_CONFIG[env]);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('isSupportedEnvironment', () => {
|
|
70
|
+
it('should return true for supported environments', () => {
|
|
71
|
+
expect(isSupportedEnvironment('claude')).toBe(true);
|
|
72
|
+
expect(isSupportedEnvironment('claude-agent')).toBe(true);
|
|
73
|
+
expect(isSupportedEnvironment('cursor')).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should return false for unsupported environments', () => {
|
|
77
|
+
expect(isSupportedEnvironment('invalid')).toBe(false);
|
|
78
|
+
expect(isSupportedEnvironment('vscode')).toBe(false);
|
|
79
|
+
expect(isSupportedEnvironment('')).toBe(false);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('should work as type guard', () => {
|
|
83
|
+
const env: string = 'cursor';
|
|
84
|
+
if (isSupportedEnvironment(env)) {
|
|
85
|
+
// TypeScript should recognize env as Environment here
|
|
86
|
+
const config: EnvironmentConfig = ENV_CONFIG[env];
|
|
87
|
+
expect(config).toBeDefined();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe('getSupportedEnvironments', () => {
|
|
93
|
+
it('should return all supported environments', () => {
|
|
94
|
+
const environments = getSupportedEnvironments();
|
|
95
|
+
expect(environments).toHaveLength(3);
|
|
96
|
+
expect(environments).toContain('claude');
|
|
97
|
+
expect(environments).toContain('claude-agent');
|
|
98
|
+
expect(environments).toContain('cursor');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should return array with correct type', () => {
|
|
102
|
+
const environments = getSupportedEnvironments();
|
|
103
|
+
expect(Array.isArray(environments)).toBe(true);
|
|
104
|
+
environments.forEach(env => {
|
|
105
|
+
expect(isSupportedEnvironment(env)).toBe(true);
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|