repoweaver
Version:
A GitHub App that skillfully weaves multiple templates together to create and update repositories with intelligent merge strategies
218 lines (203 loc) • 8.67 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.GitHubBootstrapper = void 0;
const github_template_manager_1 = require("./github-template-manager");
class GitHubBootstrapper {
constructor(client) {
this.client = client;
this.templateManager = new github_template_manager_1.GitHubTemplateManager(client);
}
async bootstrap(options) {
const result = {
success: true,
repositoryPath: `${options.targetOwner}/${options.targetRepo}`,
templateResults: [],
totalFilesProcessed: 0,
errors: []
};
try {
// Create repository if requested
if (options.createRepository) {
await this.createRepository(options);
}
// Process each template
for (const template of options.templates) {
const templateResult = await this.templateManager.processTemplate(template, options.targetOwner, options.targetRepo, options.excludePatterns, options.mergeStrategy);
result.templateResults.push(templateResult);
result.totalFilesProcessed += templateResult.filesProcessed;
if (!templateResult.success) {
result.success = false;
result.errors.push(...templateResult.errors);
}
}
// If all templates were processed successfully, create a summary PR
if (result.success && result.templateResults.length > 1) {
await this.createSummaryPullRequest(options, result);
}
}
catch (error) {
result.success = false;
result.errors.push(`Bootstrap failed: ${error}`);
}
return result;
}
async updateRepository(options) {
const result = {
success: true,
repositoryPath: `${options.targetOwner}/${options.targetRepo}`,
templateResults: [],
totalFilesProcessed: 0,
errors: []
};
try {
// Verify repository exists
await this.client.getRepository(options.targetOwner, options.targetRepo);
// Process templates with merge strategy
for (const template of options.templates) {
const templateResult = await this.templateManager.processTemplate(template, options.targetOwner, options.targetRepo, options.excludePatterns, options.mergeStrategy || 'merge');
result.templateResults.push(templateResult);
result.totalFilesProcessed += templateResult.filesProcessed;
if (!templateResult.success) {
result.success = false;
result.errors.push(...templateResult.errors);
}
}
}
catch (error) {
result.success = false;
result.errors.push(`Update failed: ${error}`);
}
return result;
}
async createRepository(options) {
try {
return await this.client.createRepository(options.targetRepo, options.repositoryDescription, options.privateRepository);
}
catch (error) {
throw new Error(`Failed to create repository: ${error}`);
}
}
async createSummaryPullRequest(options, result) {
try {
const branch = `boots-strapper-multi-template-${Date.now()}`;
await this.client.createBranch(options.targetOwner, options.targetRepo, branch);
// Create a summary file
const summaryContent = this.generateSummaryContent(options, result);
await this.client.createOrUpdateFile(options.targetOwner, options.targetRepo, 'BOOTSTRAP_SUMMARY.md', summaryContent, 'Add bootstrap summary', branch);
// Create pull request
await this.client.createPullRequest(options.targetOwner, options.targetRepo, `Bootstrap repository with ${options.templates.length} templates`, this.generateMultiTemplatePRBody(options, result), branch, 'main');
}
catch (error) {
result.errors.push(`Failed to create summary PR: ${error}`);
}
}
generateSummaryContent(options, result) {
const timestamp = new Date().toISOString();
return `
# Bootstrap Summary
**Repository:** ${options.targetOwner}/${options.targetRepo}
**Generated:** ${timestamp}
**Total Files Processed:** ${result.totalFilesProcessed}
## Templates Applied
${options.templates.map(template => `
### ${template.name}
- **URL:** ${template.url}
- **Branch:** ${template.branch || 'main'}
${template.subDirectory ? `- **Subdirectory:** ${template.subDirectory}` : ''}
- **Files Processed:** ${result.templateResults.find(r => r.template.name === template.name)?.filesProcessed || 0}
`).join('\n')}
## Configuration
- **Merge Strategy:** ${options.mergeStrategy || 'merge'}
- **Exclude Patterns:** ${options.excludePatterns?.join(', ') || 'None'}
---
*Generated by [RepoWeaver](https://github.com/apps/repoweaver)*
`.trim();
}
generateMultiTemplatePRBody(options, result) {
return `
## Multi-Template Bootstrap
This pull request bootstraps the repository with **${options.templates.length} templates**.
**Summary:**
- Total files processed: **${result.totalFilesProcessed}**
- Templates applied: **${options.templates.length}**
- Merge strategy: **${options.mergeStrategy || 'merge'}**
**Templates:**
${options.templates.map((template, index) => {
const templateResult = result.templateResults[index];
return `${index + 1}. **${template.name}** - ${templateResult.filesProcessed} files`;
}).join('\n')}
**Pull Requests Created:**
${result.templateResults
.filter(r => r.pullRequestNumber)
.map(r => `- ${r.template.name}: #${r.pullRequestNumber}`)
.join('\n')}
See \`BOOTSTRAP_SUMMARY.md\` for detailed information.
---
*This PR was automatically generated by [RepoWeaver](https://github.com/apps/repoweaver)*
`.trim();
}
async getRepositoryTemplates(owner, repo) {
try {
// Look for RepoWeaver configuration files
const configFiles = ['weaver.json', '.weaver.json', '.repoweaver.json'];
for (const configFileName of configFiles) {
try {
const files = await this.client.getRepositoryContents(owner, repo, configFileName);
const configFile = files.find(f => f.name === configFileName);
if (configFile) {
const config = JSON.parse(configFile.content);
return config.templates || [];
}
}
catch (error) {
// File doesn't exist, try next one
continue;
}
}
return [];
}
catch (error) {
return [];
}
}
async getRepositoryConfig(owner, repo) {
try {
// Look for RepoWeaver configuration files
const configFiles = ['weaver.json', '.weaver.json', '.repoweaver.json'];
for (const configFileName of configFiles) {
try {
const files = await this.client.getRepositoryContents(owner, repo, configFileName);
const configFile = files.find(f => f.name === configFileName);
if (configFile) {
const config = JSON.parse(configFile.content);
return config;
}
}
catch (error) {
// File doesn't exist, try next one
continue;
}
}
return null;
}
catch (error) {
return null;
}
}
async saveRepositoryTemplates(owner, repo, templates) {
const config = {
templates,
lastUpdated: new Date().toISOString()
};
await this.client.createOrUpdateFile(owner, repo, 'weaver.json', JSON.stringify(config, null, 2), 'Update RepoWeaver configuration');
}
async saveRepositoryConfig(owner, repo, config) {
const configWithMetadata = {
...config,
lastUpdated: new Date().toISOString()
};
await this.client.createOrUpdateFile(owner, repo, 'weaver.json', JSON.stringify(configWithMetadata, null, 2), 'Update RepoWeaver configuration');
}
}
exports.GitHubBootstrapper = GitHubBootstrapper;
//# sourceMappingURL=github-bootstrapper.js.map