From 4195eb3b30bdb4c5e8b468b9b12371769bc43b9e Mon Sep 17 00:00:00 2001 From: Brian Madison Date: Tue, 23 Dec 2025 21:43:29 +0800 Subject: [PATCH] installation intro and outtro custom messages, configurable in install-messages.yaml --- .github/workflows/quality.yaml | 3 - package.json | 3 +- tools/cli/commands/install.js | 16 ++-- tools/cli/installers/install-messages.yaml | 52 +++++++++++++ tools/cli/installers/lib/message-loader.js | 85 +++++++++++++++++++++ tools/cli/lib/ui.js | 5 +- tools/validate-bundles.js | 87 ---------------------- 7 files changed, 153 insertions(+), 98 deletions(-) create mode 100644 tools/cli/installers/install-messages.yaml create mode 100644 tools/cli/installers/lib/message-loader.js delete mode 100644 tools/validate-bundles.js diff --git a/.github/workflows/quality.yaml b/.github/workflows/quality.yaml index 8111ca44..495b66f5 100644 --- a/.github/workflows/quality.yaml +++ b/.github/workflows/quality.yaml @@ -92,6 +92,3 @@ jobs: - name: Test agent compilation components run: npm run test:install - - - name: Validate web bundles - run: npm run validate:bundles diff --git a/package.json b/package.json index e8583be3..b116ecbd 100644 --- a/package.json +++ b/package.json @@ -39,11 +39,10 @@ "release:minor": "gh workflow run \"Manual Release\" -f version_bump=minor", "release:patch": "gh workflow run \"Manual Release\" -f version_bump=patch", "release:watch": "gh run watch", - "test": "npm run test:schemas && npm run test:install && npm run validate:bundles && npm run validate:schemas && npm run lint && npm run lint:md && npm run format:check", + "test": "npm run test:schemas && npm run test:install && npm run validate:schemas && npm run lint && npm run lint:md && npm run format:check", "test:coverage": "c8 --reporter=text --reporter=html npm run test:schemas", "test:install": "node test/test-installation-components.js", "test:schemas": "node test/test-agent-schema.js", - "validate:bundles": "node tools/validate-bundles.js", "validate:schemas": "node tools/validate-agent-schema.js" }, "lint-staged": { diff --git a/tools/cli/commands/install.js b/tools/cli/commands/install.js index d2f72ef6..6e241610 100644 --- a/tools/cli/commands/install.js +++ b/tools/cli/commands/install.js @@ -26,11 +26,12 @@ module.exports = { const result = await installer.quickUpdate(config); console.log(chalk.green('\n✨ Quick update complete!')); console.log(chalk.cyan(`Updated ${result.moduleCount} modules with preserved settings`)); - console.log( - chalk.magenta( - "\nπŸ“‹ Want to see what's new? Check out the changelog: https://github.com/bmad-code-org/BMAD-METHOD/blob/main/CHANGELOG.md", - ), - ); + + // Display version-specific end message + const { MessageLoader } = require('../installers/lib/message-loader'); + const messageLoader = new MessageLoader(); + messageLoader.displayEndMessage(); + process.exit(0); return; } @@ -97,6 +98,11 @@ module.exports = { } } + // Display version-specific end message from install-messages.yaml + const { MessageLoader } = require('../installers/lib/message-loader'); + const messageLoader = new MessageLoader(); + messageLoader.displayEndMessage(); + process.exit(0); } } catch (error) { diff --git a/tools/cli/installers/install-messages.yaml b/tools/cli/installers/install-messages.yaml new file mode 100644 index 00000000..1de5c070 --- /dev/null +++ b/tools/cli/installers/install-messages.yaml @@ -0,0 +1,52 @@ +# BMAD Installer Messages +# These messages are displayed during installation +# Edit this file to change what users see during the install process + +# Display at the START of installation (after logo, before prompts) +startMessage: | + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + + πŸŽ‰πŸŽ‰ Happy Holidays and New Year 🍾🍾 + + IMPORTANT Changes with Version Alpha.20 - PLEASE READ THIS if upgrading from earlier Alpha Versions: + + 1. The BMad Core default output folder has changed from docs to `_bmad-output`. `docs` is meant for long-term artifacts, which you can always decide to move content to. + + 2. If utilizing the BMad Method Module (BMM) please be aware of the following important recent changes: + + - Phases 1-3 (Analysis, Planning, Solutioning) will now default output to _bmad-output/planning-artifacts + - Phase 4 (Implementation) will now default output to _bmad-output/implementation-artifacts + - Long term project knowledge (research, docs, references, document-project output) will now default to docs/ + + IT IS STRONGLY SUGGESTED to align with these folder conventions instead of dumping all to docs/ - if you are upgrading from a prior + version where all output was going to docs or docs/sprint-artifacts, it is suggested to reset configs to these new values. + + If you have anything in progress, you can move what was in sprint-artifacts to _bmad-output/implementation-artifacts, and if you had brainstorming + content, a PRD, UX or Architecture, you can move the content to _bmad-output/planning-artifacts. + + Read the latest updates before continuing: + https://github.com/bmad-code-org/BMAD-METHOD/blob/main/CHANGELOG.md + + ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ + +# Display at the END of installation (after all setup completes) +endMessage: | + ════════════════════════════════════════════════════════════════════════════════ + + ✨ BMAD IS READY TO USE! + + ONE FINAL NOTE WITH VERSION Alpha.20: Phase 4 (Implementation) is still in the process of being migrated to the improved workflow progressive disclosure system. + Along with this, the full conversion to the new path locations for content being searched may possibly be incomplete. If you run a workflow that relies on finding input documents automatically, and you notice they are not being found / looking in the wrong location, either: + 1. Manually specify the correct input location when prompted + 2. Open an issue on GitHub so we can address the problem quickly if you think its a bug. + 3. Ensure your content is in the new locations for best results: + - Planning Artifacts (Phases 1-3): _bmad-output/planning-artifacts + - Implementation Artifacts (Phase 4): _bmad-output/implementation-artifacts + - Long Term Project Knowledge (docs, research, references): docs/ + + Thank you for helping test the early release version of the new BMad Core and BMad Method! + Stable Beta coming soon - please read the full README.md and linked documentation to get started. + + And again, here is the Change Log with all the details of recent updates: https://github.com/bmad-code-org/BMAD-METHOD/blob/main/CHANGELOG.md + + ════════════════════════════════════════════════════════════════════════════════ diff --git a/tools/cli/installers/lib/message-loader.js b/tools/cli/installers/lib/message-loader.js new file mode 100644 index 00000000..dd112669 --- /dev/null +++ b/tools/cli/installers/lib/message-loader.js @@ -0,0 +1,85 @@ +const fs = require('fs-extra'); +const path = require('node:path'); +const yaml = require('yaml'); +const chalk = require('chalk'); + +/** + * Load and display installer messages from messages.yaml + */ +class MessageLoader { + constructor() {} + + /** + * Load messages from the YAML file + * @returns {Object|null} Messages object or null if not found + */ + load() { + if (this.messages) { + return this.messages; + } + + const messagesPath = path.join(__dirname, '..', 'install-messages.yaml'); + + try { + const content = fs.readFileSync(messagesPath, 'utf8'); + this.messages = yaml.parse(content); + return this.messages; + } catch { + // File doesn't exist or is invalid - return null + return null; + } + } + + /** + * Get the start message for display + * @returns {string|null} Start message or null + */ + getStartMessage() { + const messages = this.load(); + return messages?.startMessage || null; + } + + /** + * Get the end message for display + * @returns {string|null} End message or null + */ + getEndMessage() { + const messages = this.load(); + return messages?.endMessage || null; + } + + /** + * Display the start message (after logo, before prompts) + */ + displayStartMessage() { + const message = this.getStartMessage(); + if (message) { + console.log(chalk.cyan(message)); + console.log(); + } + } + + /** + * Display the end message (after installation completes) + */ + displayEndMessage() { + const message = this.getEndMessage(); + if (message) { + console.log(); + console.log(chalk.cyan(message)); + } + } + + /** + * Check if messages exist for the current version + * @param {string} currentVersion - Current package version + * @returns {boolean} True if messages match current version + */ + isCurrent(currentVersion) { + const messages = this.load(); + return messages && messages.version === currentVersion; + } + messages = null; +} + +module.exports = { MessageLoader }; diff --git a/tools/cli/lib/ui.js b/tools/cli/lib/ui.js index 7aae6456..ab055643 100644 --- a/tools/cli/lib/ui.js +++ b/tools/cli/lib/ui.js @@ -17,7 +17,10 @@ class UI { async promptInstall() { CLIUtils.displayLogo(); - console.log(chalk.cyan('\nRead the latest updates: https://github.com/bmad-code-org/BMAD-METHOD/blob/main/CHANGELOG.md\n')); + // Display version-specific start message from install-messages.yaml + const { MessageLoader } = require('../installers/lib/message-loader'); + const messageLoader = new MessageLoader(); + messageLoader.displayStartMessage(); const confirmedDirectory = await this.getConfirmedDirectory(); diff --git a/tools/validate-bundles.js b/tools/validate-bundles.js deleted file mode 100644 index 674e4c63..00000000 --- a/tools/validate-bundles.js +++ /dev/null @@ -1,87 +0,0 @@ -const fs = require('fs-extra'); -const path = require('node:path'); -const xml2js = require('xml2js'); -const chalk = require('chalk'); -const glob = require('glob'); - -async function validateXmlFile(filePath) { - try { - const content = await fs.readFile(filePath, 'utf8'); - await xml2js.parseStringPromise(content, { - strict: true, - explicitArray: false, - }); - return { valid: true }; - } catch (error) { - return { valid: false, error: error.message }; - } -} - -async function validateAllBundles() { - console.log(chalk.cyan.bold('\n═══════════════════════════════════════════════')); - console.log(chalk.cyan.bold(' VALIDATING WEB BUNDLE XML FILES')); - console.log(chalk.cyan.bold('═══════════════════════════════════════════════\n')); - - const bundlesDir = path.join(__dirname, '..', 'web-bundles'); - - // Find all XML files in web-bundles - const pattern = path.join(bundlesDir, '**/*.xml'); - const files = glob.sync(pattern); - - if (files.length === 0) { - console.log(chalk.yellow('No XML files found in web-bundles directory')); - return; - } - - console.log(`Found ${chalk.bold(files.length)} XML files to validate\n`); - - let validCount = 0; - let invalidCount = 0; - const invalidFiles = []; - - for (const file of files) { - const relativePath = path.relative(bundlesDir, file); - const result = await validateXmlFile(file); - - if (result.valid) { - console.log(`${chalk.green('βœ“')} ${relativePath}`); - validCount++; - } else { - console.log(`${chalk.red('βœ—')} ${relativePath}`); - console.log(` ${chalk.red('β†’')} ${result.error}`); - invalidCount++; - invalidFiles.push({ path: relativePath, error: result.error }); - } - } - - // Summary - console.log(chalk.cyan.bold('\n═══════════════════════════════════════════════')); - console.log(chalk.cyan.bold(' SUMMARY')); - console.log(chalk.cyan.bold('═══════════════════════════════════════════════\n')); - - console.log(` Total files checked: ${chalk.bold(files.length)}`); - console.log(` Valid XML files: ${chalk.green(validCount)}`); - console.log(` Invalid XML files: ${invalidCount > 0 ? chalk.red(invalidCount) : chalk.green(invalidCount)}`); - - if (invalidFiles.length > 0) { - console.log(chalk.red.bold('\n Invalid Files:')); - for (const { path, error } of invalidFiles) { - console.log(` ${chalk.red('β€’')} ${path}`); - if (error.length > 100) { - console.log(` ${error.slice(0, 100)}...`); - } else { - console.log(` ${error}`); - } - } - } - - console.log(chalk.cyan.bold('\n═══════════════════════════════════════════════\n')); - - process.exit(invalidCount > 0 ? 1 : 0); -} - -// Run validation -validateAllBundles().catch((error) => { - console.error(chalk.red('Error running validation:'), error); - process.exit(1); -});