@wyxos/zephyr 0.2.15 → 0.2.16
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/package.json +1 -1
- package/src/dependency-scanner.mjs +122 -1
- package/src/index.mjs +1 -1
- package/src/release-node.mjs +1 -1
- package/src/release-packagist.mjs +1 -1
package/package.json
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { readFile, writeFile } from 'node:fs/promises'
|
|
2
2
|
import path from 'node:path'
|
|
3
|
+
import { spawn } from 'node:child_process'
|
|
4
|
+
import process from 'node:process'
|
|
5
|
+
|
|
6
|
+
const IS_WINDOWS = process.platform === 'win32'
|
|
3
7
|
|
|
4
8
|
function isLocalPathOutsideRepo(depPath, rootDir) {
|
|
5
9
|
if (!depPath || typeof depPath !== 'string') {
|
|
@@ -212,7 +216,113 @@ async function updateComposerJsonDependency(rootDir, packageName, newVersion, fi
|
|
|
212
216
|
await writeFile(composerJsonPath, updatedContent, 'utf8')
|
|
213
217
|
}
|
|
214
218
|
|
|
215
|
-
async function
|
|
219
|
+
async function runCommand(command, args, { cwd = process.cwd(), capture = false } = {}) {
|
|
220
|
+
return new Promise((resolve, reject) => {
|
|
221
|
+
const spawnOptions = {
|
|
222
|
+
stdio: capture ? ['ignore', 'pipe', 'pipe'] : 'inherit',
|
|
223
|
+
cwd
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (IS_WINDOWS && command !== 'git') {
|
|
227
|
+
spawnOptions.shell = true
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const child = spawn(command, args, spawnOptions)
|
|
231
|
+
let stdout = ''
|
|
232
|
+
let stderr = ''
|
|
233
|
+
|
|
234
|
+
if (capture) {
|
|
235
|
+
child.stdout.on('data', (chunk) => {
|
|
236
|
+
stdout += chunk
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
child.stderr.on('data', (chunk) => {
|
|
240
|
+
stderr += chunk
|
|
241
|
+
})
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
child.on('error', reject)
|
|
245
|
+
child.on('close', (code) => {
|
|
246
|
+
if (code === 0) {
|
|
247
|
+
resolve(capture ? { stdout: stdout.trim(), stderr: stderr.trim() } : undefined)
|
|
248
|
+
} else {
|
|
249
|
+
const error = new Error(`Command failed (${code}): ${command} ${args.join(' ')}`)
|
|
250
|
+
if (capture) {
|
|
251
|
+
error.stdout = stdout
|
|
252
|
+
error.stderr = stderr
|
|
253
|
+
}
|
|
254
|
+
error.exitCode = code
|
|
255
|
+
reject(error)
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
})
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async function getGitStatus(rootDir) {
|
|
262
|
+
try {
|
|
263
|
+
const result = await runCommand('git', ['status', '--porcelain'], { capture: true, cwd: rootDir })
|
|
264
|
+
return result.stdout || ''
|
|
265
|
+
} catch (error) {
|
|
266
|
+
return ''
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function hasStagedChanges(statusOutput) {
|
|
271
|
+
if (!statusOutput || statusOutput.length === 0) {
|
|
272
|
+
return false
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const lines = statusOutput.split('\n').filter((line) => line.trim().length > 0)
|
|
276
|
+
|
|
277
|
+
return lines.some((line) => {
|
|
278
|
+
const firstChar = line[0]
|
|
279
|
+
return firstChar && firstChar !== ' ' && firstChar !== '?'
|
|
280
|
+
})
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
async function commitDependencyUpdates(rootDir, updatedFiles, logFn) {
|
|
284
|
+
try {
|
|
285
|
+
// Check if we're in a git repository
|
|
286
|
+
await runCommand('git', ['rev-parse', '--is-inside-work-tree'], { capture: true, cwd: rootDir })
|
|
287
|
+
} catch {
|
|
288
|
+
// Not a git repository, skip commit
|
|
289
|
+
return false
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const status = await getGitStatus(rootDir)
|
|
293
|
+
|
|
294
|
+
// Stage the updated files
|
|
295
|
+
for (const file of updatedFiles) {
|
|
296
|
+
try {
|
|
297
|
+
await runCommand('git', ['add', file], { cwd: rootDir })
|
|
298
|
+
} catch {
|
|
299
|
+
// File might not exist or not be tracked, continue
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const newStatus = await getGitStatus(rootDir)
|
|
304
|
+
if (!hasStagedChanges(newStatus)) {
|
|
305
|
+
return false
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Build commit message
|
|
309
|
+
const fileList = updatedFiles.map(f => path.basename(f)).join(', ')
|
|
310
|
+
const commitMessage = `chore: update local file dependencies to online versions (${fileList})`
|
|
311
|
+
|
|
312
|
+
if (logFn) {
|
|
313
|
+
logFn('Committing dependency updates...')
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
await runCommand('git', ['commit', '-m', commitMessage], { cwd: rootDir })
|
|
317
|
+
|
|
318
|
+
if (logFn) {
|
|
319
|
+
logFn('Dependency updates committed.')
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return true
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
async function validateLocalDependencies(rootDir, promptFn, logFn = null) {
|
|
216
326
|
const packageDeps = await scanPackageJsonDependencies(rootDir)
|
|
217
327
|
const composerDeps = await scanComposerJsonDependencies(rootDir)
|
|
218
328
|
|
|
@@ -265,6 +375,9 @@ async function validateLocalDependencies(rootDir, promptFn) {
|
|
|
265
375
|
throw new Error('Release cancelled: local file dependencies must be updated before release.')
|
|
266
376
|
}
|
|
267
377
|
|
|
378
|
+
// Track which files were updated
|
|
379
|
+
const updatedFiles = new Set()
|
|
380
|
+
|
|
268
381
|
// Update dependencies
|
|
269
382
|
for (const dep of depsWithVersions) {
|
|
270
383
|
if (!dep.latestVersion) {
|
|
@@ -273,8 +386,10 @@ async function validateLocalDependencies(rootDir, promptFn) {
|
|
|
273
386
|
|
|
274
387
|
if (dep.field === 'dependencies' || dep.field === 'devDependencies') {
|
|
275
388
|
await updatePackageJsonDependency(rootDir, dep.packageName, dep.latestVersion, dep.field)
|
|
389
|
+
updatedFiles.add('package.json')
|
|
276
390
|
} else if (dep.field === 'require' || dep.field === 'require-dev') {
|
|
277
391
|
await updateComposerJsonDependency(rootDir, dep.packageName, dep.latestVersion, dep.field)
|
|
392
|
+
updatedFiles.add('composer.json')
|
|
278
393
|
} else if (dep.field === 'repositories') {
|
|
279
394
|
// For repositories, we need to remove the repository entry
|
|
280
395
|
// But we still need to update the dependency version
|
|
@@ -319,9 +434,15 @@ async function validateLocalDependencies(rootDir, promptFn) {
|
|
|
319
434
|
const updatedContent = JSON.stringify(updatedComposer, null, 2) + '\n'
|
|
320
435
|
await writeFile(composerJsonPath, updatedContent, 'utf8')
|
|
321
436
|
}
|
|
437
|
+
updatedFiles.add('composer.json')
|
|
322
438
|
}
|
|
323
439
|
}
|
|
324
440
|
}
|
|
441
|
+
|
|
442
|
+
// Commit the changes if any files were updated
|
|
443
|
+
if (updatedFiles.size > 0) {
|
|
444
|
+
await commitDependencyUpdates(rootDir, Array.from(updatedFiles), logFn)
|
|
445
|
+
}
|
|
325
446
|
}
|
|
326
447
|
|
|
327
448
|
export {
|
package/src/index.mjs
CHANGED
|
@@ -1915,7 +1915,7 @@ async function main(releaseType = null) {
|
|
|
1915
1915
|
|
|
1916
1916
|
if (hasPackageJson || hasComposerJson) {
|
|
1917
1917
|
logProcessing('Validating dependencies...')
|
|
1918
|
-
await validateLocalDependencies(rootDir, runPrompt)
|
|
1918
|
+
await validateLocalDependencies(rootDir, runPrompt, logSuccess)
|
|
1919
1919
|
}
|
|
1920
1920
|
|
|
1921
1921
|
// Load servers first (they may be migrated)
|
package/src/release-node.mjs
CHANGED
|
@@ -583,7 +583,7 @@ export async function releaseNode() {
|
|
|
583
583
|
const pkg = await readPackage(rootDir)
|
|
584
584
|
|
|
585
585
|
logStep('Validating dependencies...')
|
|
586
|
-
await validateLocalDependencies(rootDir, (questions) => inquirer.prompt(questions))
|
|
586
|
+
await validateLocalDependencies(rootDir, (questions) => inquirer.prompt(questions), logSuccess)
|
|
587
587
|
|
|
588
588
|
logStep('Checking working tree status...')
|
|
589
589
|
await ensureCleanWorkingTree(rootDir)
|
|
@@ -387,7 +387,7 @@ export async function releasePackagist() {
|
|
|
387
387
|
}
|
|
388
388
|
|
|
389
389
|
logStep('Validating dependencies...')
|
|
390
|
-
await validateLocalDependencies(rootDir, (questions) => inquirer.prompt(questions))
|
|
390
|
+
await validateLocalDependencies(rootDir, (questions) => inquirer.prompt(questions), logSuccess)
|
|
391
391
|
|
|
392
392
|
logStep('Checking working tree status...')
|
|
393
393
|
await ensureCleanWorkingTree(rootDir)
|