bmad-method 5.0.0-beta.2 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.md +3 -3
- package/.github/ISSUE_TEMPLATE/feature_request.md +3 -3
- package/.github/workflows/discord.yaml +11 -2
- package/.github/workflows/format-check.yaml +42 -0
- package/.github/workflows/manual-release.yaml +173 -0
- package/.husky/pre-commit +3 -0
- package/.vscode/settings.json +26 -1
- package/CHANGELOG.md +0 -11
- package/README.md +2 -0
- package/bmad-core/agent-teams/team-all.yaml +1 -1
- package/bmad-core/agents/bmad-orchestrator.md +1 -1
- package/bmad-core/agents/dev.md +4 -4
- package/bmad-core/data/bmad-kb.md +1 -1
- package/bmad-core/data/test-levels-framework.md +12 -12
- package/bmad-core/tasks/facilitate-brainstorming-session.md +1 -1
- package/bmad-core/tasks/nfr-assess.md +10 -10
- package/bmad-core/tasks/qa-gate.md +23 -23
- package/bmad-core/tasks/review-story.md +18 -18
- package/bmad-core/tasks/risk-profile.md +25 -25
- package/bmad-core/tasks/test-design.md +9 -9
- package/bmad-core/tasks/trace-requirements.md +21 -21
- package/bmad-core/templates/architecture-tmpl.yaml +49 -49
- package/bmad-core/templates/brainstorming-output-tmpl.yaml +5 -5
- package/bmad-core/templates/brownfield-architecture-tmpl.yaml +31 -31
- package/bmad-core/templates/brownfield-prd-tmpl.yaml +13 -13
- package/bmad-core/templates/competitor-analysis-tmpl.yaml +19 -6
- package/bmad-core/templates/front-end-architecture-tmpl.yaml +21 -9
- package/bmad-core/templates/front-end-spec-tmpl.yaml +24 -24
- package/bmad-core/templates/fullstack-architecture-tmpl.yaml +122 -104
- package/bmad-core/templates/market-research-tmpl.yaml +2 -2
- package/bmad-core/templates/prd-tmpl.yaml +9 -9
- package/bmad-core/templates/project-brief-tmpl.yaml +4 -4
- package/bmad-core/templates/qa-gate-tmpl.yaml +9 -9
- package/bmad-core/templates/story-tmpl.yaml +12 -12
- package/bmad-core/workflows/brownfield-fullstack.yaml +9 -9
- package/bmad-core/workflows/brownfield-service.yaml +1 -1
- package/bmad-core/workflows/brownfield-ui.yaml +1 -1
- package/bmad-core/workflows/greenfield-fullstack.yaml +1 -1
- package/bmad-core/workflows/greenfield-service.yaml +1 -1
- package/bmad-core/workflows/greenfield-ui.yaml +1 -1
- package/common/utils/bmad-doc-template.md +5 -5
- package/dist/agents/analyst.txt +28 -15
- package/dist/agents/architect.txt +220 -190
- package/dist/agents/bmad-master.txt +298 -255
- package/dist/agents/bmad-orchestrator.txt +1 -1
- package/dist/agents/pm.txt +20 -20
- package/dist/agents/po.txt +11 -11
- package/dist/agents/qa.txt +275 -618
- package/dist/agents/sm.txt +11 -11
- package/dist/agents/ux-expert.txt +23 -23
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +109 -109
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +75 -77
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +41 -41
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +483 -474
- package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.txt +1 -1
- package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.txt +149 -149
- package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.txt +20 -20
- package/dist/expansion-packs/bmad-2d-unity-game-dev/teams/unity-2d-game-team.txt +371 -358
- package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +25 -25
- package/dist/teams/team-all.txt +581 -881
- package/dist/teams/team-fullstack.txt +316 -273
- package/dist/teams/team-ide-minimal.txt +276 -619
- package/dist/teams/team-no-ui.txt +281 -238
- package/docs/versioning-and-releases.md +114 -44
- package/eslint.config.mjs +119 -0
- package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.4 Deployment Configuration/1.4.2 - cloudbuild.yaml +26 -26
- package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.md +4 -4
- package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.md +1 -1
- package/expansion-packs/bmad-2d-phaser-game-dev/data/development-guidelines.md +26 -28
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-architecture-tmpl.yaml +50 -50
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-brief-tmpl.yaml +23 -23
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-design-doc-tmpl.yaml +24 -24
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-story-tmpl.yaml +42 -42
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/level-design-doc-tmpl.yaml +65 -65
- package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-dev-greenfield.yaml +5 -5
- package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-prototype.yaml +1 -1
- package/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.md +3 -3
- package/expansion-packs/bmad-2d-unity-game-dev/data/bmad-kb.md +1 -1
- package/expansion-packs/bmad-2d-unity-game-dev/templates/game-brief-tmpl.yaml +23 -23
- package/expansion-packs/bmad-2d-unity-game-dev/templates/game-design-doc-tmpl.yaml +63 -63
- package/expansion-packs/bmad-2d-unity-game-dev/templates/game-story-tmpl.yaml +20 -20
- package/expansion-packs/bmad-2d-unity-game-dev/templates/level-design-doc-tmpl.yaml +65 -65
- package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-dev-greenfield.yaml +5 -5
- package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-prototype.yaml +1 -1
- package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-architecture-tmpl.yaml +20 -20
- package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.yaml +7 -7
- package/package.json +62 -39
- package/prettier.config.mjs +32 -0
- package/release_notes.md +30 -0
- package/tools/bmad-npx-wrapper.js +10 -10
- package/tools/builders/web-builder.js +124 -130
- package/tools/bump-all-versions.js +42 -33
- package/tools/bump-expansion-version.js +23 -16
- package/tools/cli.js +10 -12
- package/tools/flattener/aggregate.js +10 -10
- package/tools/flattener/binary.js +44 -17
- package/tools/flattener/discovery.js +19 -18
- package/tools/flattener/files.js +6 -6
- package/tools/flattener/ignoreRules.js +125 -125
- package/tools/flattener/main.js +201 -304
- package/tools/flattener/projectRoot.js +75 -73
- package/tools/flattener/prompts.js +9 -9
- package/tools/flattener/stats.helpers.js +131 -67
- package/tools/flattener/stats.js +3 -3
- package/tools/flattener/test-matrix.js +201 -193
- package/tools/flattener/xml.js +33 -31
- package/tools/installer/bin/bmad.js +130 -89
- package/tools/installer/config/ide-agent-config.yaml +1 -1
- package/tools/installer/config/install.config.yaml +2 -2
- package/tools/installer/lib/config-loader.js +46 -42
- package/tools/installer/lib/file-manager.js +91 -113
- package/tools/installer/lib/ide-base-setup.js +57 -56
- package/tools/installer/lib/ide-setup.js +375 -343
- package/tools/installer/lib/installer.js +875 -714
- package/tools/installer/lib/memory-profiler.js +54 -53
- package/tools/installer/lib/module-manager.js +19 -15
- package/tools/installer/lib/resource-locator.js +26 -28
- package/tools/installer/package.json +19 -19
- package/tools/lib/dependency-resolver.js +26 -30
- package/tools/lib/yaml-utils.js +7 -7
- package/tools/preview-release-notes.js +66 -0
- package/tools/shared/bannerArt.js +3 -3
- package/tools/sync-installer-version.js +7 -9
- package/tools/update-expansion-version.js +14 -15
- package/tools/upgraders/v3-to-v4-upgrader.js +203 -294
- package/tools/version-bump.js +41 -26
- package/tools/yaml-format.js +56 -43
- package/.github/workflows/promote-to-stable.yml +0 -144
- package/.github/workflows/release.yaml +0 -60
- package/.releaserc.json +0 -21
- package/tools/semantic-release-sync-installer.js +0 -30
package/tools/version-bump.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const { execSync } = require('child_process');
|
|
5
|
-
const path = require('path');
|
|
1
|
+
const fs = require('node:fs');
|
|
2
|
+
const { execSync } = require('node:child_process');
|
|
3
|
+
const path = require('node:path');
|
|
6
4
|
|
|
7
5
|
// Dynamic import for ES module
|
|
8
6
|
let chalk;
|
|
@@ -26,54 +24,71 @@ function getCurrentVersion() {
|
|
|
26
24
|
|
|
27
25
|
async function bumpVersion(type = 'patch') {
|
|
28
26
|
await initializeModules();
|
|
29
|
-
|
|
27
|
+
|
|
30
28
|
const validTypes = ['patch', 'minor', 'major'];
|
|
31
29
|
if (!validTypes.includes(type)) {
|
|
32
30
|
console.error(chalk.red(`Invalid version type: ${type}. Use: ${validTypes.join(', ')}`));
|
|
33
31
|
process.exit(1);
|
|
34
32
|
}
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
34
|
+
const currentVersion = getCurrentVersion();
|
|
35
|
+
const versionParts = currentVersion.split('.').map(Number);
|
|
36
|
+
let newVersion;
|
|
37
|
+
|
|
38
|
+
switch (type) {
|
|
39
|
+
case 'major': {
|
|
40
|
+
newVersion = `${versionParts[0] + 1}.0.0`;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
case 'minor': {
|
|
44
|
+
newVersion = `${versionParts[0]}.${versionParts[1] + 1}.0`;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
case 'patch': {
|
|
48
|
+
newVersion = `${versionParts[0]}.${versionParts[1]}.${versionParts[2] + 1}`;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
console.log(chalk.blue(`Bumping version: ${currentVersion} → ${newVersion}`));
|
|
54
|
+
|
|
55
|
+
// Update package.json
|
|
56
|
+
const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
|
57
|
+
packageJson.version = newVersion;
|
|
58
|
+
fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2) + '\n');
|
|
59
|
+
|
|
60
|
+
console.log(chalk.green(`✓ Updated package.json to ${newVersion}`));
|
|
61
|
+
|
|
62
|
+
return newVersion;
|
|
48
63
|
}
|
|
49
64
|
|
|
50
65
|
async function main() {
|
|
51
66
|
await initializeModules();
|
|
52
|
-
|
|
67
|
+
|
|
53
68
|
const type = process.argv[2] || 'patch';
|
|
54
69
|
const currentVersion = getCurrentVersion();
|
|
55
|
-
|
|
70
|
+
|
|
56
71
|
console.log(chalk.blue(`Current version: ${currentVersion}`));
|
|
57
|
-
|
|
72
|
+
|
|
58
73
|
// Check if working directory is clean
|
|
59
74
|
try {
|
|
60
75
|
execSync('git diff-index --quiet HEAD --');
|
|
61
|
-
} catch
|
|
76
|
+
} catch {
|
|
62
77
|
console.error(chalk.red('❌ Working directory is not clean. Commit your changes first.'));
|
|
63
78
|
process.exit(1);
|
|
64
79
|
}
|
|
65
|
-
|
|
80
|
+
|
|
66
81
|
const newVersion = await bumpVersion(type);
|
|
67
|
-
|
|
82
|
+
|
|
68
83
|
console.log(chalk.green(`\n🎉 Version bump complete!`));
|
|
69
84
|
console.log(chalk.blue(`📦 ${currentVersion} → ${newVersion}`));
|
|
70
85
|
}
|
|
71
86
|
|
|
72
87
|
if (require.main === module) {
|
|
73
|
-
main().catch(error => {
|
|
88
|
+
main().catch((error) => {
|
|
74
89
|
console.error('Error:', error);
|
|
75
90
|
process.exit(1);
|
|
76
91
|
});
|
|
77
92
|
}
|
|
78
93
|
|
|
79
|
-
module.exports = { bumpVersion, getCurrentVersion };
|
|
94
|
+
module.exports = { bumpVersion, getCurrentVersion };
|
package/tools/yaml-format.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
1
|
+
const fs = require('node:fs');
|
|
2
|
+
const path = require('node:path');
|
|
5
3
|
const yaml = require('js-yaml');
|
|
6
|
-
const { execSync } = require('child_process');
|
|
4
|
+
const { execSync } = require('node:child_process');
|
|
7
5
|
|
|
8
6
|
// Dynamic import for ES module
|
|
9
7
|
let chalk;
|
|
@@ -26,43 +24,50 @@ async function formatYamlContent(content, filename) {
|
|
|
26
24
|
// First try to fix common YAML issues
|
|
27
25
|
let fixedContent = content
|
|
28
26
|
// Fix "commands :" -> "commands:"
|
|
29
|
-
.
|
|
27
|
+
.replaceAll(/^(\s*)(\w+)\s+:/gm, '$1$2:')
|
|
30
28
|
// Fix inconsistent list indentation
|
|
31
|
-
.
|
|
32
|
-
|
|
29
|
+
.replaceAll(/^(\s*)-\s{3,}/gm, '$1- ');
|
|
30
|
+
|
|
33
31
|
// Skip auto-fixing for .roomodes files - they have special nested structure
|
|
34
32
|
if (!filename.includes('.roomodes')) {
|
|
35
33
|
fixedContent = fixedContent
|
|
36
34
|
// Fix unquoted list items that contain special characters or multiple parts
|
|
37
|
-
.
|
|
35
|
+
.replaceAll(/^(\s*)-\s+(.*)$/gm, (match, indent, content) => {
|
|
38
36
|
// Skip if already quoted
|
|
39
37
|
if (content.startsWith('"') && content.endsWith('"')) {
|
|
40
38
|
return match;
|
|
41
39
|
}
|
|
42
40
|
// If the content contains special YAML characters or looks complex, quote it
|
|
43
41
|
// BUT skip if it looks like a proper YAML key-value pair (like "key: value")
|
|
44
|
-
if (
|
|
45
|
-
|
|
42
|
+
if (
|
|
43
|
+
(content.includes(':') ||
|
|
44
|
+
content.includes('-') ||
|
|
45
|
+
content.includes('{') ||
|
|
46
|
+
content.includes('}')) &&
|
|
47
|
+
!/^\w+:\s/.test(content)
|
|
48
|
+
) {
|
|
46
49
|
// Remove any existing quotes first, escape internal quotes, then add proper quotes
|
|
47
|
-
const cleanContent = content
|
|
50
|
+
const cleanContent = content
|
|
51
|
+
.replaceAll(/^["']|["']$/g, '')
|
|
52
|
+
.replaceAll('"', String.raw`\"`);
|
|
48
53
|
return `${indent}- "${cleanContent}"`;
|
|
49
54
|
}
|
|
50
55
|
return match;
|
|
51
56
|
});
|
|
52
57
|
}
|
|
53
|
-
|
|
58
|
+
|
|
54
59
|
// Debug: show what we're trying to parse
|
|
55
60
|
if (fixedContent !== content) {
|
|
56
61
|
console.log(chalk.blue(`🔧 Applied YAML fixes to ${filename}`));
|
|
57
62
|
}
|
|
58
|
-
|
|
63
|
+
|
|
59
64
|
// Parse and re-dump YAML to format it
|
|
60
65
|
const parsed = yaml.load(fixedContent);
|
|
61
66
|
const formatted = yaml.dump(parsed, {
|
|
62
67
|
indent: 2,
|
|
63
68
|
lineWidth: -1, // Disable line wrapping
|
|
64
69
|
noRefs: true,
|
|
65
|
-
sortKeys: false // Preserve key order
|
|
70
|
+
sortKeys: false, // Preserve key order
|
|
66
71
|
});
|
|
67
72
|
return formatted;
|
|
68
73
|
} catch (error) {
|
|
@@ -80,7 +85,7 @@ async function processMarkdownFile(filePath) {
|
|
|
80
85
|
|
|
81
86
|
// Fix untyped code blocks by adding 'text' type
|
|
82
87
|
// Match ``` at start of line followed by newline, but only if it's an opening fence
|
|
83
|
-
newContent = newContent.
|
|
88
|
+
newContent = newContent.replaceAll(/^```\n([\s\S]*?)\n```$/gm, '```text\n$1\n```');
|
|
84
89
|
if (newContent !== content) {
|
|
85
90
|
modified = true;
|
|
86
91
|
console.log(chalk.blue(`🔧 Added 'text' type to untyped code blocks in ${filePath}`));
|
|
@@ -90,30 +95,30 @@ async function processMarkdownFile(filePath) {
|
|
|
90
95
|
const yamlBlockRegex = /```ya?ml\n([\s\S]*?)\n```/g;
|
|
91
96
|
let match;
|
|
92
97
|
const replacements = [];
|
|
93
|
-
|
|
98
|
+
|
|
94
99
|
while ((match = yamlBlockRegex.exec(newContent)) !== null) {
|
|
95
100
|
const [fullMatch, yamlContent] = match;
|
|
96
101
|
const formatted = await formatYamlContent(yamlContent, filePath);
|
|
97
102
|
if (formatted !== null) {
|
|
98
103
|
// Remove trailing newline that js-yaml adds
|
|
99
104
|
const trimmedFormatted = formatted.replace(/\n$/, '');
|
|
100
|
-
|
|
105
|
+
|
|
101
106
|
if (trimmedFormatted !== yamlContent) {
|
|
102
107
|
modified = true;
|
|
103
108
|
console.log(chalk.green(`✓ Formatted YAML in ${filePath}`));
|
|
104
109
|
}
|
|
105
|
-
|
|
110
|
+
|
|
106
111
|
replacements.push({
|
|
107
112
|
start: match.index,
|
|
108
113
|
end: match.index + fullMatch.length,
|
|
109
|
-
replacement: `\`\`\`yaml\n${trimmedFormatted}\n
|
|
114
|
+
replacement: `\`\`\`yaml\n${trimmedFormatted}\n\`\`\``,
|
|
110
115
|
});
|
|
111
116
|
}
|
|
112
117
|
}
|
|
113
|
-
|
|
118
|
+
|
|
114
119
|
// Apply replacements in reverse order to maintain indices
|
|
115
|
-
for (let
|
|
116
|
-
const { start, end, replacement } = replacements[
|
|
120
|
+
for (let index = replacements.length - 1; index >= 0; index--) {
|
|
121
|
+
const { start, end, replacement } = replacements[index];
|
|
117
122
|
newContent = newContent.slice(0, start) + replacement + newContent.slice(end);
|
|
118
123
|
}
|
|
119
124
|
|
|
@@ -128,11 +133,11 @@ async function processYamlFile(filePath) {
|
|
|
128
133
|
await initializeModules();
|
|
129
134
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
130
135
|
const formatted = await formatYamlContent(content, filePath);
|
|
131
|
-
|
|
136
|
+
|
|
132
137
|
if (formatted === null) {
|
|
133
138
|
return false; // Syntax error
|
|
134
139
|
}
|
|
135
|
-
|
|
140
|
+
|
|
136
141
|
if (formatted !== content) {
|
|
137
142
|
fs.writeFileSync(filePath, formatted);
|
|
138
143
|
return true;
|
|
@@ -155,10 +160,10 @@ async function lintYamlFile(filePath) {
|
|
|
155
160
|
|
|
156
161
|
async function main() {
|
|
157
162
|
await initializeModules();
|
|
158
|
-
const
|
|
163
|
+
const arguments_ = process.argv.slice(2);
|
|
159
164
|
const glob = require('glob');
|
|
160
|
-
|
|
161
|
-
if (
|
|
165
|
+
|
|
166
|
+
if (arguments_.length === 0) {
|
|
162
167
|
console.error('Usage: node yaml-format.js <file1> [file2] ...');
|
|
163
168
|
process.exit(1);
|
|
164
169
|
}
|
|
@@ -169,38 +174,44 @@ async function main() {
|
|
|
169
174
|
|
|
170
175
|
// Expand glob patterns and collect all files
|
|
171
176
|
const allFiles = [];
|
|
172
|
-
for (const
|
|
173
|
-
if (
|
|
177
|
+
for (const argument of arguments_) {
|
|
178
|
+
if (argument.includes('*')) {
|
|
174
179
|
// It's a glob pattern
|
|
175
|
-
const matches = glob.sync(
|
|
180
|
+
const matches = glob.sync(argument);
|
|
176
181
|
allFiles.push(...matches);
|
|
177
182
|
} else {
|
|
178
183
|
// It's a direct file path
|
|
179
|
-
allFiles.push(
|
|
184
|
+
allFiles.push(argument);
|
|
180
185
|
}
|
|
181
186
|
}
|
|
182
187
|
|
|
183
188
|
for (const filePath of allFiles) {
|
|
184
189
|
if (!fs.existsSync(filePath)) {
|
|
185
190
|
// Skip silently for glob patterns that don't match anything
|
|
186
|
-
if (!
|
|
191
|
+
if (!arguments_.some((argument) => argument.includes('*') && filePath === argument)) {
|
|
187
192
|
console.error(chalk.red(`❌ File not found: ${filePath}`));
|
|
188
193
|
hasErrors = true;
|
|
189
194
|
}
|
|
190
195
|
continue;
|
|
191
196
|
}
|
|
192
197
|
|
|
193
|
-
const
|
|
198
|
+
const extension = path.extname(filePath).toLowerCase();
|
|
194
199
|
const basename = path.basename(filePath).toLowerCase();
|
|
195
|
-
|
|
200
|
+
|
|
196
201
|
try {
|
|
197
202
|
let changed = false;
|
|
198
|
-
if (
|
|
203
|
+
if (extension === '.md') {
|
|
199
204
|
changed = await processMarkdownFile(filePath);
|
|
200
|
-
} else if (
|
|
205
|
+
} else if (
|
|
206
|
+
extension === '.yaml' ||
|
|
207
|
+
extension === '.yml' ||
|
|
208
|
+
basename.includes('roomodes') ||
|
|
209
|
+
basename.includes('.yaml') ||
|
|
210
|
+
basename.includes('.yml')
|
|
211
|
+
) {
|
|
201
212
|
// Handle YAML files and special cases like .roomodes
|
|
202
213
|
changed = await processYamlFile(filePath);
|
|
203
|
-
|
|
214
|
+
|
|
204
215
|
// Also run linting
|
|
205
216
|
const lintPassed = await lintYamlFile(filePath);
|
|
206
217
|
if (!lintPassed) hasErrors = true;
|
|
@@ -208,7 +219,7 @@ async function main() {
|
|
|
208
219
|
// Skip silently for unsupported files
|
|
209
220
|
continue;
|
|
210
221
|
}
|
|
211
|
-
|
|
222
|
+
|
|
212
223
|
if (changed) {
|
|
213
224
|
hasChanges = true;
|
|
214
225
|
filesProcessed.push(filePath);
|
|
@@ -220,8 +231,10 @@ async function main() {
|
|
|
220
231
|
}
|
|
221
232
|
|
|
222
233
|
if (hasChanges) {
|
|
223
|
-
console.log(
|
|
224
|
-
|
|
234
|
+
console.log(
|
|
235
|
+
chalk.green(`\n✨ YAML formatting completed! Modified ${filesProcessed.length} files:`),
|
|
236
|
+
);
|
|
237
|
+
for (const file of filesProcessed) console.log(chalk.blue(` 📝 ${file}`));
|
|
225
238
|
}
|
|
226
239
|
|
|
227
240
|
if (hasErrors) {
|
|
@@ -231,10 +244,10 @@ async function main() {
|
|
|
231
244
|
}
|
|
232
245
|
|
|
233
246
|
if (require.main === module) {
|
|
234
|
-
main().catch(error => {
|
|
247
|
+
main().catch((error) => {
|
|
235
248
|
console.error('Error:', error);
|
|
236
249
|
process.exit(1);
|
|
237
250
|
});
|
|
238
251
|
}
|
|
239
252
|
|
|
240
|
-
module.exports = { formatYamlContent, processMarkdownFile, processYamlFile };
|
|
253
|
+
module.exports = { formatYamlContent, processMarkdownFile, processYamlFile };
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
name: Promote to Stable
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
workflow_dispatch:
|
|
5
|
-
inputs:
|
|
6
|
-
version_bump:
|
|
7
|
-
description: 'Version bump type'
|
|
8
|
-
required: true
|
|
9
|
-
default: 'minor'
|
|
10
|
-
type: choice
|
|
11
|
-
options:
|
|
12
|
-
- patch
|
|
13
|
-
- minor
|
|
14
|
-
- major
|
|
15
|
-
|
|
16
|
-
jobs:
|
|
17
|
-
promote:
|
|
18
|
-
runs-on: ubuntu-latest
|
|
19
|
-
permissions:
|
|
20
|
-
contents: write
|
|
21
|
-
pull-requests: write
|
|
22
|
-
|
|
23
|
-
steps:
|
|
24
|
-
- name: Checkout repository
|
|
25
|
-
uses: actions/checkout@v4
|
|
26
|
-
with:
|
|
27
|
-
fetch-depth: 0
|
|
28
|
-
token: ${{ secrets.GITHUB_TOKEN }}
|
|
29
|
-
|
|
30
|
-
- name: Setup Node.js
|
|
31
|
-
uses: actions/setup-node@v4
|
|
32
|
-
with:
|
|
33
|
-
node-version: '20'
|
|
34
|
-
registry-url: 'https://registry.npmjs.org'
|
|
35
|
-
|
|
36
|
-
- name: Configure Git
|
|
37
|
-
run: |
|
|
38
|
-
git config --global user.name "github-actions[bot]"
|
|
39
|
-
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
40
|
-
git config --global url."https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/".insteadOf "https://github.com/"
|
|
41
|
-
|
|
42
|
-
- name: Switch to stable branch
|
|
43
|
-
run: |
|
|
44
|
-
git checkout stable
|
|
45
|
-
git pull origin stable
|
|
46
|
-
|
|
47
|
-
- name: Merge main into stable
|
|
48
|
-
run: |
|
|
49
|
-
git merge origin/main --no-edit
|
|
50
|
-
|
|
51
|
-
- name: Install dependencies
|
|
52
|
-
run: npm ci
|
|
53
|
-
|
|
54
|
-
- name: Get current version and calculate new version
|
|
55
|
-
id: version
|
|
56
|
-
run: |
|
|
57
|
-
# Get current version from package.json
|
|
58
|
-
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
59
|
-
echo "current_version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
|
|
60
|
-
|
|
61
|
-
# Remove beta suffix if present
|
|
62
|
-
BASE_VERSION=$(echo $CURRENT_VERSION | sed 's/-beta\.[0-9]\+//')
|
|
63
|
-
echo "base_version=$BASE_VERSION" >> $GITHUB_OUTPUT
|
|
64
|
-
|
|
65
|
-
# Calculate new version based on bump type
|
|
66
|
-
IFS='.' read -ra VERSION_PARTS <<< "$BASE_VERSION"
|
|
67
|
-
MAJOR=${VERSION_PARTS[0]}
|
|
68
|
-
MINOR=${VERSION_PARTS[1]}
|
|
69
|
-
PATCH=${VERSION_PARTS[2]}
|
|
70
|
-
|
|
71
|
-
case "${{ github.event.inputs.version_bump }}" in
|
|
72
|
-
"major")
|
|
73
|
-
NEW_VERSION="$((MAJOR + 1)).0.0"
|
|
74
|
-
;;
|
|
75
|
-
"minor")
|
|
76
|
-
NEW_VERSION="$MAJOR.$((MINOR + 1)).0"
|
|
77
|
-
;;
|
|
78
|
-
"patch")
|
|
79
|
-
NEW_VERSION="$MAJOR.$MINOR.$((PATCH + 1))"
|
|
80
|
-
;;
|
|
81
|
-
*)
|
|
82
|
-
NEW_VERSION="$BASE_VERSION"
|
|
83
|
-
;;
|
|
84
|
-
esac
|
|
85
|
-
|
|
86
|
-
# Check if calculated version already exists on NPM and increment if necessary
|
|
87
|
-
while npm view bmad-method@$NEW_VERSION version >/dev/null 2>&1; do
|
|
88
|
-
echo "Version $NEW_VERSION already exists, incrementing..."
|
|
89
|
-
IFS='.' read -ra NEW_VERSION_PARTS <<< "$NEW_VERSION"
|
|
90
|
-
NEW_MAJOR=${NEW_VERSION_PARTS[0]}
|
|
91
|
-
NEW_MINOR=${NEW_VERSION_PARTS[1]}
|
|
92
|
-
NEW_PATCH=${NEW_VERSION_PARTS[2]}
|
|
93
|
-
|
|
94
|
-
case "${{ github.event.inputs.version_bump }}" in
|
|
95
|
-
"major")
|
|
96
|
-
NEW_VERSION="$((NEW_MAJOR + 1)).0.0"
|
|
97
|
-
;;
|
|
98
|
-
"minor")
|
|
99
|
-
NEW_VERSION="$NEW_MAJOR.$((NEW_MINOR + 1)).0"
|
|
100
|
-
;;
|
|
101
|
-
"patch")
|
|
102
|
-
NEW_VERSION="$NEW_MAJOR.$NEW_MINOR.$((NEW_PATCH + 1))"
|
|
103
|
-
;;
|
|
104
|
-
esac
|
|
105
|
-
done
|
|
106
|
-
|
|
107
|
-
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
|
108
|
-
echo "Promoting from $CURRENT_VERSION to $NEW_VERSION"
|
|
109
|
-
|
|
110
|
-
- name: Update package.json versions
|
|
111
|
-
run: |
|
|
112
|
-
# Update main package.json
|
|
113
|
-
npm version ${{ steps.version.outputs.new_version }} --no-git-tag-version
|
|
114
|
-
|
|
115
|
-
# Update installer package.json
|
|
116
|
-
sed -i 's/"version": ".*"/"version": "${{ steps.version.outputs.new_version }}"/' tools/installer/package.json
|
|
117
|
-
|
|
118
|
-
- name: Update package-lock.json
|
|
119
|
-
run: npm install --package-lock-only
|
|
120
|
-
|
|
121
|
-
- name: Commit stable release
|
|
122
|
-
run: |
|
|
123
|
-
git add .
|
|
124
|
-
git commit -m "feat: promote to stable ${{ steps.version.outputs.new_version }}
|
|
125
|
-
|
|
126
|
-
BREAKING CHANGE: Promote beta features to stable release
|
|
127
|
-
|
|
128
|
-
- Update version from ${{ steps.version.outputs.current_version }} to ${{ steps.version.outputs.new_version }}
|
|
129
|
-
- Automated promotion via GitHub Actions"
|
|
130
|
-
|
|
131
|
-
- name: Push stable release
|
|
132
|
-
run: |
|
|
133
|
-
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git
|
|
134
|
-
git push origin stable
|
|
135
|
-
|
|
136
|
-
- name: Switch back to main
|
|
137
|
-
run: git checkout main
|
|
138
|
-
|
|
139
|
-
- name: Summary
|
|
140
|
-
run: |
|
|
141
|
-
echo "🎉 Successfully promoted to stable!"
|
|
142
|
-
echo "📦 Version: ${{ steps.version.outputs.new_version }}"
|
|
143
|
-
echo "🚀 The stable release will be automatically published to NPM via semantic-release"
|
|
144
|
-
echo "✅ Users running 'npx bmad-method install' will now get version ${{ steps.version.outputs.new_version }}"
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
name: Release
|
|
2
|
-
'on':
|
|
3
|
-
push:
|
|
4
|
-
branches:
|
|
5
|
-
- main
|
|
6
|
-
- stable
|
|
7
|
-
workflow_dispatch:
|
|
8
|
-
inputs:
|
|
9
|
-
version_type:
|
|
10
|
-
description: Version bump type
|
|
11
|
-
required: true
|
|
12
|
-
default: patch
|
|
13
|
-
type: choice
|
|
14
|
-
options:
|
|
15
|
-
- patch
|
|
16
|
-
- minor
|
|
17
|
-
- major
|
|
18
|
-
permissions:
|
|
19
|
-
contents: write
|
|
20
|
-
issues: write
|
|
21
|
-
pull-requests: write
|
|
22
|
-
packages: write
|
|
23
|
-
jobs:
|
|
24
|
-
release:
|
|
25
|
-
runs-on: ubuntu-latest
|
|
26
|
-
if: '!contains(github.event.head_commit.message, ''[skip ci]'')'
|
|
27
|
-
steps:
|
|
28
|
-
- name: Checkout
|
|
29
|
-
uses: actions/checkout@v4
|
|
30
|
-
with:
|
|
31
|
-
fetch-depth: 0
|
|
32
|
-
token: ${{ secrets.GITHUB_TOKEN }}
|
|
33
|
-
- name: Setup Node.js
|
|
34
|
-
uses: actions/setup-node@v4
|
|
35
|
-
with:
|
|
36
|
-
node-version: '20'
|
|
37
|
-
cache: npm
|
|
38
|
-
registry-url: https://registry.npmjs.org
|
|
39
|
-
- name: Install dependencies
|
|
40
|
-
run: npm ci
|
|
41
|
-
- name: Run tests and validation
|
|
42
|
-
run: |
|
|
43
|
-
npm run validate
|
|
44
|
-
npm run format
|
|
45
|
-
- name: Debug permissions
|
|
46
|
-
run: |
|
|
47
|
-
echo "Testing git permissions..."
|
|
48
|
-
git config user.name "github-actions[bot]"
|
|
49
|
-
git config user.email "github-actions[bot]@users.noreply.github.com"
|
|
50
|
-
echo "Git config set successfully"
|
|
51
|
-
- name: Manual version bump
|
|
52
|
-
if: github.event_name == 'workflow_dispatch'
|
|
53
|
-
run: npm run version:${{ github.event.inputs.version_type }}
|
|
54
|
-
- name: Semantic Release
|
|
55
|
-
if: github.event_name == 'push'
|
|
56
|
-
env:
|
|
57
|
-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
58
|
-
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
59
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
60
|
-
run: npm run release
|
package/.releaserc.json
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"branches": [
|
|
3
|
-
{
|
|
4
|
-
"name": "main",
|
|
5
|
-
"prerelease": "beta",
|
|
6
|
-
"channel": "beta"
|
|
7
|
-
},
|
|
8
|
-
{
|
|
9
|
-
"name": "stable",
|
|
10
|
-
"channel": "latest"
|
|
11
|
-
}
|
|
12
|
-
],
|
|
13
|
-
"plugins": [
|
|
14
|
-
"@semantic-release/commit-analyzer",
|
|
15
|
-
"@semantic-release/release-notes-generator",
|
|
16
|
-
"@semantic-release/changelog",
|
|
17
|
-
"@semantic-release/npm",
|
|
18
|
-
"./tools/semantic-release-sync-installer.js",
|
|
19
|
-
"@semantic-release/github"
|
|
20
|
-
]
|
|
21
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Semantic-release plugin to sync installer package.json version
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const fs = require('fs');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
|
|
8
|
-
// This function runs during the "prepare" step of semantic-release
|
|
9
|
-
function prepare(_, { nextRelease, logger }) {
|
|
10
|
-
// Define the path to the installer package.json file
|
|
11
|
-
const file = path.join(process.cwd(), 'tools/installer/package.json');
|
|
12
|
-
|
|
13
|
-
// If the file does not exist, skip syncing and log a message
|
|
14
|
-
if (!fs.existsSync(file)) return logger.log('Installer package.json not found, skipping');
|
|
15
|
-
|
|
16
|
-
// Read and parse the package.json file
|
|
17
|
-
const pkg = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
18
|
-
|
|
19
|
-
// Update the version field with the next release version
|
|
20
|
-
pkg.version = nextRelease.version;
|
|
21
|
-
|
|
22
|
-
// Write the updated JSON back to the file
|
|
23
|
-
fs.writeFileSync(file, JSON.stringify(pkg, null, 2) + '\n');
|
|
24
|
-
|
|
25
|
-
// Log success message
|
|
26
|
-
logger.log(`Synced installer package.json to version ${nextRelease.version}`);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Export the prepare function so semantic-release can use it
|
|
30
|
-
module.exports = { prepare };
|