github-mcp-auto-git
Version:
GitHub MCP Auto Git v3.0 - メモリ効率化・統合MCP・モジュール化完了の完全自動Git操作システム
398 lines (396 loc) • 18.2 kB
JavaScript
/**
* ユーザー向けセットアップウィザード
* 初心者にやさしいインタラクティブな設定ガイド
*/
import * as readline from 'readline';
import { promises as fs } from 'fs';
import { join } from 'path';
export class SetupWizard {
constructor(projectPath = process.cwd()) {
this.projectPath = projectPath;
}
/**
* メインのセットアップウィザード実行
*/
async run() {
try {
console.log('\n🚀 GitHub MCP Auto Git System セットアップウィザード');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
console.log('このウィザードで簡単にセットアップが完了します!\n');
// ステップ 1: プロジェクト確認
await this.confirmProject();
// ステップ 2: 機能選択
const features = await this.selectFeatures();
// ステップ 3: 監視設定
const watchConfig = await this.configureWatching();
// ステップ 4: GitHub設定(必要な場合)
let githubConfig = null;
if (features.enablePR || features.enableAutoMerge) {
githubConfig = await this.configureGitHub();
}
// ステップ 5: サブエージェント設定
const agentConfig = await this.configureAgents();
// ステップ 6: 設定ファイル生成
const configResult = await this.generateConfigFiles({
features,
watchConfig,
githubConfig,
agentConfig
});
// ステップ 7: 最終確認とテスト
await this.finalConfirmation(configResult);
return configResult;
}
catch (error) {
console.error('❌ セットアップ中にエラーが発生しました:', error);
return { success: false };
}
finally {
// ReadlineInterfaceは各メソッドで個別管理
}
}
/**
* ステップ 1: プロジェクト確認
*/
async confirmProject() {
console.log('📁 ステップ 1: プロジェクト確認');
console.log(`現在のディレクトリ: ${this.projectPath}`);
// package.jsonの存在確認
try {
const packageJsonPath = join(this.projectPath, 'package.json');
await fs.access(packageJsonPath);
const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8'));
console.log(`✅ プロジェクト名: ${packageJson.name || '未設定'}`);
console.log(`✅ プロジェクト言語: ${packageJson.dependencies?.typescript ? 'TypeScript' : 'JavaScript'}`);
}
catch {
console.log('ℹ️ package.json が見つかりません(Node.js以外のプロジェクトでも使用可能)');
}
// .gitの存在確認
try {
await fs.access(join(this.projectPath, '.git'));
console.log('✅ Gitリポジトリが初期化済み');
}
catch {
console.log('⚠️ Gitリポジトリが未初期化です');
const initGit = await this.askQuestion('Git リポジトリを初期化しますか? (y/n): ');
if (initGit.toLowerCase() === 'y') {
console.log('\n📋 以下のコマンドを実行してください:');
console.log(' git init');
console.log(' git add .');
console.log(' git commit -m "Initial commit"');
console.log('\nGit初期化後、再度セットアップを実行してください。');
process.exit(0);
}
}
console.log('\n✅ プロジェクト確認完了\n');
}
/**
* ステップ 2: 機能選択
*/
async selectFeatures() {
console.log('🎯 ステップ 2: 使用する機能を選択');
console.log('必要な機能を選択してください(後で変更可能):\n');
const enableAutoCommit = await this.askYesNo('📝 自動コミット機能を有効にしますか?\n' +
' → ファイル保存時に自動的にGitコミットを実行');
const enableSafetyCheck = await this.askYesNo('🛡️ 安全性チェック機能を有効にしますか?\n' +
' → 機密情報の検出、破壊的変更の防止');
const enableSmartMessages = await this.askYesNo('🤖 スマートなコミットメッセージ生成を有効にしますか?\n' +
' → AI による分かりやすいメッセージ自動生成');
const enablePR = await this.askYesNo('🔀 プルリクエスト自動作成を有効にしますか?\n' +
' → GitHub への自動PR作成(GITHUB_TOKEN必要)');
let enableAutoMerge = false;
if (enablePR) {
enableAutoMerge = await this.askYesNo('⚡ 自動マージ機能を有効にしますか?\n' +
' → 条件を満たした場合の自動PR マージ(注意が必要)');
}
console.log('\n✅ 機能選択完了\n');
return {
enableAutoCommit,
enablePR,
enableAutoMerge,
enableSafetyCheck,
enableSmartMessages
};
}
/**
* ステップ 3: 監視設定
*/
async configureWatching() {
console.log('👀 ステップ 3: ファイル監視設定');
console.log('監視対象のファイル・フォルダを設定します:\n');
const scope = await this.askChoice('監視する範囲を選択してください:', [
{ key: '1', label: 'プロジェクト全体 (推奨)', description: '全てのファイルを監視' },
{ key: '2', label: 'src フォルダのみ', description: 'src/ 以下のファイルのみ監視' },
{ key: '3', label: 'カスタム設定', description: '独自のパターンを指定' }
]);
let patterns;
const excludePatterns = ['node_modules/**', '.git/**', 'dist/**', 'build/**', '**/*.log'];
switch (scope) {
case '1':
patterns = ['**/*'];
break;
case '2':
patterns = ['src/**/*'];
break;
case '3':
const customPattern = await this.askQuestion('監視パターンを入力してください (例: src/**/*,*.md): ');
patterns = customPattern.split(',').map(p => p.trim()).filter(p => p.length > 0);
break;
default:
patterns = ['src/**/*'];
}
console.log('\n📋 監視設定確認:');
console.log(` 監視対象: ${patterns.join(', ')}`);
console.log(` 除外対象: ${excludePatterns.join(', ')}`);
console.log('\n✅ 監視設定完了\n');
return { patterns, excludePatterns };
}
/**
* ステップ 4: GitHub設定
*/
async configureGitHub() {
console.log('🔗 ステップ 4: GitHub連携設定');
console.log('PR機能を使用するためのGitHub設定を行います:\n');
const owner = await this.askQuestion('GitHubユーザー名またはOrganization名: ');
const repo = await this.askQuestion('リポジトリ名: ');
console.log('\n🔑 GITHUB_TOKEN の設定');
console.log('PR作成・マージにはGitHub Personal Access Tokenが必要です。\n');
const tokenChoice = await this.askChoice('トークンの設定方法を選択してください:', [
{ key: '1', label: '今すぐ設定', description: 'トークンを入力して .env に保存' },
{ key: '2', label: '後で設定', description: '設定方法を表示して後で手動設定' },
{ key: '3', label: 'スキップ', description: 'ローカルGit機能のみ使用' }
]);
let token;
let setupToken = false;
switch (tokenChoice) {
case '1':
console.log('\n🔧 トークン作成ガイド:');
console.log('1. https://github.com/settings/tokens にアクセス');
console.log('2. "Generate new token (classic)" をクリック');
console.log('3. 必要な権限を選択: repo, workflow');
console.log('4. トークンを生成してコピー\n');
token = await this.askQuestion('GITHUB_TOKEN を入力してください: ');
setupToken = true;
break;
case '2':
console.log('\n📋 後で設定する場合:');
console.log('1. https://github.com/settings/tokens でトークンを作成');
console.log('2. プロジェクトルートに .env ファイルを作成');
console.log('3. 以下の内容を追加:');
console.log(` GITHUB_OWNER=${owner}`);
console.log(` GITHUB_REPO=${repo}`);
console.log(' GITHUB_TOKEN=your_token_here');
setupToken = false;
break;
case '3':
console.log('\n⏭️ GitHub連携をスキップします');
console.log('ローカルGit機能のみが有効になります。');
return null;
}
console.log('\n✅ GitHub設定完了\n');
return { owner, repo, token, setupToken };
}
/**
* ステップ 5: サブエージェント設定
*/
async configureAgents() {
console.log('🤖 ステップ 5: サブエージェント詳細設定');
console.log('各サブエージェントの動作を調整します:\n');
// 簡略化されたエージェント設定
const safetyEnabled = await this.askYesNo('🛡️ Git Safety Analyzer を有効にしますか?');
const messageEnabled = await this.askYesNo('📝 Commit Message Generator を有効にしますか?');
const prEnabled = await this.askYesNo('🔀 PR Management Agent を有効にしますか?');
console.log('\n✅ サブエージェント設定完了\n');
return {
gitSafetyAnalyzer: { enabled: safetyEnabled, threshold: 0.85 },
commitMessageGenerator: { enabled: messageEnabled, language: 'ja', style: 'friendly' },
prManagementAgent: { enabled: prEnabled, autoMergeThreshold: 0.85 }
};
}
/**
* ステップ 6: 設定ファイル生成
*/
async generateConfigFiles(config) {
console.log('📄 ステップ 6: 設定ファイル生成');
console.log('設定に基づいてファイルを作成します:\n');
const warnings = [];
const nextSteps = [];
try {
// git-auto-mcp.config.js の生成
const configPath = join(this.projectPath, 'git-auto-mcp.config.js');
const configContent = this.generateConfigFileContent(config);
await fs.writeFile(configPath, configContent);
console.log(`✅ 設定ファイル作成: ${configPath}`);
// .env ファイルの生成(必要な場合)
let envPath;
if (config.githubConfig?.setupToken) {
envPath = join(this.projectPath, '.env');
const envContent = this.generateEnvFileContent(config.githubConfig);
await fs.writeFile(envPath, envContent);
console.log(`✅ 環境変数ファイル作成: ${envPath}`);
warnings.push('.env ファイルを .gitignore に追加することを強く推奨します');
}
// 次のステップの提案
nextSteps.push('github-auto-git status で設定を確認');
nextSteps.push('github-auto-git watch でファイル監視を開始');
if (config.githubConfig && !config.githubConfig.setupToken) {
nextSteps.push('github-auto-git token でGITHUB_TOKEN設定方法を確認');
}
console.log('\n✅ 設定ファイル生成完了\n');
return {
success: true,
configPath,
envPath,
warnings,
nextSteps
};
}
catch (error) {
console.error('❌ 設定ファイル生成に失敗:', error);
return { success: false };
}
}
/**
* ステップ 7: 最終確認
*/
async finalConfirmation(result) {
console.log('🎉 ステップ 7: セットアップ完了');
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
if (result.success) {
console.log('✅ GitHub MCP Auto Git System のセットアップが完了しました!\n');
if (result.warnings && result.warnings.length > 0) {
console.log('⚠️ 注意事項:');
result.warnings.forEach(warning => console.log(` • ${warning}`));
console.log('');
}
if (result.nextSteps && result.nextSteps.length > 0) {
console.log('📋 次のステップ:');
result.nextSteps.forEach((step, index) => {
console.log(` ${index + 1}. ${step}`);
});
console.log('');
}
console.log('💡 ヘルプとドキュメント:');
console.log(' • github-auto-git --help で全コマンドを表示');
console.log(' • github-auto-git token でGitHub設定ガイドを表示');
console.log('\n🚀 使用開始:');
console.log(' github-auto-git watch');
}
else {
console.log('❌ セットアップに失敗しました。');
console.log('手動設定を行うか、再度ウィザードを実行してください。');
}
}
/**
* 設定ファイルの内容生成
*/
generateConfigFileContent(config) {
const patterns = config.watchConfig.patterns.concat(config.watchConfig.excludePatterns.map((p) => `!${p}`));
return `module.exports = {
enabled: true,
triggers: ['save', 'auto'],
paths: ${JSON.stringify(patterns, null, 4)},
subAgents: {
gitSafetyAnalyzer: {
enabled: ${config.agentConfig.gitSafetyAnalyzer.enabled},
safetyThreshold: ${config.agentConfig.gitSafetyAnalyzer.threshold}
},
commitMessageGenerator: {
enabled: ${config.agentConfig.commitMessageGenerator.enabled},
language: '${config.agentConfig.commitMessageGenerator.language}',
style: '${config.agentConfig.commitMessageGenerator.style}'
},
prManagementAgent: {
enabled: ${config.agentConfig.prManagementAgent.enabled},
autoMergeThreshold: ${config.agentConfig.prManagementAgent.autoMergeThreshold}
}
},
notifications: {
success: true,
warnings: true,
detailed: false
},
github: {
owner: process.env.GITHUB_OWNER || '${config.githubConfig?.owner || ''}',
repo: process.env.GITHUB_REPO || '${config.githubConfig?.repo || ''}',
token: process.env.GITHUB_TOKEN || ''
}
};
`;
}
/**
* .env ファイルの内容生成
*/
generateEnvFileContent(githubConfig) {
return `# GitHub MCP Auto Git System 設定
# このファイルは .gitignore に追加してください
GITHUB_OWNER=${githubConfig.owner}
GITHUB_REPO=${githubConfig.repo}
GITHUB_TOKEN=${githubConfig.token || 'your_token_here'}
# 追加の環境変数があればここに記載
`;
}
/**
* ユーティリティメソッド
*/
async askQuestion(question) {
return new Promise((resolve, reject) => {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let isCompleted = false;
const cleanup = () => {
if (!isCompleted) {
isCompleted = true;
try {
rl.close();
}
catch (error) {
// ReadlineInterface already closed - ignore error
}
}
};
rl.question(question, (answer) => {
if (!isCompleted) {
cleanup();
resolve(answer.trim());
}
});
// エラーハンドリング
rl.on('error', (error) => {
if (!isCompleted) {
cleanup();
reject(error);
}
});
// プロセス終了時のクリーンアップ
const sigintHandler = () => {
if (!isCompleted) {
cleanup();
process.removeListener('SIGINT', sigintHandler);
reject(new Error('User interrupted'));
}
};
process.once('SIGINT', sigintHandler);
});
}
async askYesNo(question) {
const answer = await this.askQuestion(`${question} (y/n): `);
return answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes';
}
async askChoice(question, choices) {
console.log(question);
choices.forEach(choice => {
const desc = choice.description ? ` - ${choice.description}` : '';
console.log(` ${choice.key}. ${choice.label}${desc}`);
});
let answer;
do {
answer = await this.askQuestion('選択してください: ');
} while (!choices.some(choice => choice.key === answer));
return answer;
}
}
//# sourceMappingURL=setup-wizard.js.map