@sk8metal/michi-cli 0.10.1 → 0.11.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.
- package/README.md +77 -847
- package/dist/scripts/phase-runner.js +1 -1
- package/dist/scripts/phase-runner.js.map +1 -1
- package/dist/scripts/utils/multi-repo-validator.d.ts +18 -0
- package/dist/scripts/utils/multi-repo-validator.d.ts.map +1 -1
- package/dist/scripts/utils/multi-repo-validator.js +42 -0
- package/dist/scripts/utils/multi-repo-validator.js.map +1 -1
- package/dist/scripts/utils/tasks-format-validator.js +3 -3
- package/dist/scripts/utils/tasks-format-validator.js.map +1 -1
- package/docs/README.md +20 -83
- package/docs/getting-started/configuration.md +379 -0
- package/docs/getting-started/installation.md +59 -0
- package/docs/getting-started/quick-start.md +76 -0
- package/docs/guides/ai-tools.md +311 -0
- package/docs/guides/atlassian-integration.md +116 -0
- package/docs/guides/claude-code.md +155 -0
- package/docs/guides/multi-repo.md +117 -0
- package/docs/guides/workflow.md +382 -0
- package/docs/reference/ai-commands.md +92 -0
- package/docs/reference/cli.md +756 -0
- package/docs/reference/environment-variables.md +192 -0
- package/docs/troubleshooting.md +543 -0
- package/package.json +1 -1
- package/scripts/phase-runner.ts +1 -1
- package/scripts/utils/__tests__/multi-repo-validator.test.ts +159 -1
- package/scripts/utils/multi-repo-validator.ts +50 -0
- package/scripts/utils/tasks-format-validator.ts +3 -3
- package/templates/claude/agents/e2e-first-planner/AGENT.md +1 -1
- package/templates/claude/agents/pr-resolver/AGENT.md +15 -3
- package/templates/claude/commands/michi/e2e-plan.md +1 -1
- package/templates/claude/commands/michi/spec-design.md +2 -2
- package/templates/claude/commands/michi/spec-tasks.md +156 -0
- package/templates/claude/commands/michi/test-planning.md +1 -1
- package/templates/claude/commands/michi/validate-design.md +3 -3
- package/templates/claude/commands/michi-multi-repo/impl-all.md +30 -1
- package/templates/claude/commands/michi-multi-repo/propagate-specs.md +14 -1
- package/templates/claude/commands/michi-multi-repo/spec-review.md +16 -2
- package/templates/claude-agent/agents/repo-spec-executor.md +1 -1
- package/templates/claude-agent/commands/michi/spec-tasks.md +117 -0
- package/templates/claude-agent/rules/code-size-monitor.md +26 -0
- package/templates/claude-agent/rules/code-size-rules.md +32 -0
- package/templates/codex/AGENTS.override.md +1 -1
- package/templates/codex/rules/README.md +2 -2
- package/templates/cursor/commands/michi/spec-tasks.md +117 -0
- package/templates/michi/cc-sdd-overrides/settings/rules/design-review-michi.md +1 -1
- package/docs/context.md +0 -59
- package/docs/michi-development/contributing/development.md +0 -341
- package/docs/michi-development/contributing/release.md +0 -365
- package/docs/michi-development/design/config-unification.md +0 -733
- package/docs/michi-development/design/design-config-current-state.md +0 -330
- package/docs/michi-development/design/design-config-implementation.md +0 -628
- package/docs/michi-development/design/design-config-migration.md +0 -952
- package/docs/michi-development/design/design-config-security.md +0 -771
- package/docs/michi-development/design/design-config-solution.md +0 -583
- package/docs/michi-development/design/design-config-testing.md +0 -892
- package/docs/michi-development/testing/manual-verification-flow.md +0 -871
- package/docs/michi-development/testing/manual-verification-other-tools.md +0 -1279
- package/docs/michi-development/testing/manual-verification-troubleshooting.md +0 -122
- package/docs/michi-development/testing/pre-publish-checklist.md +0 -560
- package/docs/michi-development/testing-strategy.md +0 -87
- package/docs/plan.md +0 -275
- package/docs/user-guide/getting-started/github-token-setup.md +0 -510
- package/docs/user-guide/getting-started/new-repository-setup.md +0 -704
- package/docs/user-guide/getting-started/quick-start.md +0 -212
- package/docs/user-guide/getting-started/setup.md +0 -819
- package/docs/user-guide/guides/agent-skills-integration.md +0 -222
- package/docs/user-guide/guides/customization.md +0 -537
- package/docs/user-guide/guides/internationalization.md +0 -540
- package/docs/user-guide/guides/migration-guide.md +0 -138
- package/docs/user-guide/guides/multi-project.md +0 -368
- package/docs/user-guide/guides/multi-repo-guide.md +0 -1590
- package/docs/user-guide/guides/phase-automation.md +0 -419
- package/docs/user-guide/guides/workflow.md +0 -574
- package/docs/user-guide/hands-on/README.md +0 -142
- package/docs/user-guide/hands-on/claude-agent-setup.md +0 -597
- package/docs/user-guide/hands-on/claude-setup.md +0 -452
- package/docs/user-guide/hands-on/cursor-setup.md +0 -353
- package/docs/user-guide/hands-on/troubleshooting.md +0 -964
- package/docs/user-guide/hands-on/verification-checklist.md +0 -439
- package/docs/user-guide/hands-on/workflow-walkthrough.md +0 -1078
- package/docs/user-guide/reference/config.md +0 -589
- package/docs/user-guide/reference/multi-repo-api.md +0 -771
- package/docs/user-guide/reference/quick-reference.md +0 -297
- package/docs/user-guide/reference/security-test-payloads.md +0 -50
- package/docs/user-guide/reference/tasks-template.md +0 -550
- package/docs/user-guide/release/ci-setup-java.md +0 -114
- package/docs/user-guide/release/ci-setup-nodejs.md +0 -94
- package/docs/user-guide/release/ci-setup-php.md +0 -102
- package/docs/user-guide/release/ci-setup-troubleshooting.md +0 -94
- package/docs/user-guide/release/ci-setup.md +0 -188
- package/docs/user-guide/release/release-flow.md +0 -476
- package/docs/user-guide/templates/test-specs/README.md +0 -173
- package/docs/user-guide/templates/test-specs/e2e-test-spec-template.md +0 -553
- package/docs/user-guide/templates/test-specs/integration-test-spec-template.md +0 -435
- package/docs/user-guide/templates/test-specs/performance-test-spec-template.md +0 -454
- package/docs/user-guide/templates/test-specs/security-test-spec-template.md +0 -625
- package/docs/user-guide/templates/test-specs/unit-test-spec-template.md +0 -328
- package/docs/user-guide/testing/integration-tests.md +0 -312
- package/docs/user-guide/testing/tdd-cycle.md +0 -349
- package/docs/user-guide/testing/test-execution-flow.md +0 -396
- package/docs/user-guide/testing/test-failure-handling.md +0 -521
- package/docs/user-guide/testing/test-planning-flow.md +0 -185
- package/docs/user-guide/testing-strategy.md +0 -185
- package/docs/verification-guide.md +0 -518
|
@@ -1,771 +0,0 @@
|
|
|
1
|
-
# Multi-Repo API仕様書
|
|
2
|
-
|
|
3
|
-
このドキュメントは、Multi-Repo機能のAPI仕様を定義します。データモデル、設定スキーマ、外部API統合、内部APIのインターフェースを含みます。
|
|
4
|
-
|
|
5
|
-
## 目次
|
|
6
|
-
|
|
7
|
-
1. [データモデル](#データモデル)
|
|
8
|
-
2. [設定スキーマ](#設定スキーマ)
|
|
9
|
-
3. [外部API統合](#外部api統合)
|
|
10
|
-
4. [内部API](#内部api)
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## データモデル
|
|
15
|
-
|
|
16
|
-
### MultiRepoProject
|
|
17
|
-
|
|
18
|
-
Multi-Repoプロジェクトを表すデータモデル。
|
|
19
|
-
|
|
20
|
-
```typescript
|
|
21
|
-
interface MultiRepoProject {
|
|
22
|
-
name: string; // プロジェクト名(1-100文字、パス区切り文字・制御文字禁止)
|
|
23
|
-
jiraKey: string; // JIRAキー(2-10文字の大文字英字)
|
|
24
|
-
confluenceSpace: string; // Confluenceスペースキー
|
|
25
|
-
createdAt: string; // 作成日時(ISO 8601形式)
|
|
26
|
-
repositories: Repository[]; // リポジトリリスト
|
|
27
|
-
}
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
**バリデーションルール:**
|
|
31
|
-
- `name`:
|
|
32
|
-
- 長さ: 1-100文字
|
|
33
|
-
- 禁止文字: `/`, `\`, `.`, `..`, 制御文字(`\x00-\x1F`, `\x7F`)
|
|
34
|
-
- `jiraKey`: 正規表現 `/^[A-Z]{2,10}$/`(2-10文字の大文字英字のみ)
|
|
35
|
-
- `confluenceSpace`: 非空文字列
|
|
36
|
-
- `createdAt`: ISO 8601形式(タイムゾーン付き)
|
|
37
|
-
- `repositories`: Repositoryの配列(デフォルト: 空配列)
|
|
38
|
-
|
|
39
|
-
### Repository
|
|
40
|
-
|
|
41
|
-
Multi-Repoプロジェクトに含まれるGitHubリポジトリ情報。
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
interface Repository {
|
|
45
|
-
name: string; // リポジトリ名(識別用)
|
|
46
|
-
url: string; // GitHub HTTPS URL
|
|
47
|
-
branch: string; // ブランチ名(デフォルト: 'main')
|
|
48
|
-
}
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
**バリデーションルール:**
|
|
52
|
-
- `name`: 非空文字列
|
|
53
|
-
- `url`:
|
|
54
|
-
- プロトコル: HTTPS必須
|
|
55
|
-
- 形式: `https://github.com/{owner}/{repo}`
|
|
56
|
-
- 禁止: `.git`拡張子、プレースホルダー値(`your-org`, `your-repo`, `repo-name`)
|
|
57
|
-
- `branch`: デフォルト値 `'main'`
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## 設定スキーマ
|
|
62
|
-
|
|
63
|
-
### AppConfigSchema
|
|
64
|
-
|
|
65
|
-
`.michi/config.json`のトップレベル設定スキーマ。
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
interface AppConfig {
|
|
69
|
-
confluence?: ConfluenceConfig;
|
|
70
|
-
jira?: JiraConfig;
|
|
71
|
-
workflow?: WorkflowConfig;
|
|
72
|
-
validation?: ValidationConfig;
|
|
73
|
-
atlassian?: AtlassianConfig;
|
|
74
|
-
project?: ProjectMeta;
|
|
75
|
-
multiRepoProjects?: MultiRepoProject[]; // Multi-Repo拡張
|
|
76
|
-
}
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### MultiRepoProjectSchema
|
|
80
|
-
|
|
81
|
-
Multi-Repoプロジェクトのスキーマ定義(Zod)。
|
|
82
|
-
|
|
83
|
-
```typescript
|
|
84
|
-
import { z } from 'zod';
|
|
85
|
-
|
|
86
|
-
export const MultiRepoProjectSchema = z.object({
|
|
87
|
-
name: z
|
|
88
|
-
.string()
|
|
89
|
-
.min(1, { message: 'Project name must be at least 1 character' })
|
|
90
|
-
.max(100, { message: 'Project name must be at most 100 characters' })
|
|
91
|
-
.refine(
|
|
92
|
-
(name) => {
|
|
93
|
-
// パストラバーサル対策
|
|
94
|
-
if (name.includes('/') || name.includes('\\')) return false;
|
|
95
|
-
// 相対パス対策
|
|
96
|
-
if (name === '.' || name === '..') return false;
|
|
97
|
-
// 制御文字対策
|
|
98
|
-
const controlCharRegex = /[\x00-\x1F\x7F]/;
|
|
99
|
-
if (controlCharRegex.test(name)) return false;
|
|
100
|
-
return true;
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
message: 'Project name must not contain path traversal characters (/, \\), relative path components (., ..), or control characters',
|
|
104
|
-
}
|
|
105
|
-
),
|
|
106
|
-
jiraKey: z
|
|
107
|
-
.string()
|
|
108
|
-
.min(1)
|
|
109
|
-
.regex(/^[A-Z]{2,10}$/, {
|
|
110
|
-
message: 'JIRA key must be 2-10 uppercase letters',
|
|
111
|
-
}),
|
|
112
|
-
confluenceSpace: z.string().min(1, {
|
|
113
|
-
message: 'Confluence space must be a non-empty string',
|
|
114
|
-
}),
|
|
115
|
-
createdAt: z.string().datetime({
|
|
116
|
-
offset: true,
|
|
117
|
-
message: 'createdAt must be in ISO 8601 format',
|
|
118
|
-
}),
|
|
119
|
-
repositories: z.array(RepositorySchema).default([]),
|
|
120
|
-
});
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### RepositorySchema
|
|
124
|
-
|
|
125
|
-
リポジトリのスキーマ定義(Zod)。
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
export const RepositorySchema = z.object({
|
|
129
|
-
name: z.string().min(1),
|
|
130
|
-
url: z
|
|
131
|
-
.string()
|
|
132
|
-
.url()
|
|
133
|
-
.regex(/^https:\/\/github\.com\/[^/]+\/[^/]+$/, {
|
|
134
|
-
message: 'GitHub URL must be in format: https://github.com/{owner}/{repo}',
|
|
135
|
-
}),
|
|
136
|
-
branch: z.string().default('main'),
|
|
137
|
-
});
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### バリデーション関数
|
|
141
|
-
|
|
142
|
-
#### validateProjectName
|
|
143
|
-
|
|
144
|
-
```typescript
|
|
145
|
-
export interface ValidationResult {
|
|
146
|
-
isValid: boolean;
|
|
147
|
-
errors: string[];
|
|
148
|
-
warnings: string[];
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export function validateProjectName(name: string): ValidationResult;
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
**用途**: プロジェクト名のセキュリティバリデーション(パストラバーサル、相対パス、制御文字対策)
|
|
155
|
-
|
|
156
|
-
**戻り値**:
|
|
157
|
-
- `isValid`: バリデーション成功の場合 `true`
|
|
158
|
-
- `errors`: エラーメッセージの配列
|
|
159
|
-
- `warnings`: 警告メッセージの配列
|
|
160
|
-
|
|
161
|
-
#### validateJiraKey
|
|
162
|
-
|
|
163
|
-
```typescript
|
|
164
|
-
export function validateJiraKey(key: string): ValidationResult;
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
**用途**: JIRAキーの形式バリデーション(2-10文字の大文字英字)
|
|
168
|
-
|
|
169
|
-
#### validateRepositoryUrl
|
|
170
|
-
|
|
171
|
-
```typescript
|
|
172
|
-
export function validateRepositoryUrl(url: string): ValidationResult;
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
**用途**: リポジトリURLの形式バリデーション(GitHub HTTPS URLのみ許可)
|
|
176
|
-
|
|
177
|
-
**検証項目**:
|
|
178
|
-
- HTTPSプロトコル必須
|
|
179
|
-
- GitHub URL形式: `https://github.com/{owner}/{repo}`
|
|
180
|
-
- `.git`拡張子禁止
|
|
181
|
-
- プレースホルダー値禁止
|
|
182
|
-
- SSH URL形式(`git@github.com:`)禁止
|
|
183
|
-
|
|
184
|
-
---
|
|
185
|
-
|
|
186
|
-
## 外部API統合
|
|
187
|
-
|
|
188
|
-
### GitHub Actions API
|
|
189
|
-
|
|
190
|
-
Multi-Repo機能は、GitHub Actions APIを使用してWorkflow Runsを取得します。
|
|
191
|
-
|
|
192
|
-
#### 使用ライブラリ
|
|
193
|
-
|
|
194
|
-
- `@octokit/rest`: GitHub REST APIクライアント
|
|
195
|
-
|
|
196
|
-
#### 認証
|
|
197
|
-
|
|
198
|
-
環境変数 `GITHUB_TOKEN` にPersonal Access Token(PAT)を設定。
|
|
199
|
-
|
|
200
|
-
**必要なスコープ**:
|
|
201
|
-
- `repo`: リポジトリへのフルアクセス(publicリポジトリの場合は `public_repo`)
|
|
202
|
-
- `workflow`: GitHub Actionsワークフローへのアクセス
|
|
203
|
-
|
|
204
|
-
#### API呼び出し例
|
|
205
|
-
|
|
206
|
-
```typescript
|
|
207
|
-
import { Octokit } from '@octokit/rest';
|
|
208
|
-
|
|
209
|
-
const octokit = new Octokit({
|
|
210
|
-
auth: process.env.GITHUB_TOKEN,
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
// Workflow Runs取得
|
|
214
|
-
const response = await octokit.actions.listWorkflowRunsForRepo({
|
|
215
|
-
owner: 'gotalab',
|
|
216
|
-
repo: 'michi',
|
|
217
|
-
branch: 'main',
|
|
218
|
-
status: 'completed',
|
|
219
|
-
per_page: 1,
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
const latestRun = response.data.workflow_runs[0];
|
|
223
|
-
console.log(`Status: ${latestRun.conclusion}`);
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
#### レート制限対策
|
|
227
|
-
|
|
228
|
-
- **Exponential Backoff**: レート制限エラー(403)発生時、指数関数的に待機時間を増やして再試行
|
|
229
|
-
- **再試行回数**: 最大3回
|
|
230
|
-
- **待機時間**: 1秒、2秒、4秒
|
|
231
|
-
|
|
232
|
-
```typescript
|
|
233
|
-
async function exponentialBackoff<T>(
|
|
234
|
-
fn: () => Promise<T>,
|
|
235
|
-
maxRetries: number = 3
|
|
236
|
-
): Promise<T> {
|
|
237
|
-
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
238
|
-
try {
|
|
239
|
-
return await fn();
|
|
240
|
-
} catch (error: any) {
|
|
241
|
-
if (error.status !== 403 || attempt === maxRetries - 1) {
|
|
242
|
-
throw error;
|
|
243
|
-
}
|
|
244
|
-
const waitTime = Math.pow(2, attempt) * 1000;
|
|
245
|
-
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
throw new Error('Max retries exceeded');
|
|
249
|
-
}
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
### Confluence API
|
|
253
|
-
|
|
254
|
-
Multi-Repo機能は、Confluence REST APIを使用してページの作成・更新を行います。
|
|
255
|
-
|
|
256
|
-
#### 認証
|
|
257
|
-
|
|
258
|
-
環境変数による認証:
|
|
259
|
-
- `ATLASSIAN_URL`: Atlassianインスタンス URL(例: `https://your-company.atlassian.net`)
|
|
260
|
-
- `ATLASSIAN_EMAIL`: Atlassianアカウントのメールアドレス
|
|
261
|
-
- `ATLASSIAN_API_TOKEN`: Atlassian API トークン([アカウント設定](https://id.atlassian.com/manage/api-tokens)で生成)
|
|
262
|
-
|
|
263
|
-
#### API呼び出し例
|
|
264
|
-
|
|
265
|
-
```typescript
|
|
266
|
-
import axios from 'axios';
|
|
267
|
-
|
|
268
|
-
const config = {
|
|
269
|
-
url: process.env.ATLASSIAN_URL,
|
|
270
|
-
email: process.env.ATLASSIAN_EMAIL,
|
|
271
|
-
apiToken: process.env.ATLASSIAN_API_TOKEN,
|
|
272
|
-
space: 'PRD',
|
|
273
|
-
};
|
|
274
|
-
|
|
275
|
-
const baseUrl = `${config.url}/wiki/rest/api`;
|
|
276
|
-
const auth = Buffer.from(`${config.email}:${config.apiToken}`).toString('base64');
|
|
277
|
-
|
|
278
|
-
// ページ検索
|
|
279
|
-
const response = await axios.get(`${baseUrl}/content/search`, {
|
|
280
|
-
params: {
|
|
281
|
-
cql: `space = PRD AND title = "My Project"`,
|
|
282
|
-
expand: 'version',
|
|
283
|
-
},
|
|
284
|
-
headers: {
|
|
285
|
-
'Authorization': `Basic ${auth}`,
|
|
286
|
-
'Content-Type': 'application/json',
|
|
287
|
-
},
|
|
288
|
-
});
|
|
289
|
-
|
|
290
|
-
const page = response.data.results[0];
|
|
291
|
-
console.log(`Page ID: ${page.id}`);
|
|
292
|
-
```
|
|
293
|
-
|
|
294
|
-
#### ページ作成例
|
|
295
|
-
|
|
296
|
-
```typescript
|
|
297
|
-
// ページ作成ペイロード
|
|
298
|
-
const payload = {
|
|
299
|
-
type: 'page',
|
|
300
|
-
title: 'My Project',
|
|
301
|
-
space: { key: 'PRD' },
|
|
302
|
-
body: {
|
|
303
|
-
storage: {
|
|
304
|
-
value: '<p>This is the page content.</p>',
|
|
305
|
-
representation: 'storage',
|
|
306
|
-
},
|
|
307
|
-
},
|
|
308
|
-
metadata: {
|
|
309
|
-
labels: [{ name: 'multi-repo' }, { name: 'michi' }],
|
|
310
|
-
},
|
|
311
|
-
ancestors: [{ id: '12345678' }], // 親ページID(オプション)
|
|
312
|
-
};
|
|
313
|
-
|
|
314
|
-
const response = await axios.post(`${baseUrl}/content`, payload, {
|
|
315
|
-
headers: {
|
|
316
|
-
'Authorization': `Basic ${auth}`,
|
|
317
|
-
'Content-Type': 'application/json',
|
|
318
|
-
},
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
console.log(`Created page: ${response.data.id}`);
|
|
322
|
-
```
|
|
323
|
-
|
|
324
|
-
#### レート制限対策
|
|
325
|
-
|
|
326
|
-
- **リクエスト間隔**: デフォルト500ms(環境変数 `ATLASSIAN_REQUEST_DELAY` で調整可能)
|
|
327
|
-
- **待機処理**: すべてのAPI呼び出し前に `sleep()` 関数で待機
|
|
328
|
-
|
|
329
|
-
```typescript
|
|
330
|
-
function sleep(ms: number): Promise<void> {
|
|
331
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
async function makeRequest() {
|
|
335
|
-
await sleep(500); // レート制限対策
|
|
336
|
-
const response = await axios.get(url);
|
|
337
|
-
return response.data;
|
|
338
|
-
}
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
---
|
|
342
|
-
|
|
343
|
-
## 内部API
|
|
344
|
-
|
|
345
|
-
### ConfigManagement
|
|
346
|
-
|
|
347
|
-
設定ファイル(`.michi/config.json`)の読み込み・書き込み・バリデーションを行うAPI。
|
|
348
|
-
|
|
349
|
-
#### getConfig
|
|
350
|
-
|
|
351
|
-
```typescript
|
|
352
|
-
export function getConfig(rootDir?: string): AppConfig;
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
**用途**: プロジェクト設定を読み込み、デフォルト設定とマージして返す。
|
|
356
|
-
|
|
357
|
-
**引数**:
|
|
358
|
-
- `rootDir` (optional): プロジェクトルートディレクトリ(省略時はカレントディレクトリ)
|
|
359
|
-
|
|
360
|
-
**戻り値**: `AppConfig` オブジェクト(型安全、Zodバリデーション済み)
|
|
361
|
-
|
|
362
|
-
**動作**:
|
|
363
|
-
1. デフォルト設定読み込み(`scripts/config/default-config.json`)
|
|
364
|
-
2. グローバル設定読み込み(`~/.michi/config.json`)
|
|
365
|
-
3. プロジェクト設定読み込み(`.michi/config.json`)
|
|
366
|
-
4. 設定マージ(優先順位: プロジェクト > グローバル > デフォルト)
|
|
367
|
-
5. Zodスキーマバリデーション
|
|
368
|
-
6. キャッシング(ファイル更新時刻を監視)
|
|
369
|
-
|
|
370
|
-
**例**:
|
|
371
|
-
|
|
372
|
-
```typescript
|
|
373
|
-
import { getConfig } from './scripts/utils/config-loader.js';
|
|
374
|
-
|
|
375
|
-
const config = getConfig('/path/to/project');
|
|
376
|
-
console.log(config.multiRepoProjects.length);
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
#### saveConfig
|
|
380
|
-
|
|
381
|
-
```typescript
|
|
382
|
-
export function saveConfig(config: AppConfig, rootDir?: string): void;
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
**用途**: プロジェクト設定を `.michi/config.json` に保存。
|
|
386
|
-
|
|
387
|
-
**引数**:
|
|
388
|
-
- `config`: 保存する設定オブジェクト
|
|
389
|
-
- `rootDir` (optional): プロジェクトルートディレクトリ
|
|
390
|
-
|
|
391
|
-
**動作**:
|
|
392
|
-
1. Zodスキーマバリデーション
|
|
393
|
-
2. JSON形式で保存(インデント2スペース)
|
|
394
|
-
3. キャッシュクリア
|
|
395
|
-
|
|
396
|
-
**例**:
|
|
397
|
-
|
|
398
|
-
```typescript
|
|
399
|
-
import { getConfig, saveConfig } from './scripts/utils/config-loader.js';
|
|
400
|
-
|
|
401
|
-
const config = getConfig();
|
|
402
|
-
config.multiRepoProjects.push({
|
|
403
|
-
name: 'my-project',
|
|
404
|
-
jiraKey: 'MYPROJ',
|
|
405
|
-
confluenceSpace: 'PRD',
|
|
406
|
-
createdAt: new Date().toISOString(),
|
|
407
|
-
repositories: [],
|
|
408
|
-
});
|
|
409
|
-
saveConfig(config);
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
#### clearConfigCache
|
|
413
|
-
|
|
414
|
-
```typescript
|
|
415
|
-
export function clearConfigCache(): void;
|
|
416
|
-
```
|
|
417
|
-
|
|
418
|
-
**用途**: 設定キャッシュをクリア(テスト用)。
|
|
419
|
-
|
|
420
|
-
### GitHubActionsClient
|
|
421
|
-
|
|
422
|
-
GitHub Actions APIへのアクセスを抽象化し、Workflow Runsの取得とレート制限対策を提供。
|
|
423
|
-
|
|
424
|
-
#### コンストラクタ
|
|
425
|
-
|
|
426
|
-
```typescript
|
|
427
|
-
export class GitHubActionsClient {
|
|
428
|
-
constructor();
|
|
429
|
-
}
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
**用途**: GitHub Actions Clientのインスタンスを作成。
|
|
433
|
-
|
|
434
|
-
**動作**:
|
|
435
|
-
- 環境変数 `GITHUB_TOKEN` を読み込み
|
|
436
|
-
- Octokitインスタンスを初期化
|
|
437
|
-
|
|
438
|
-
**エラー**: `GITHUB_TOKEN` が未設定の場合、エラーをスロー
|
|
439
|
-
|
|
440
|
-
**例**:
|
|
441
|
-
|
|
442
|
-
```typescript
|
|
443
|
-
import { GitHubActionsClient } from './scripts/github-actions-client.js';
|
|
444
|
-
|
|
445
|
-
const client = new GitHubActionsClient();
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
#### getLatestWorkflowRun
|
|
449
|
-
|
|
450
|
-
```typescript
|
|
451
|
-
async getLatestWorkflowRun(
|
|
452
|
-
owner: string,
|
|
453
|
-
repo: string,
|
|
454
|
-
branch: string
|
|
455
|
-
): Promise<Result<IGitHubWorkflowRun, GitHubAPIError>>;
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
**用途**: 指定リポジトリ・ブランチの最新Workflow Runを取得。
|
|
459
|
-
|
|
460
|
-
**引数**:
|
|
461
|
-
- `owner`: リポジトリオーナー(例: `'gotalab'`)
|
|
462
|
-
- `repo`: リポジトリ名(例: `'michi'`)
|
|
463
|
-
- `branch`: ブランチ名(例: `'main'`)
|
|
464
|
-
|
|
465
|
-
**戻り値**: `Result<IGitHubWorkflowRun, GitHubAPIError>`
|
|
466
|
-
- 成功時: `{ success: true, data: IGitHubWorkflowRun }`
|
|
467
|
-
- 失敗時: `{ success: false, error: GitHubAPIError }`
|
|
468
|
-
|
|
469
|
-
**エラー型**:
|
|
470
|
-
|
|
471
|
-
```typescript
|
|
472
|
-
export type GitHubAPIError =
|
|
473
|
-
| { type: 'RATE_LIMIT_EXCEEDED'; retryAfter: number }
|
|
474
|
-
| { type: 'NOT_FOUND'; message: string }
|
|
475
|
-
| { type: 'UNAUTHORIZED'; message: string }
|
|
476
|
-
| { type: 'SERVER_ERROR'; message: string; statusCode: number };
|
|
477
|
-
```
|
|
478
|
-
|
|
479
|
-
**例**:
|
|
480
|
-
|
|
481
|
-
```typescript
|
|
482
|
-
const result = await client.getLatestWorkflowRun('gotalab', 'michi', 'main');
|
|
483
|
-
|
|
484
|
-
if (result.success) {
|
|
485
|
-
const run = result.data;
|
|
486
|
-
console.log(`Status: ${run.conclusion}`);
|
|
487
|
-
} else {
|
|
488
|
-
const error = result.error;
|
|
489
|
-
if (error.type === 'RATE_LIMIT_EXCEEDED') {
|
|
490
|
-
console.error(`Rate limit exceeded. Retry after ${error.retryAfter} seconds.`);
|
|
491
|
-
} else {
|
|
492
|
-
console.error(`Error: ${error.message}`);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
```
|
|
496
|
-
|
|
497
|
-
#### IGitHubWorkflowRun
|
|
498
|
-
|
|
499
|
-
```typescript
|
|
500
|
-
export interface IGitHubWorkflowRun {
|
|
501
|
-
id: number;
|
|
502
|
-
name: string;
|
|
503
|
-
head_branch: string;
|
|
504
|
-
status: 'completed' | 'in_progress' | 'queued';
|
|
505
|
-
conclusion: 'success' | 'failure' | 'cancelled' | 'skipped' | null;
|
|
506
|
-
created_at: string;
|
|
507
|
-
updated_at: string;
|
|
508
|
-
html_url: string;
|
|
509
|
-
}
|
|
510
|
-
```
|
|
511
|
-
|
|
512
|
-
#### parseGitHubWorkflowRun
|
|
513
|
-
|
|
514
|
-
```typescript
|
|
515
|
-
export function parseGitHubWorkflowRun(
|
|
516
|
-
run: IGitHubWorkflowRun
|
|
517
|
-
): Omit<IRepositoryCIStatus, 'name' | 'url' | 'branch'>;
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
**用途**: GitHub Workflow Runを解析してCI結果に変換。
|
|
521
|
-
|
|
522
|
-
**引数**: `IGitHubWorkflowRun` オブジェクト
|
|
523
|
-
|
|
524
|
-
**戻り値**: 部分的な `IRepositoryCIStatus` オブジェクト
|
|
525
|
-
|
|
526
|
-
```typescript
|
|
527
|
-
{
|
|
528
|
-
status: 'success' | 'failure' | 'running' | 'unknown';
|
|
529
|
-
testStatus: 'passed' | 'failed' | 'skipped' | 'unknown';
|
|
530
|
-
lastExecutionTime: Date;
|
|
531
|
-
failureDetails?: string;
|
|
532
|
-
}
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
**変換ルール**:
|
|
536
|
-
- `status === 'completed' && conclusion === 'success'` → `status: 'success', testStatus: 'passed'`
|
|
537
|
-
- `status === 'completed' && conclusion === 'failure'` → `status: 'failure', testStatus: 'failed'`
|
|
538
|
-
- `status === 'in_progress' || status === 'queued'` → `status: 'running', testStatus: 'unknown'`
|
|
539
|
-
- その他 → `status: 'unknown', testStatus: 'unknown'`
|
|
540
|
-
|
|
541
|
-
### ConfluenceClient
|
|
542
|
-
|
|
543
|
-
Confluence REST APIへのアクセスを抽象化し、ページの検索・作成・更新を提供。
|
|
544
|
-
|
|
545
|
-
#### コンストラクタ
|
|
546
|
-
|
|
547
|
-
```typescript
|
|
548
|
-
export class ConfluenceClient {
|
|
549
|
-
constructor(config: ConfluenceConfig);
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
interface ConfluenceConfig {
|
|
553
|
-
url: string;
|
|
554
|
-
email: string;
|
|
555
|
-
apiToken: string;
|
|
556
|
-
space: string;
|
|
557
|
-
}
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
**用途**: Confluence Clientのインスタンスを作成。
|
|
561
|
-
|
|
562
|
-
**例**:
|
|
563
|
-
|
|
564
|
-
```typescript
|
|
565
|
-
import { ConfluenceClient, getConfluenceConfig } from './scripts/confluence-sync.js';
|
|
566
|
-
|
|
567
|
-
const config = getConfluenceConfig();
|
|
568
|
-
const client = new ConfluenceClient(config);
|
|
569
|
-
```
|
|
570
|
-
|
|
571
|
-
#### searchPage
|
|
572
|
-
|
|
573
|
-
```typescript
|
|
574
|
-
async searchPage(
|
|
575
|
-
spaceKey: string,
|
|
576
|
-
title: string,
|
|
577
|
-
parentId?: string
|
|
578
|
-
): Promise<ConfluencePage | null>;
|
|
579
|
-
```
|
|
580
|
-
|
|
581
|
-
**用途**: Confluenceページを検索。
|
|
582
|
-
|
|
583
|
-
**引数**:
|
|
584
|
-
- `spaceKey`: Confluenceスペースキー(例: `'PRD'`)
|
|
585
|
-
- `title`: ページタイトル(完全一致)
|
|
586
|
-
- `parentId` (optional): 親ページID(指定時は子ページのみ検索)
|
|
587
|
-
|
|
588
|
-
**戻り値**: `ConfluencePage | null`
|
|
589
|
-
- 見つかった場合: `ConfluencePage` オブジェクト
|
|
590
|
-
- 見つからない場合: `null`
|
|
591
|
-
|
|
592
|
-
**例**:
|
|
593
|
-
|
|
594
|
-
```typescript
|
|
595
|
-
const page = await client.searchPage('PRD', 'My Project');
|
|
596
|
-
if (page) {
|
|
597
|
-
console.log(`Page ID: ${page.id}`);
|
|
598
|
-
} else {
|
|
599
|
-
console.log('Page not found');
|
|
600
|
-
}
|
|
601
|
-
```
|
|
602
|
-
|
|
603
|
-
#### createPage
|
|
604
|
-
|
|
605
|
-
```typescript
|
|
606
|
-
async createPage(
|
|
607
|
-
spaceKey: string,
|
|
608
|
-
title: string,
|
|
609
|
-
content: string,
|
|
610
|
-
parentId?: string,
|
|
611
|
-
labels?: string[]
|
|
612
|
-
): Promise<ConfluencePage>;
|
|
613
|
-
```
|
|
614
|
-
|
|
615
|
-
**用途**: Confluenceページを作成。
|
|
616
|
-
|
|
617
|
-
**引数**:
|
|
618
|
-
- `spaceKey`: Confluenceスペースキー
|
|
619
|
-
- `title`: ページタイトル
|
|
620
|
-
- `content`: ページ内容(Confluence Storage形式)
|
|
621
|
-
- `parentId` (optional): 親ページID
|
|
622
|
-
- `labels` (optional): ページラベルの配列
|
|
623
|
-
|
|
624
|
-
**戻り値**: 作成された `ConfluencePage` オブジェクト
|
|
625
|
-
|
|
626
|
-
**例**:
|
|
627
|
-
|
|
628
|
-
```typescript
|
|
629
|
-
const page = await client.createPage(
|
|
630
|
-
'PRD',
|
|
631
|
-
'My Project',
|
|
632
|
-
'<p>This is the page content.</p>',
|
|
633
|
-
'12345678',
|
|
634
|
-
['multi-repo', 'michi']
|
|
635
|
-
);
|
|
636
|
-
console.log(`Created page: ${page.id}`);
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
#### updatePage
|
|
640
|
-
|
|
641
|
-
```typescript
|
|
642
|
-
async updatePage(
|
|
643
|
-
pageId: string,
|
|
644
|
-
title: string,
|
|
645
|
-
content: string,
|
|
646
|
-
currentVersion: number
|
|
647
|
-
): Promise<ConfluencePage>;
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
**用途**: 既存Confluenceページを更新。
|
|
651
|
-
|
|
652
|
-
**引数**:
|
|
653
|
-
- `pageId`: ページID
|
|
654
|
-
- `title`: ページタイトル
|
|
655
|
-
- `content`: 更新後のページ内容(Confluence Storage形式)
|
|
656
|
-
- `currentVersion`: 現在のページバージョン番号
|
|
657
|
-
|
|
658
|
-
**戻り値**: 更新された `ConfluencePage` オブジェクト
|
|
659
|
-
|
|
660
|
-
**例**:
|
|
661
|
-
|
|
662
|
-
```typescript
|
|
663
|
-
const existingPage = await client.searchPage('PRD', 'My Project');
|
|
664
|
-
if (existingPage) {
|
|
665
|
-
const updatedPage = await client.updatePage(
|
|
666
|
-
existingPage.id,
|
|
667
|
-
'My Project',
|
|
668
|
-
'<p>Updated content.</p>',
|
|
669
|
-
existingPage.version!.number
|
|
670
|
-
);
|
|
671
|
-
console.log(`Updated page: ${updatedPage.id}`);
|
|
672
|
-
}
|
|
673
|
-
```
|
|
674
|
-
|
|
675
|
-
#### ConfluencePage
|
|
676
|
-
|
|
677
|
-
```typescript
|
|
678
|
-
export interface ConfluencePage {
|
|
679
|
-
id: string;
|
|
680
|
-
title: string;
|
|
681
|
-
type: string;
|
|
682
|
-
version?: {
|
|
683
|
-
number: number;
|
|
684
|
-
};
|
|
685
|
-
_links?: {
|
|
686
|
-
webui: string;
|
|
687
|
-
};
|
|
688
|
-
ancestors?: Array<{ id: string }>;
|
|
689
|
-
}
|
|
690
|
-
```
|
|
691
|
-
|
|
692
|
-
### MermaidConverter
|
|
693
|
-
|
|
694
|
-
MarkdownテキストからMermaidブロックを検出し、Confluenceマクロ形式に変換。
|
|
695
|
-
|
|
696
|
-
#### convertMermaidToConfluence
|
|
697
|
-
|
|
698
|
-
```typescript
|
|
699
|
-
export class MermaidConverter {
|
|
700
|
-
convertMermaidToConfluence(markdown: string): string;
|
|
701
|
-
}
|
|
702
|
-
```
|
|
703
|
-
|
|
704
|
-
**用途**: MarkdownテキストからMermaidブロック(` ```mermaid ... ``` `)を検出し、Confluenceマクロ形式(`<ac:structured-macro ac:name="mermaid">`)に変換。
|
|
705
|
-
|
|
706
|
-
**引数**:
|
|
707
|
-
- `markdown`: Markdownテキスト
|
|
708
|
-
|
|
709
|
-
**戻り値**: 変換後のテキスト
|
|
710
|
-
|
|
711
|
-
**変換ルール**:
|
|
712
|
-
1. ` ```mermaid\n...\n``` ` 形式を検出
|
|
713
|
-
2. Mermaidコードを抽出
|
|
714
|
-
3. CDATA内の `]]>` をエスケープ(`]]]]><![CDATA[>` に置換)
|
|
715
|
-
4. Confluenceマクロ形式に変換
|
|
716
|
-
|
|
717
|
-
**例**:
|
|
718
|
-
|
|
719
|
-
```typescript
|
|
720
|
-
import { MermaidConverter } from './scripts/mermaid-converter.js';
|
|
721
|
-
|
|
722
|
-
const converter = new MermaidConverter();
|
|
723
|
-
const markdown = `
|
|
724
|
-
# My Diagram
|
|
725
|
-
|
|
726
|
-
\`\`\`mermaid
|
|
727
|
-
graph TD
|
|
728
|
-
A[Start] --> B[End]
|
|
729
|
-
\`\`\`
|
|
730
|
-
`;
|
|
731
|
-
|
|
732
|
-
const converted = converter.convertMermaidToConfluence(markdown);
|
|
733
|
-
console.log(converted);
|
|
734
|
-
// Output:
|
|
735
|
-
// # My Diagram
|
|
736
|
-
//
|
|
737
|
-
// <ac:structured-macro ac:name="mermaid">
|
|
738
|
-
// <ac:plain-text-body><![CDATA[graph TD
|
|
739
|
-
// A[Start] --> B[End]]]></ac:plain-text-body>
|
|
740
|
-
// </ac:structured-macro>
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
---
|
|
744
|
-
|
|
745
|
-
## セキュリティ考慮事項
|
|
746
|
-
|
|
747
|
-
### パストラバーサル対策
|
|
748
|
-
|
|
749
|
-
- プロジェクト名、リポジトリ名に `/`, `\`, `.`, `..` を禁止
|
|
750
|
-
- 制御文字(`\x00-\x1F`, `\x7F`)を禁止
|
|
751
|
-
- 固定パスプレフィックス使用(`docs/michi/{project-name}/`)
|
|
752
|
-
|
|
753
|
-
### コマンドインジェクション対策
|
|
754
|
-
|
|
755
|
-
- `execSync()` の引数に固定パスを使用
|
|
756
|
-
- ユーザー入力を直接シェルコマンドに渡さない
|
|
757
|
-
- リポジトリURLはHTTPS GitHub URLのみ許可
|
|
758
|
-
|
|
759
|
-
### 認証情報管理
|
|
760
|
-
|
|
761
|
-
- 環境変数による認証情報管理(`.env`ファイル)
|
|
762
|
-
- API Tokenは平文で保存しない
|
|
763
|
-
- `.env`ファイルを `.gitignore` に追加
|
|
764
|
-
|
|
765
|
-
---
|
|
766
|
-
|
|
767
|
-
## 関連ドキュメント
|
|
768
|
-
|
|
769
|
-
- [Multi-Repoユーザーガイド](../guides/multi-repo-guide.md)
|
|
770
|
-
- [設定リファレンス](./config.md)
|
|
771
|
-
- [クイックリファレンス](./quick-reference.md)
|