remcode
Version:
Turn your AI assistant into a codebase expert. Intelligent code analysis, semantic search, and software engineering guidance through MCP integration.
177 lines (176 loc) • 7.46 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.SetupInitializer = void 0;
const logger_1 = require("../utils/logger");
const detector_1 = require("./detector");
const prerequisites_1 = require("./prerequisites");
const secrets_1 = require("./secrets");
const workflow_generator_1 = require("./workflow-generator");
const remcode_config_1 = require("./remcode-config");
const logger = (0, logger_1.getLogger)('SetupInitializer');
/**
* Class for initializing Remcode in a repository
*/
class SetupInitializer {
/**
* Constructor
* @param repoPath Path to the repository
* @param githubToken GitHub API token
*/
constructor(repoPath = process.cwd(), githubToken) {
this.repoPath = repoPath;
this.detector = new detector_1.SetupDetector(repoPath);
this.prerequisites = new prerequisites_1.Prerequisites(repoPath);
this.secretsManager = new secrets_1.SecretsManager(githubToken);
this.workflowGenerator = new workflow_generator_1.WorkflowGenerator(repoPath);
this.configManager = new remcode_config_1.RemcodeConfigManager(repoPath);
logger.debug(`SetupInitializer initialized for path: ${repoPath}`);
}
/**
* Initialize a repository with Remcode
* @param options Setup options
* @returns Setup result
*/
async initializeRepository(options) {
const startTime = Date.now();
const { owner, repo, forceUpdate = false } = options;
logger.info(`Initializing remcode for ${owner}/${repo}`);
try {
// Phase 0: Detect current setup status
const setupStatus = await this.detector.detectSetupNeeds();
// If setup is already complete and not forcing update, return early
if (!setupStatus.needsSetup && !forceUpdate) {
logger.info('Repository already set up, no changes needed');
return {
success: true,
setupStatus,
duration: Date.now() - startTime
};
}
// Phase 1: Check prerequisites
logger.info('Phase 1: Checking prerequisites');
const prerequisiteChecks = await this.prerequisites.checkAll();
const prerequisitesPass = prerequisiteChecks.every((check) => check.passed);
if (!prerequisitesPass) {
const failedChecks = prerequisiteChecks.filter((check) => !check.passed);
const errors = failedChecks.map((check) => check.message).join(', ');
throw new Error(`Prerequisites check failed: ${errors}`);
}
// Use Git info from detector if available
const gitInfo = setupStatus.gitInfo;
const defaultBranch = options.defaultBranch || gitInfo?.defaultBranch || 'main';
// Phase 2: Configure repository secrets (if not skipped)
let secretsResult;
if (!options.skipSecrets) {
logger.info('Phase 2: Configuring repository secrets');
secretsResult = await this.secretsManager.configureRepositorySecrets(owner, repo);
if (secretsResult.failed > 0 && secretsResult.results.some(r => !r.success && r.secretName.includes('REQUIRED'))) {
throw new Error('Failed to configure required secrets');
}
}
else {
logger.info('Phase 2: Skipping repository secrets configuration');
}
// Phase 3: Generate workflow (if not skipped)
let workflowResult;
if (!options.skipWorkflow) {
logger.info('Phase 3: Generating GitHub Actions workflow');
const workflowOptions = {
repoName: repo,
owner,
branches: [defaultBranch],
customSecrets: options.customSecrets
};
workflowResult = await this.workflowGenerator.generateWorkflow(workflowOptions, options.workflowType || workflow_generator_1.WorkflowTemplateType.BASIC);
if (!workflowResult.success) {
throw new Error(`Failed to generate workflow: ${workflowResult.error}`);
}
}
else {
logger.info('Phase 3: Skipping workflow generation');
}
// Phase 4: Create or update .remcode configuration
logger.info('Phase 4: Creating .remcode configuration');
const configOptions = {
repository: {
name: repo,
owner,
url: `https://github.com/${owner}/${repo}`,
defaultBranch
}
};
const configResult = await this.configManager.createInitialConfig(owner, repo, configOptions);
// Final phase: Update setup status
const updatedStatus = await this.detector.detectSetupNeeds();
logger.info('Repository initialization complete');
return {
success: true,
setupStatus: updatedStatus,
prerequisites: prerequisiteChecks,
secretsResult,
workflowResult,
configResult,
duration: Date.now() - startTime
};
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error(`Repository initialization failed: ${errorMessage}`);
const finalStatus = await this.detector.detectSetupNeeds().catch(() => ({
needsSetup: true,
hasRemcodeFile: false,
hasGitRepo: false,
hasGitHubRepo: false,
hasWorkflow: false,
hasRequiredSecrets: false,
hasValidConfig: false,
reason: detector_1.SetupReason.NO_GITHUB_REPO,
detectionTimestamp: new Date().toISOString()
}));
return {
success: false,
setupStatus: finalStatus,
error: errorMessage,
duration: Date.now() - startTime
};
}
}
/**
* Check if a repository needs setup
* @returns Setup status
*/
async checkSetupNeeds() {
return this.detector.detectSetupNeeds();
}
/**
* Update an existing Remcode setup
* @param options Setup options
* @returns Setup result
*/
async updateSetup(options) {
// Force update
return this.initializeRepository({
...options,
forceUpdate: true
});
}
/**
* Clean up Remcode setup
* @returns True if cleanup was successful
*/
async cleanupSetup() {
try {
// Delete configuration file
const configDeleted = this.configManager.deleteConfig();
// Could also remove workflow and secrets, but that's potentially destructive
// so we'll leave that for manual cleanup
return configDeleted;
}
catch (error) {
const errorMessage = error instanceof Error ? error.message : String(error);
logger.error(`Cleanup failed: ${errorMessage}`);
return false;
}
}
}
exports.SetupInitializer = SetupInitializer;
;