Fix installer upgrade issues from v4 to v6. and v6 custom files will no longer be lost (modified ones will though for now still)
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
<!-- Powered by BMAD-CORE™ -->
|
<!-- Powered by BMAD-CORE™ -->
|
||||||
<!-- Agent Manifest - Generated during BMAD installation -->
|
<!-- Agent Manifest - Generated during BMAD installation -->
|
||||||
<!-- This file contains a summary of all installed agents for quick reference -->
|
<!-- This file contains a summary of all installed agents for quick reference -->
|
||||||
<manifest id="bmad/_cfg/agent-party.xml" version="1.0" generated="2025-10-01T00:22:43.657Z">
|
<manifest id="bmad/_cfg/agent-party.xml" version="1.0" generated="2025-10-01T00:47:33.050Z">
|
||||||
<description>
|
<description>
|
||||||
Complete roster of installed BMAD agents with summarized personas for efficient multi-agent orchestration.
|
Complete roster of installed BMAD agents with summarized personas for efficient multi-agent orchestration.
|
||||||
Used by party-mode and other multi-agent coordination features.
|
Used by party-mode and other multi-agent coordination features.
|
||||||
@@ -164,6 +164,6 @@
|
|||||||
<statistics>
|
<statistics>
|
||||||
<total_agents>18</total_agents>
|
<total_agents>18</total_agents>
|
||||||
<modules>bmm, cis, core, custom</modules>
|
<modules>bmm, cis, core, custom</modules>
|
||||||
<last_updated>2025-10-01T00:22:43.657Z</last_updated>
|
<last_updated>2025-10-01T00:47:33.050Z</last_updated>
|
||||||
</statistics>
|
</statistics>
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
# BMAD Manifest
|
# BMAD Manifest
|
||||||
# Generated: 2025-10-01T00:22:43.703Z
|
# Generated: 2025-10-01T00:47:33.096Z
|
||||||
|
|
||||||
## Installation Info
|
## Installation Info
|
||||||
Property,Value
|
Property,Value
|
||||||
Version,6.0.0-alpha.0
|
Version,6.0.0-alpha.0
|
||||||
InstallDate,2025-10-01T00:22:43.690Z
|
InstallDate,2025-10-01T00:47:33.083Z
|
||||||
LastUpdated,2025-10-01T00:22:43.703Z
|
LastUpdated,2025-10-01T00:47:33.096Z
|
||||||
|
|
||||||
## Modules
|
## Modules
|
||||||
Name,Version,ShortTitle
|
Name,Version,ShortTitle
|
||||||
|
|||||||
|
@@ -1,7 +1,7 @@
|
|||||||
installation:
|
installation:
|
||||||
version: 6.0.0-alpha.0
|
version: 6.0.0-alpha.0
|
||||||
installDate: "2025-10-01T00:22:43.664Z"
|
installDate: "2025-10-01T00:47:33.058Z"
|
||||||
lastUpdated: "2025-10-01T00:22:43.664Z"
|
lastUpdated: "2025-10-01T00:47:33.058Z"
|
||||||
modules:
|
modules:
|
||||||
- name: core
|
- name: core
|
||||||
version: ""
|
version: ""
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# BMB Module Configuration
|
# BMB Module Configuration
|
||||||
# Generated by BMAD installer
|
# Generated by BMAD installer
|
||||||
# Version: 6.0.0-alpha.0
|
# Version: 6.0.0-alpha.0
|
||||||
# Date: 2025-10-01T00:22:43.652Z
|
# Date: 2025-10-01T00:47:33.045Z
|
||||||
|
|
||||||
# Core Configuration Values
|
# Core Configuration Values
|
||||||
user_name: BMad
|
user_name: BMad
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# BMM Module Configuration
|
# BMM Module Configuration
|
||||||
# Generated by BMAD installer
|
# Generated by BMAD installer
|
||||||
# Version: 6.0.0-alpha.0
|
# Version: 6.0.0-alpha.0
|
||||||
# Date: 2025-10-01T00:22:43.653Z
|
# Date: 2025-10-01T00:47:33.046Z
|
||||||
|
|
||||||
project_name: My Project
|
project_name: My Project
|
||||||
tech_docs: "{project-root}/docs"
|
tech_docs: "{project-root}/docs"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# CIS Module Configuration
|
# CIS Module Configuration
|
||||||
# Generated by BMAD installer
|
# Generated by BMAD installer
|
||||||
# Version: 6.0.0-alpha.0
|
# Version: 6.0.0-alpha.0
|
||||||
# Date: 2025-10-01T00:22:43.653Z
|
# Date: 2025-10-01T00:47:33.046Z
|
||||||
|
|
||||||
# Core Configuration Values
|
# Core Configuration Values
|
||||||
user_name: BMad
|
user_name: BMad
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# CORE Module Configuration
|
# CORE Module Configuration
|
||||||
# Generated by BMAD installer
|
# Generated by BMAD installer
|
||||||
# Version: 6.0.0-alpha.0
|
# Version: 6.0.0-alpha.0
|
||||||
# Date: 2025-10-01T00:22:43.654Z
|
# Date: 2025-10-01T00:47:33.046Z
|
||||||
|
|
||||||
user_name: BMad
|
user_name: BMad
|
||||||
communication_language: English
|
communication_language: English
|
||||||
|
|||||||
@@ -185,12 +185,61 @@ class Installer {
|
|||||||
console.log(chalk.dim(` Location: ${bmadDir}`));
|
console.log(chalk.dim(` Location: ${bmadDir}`));
|
||||||
console.log(chalk.dim(` Version: ${existingInstall.version}`));
|
console.log(chalk.dim(` Version: ${existingInstall.version}`));
|
||||||
|
|
||||||
// TODO: Handle update scenario
|
|
||||||
const { action } = await this.promptUpdateAction();
|
const { action } = await this.promptUpdateAction();
|
||||||
if (action === 'cancel') {
|
if (action === 'cancel') {
|
||||||
console.log('Installation cancelled.');
|
console.log('Installation cancelled.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action === 'reinstall') {
|
||||||
|
// Warn about destructive operation
|
||||||
|
console.log(chalk.red.bold('\n⚠️ WARNING: This is a destructive operation!'));
|
||||||
|
console.log(chalk.red('All custom files and modifications in the bmad directory will be lost.'));
|
||||||
|
|
||||||
|
const inquirer = require('inquirer');
|
||||||
|
const { confirmReinstall } = await inquirer.prompt([
|
||||||
|
{
|
||||||
|
type: 'confirm',
|
||||||
|
name: 'confirmReinstall',
|
||||||
|
message: chalk.yellow('Are you sure you want to delete and reinstall?'),
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!confirmReinstall) {
|
||||||
|
console.log('Installation cancelled.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove existing installation
|
||||||
|
await fs.remove(bmadDir);
|
||||||
|
console.log(chalk.green('✓ Removed existing installation\n'));
|
||||||
|
} else if (action === 'update') {
|
||||||
|
// Store that we're updating for later processing
|
||||||
|
config._isUpdate = true;
|
||||||
|
config._existingInstall = existingInstall;
|
||||||
|
|
||||||
|
// Detect custom files BEFORE updating (compare current files vs manifest)
|
||||||
|
const existingManifest = await this.manifest.read(bmadDir);
|
||||||
|
config._customFiles = await this.detectCustomFiles(bmadDir, existingManifest);
|
||||||
|
|
||||||
|
// If there are custom files, back them up temporarily
|
||||||
|
if (config._customFiles.length > 0) {
|
||||||
|
const tempBackupDir = path.join(projectDir, '.bmad-custom-backup-temp');
|
||||||
|
await fs.ensureDir(tempBackupDir);
|
||||||
|
|
||||||
|
spinner.start(`Backing up ${config._customFiles.length} custom files...`);
|
||||||
|
for (const customFile of config._customFiles) {
|
||||||
|
const relativePath = path.relative(bmadDir, customFile);
|
||||||
|
const backupPath = path.join(tempBackupDir, relativePath);
|
||||||
|
await fs.ensureDir(path.dirname(backupPath));
|
||||||
|
await fs.copy(customFile, backupPath);
|
||||||
|
}
|
||||||
|
spinner.succeed(`Backed up ${config._customFiles.length} custom files`);
|
||||||
|
|
||||||
|
config._tempBackupDir = tempBackupDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create bmad directory structure
|
// Create bmad directory structure
|
||||||
@@ -352,8 +401,42 @@ class Installer {
|
|||||||
);
|
);
|
||||||
spinner.succeed(`Manifest created (${manifestResult.filesTracked} files tracked)`);
|
spinner.succeed(`Manifest created (${manifestResult.filesTracked} files tracked)`);
|
||||||
|
|
||||||
|
// If this was an update, restore custom files
|
||||||
|
let customFiles = [];
|
||||||
|
if (config._isUpdate && config._customFiles && config._customFiles.length > 0) {
|
||||||
|
spinner.start(`Restoring ${config._customFiles.length} custom files...`);
|
||||||
|
|
||||||
|
for (const originalPath of config._customFiles) {
|
||||||
|
const relativePath = path.relative(bmadDir, originalPath);
|
||||||
|
const backupPath = path.join(config._tempBackupDir, relativePath);
|
||||||
|
|
||||||
|
if (await fs.pathExists(backupPath)) {
|
||||||
|
await fs.ensureDir(path.dirname(originalPath));
|
||||||
|
await fs.copy(backupPath, originalPath, { overwrite: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up temp backup
|
||||||
|
if (config._tempBackupDir && (await fs.pathExists(config._tempBackupDir))) {
|
||||||
|
await fs.remove(config._tempBackupDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
spinner.succeed(`Restored ${config._customFiles.length} custom files`);
|
||||||
|
customFiles = config._customFiles;
|
||||||
|
}
|
||||||
|
|
||||||
spinner.stop();
|
spinner.stop();
|
||||||
|
|
||||||
|
// Report custom files if any were found
|
||||||
|
if (customFiles.length > 0) {
|
||||||
|
console.log(chalk.cyan(`\n📁 Custom files preserved: ${customFiles.length}`));
|
||||||
|
console.log(chalk.dim('The following custom files were found and restored:\n'));
|
||||||
|
for (const file of customFiles) {
|
||||||
|
console.log(chalk.dim(` - ${path.relative(bmadDir, file)}`));
|
||||||
|
}
|
||||||
|
console.log('');
|
||||||
|
}
|
||||||
|
|
||||||
// Display completion message
|
// Display completion message
|
||||||
const { UI } = require('../../../lib/ui');
|
const { UI } = require('../../../lib/ui');
|
||||||
const ui = new UI();
|
const ui = new UI();
|
||||||
@@ -361,6 +444,7 @@ class Installer {
|
|||||||
path: bmadDir,
|
path: bmadDir,
|
||||||
modules: config.modules,
|
modules: config.modules,
|
||||||
ides: config.ides,
|
ides: config.ides,
|
||||||
|
customFiles: customFiles.length > 0 ? customFiles : undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
return { success: true, path: bmadDir, modules: config.modules, ides: config.ides };
|
return { success: true, path: bmadDir, modules: config.modules, ides: config.ides };
|
||||||
@@ -922,6 +1006,59 @@ class Installer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect custom files that were not installed by the installer
|
||||||
|
* @param {string} bmadDir - BMAD installation directory
|
||||||
|
* @param {Object} existingManifest - Previous installation manifest
|
||||||
|
* @returns {Array} List of custom files found
|
||||||
|
*/
|
||||||
|
async detectCustomFiles(bmadDir, existingManifest) {
|
||||||
|
const customFiles = [];
|
||||||
|
|
||||||
|
// Build set of previously installed files from manifest
|
||||||
|
const installedSet = new Set();
|
||||||
|
if (existingManifest && existingManifest.files) {
|
||||||
|
for (const fileEntry of existingManifest.files) {
|
||||||
|
if (fileEntry.file) {
|
||||||
|
// Files in manifest are stored as relative paths starting with 'bmad/'
|
||||||
|
// Convert to absolute path
|
||||||
|
const relativePath = fileEntry.file.startsWith('bmad/') ? fileEntry.file.slice(5) : fileEntry.file;
|
||||||
|
const absolutePath = path.join(bmadDir, relativePath);
|
||||||
|
installedSet.add(path.normalize(absolutePath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursively scan bmadDir for all files
|
||||||
|
const scanDirectory = async (dir) => {
|
||||||
|
try {
|
||||||
|
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
for (const entry of entries) {
|
||||||
|
const fullPath = path.join(dir, entry.name);
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
// Skip certain directories
|
||||||
|
if (entry.name === 'node_modules' || entry.name === '.git') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
await scanDirectory(fullPath);
|
||||||
|
} else if (entry.isFile()) {
|
||||||
|
const normalizedPath = path.normalize(fullPath);
|
||||||
|
// If file is not in the previous manifest, it's custom
|
||||||
|
if (!installedSet.has(normalizedPath)) {
|
||||||
|
customFiles.push(fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Ignore errors scanning directories
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await scanDirectory(bmadDir);
|
||||||
|
return customFiles;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private: Create agent configuration files
|
* Private: Create agent configuration files
|
||||||
* @param {string} bmadDir - BMAD installation directory
|
* @param {string} bmadDir - BMAD installation directory
|
||||||
|
|||||||
Reference in New Issue
Block a user