maiass 5.9.12 → 5.9.17
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/lib/bootstrap.js +15 -0
- package/lib/changelog.js +8 -6
- package/lib/devlog.js +28 -13
- package/lib/maiass-pipeline.js +0 -255
- package/lib/version-manager.js +5 -2
- package/package.json +1 -1
package/lib/bootstrap.js
CHANGED
|
@@ -105,6 +105,19 @@ function detectVersionSource() {
|
|
|
105
105
|
return 'package.json'; // Default
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
/**
|
|
109
|
+
* Infer version file type from filename/extension
|
|
110
|
+
* @param {string} filename - Version file name or path
|
|
111
|
+
* @returns {string} File type: 'json', 'php', or 'txt'
|
|
112
|
+
*/
|
|
113
|
+
function inferVersionFileType(filename) {
|
|
114
|
+
if (!filename) return 'txt';
|
|
115
|
+
if (filename.endsWith('.json')) return 'json';
|
|
116
|
+
if (filename.endsWith('.php')) return 'php';
|
|
117
|
+
if (filename.endsWith('.css')) return 'php'; // CSS version headers use same pattern as PHP
|
|
118
|
+
return 'txt';
|
|
119
|
+
}
|
|
120
|
+
|
|
108
121
|
/**
|
|
109
122
|
* Main bootstrap function
|
|
110
123
|
* @returns {Promise<boolean>} True if bootstrap completed, false if skipped
|
|
@@ -431,7 +444,9 @@ async function saveConfiguration(config) {
|
|
|
431
444
|
MAIASS_REPO_TYPE=${config.projectType}
|
|
432
445
|
|
|
433
446
|
# Version Management Settings
|
|
447
|
+
# Primary version file (usually auto-detected from package.json)
|
|
434
448
|
MAIASS_VERSION_PRIMARY_FILE=${config.versionSource}
|
|
449
|
+
MAIASS_VERSION_PRIMARY_TYPE=${inferVersionFileType(config.versionSource)}
|
|
435
450
|
# Secondary files that should have their versions updated (comma-separated)
|
|
436
451
|
#MAIASS_VERSION_SECONDARY_FILES=
|
|
437
452
|
|
package/lib/changelog.js
CHANGED
|
@@ -149,9 +149,10 @@ export async function updateChangelog(changelogPath = '.', version) {
|
|
|
149
149
|
} catch {}
|
|
150
150
|
|
|
151
151
|
if (existingContent) {
|
|
152
|
-
|
|
153
|
-
const
|
|
154
|
-
const
|
|
152
|
+
// Normalize \r\n to \n for cross-platform compatibility (Windows writes \r\n)
|
|
153
|
+
const lines = existingContent.replace(/\r\n/g, '\n').split('\n');
|
|
154
|
+
const firstVersion = lines[0]?.match(/^## (.+)$/)?.[1]?.trim();
|
|
155
|
+
const secondLine = lines[1]?.trim();
|
|
155
156
|
|
|
156
157
|
// Check if we're updating the same minor version on the same date
|
|
157
158
|
const currentMinor = version.split('.').slice(0, 2).join('.');
|
|
@@ -186,9 +187,10 @@ export async function updateChangelog(changelogPath = '.', version) {
|
|
|
186
187
|
await fs.access(changelogInternalFile);
|
|
187
188
|
|
|
188
189
|
let existingContent = await fs.readFile(changelogInternalFile, 'utf8');
|
|
189
|
-
|
|
190
|
-
const
|
|
191
|
-
const
|
|
190
|
+
// Normalize \r\n to \n for cross-platform compatibility (Windows writes \r\n)
|
|
191
|
+
const lines = existingContent.replace(/\r\n/g, '\n').split('\n');
|
|
192
|
+
const firstVersion = lines[0]?.match(/^## (.+)$/)?.[1]?.trim();
|
|
193
|
+
const secondLine = lines[1]?.trim();
|
|
192
194
|
|
|
193
195
|
// Check if we're updating the same minor version on the same date
|
|
194
196
|
const currentMinor = version.split('.').slice(0, 2).join('.');
|
package/lib/devlog.js
CHANGED
|
@@ -8,13 +8,22 @@ import { getGitInfo } from './git-info.js';
|
|
|
8
8
|
import { logger } from './logger.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
12
|
-
* @returns {
|
|
11
|
+
* Get the path to devlog.ps1 on Windows via MAIASS_DEVLOG_SCRIPT env var
|
|
12
|
+
* @returns {string|null} Full path to devlog.ps1, or null if not found/set
|
|
13
|
+
*/
|
|
14
|
+
function getDevlogPs1Path() {
|
|
15
|
+
const scriptPath = process.env.MAIASS_DEVLOG_SCRIPT;
|
|
16
|
+
if (scriptPath && existsSync(scriptPath)) return scriptPath;
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Check if devlog script exists and is available
|
|
22
|
+
* @returns {boolean} True if devlog.sh (unix) or devlog.ps1 (windows) is available
|
|
13
23
|
*/
|
|
14
24
|
function isDevlogAvailable() {
|
|
15
|
-
// On Windows, devlog.sh is never available
|
|
16
25
|
if (process.platform === 'win32') {
|
|
17
|
-
return
|
|
26
|
+
return getDevlogPs1Path() !== null;
|
|
18
27
|
}
|
|
19
28
|
// Check if devlog.sh exists in common locations (sync check for immediate availability)
|
|
20
29
|
const commonPaths = [
|
|
@@ -23,8 +32,7 @@ function isDevlogAvailable() {
|
|
|
23
32
|
path.join(process.env.HOME || '', 'bin/devlog.sh'),
|
|
24
33
|
path.join(process.env.HOME || '', '.local/bin/devlog.sh')
|
|
25
34
|
];
|
|
26
|
-
|
|
27
|
-
if (commonPaths.some(path => existsSync(path))) {
|
|
35
|
+
if (commonPaths.some(p => existsSync(p))) {
|
|
28
36
|
return true;
|
|
29
37
|
}
|
|
30
38
|
// For PATH check, we'll assume it's available and let the async call handle errors
|
|
@@ -70,7 +78,7 @@ export function logThis(message, options = {}) {
|
|
|
70
78
|
|
|
71
79
|
// If devlog.sh is not available, return null (equivalent to empty function in bash)
|
|
72
80
|
if (!isDevlogAvailable()) {
|
|
73
|
-
|
|
81
|
+
logger.debug(`devlog not available, skipping log: ${message}`);
|
|
74
82
|
return null;
|
|
75
83
|
}
|
|
76
84
|
|
|
@@ -81,11 +89,18 @@ export function logThis(message, options = {}) {
|
|
|
81
89
|
|
|
82
90
|
// Escape the message for shell execution
|
|
83
91
|
const escapedMessage = message.replace(/"/g, '\\"').replace(/\n/g, '; ');
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
92
|
+
|
|
93
|
+
let command;
|
|
94
|
+
if (process.platform === 'win32') {
|
|
95
|
+
const ps1Path = getDevlogPs1Path();
|
|
96
|
+
// Args in order: message minutes project client ticket subclient
|
|
97
|
+
// -s = silent (no interactive prompts when called from maiass)
|
|
98
|
+
command = `powershell.exe -ExecutionPolicy Bypass -NonInteractive -File "${ps1Path}" -s "${escapedMessage}" "?" "${project}" "${client}" "${jiraTicket}" "${subClient}"`;
|
|
99
|
+
} else {
|
|
100
|
+
command = `devlog.sh "${escapedMessage}" "?" "${project}" "${client}" "${jiraTicket}" "${subClient}"`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
logger.debug(`Executing devlog command: ${command}`);
|
|
89
104
|
|
|
90
105
|
// Execute asynchronously - don't block the main workflow (fire-and-forget)
|
|
91
106
|
exec(command, { encoding: 'utf8' }, (error, stdout, stderr) => {
|
|
@@ -99,7 +114,7 @@ export function logThis(message, options = {}) {
|
|
|
99
114
|
|
|
100
115
|
// Only log success confirmation, not the verbose stdout output
|
|
101
116
|
|
|
102
|
-
logger.debug(`Logged to devlog
|
|
117
|
+
logger.debug(`Logged to devlog: ${escapedMessage}`);
|
|
103
118
|
});
|
|
104
119
|
|
|
105
120
|
// Return immediately (don't wait for devlog.sh to complete)
|
package/lib/maiass-pipeline.js
CHANGED
|
@@ -70,261 +70,6 @@ async function checkRemoteExists(remoteName) {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
/**
|
|
74
|
-
* Update changelog with new version and commit messages
|
|
75
|
-
* @param {string} newVersion - New version number
|
|
76
|
-
* @param {string} currentVersion - Current version (to get commits since this tag)
|
|
77
|
-
*/
|
|
78
|
-
async function updateChangelog(newVersion, currentVersion) {
|
|
79
|
-
const changelogPath = process.env.MAIASS_CHANGELOG_PATH || 'CHANGELOG.md';
|
|
80
|
-
const changelogName = process.env.MAIASS_CHANGELOG_NAME || 'CHANGELOG.md';
|
|
81
|
-
const fs = await import('fs/promises');
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
// Determine the latest version from the top of the changelog file (not git tags)
|
|
85
|
-
let lastVersion = null;
|
|
86
|
-
let changelogLines = [];
|
|
87
|
-
try {
|
|
88
|
-
await fs.access(changelogPath);
|
|
89
|
-
const changelogContent = await fs.readFile(changelogPath, 'utf8');
|
|
90
|
-
changelogLines = changelogContent.split('\n');
|
|
91
|
-
for (const line of changelogLines) {
|
|
92
|
-
const match = line.match(/^##\s+(\d+\.\d+\.\d+)/);
|
|
93
|
-
if (match) {
|
|
94
|
-
lastVersion = match[1];
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
} catch {
|
|
99
|
-
// changelog does not exist yet
|
|
100
|
-
}
|
|
101
|
-
if (!lastVersion) {
|
|
102
|
-
// Fallback: try package.json or all commits
|
|
103
|
-
try {
|
|
104
|
-
const pkg = JSON.parse(await fs.readFile('package.json', 'utf8'));
|
|
105
|
-
if (pkg.version) lastVersion = pkg.version;
|
|
106
|
-
} catch {}
|
|
107
|
-
}
|
|
108
|
-
log.blue(SYMBOLS.GEAR, lastVersion ? `Getting commits since last changelog version: ${lastVersion}` : 'No previous version found, getting all commits');
|
|
109
|
-
// Get commit messages since last version for main changelog
|
|
110
|
-
const gitLogCommand = lastVersion
|
|
111
|
-
? `git log ${lastVersion}..HEAD --pretty=format:"%B"`
|
|
112
|
-
: `git log --pretty=format:"%B"`;
|
|
113
|
-
const mainLogResult = executeGitCommand(gitLogCommand, true);
|
|
114
|
-
let hasCommits = mainLogResult.success && mainLogResult.output.trim();
|
|
115
|
-
|
|
116
|
-
if (!hasCommits) {
|
|
117
|
-
log.warning(SYMBOLS.INFO, 'No commits found since last release');
|
|
118
|
-
// Still proceed to update changelog with version entry
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Get commit messages for internal changelog (with author info, patch, and date)
|
|
122
|
-
// Use git log to get patch version, date, author, and subject for each commit
|
|
123
|
-
const internalGitLogCommand = lastVersion
|
|
124
|
-
? `git log ${lastVersion}..HEAD --pretty=format:"%h|%ad|%an|%s" --date=short`
|
|
125
|
-
: `git log --pretty=format:"%h|%ad|%an|%s" --date=short`;
|
|
126
|
-
const internalLogResult = executeGitCommand(internalGitLogCommand, true);
|
|
127
|
-
if (!internalLogResult.success) {
|
|
128
|
-
log.warning(SYMBOLS.WARNING, 'Failed to get commits for internal changelog');
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
let commitMessages = [];
|
|
132
|
-
let internalCommitMessages = [];
|
|
133
|
-
|
|
134
|
-
// Only process commits if we have any
|
|
135
|
-
if (hasCommits) {
|
|
136
|
-
// Group commit messages by date (using git log with date)
|
|
137
|
-
const gitLogByDateCommand = lastVersion
|
|
138
|
-
? `git log ${lastVersion}..HEAD --pretty=format:"%ad|%B" --date=short`
|
|
139
|
-
: `git log --pretty=format:"%ad|%B" --date=short`;
|
|
140
|
-
const logByDateResult = executeGitCommand(gitLogByDateCommand, true);
|
|
141
|
-
let groupedByDate = {};
|
|
142
|
-
if (logByDateResult.success && logByDateResult.output.trim()) {
|
|
143
|
-
logByDateResult.output.split('\n\n').forEach(entry => {
|
|
144
|
-
// Each entry: 'YYYY-MM-DD|commit message'
|
|
145
|
-
const [date, ...msgParts] = entry.split('|');
|
|
146
|
-
const msg = msgParts.join('|').trim();
|
|
147
|
-
if (!msg) return;
|
|
148
|
-
if (/^merge branch/i.test(msg)) return; // Exclude merge branch commits
|
|
149
|
-
// Remove JIRA ticket numbers
|
|
150
|
-
const cleanedMsg = msg.replace(/\b[A-Z]+-[0-9]+\b:? ?/g, '');
|
|
151
|
-
if (!groupedByDate[date]) groupedByDate[date] = [];
|
|
152
|
-
groupedByDate[date].push(cleanedMsg);
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
// Now format grouped commits for changelog
|
|
156
|
-
commitMessages = [];
|
|
157
|
-
Object.entries(groupedByDate).forEach(([date, msgs]) => {
|
|
158
|
-
// Format date as '23 July 2025'
|
|
159
|
-
const formattedDate = new Date(date).toLocaleDateString('en-GB', { day: 'numeric', month: 'long', year: 'numeric' });
|
|
160
|
-
commitMessages.push(`### ${formattedDate}`);
|
|
161
|
-
msgs.forEach(m => {
|
|
162
|
-
// Format as bullet points (with sub-bullets if multi-line)
|
|
163
|
-
const lines = m.split('\n').filter(line => line.trim());
|
|
164
|
-
if (lines.length === 1) {
|
|
165
|
-
commitMessages.push(`- ${lines[0]}`);
|
|
166
|
-
} else if (lines.length > 1) {
|
|
167
|
-
commitMessages.push(`- ${lines[0]}`);
|
|
168
|
-
lines.slice(1).forEach(l => commitMessages.push(`\t- ${l}`));
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
commitMessages.push(''); // Blank line after each date group
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Process internal changelog commits: group by patch version and date, include author and subject
|
|
176
|
-
if (hasCommits && internalLogResult.success) {
|
|
177
|
-
// Get all patch versions and their commit hashes between lastVersion and HEAD
|
|
178
|
-
const patchLogCommand = lastVersion
|
|
179
|
-
? `git log ${lastVersion}..HEAD --pretty=format:"%h|%ad|%an|%s" --date=short`
|
|
180
|
-
: `git log --pretty=format:"%h|%ad|%an|%s" --date=short`;
|
|
181
|
-
const patchLogResult = executeGitCommand(patchLogCommand, true);
|
|
182
|
-
let patchGroups = {};
|
|
183
|
-
if (patchLogResult.success && patchLogResult.output.trim()) {
|
|
184
|
-
patchLogResult.output.split('\n').forEach(line => {
|
|
185
|
-
if (!line.trim()) return;
|
|
186
|
-
const parts = line.split('|');
|
|
187
|
-
if (parts.length < 4) return;
|
|
188
|
-
const [hash, date, author, subject] = parts;
|
|
189
|
-
if (/^merge branch/i.test(subject) || /^(ncl|bump|bumping|fixing merge conflicts|version bump|merged)/i.test(subject)) return;
|
|
190
|
-
// Try to extract patch version from subject if present, else group all under newVersion
|
|
191
|
-
// (This logic can be improved if commit messages always contain version, else just group all under newVersion)
|
|
192
|
-
let patch = newVersion;
|
|
193
|
-
// Optionally, extract patch version from subject, but fallback to newVersion
|
|
194
|
-
// Format commit entry
|
|
195
|
-
const commitEntry = `(${author}) ${subject}\n\t- hash: ${hash} date: ${date}`;
|
|
196
|
-
if (!patchGroups[patch]) patchGroups[patch] = { date, commits: [] };
|
|
197
|
-
patchGroups[patch].commits.push(commitEntry);
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
// Flatten patchGroups into internalCommitMessages in patch version order (most recent first)
|
|
201
|
-
internalCommitMessages = [];
|
|
202
|
-
Object.entries(patchGroups).forEach(([patch, group]) => {
|
|
203
|
-
internalCommitMessages.push(`## ${patch}`);
|
|
204
|
-
internalCommitMessages.push(group.date);
|
|
205
|
-
internalCommitMessages.push('');
|
|
206
|
-
group.commits.forEach(c => internalCommitMessages.push(c));
|
|
207
|
-
internalCommitMessages.push('');
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Format commit messages with proper bullets (matching bash script logic)
|
|
212
|
-
let formattedCommits = '';
|
|
213
|
-
let shouldUpdateChangelog = true;
|
|
214
|
-
|
|
215
|
-
if (commitMessages.length === 0) {
|
|
216
|
-
log.warning(SYMBOLS.INFO, 'No relevant commits found for changelog - updating version header only');
|
|
217
|
-
// Don't add any commit entries when no meaningful commits exist
|
|
218
|
-
formattedCommits = '';
|
|
219
|
-
shouldUpdateChangelog = true;
|
|
220
|
-
} else {
|
|
221
|
-
formattedCommits = commitMessages.map(commit => {
|
|
222
|
-
const lines = commit.split('\n').filter(line => line.trim());
|
|
223
|
-
if (lines.length === 0) return '';
|
|
224
|
-
|
|
225
|
-
const firstLine = lines[0].trim();
|
|
226
|
-
|
|
227
|
-
// Check if it's a single-line commit or multi-line commit
|
|
228
|
-
if (lines.length === 1) {
|
|
229
|
-
// Single line commit - just add main bullet if needed
|
|
230
|
-
return firstLine.startsWith('- ') ? firstLine : `- ${firstLine}`;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
// Multi-line commit - handle differently based on format
|
|
234
|
-
if (firstLine.startsWith('- ')) {
|
|
235
|
-
// AI commit with bullets - treat first line as main subject, rest as sub-bullets
|
|
236
|
-
const subject = firstLine;
|
|
237
|
-
const bodyLines = lines.slice(1);
|
|
238
|
-
|
|
239
|
-
const formattedBody = bodyLines.map(line => {
|
|
240
|
-
const trimmed = line.trim();
|
|
241
|
-
if (!trimmed) return '';
|
|
242
|
-
|
|
243
|
-
// If line already starts with bullet, just indent it
|
|
244
|
-
if (trimmed.startsWith('- ')) {
|
|
245
|
-
return `\t${trimmed}`;
|
|
246
|
-
} else {
|
|
247
|
-
// Non-bullet line, just indent without adding bullet
|
|
248
|
-
return `\t${trimmed}`;
|
|
249
|
-
}
|
|
250
|
-
}).filter(line => line);
|
|
251
|
-
|
|
252
|
-
return [subject, ...formattedBody].join('\n');
|
|
253
|
-
} else {
|
|
254
|
-
// Manual commit - add bullets to all lines
|
|
255
|
-
return lines.map((line, index) => {
|
|
256
|
-
const trimmed = line.trim();
|
|
257
|
-
if (index === 0) {
|
|
258
|
-
return `- ${trimmed}`; // Main bullet for subject
|
|
259
|
-
} else if (trimmed) {
|
|
260
|
-
// Check if line already has bullet to avoid double bullets
|
|
261
|
-
if (trimmed.startsWith('- ')) {
|
|
262
|
-
return `\t${trimmed}`; // Just indent, don't add extra bullet
|
|
263
|
-
} else {
|
|
264
|
-
return `\t- ${trimmed}`; // Add indented bullet
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
return '';
|
|
268
|
-
}).filter(line => line).join('\n');
|
|
269
|
-
}
|
|
270
|
-
}).filter(commit => commit).join('\n');
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Create date string (matching bash script format)
|
|
274
|
-
const date = new Date().toLocaleDateString('en-GB', {
|
|
275
|
-
day: 'numeric',
|
|
276
|
-
month: 'long',
|
|
277
|
-
year: 'numeric'
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
// Create date string with weekday for internal changelog (format: "24 November 2025 (Monday)")
|
|
281
|
-
const now = new Date();
|
|
282
|
-
const weekday = now.toLocaleDateString('en-GB', { weekday: 'long' });
|
|
283
|
-
const dateWithWeekday = `${date} (${weekday.charAt(0).toUpperCase() + weekday.slice(1)})`;
|
|
284
|
-
|
|
285
|
-
// Handle existing changelog or create new one
|
|
286
|
-
let updatedContent;
|
|
287
|
-
try {
|
|
288
|
-
await fs.access(changelogPath);
|
|
289
|
-
const currentContent = await fs.readFile(changelogPath, 'utf8');
|
|
290
|
-
|
|
291
|
-
// Split current content into lines for slicing
|
|
292
|
-
const lines = currentContent.split('\n');
|
|
293
|
-
// Find the index of the second version heading (previous version)
|
|
294
|
-
let restStartIdx = -1;
|
|
295
|
-
for (let i = 1; i < lines.length; ++i) {
|
|
296
|
-
if (/^##\s+\d+\.\d+\.\d+/.test(lines[i])) {
|
|
297
|
-
restStartIdx = i;
|
|
298
|
-
break;
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
const restOfContent = restStartIdx !== -1 ? lines.slice(restStartIdx).join('\n') : '';
|
|
302
|
-
// Always prepend new entry, never duplicate previous section
|
|
303
|
-
if (formattedCommits.trim()) {
|
|
304
|
-
updatedContent = `## ${newVersion}\n${date}\n\n${formattedCommits}\n\n${restOfContent}`;
|
|
305
|
-
} else {
|
|
306
|
-
updatedContent = `## ${newVersion}\n${date}\n\n${restOfContent}`;
|
|
307
|
-
}
|
|
308
|
-
} catch (error) {
|
|
309
|
-
// Changelog doesn't exist - create new one
|
|
310
|
-
if (formattedCommits.trim()) {
|
|
311
|
-
updatedContent = `## ${newVersion}\n${date}\n\n${formattedCommits}\n`;
|
|
312
|
-
} else {
|
|
313
|
-
updatedContent = `## ${newVersion}\n${date}\n`;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Replace all newlines with OS-specific line endings for cross-platform compatibility
|
|
318
|
-
const os = await import('os');
|
|
319
|
-
const finalContent = updatedContent.replace(/\n/g, os.EOL);
|
|
320
|
-
await fs.writeFile(changelogPath, finalContent, 'utf8');
|
|
321
|
-
log.success(SYMBOLS.CHECKMARK, `Updated ${changelogName}`);
|
|
322
|
-
|
|
323
|
-
} catch (error) {
|
|
324
|
-
log.warning(SYMBOLS.WARNING, `Failed to update changelog: ${error.message}`);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
|
|
328
73
|
/**
|
|
329
74
|
* Execute git command safely
|
|
330
75
|
* @param {string} command - Git command to execute
|
package/lib/version-manager.js
CHANGED
|
@@ -560,8 +560,11 @@ export function detectVersionFiles(projectPath = process.cwd()) {
|
|
|
560
560
|
const versionFiles = [];
|
|
561
561
|
|
|
562
562
|
// Check for custom primary version file from .env.maiass first
|
|
563
|
-
|
|
564
|
-
const
|
|
563
|
+
// Normalize path separators for cross-platform .env.maiass compatibility (\ → /)
|
|
564
|
+
const primaryFileRaw = process.env.MAIASS_VERSION_PRIMARY_FILE;
|
|
565
|
+
const primaryFile = primaryFileRaw ? primaryFileRaw.split('\\').join('/') : primaryFileRaw;
|
|
566
|
+
const primaryTypeEnv = process.env.MAIASS_VERSION_PRIMARY_TYPE;
|
|
567
|
+
const primaryType = primaryTypeEnv || (primaryFile && primaryFile.endsWith('.json') ? 'json' : 'txt');
|
|
565
568
|
const primaryLineStart = process.env.MAIASS_VERSION_PRIMARY_LINE_START || '';
|
|
566
569
|
|
|
567
570
|
if (primaryFile) {
|