@wyxos/zephyr 0.2.9 → 0.2.11
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/README.md +104 -104
- package/bin/zephyr.mjs +12 -12
- package/package.json +53 -53
- package/src/index.mjs +2121 -2121
- package/src/release-node.mjs +193 -65
- package/src/release-packagist.mjs +66 -8
- package/src/ssh-utils.mjs +277 -277
package/src/release-node.mjs
CHANGED
|
@@ -5,14 +5,24 @@ import { readFile } from 'node:fs/promises'
|
|
|
5
5
|
import fs from 'node:fs'
|
|
6
6
|
import path from 'node:path'
|
|
7
7
|
import process from 'node:process'
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
const STEP_PREFIX = '→'
|
|
10
|
+
const OK_PREFIX = '✔'
|
|
11
|
+
const WARN_PREFIX = '⚠'
|
|
9
12
|
|
|
10
13
|
const IS_WINDOWS = process.platform === 'win32'
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
function logStep(message) {
|
|
16
|
+
console.log(`${STEP_PREFIX} ${message}`)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function logSuccess(message) {
|
|
20
|
+
console.log(`${OK_PREFIX} ${message}`)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function logWarning(message) {
|
|
24
|
+
console.warn(`${WARN_PREFIX} ${message}`)
|
|
25
|
+
}
|
|
16
26
|
|
|
17
27
|
function runCommand(command, args, { cwd = process.cwd(), capture = false, useShell = false } = {}) {
|
|
18
28
|
return new Promise((resolve, reject) => {
|
|
@@ -104,12 +114,12 @@ async function ensureUpToDateWithUpstream(branch, upstreamRef, rootDir = process
|
|
|
104
114
|
const remoteBranch = branchParts.join('/')
|
|
105
115
|
|
|
106
116
|
if (remoteName && remoteBranch) {
|
|
107
|
-
|
|
117
|
+
logStep(`Fetching latest updates from ${remoteName}/${remoteBranch}...`)
|
|
108
118
|
try {
|
|
109
119
|
await runCommand('git', ['fetch', remoteName, remoteBranch], { capture: true, cwd: rootDir })
|
|
110
120
|
} catch (error) {
|
|
111
121
|
if (error.stderr) {
|
|
112
|
-
|
|
122
|
+
console.error(error.stderr)
|
|
113
123
|
}
|
|
114
124
|
throw new Error(`Failed to fetch ${upstreamRef}: ${error.message}`)
|
|
115
125
|
}
|
|
@@ -129,13 +139,13 @@ async function ensureUpToDateWithUpstream(branch, upstreamRef, rootDir = process
|
|
|
129
139
|
|
|
130
140
|
if (Number.isFinite(behind) && behind > 0) {
|
|
131
141
|
if (remoteName && remoteBranch) {
|
|
132
|
-
|
|
142
|
+
logStep(`Fast-forwarding ${branch} with ${upstreamRef}...`)
|
|
133
143
|
|
|
134
144
|
try {
|
|
135
145
|
await runCommand('git', ['pull', '--ff-only', remoteName, remoteBranch], { capture: true, cwd: rootDir })
|
|
136
146
|
} catch (error) {
|
|
137
147
|
if (error.stderr) {
|
|
138
|
-
|
|
148
|
+
console.error(error.stderr)
|
|
139
149
|
}
|
|
140
150
|
throw new Error(
|
|
141
151
|
`Unable to fast-forward ${branch} with ${upstreamRef}. Resolve conflicts manually, then rerun the release.\n${error.message}`
|
|
@@ -194,13 +204,43 @@ async function runLint(skipLint, pkg, rootDir = process.cwd()) {
|
|
|
194
204
|
}
|
|
195
205
|
|
|
196
206
|
if (!hasScript(pkg, 'lint')) {
|
|
197
|
-
|
|
207
|
+
logStep('Skipping lint (no lint script found in package.json).')
|
|
198
208
|
return
|
|
199
209
|
}
|
|
200
210
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
211
|
+
logStep('Running lint...')
|
|
212
|
+
|
|
213
|
+
let dotInterval = null
|
|
214
|
+
try {
|
|
215
|
+
// Capture output and show dots as progress
|
|
216
|
+
process.stdout.write(' ')
|
|
217
|
+
dotInterval = setInterval(() => {
|
|
218
|
+
process.stdout.write('.')
|
|
219
|
+
}, 200)
|
|
220
|
+
|
|
221
|
+
await runCommand('npm', ['run', 'lint'], { capture: true, cwd: rootDir })
|
|
222
|
+
|
|
223
|
+
if (dotInterval) {
|
|
224
|
+
clearInterval(dotInterval)
|
|
225
|
+
dotInterval = null
|
|
226
|
+
}
|
|
227
|
+
process.stdout.write('\n')
|
|
228
|
+
logSuccess('Lint passed.')
|
|
229
|
+
} catch (error) {
|
|
230
|
+
// Clear dots and show error output
|
|
231
|
+
if (dotInterval) {
|
|
232
|
+
clearInterval(dotInterval)
|
|
233
|
+
dotInterval = null
|
|
234
|
+
}
|
|
235
|
+
process.stdout.write('\n')
|
|
236
|
+
if (error.stdout) {
|
|
237
|
+
console.error(error.stdout)
|
|
238
|
+
}
|
|
239
|
+
if (error.stderr) {
|
|
240
|
+
console.error(error.stderr)
|
|
241
|
+
}
|
|
242
|
+
throw error
|
|
243
|
+
}
|
|
204
244
|
}
|
|
205
245
|
|
|
206
246
|
async function runTests(skipTests, pkg, rootDir = process.cwd()) {
|
|
@@ -211,11 +251,11 @@ async function runTests(skipTests, pkg, rootDir = process.cwd()) {
|
|
|
211
251
|
|
|
212
252
|
// Check for test:run or test script
|
|
213
253
|
if (!hasScript(pkg, 'test:run') && !hasScript(pkg, 'test')) {
|
|
214
|
-
|
|
254
|
+
logStep('Skipping tests (no test or test:run script found in package.json).')
|
|
215
255
|
return
|
|
216
256
|
}
|
|
217
257
|
|
|
218
|
-
|
|
258
|
+
logStep('Running test suite...')
|
|
219
259
|
|
|
220
260
|
let dotInterval = null
|
|
221
261
|
try {
|
|
@@ -247,10 +287,10 @@ async function runTests(skipTests, pkg, rootDir = process.cwd()) {
|
|
|
247
287
|
}
|
|
248
288
|
process.stdout.write('\n')
|
|
249
289
|
if (error.stdout) {
|
|
250
|
-
|
|
290
|
+
console.error(error.stdout)
|
|
251
291
|
}
|
|
252
292
|
if (error.stderr) {
|
|
253
|
-
|
|
293
|
+
console.error(error.stderr)
|
|
254
294
|
}
|
|
255
295
|
throw error
|
|
256
296
|
}
|
|
@@ -263,13 +303,43 @@ async function runBuild(skipBuild, pkg, rootDir = process.cwd()) {
|
|
|
263
303
|
}
|
|
264
304
|
|
|
265
305
|
if (!hasScript(pkg, 'build')) {
|
|
266
|
-
|
|
306
|
+
logStep('Skipping build (no build script found in package.json).')
|
|
267
307
|
return
|
|
268
308
|
}
|
|
269
309
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
310
|
+
logStep('Building project...')
|
|
311
|
+
|
|
312
|
+
let dotInterval = null
|
|
313
|
+
try {
|
|
314
|
+
// Capture output and show dots as progress
|
|
315
|
+
process.stdout.write(' ')
|
|
316
|
+
dotInterval = setInterval(() => {
|
|
317
|
+
process.stdout.write('.')
|
|
318
|
+
}, 200)
|
|
319
|
+
|
|
320
|
+
await runCommand('npm', ['run', 'build'], { capture: true, cwd: rootDir })
|
|
321
|
+
|
|
322
|
+
if (dotInterval) {
|
|
323
|
+
clearInterval(dotInterval)
|
|
324
|
+
dotInterval = null
|
|
325
|
+
}
|
|
326
|
+
process.stdout.write('\n')
|
|
327
|
+
logSuccess('Build completed.')
|
|
328
|
+
} catch (error) {
|
|
329
|
+
// Clear dots and show error output
|
|
330
|
+
if (dotInterval) {
|
|
331
|
+
clearInterval(dotInterval)
|
|
332
|
+
dotInterval = null
|
|
333
|
+
}
|
|
334
|
+
process.stdout.write('\n')
|
|
335
|
+
if (error.stdout) {
|
|
336
|
+
console.error(error.stdout)
|
|
337
|
+
}
|
|
338
|
+
if (error.stderr) {
|
|
339
|
+
console.error(error.stderr)
|
|
340
|
+
}
|
|
341
|
+
throw error
|
|
342
|
+
}
|
|
273
343
|
}
|
|
274
344
|
|
|
275
345
|
async function runLibBuild(skipBuild, pkg, rootDir = process.cwd()) {
|
|
@@ -279,13 +349,43 @@ async function runLibBuild(skipBuild, pkg, rootDir = process.cwd()) {
|
|
|
279
349
|
}
|
|
280
350
|
|
|
281
351
|
if (!hasScript(pkg, 'build:lib')) {
|
|
282
|
-
|
|
352
|
+
logStep('Skipping library build (no build:lib script found in package.json).')
|
|
283
353
|
return false
|
|
284
354
|
}
|
|
285
355
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
356
|
+
logStep('Building library...')
|
|
357
|
+
|
|
358
|
+
let dotInterval = null
|
|
359
|
+
try {
|
|
360
|
+
// Capture output and show dots as progress
|
|
361
|
+
process.stdout.write(' ')
|
|
362
|
+
dotInterval = setInterval(() => {
|
|
363
|
+
process.stdout.write('.')
|
|
364
|
+
}, 200)
|
|
365
|
+
|
|
366
|
+
await runCommand('npm', ['run', 'build:lib'], { capture: true, cwd: rootDir })
|
|
367
|
+
|
|
368
|
+
if (dotInterval) {
|
|
369
|
+
clearInterval(dotInterval)
|
|
370
|
+
dotInterval = null
|
|
371
|
+
}
|
|
372
|
+
process.stdout.write('\n')
|
|
373
|
+
logSuccess('Library built.')
|
|
374
|
+
} catch (error) {
|
|
375
|
+
// Clear dots and show error output
|
|
376
|
+
if (dotInterval) {
|
|
377
|
+
clearInterval(dotInterval)
|
|
378
|
+
dotInterval = null
|
|
379
|
+
}
|
|
380
|
+
process.stdout.write('\n')
|
|
381
|
+
if (error.stdout) {
|
|
382
|
+
console.error(error.stdout)
|
|
383
|
+
}
|
|
384
|
+
if (error.stderr) {
|
|
385
|
+
console.error(error.stderr)
|
|
386
|
+
}
|
|
387
|
+
throw error
|
|
388
|
+
}
|
|
289
389
|
|
|
290
390
|
// Check for lib changes and commit them if any
|
|
291
391
|
const { stdout: statusAfterBuild } = await runCommand('git', ['status', '--porcelain'], { capture: true, cwd: rootDir })
|
|
@@ -295,7 +395,7 @@ async function runLibBuild(skipBuild, pkg, rootDir = process.cwd()) {
|
|
|
295
395
|
})
|
|
296
396
|
|
|
297
397
|
if (hasLibChanges) {
|
|
298
|
-
|
|
398
|
+
logStep('Committing lib build artifacts...')
|
|
299
399
|
await runCommand('git', ['add', 'lib/'], { capture: true, cwd: rootDir })
|
|
300
400
|
await runCommand('git', ['commit', '-m', 'chore: build lib artifacts'], { capture: true, cwd: rootDir })
|
|
301
401
|
logSuccess('Lib build artifacts committed.')
|
|
@@ -305,7 +405,7 @@ async function runLibBuild(skipBuild, pkg, rootDir = process.cwd()) {
|
|
|
305
405
|
}
|
|
306
406
|
|
|
307
407
|
async function ensureNpmAuth(rootDir = process.cwd()) {
|
|
308
|
-
|
|
408
|
+
logStep('Confirming npm authentication...')
|
|
309
409
|
try {
|
|
310
410
|
const result = await runCommand('npm', ['whoami'], { capture: true, cwd: rootDir })
|
|
311
411
|
// Only show username if we captured it, otherwise just show success
|
|
@@ -315,14 +415,14 @@ async function ensureNpmAuth(rootDir = process.cwd()) {
|
|
|
315
415
|
logSuccess('npm authenticated.')
|
|
316
416
|
} catch (error) {
|
|
317
417
|
if (error.stderr) {
|
|
318
|
-
|
|
418
|
+
console.error(error.stderr)
|
|
319
419
|
}
|
|
320
420
|
throw error
|
|
321
421
|
}
|
|
322
422
|
}
|
|
323
423
|
|
|
324
424
|
async function bumpVersion(releaseType, rootDir = process.cwd()) {
|
|
325
|
-
|
|
425
|
+
logStep(`Bumping package version...`)
|
|
326
426
|
|
|
327
427
|
// Lib changes should already be committed by runLibBuild, but check anyway
|
|
328
428
|
const { stdout: statusBefore } = await runCommand('git', ['status', '--porcelain'], { capture: true, cwd: rootDir })
|
|
@@ -332,7 +432,7 @@ async function bumpVersion(releaseType, rootDir = process.cwd()) {
|
|
|
332
432
|
})
|
|
333
433
|
|
|
334
434
|
if (hasLibChanges) {
|
|
335
|
-
|
|
435
|
+
logStep('Stashing lib build artifacts...')
|
|
336
436
|
await runCommand('git', ['stash', 'push', '-u', '-m', 'temp: lib build artifacts', 'lib/'], { capture: true, cwd: rootDir })
|
|
337
437
|
}
|
|
338
438
|
|
|
@@ -349,7 +449,7 @@ async function bumpVersion(releaseType, rootDir = process.cwd()) {
|
|
|
349
449
|
} finally {
|
|
350
450
|
// Restore lib changes and ensure they're in the commit
|
|
351
451
|
if (hasLibChanges) {
|
|
352
|
-
|
|
452
|
+
logStep('Restoring lib build artifacts...')
|
|
353
453
|
await runCommand('git', ['stash', 'pop'], { capture: true, cwd: rootDir })
|
|
354
454
|
await runCommand('git', ['add', 'lib/'], { capture: true, cwd: rootDir })
|
|
355
455
|
const { stdout: statusAfter } = await runCommand('git', ['status', '--porcelain'], { capture: true, cwd: rootDir })
|
|
@@ -370,16 +470,16 @@ async function bumpVersion(releaseType, rootDir = process.cwd()) {
|
|
|
370
470
|
}
|
|
371
471
|
|
|
372
472
|
async function pushChanges(rootDir = process.cwd()) {
|
|
373
|
-
|
|
473
|
+
logStep('Pushing commits and tags to origin...')
|
|
374
474
|
try {
|
|
375
475
|
await runCommand('git', ['push', '--follow-tags'], { capture: true, cwd: rootDir })
|
|
376
476
|
logSuccess('Git push completed.')
|
|
377
477
|
} catch (error) {
|
|
378
478
|
if (error.stdout) {
|
|
379
|
-
|
|
479
|
+
console.error(error.stdout)
|
|
380
480
|
}
|
|
381
481
|
if (error.stderr) {
|
|
382
|
-
|
|
482
|
+
console.error(error.stderr)
|
|
383
483
|
}
|
|
384
484
|
throw error
|
|
385
485
|
}
|
|
@@ -395,16 +495,16 @@ async function publishPackage(pkg, rootDir = process.cwd()) {
|
|
|
395
495
|
publishArgs.push('--access', access)
|
|
396
496
|
}
|
|
397
497
|
|
|
398
|
-
|
|
498
|
+
logStep(`Publishing ${pkg.name}@${pkg.version} to npm...`)
|
|
399
499
|
try {
|
|
400
500
|
await runCommand('npm', publishArgs, { capture: true, cwd: rootDir })
|
|
401
501
|
logSuccess('npm publish completed.')
|
|
402
502
|
} catch (error) {
|
|
403
503
|
if (error.stdout) {
|
|
404
|
-
|
|
504
|
+
console.error(error.stdout)
|
|
405
505
|
}
|
|
406
506
|
if (error.stderr) {
|
|
407
|
-
|
|
507
|
+
console.error(error.stderr)
|
|
408
508
|
}
|
|
409
509
|
throw error
|
|
410
510
|
}
|
|
@@ -439,11 +539,11 @@ async function deployGHPages(skipDeploy, pkg, rootDir = process.cwd()) {
|
|
|
439
539
|
}
|
|
440
540
|
|
|
441
541
|
if (!distExists) {
|
|
442
|
-
|
|
542
|
+
logStep('Skipping GitHub Pages deployment (no dist directory found).')
|
|
443
543
|
return
|
|
444
544
|
}
|
|
445
545
|
|
|
446
|
-
|
|
546
|
+
logStep('Deploying to GitHub Pages...')
|
|
447
547
|
|
|
448
548
|
// Write CNAME file to dist if homepage is set
|
|
449
549
|
const cnamePath = path.join(distPath, 'CNAME')
|
|
@@ -462,34 +562,62 @@ async function deployGHPages(skipDeploy, pkg, rootDir = process.cwd()) {
|
|
|
462
562
|
|
|
463
563
|
const worktreeDir = path.resolve(rootDir, '.gh-pages')
|
|
464
564
|
|
|
565
|
+
let dotInterval = null
|
|
465
566
|
try {
|
|
466
|
-
|
|
467
|
-
|
|
567
|
+
// Capture output and show dots as progress
|
|
568
|
+
process.stdout.write(' ')
|
|
569
|
+
dotInterval = setInterval(() => {
|
|
570
|
+
process.stdout.write('.')
|
|
571
|
+
}, 200)
|
|
468
572
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
await runCommand('git', ['worktree', 'add', worktreeDir, '-b', 'gh-pages'], { cwd: rootDir })
|
|
473
|
-
}
|
|
573
|
+
try {
|
|
574
|
+
await runCommand('git', ['worktree', 'remove', worktreeDir, '-f'], { capture: true, cwd: rootDir })
|
|
575
|
+
} catch { }
|
|
474
576
|
|
|
475
|
-
|
|
476
|
-
|
|
577
|
+
try {
|
|
578
|
+
await runCommand('git', ['worktree', 'add', worktreeDir, 'gh-pages'], { capture: true, cwd: rootDir })
|
|
579
|
+
} catch {
|
|
580
|
+
await runCommand('git', ['worktree', 'add', worktreeDir, '-b', 'gh-pages'], { capture: true, cwd: rootDir })
|
|
581
|
+
}
|
|
477
582
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
fs.
|
|
483
|
-
|
|
583
|
+
await runCommand('git', ['-C', worktreeDir, 'config', 'user.name', 'wyxos'], { capture: true })
|
|
584
|
+
await runCommand('git', ['-C', worktreeDir, 'config', 'user.email', 'github@wyxos.com'], { capture: true })
|
|
585
|
+
|
|
586
|
+
// Clear worktree directory
|
|
587
|
+
for (const entry of fs.readdirSync(worktreeDir)) {
|
|
588
|
+
if (entry === '.git') continue
|
|
589
|
+
const target = path.join(worktreeDir, entry)
|
|
590
|
+
fs.rmSync(target, { recursive: true, force: true })
|
|
591
|
+
}
|
|
484
592
|
|
|
485
|
-
|
|
486
|
-
|
|
593
|
+
// Copy dist to worktree
|
|
594
|
+
fs.cpSync(distPath, worktreeDir, { recursive: true })
|
|
487
595
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
596
|
+
await runCommand('git', ['-C', worktreeDir, 'add', '-A'], { capture: true })
|
|
597
|
+
await runCommand('git', ['-C', worktreeDir, 'commit', '-m', `deploy: demo ${new Date().toISOString()}`, '--allow-empty'], { capture: true })
|
|
598
|
+
await runCommand('git', ['-C', worktreeDir, 'push', '-f', 'origin', 'gh-pages'], { capture: true })
|
|
491
599
|
|
|
492
|
-
|
|
600
|
+
if (dotInterval) {
|
|
601
|
+
clearInterval(dotInterval)
|
|
602
|
+
dotInterval = null
|
|
603
|
+
}
|
|
604
|
+
process.stdout.write('\n')
|
|
605
|
+
logSuccess('GitHub Pages deployment completed.')
|
|
606
|
+
} catch (error) {
|
|
607
|
+
// Clear dots and show error output
|
|
608
|
+
if (dotInterval) {
|
|
609
|
+
clearInterval(dotInterval)
|
|
610
|
+
dotInterval = null
|
|
611
|
+
}
|
|
612
|
+
process.stdout.write('\n')
|
|
613
|
+
if (error.stdout) {
|
|
614
|
+
console.error(error.stdout)
|
|
615
|
+
}
|
|
616
|
+
if (error.stderr) {
|
|
617
|
+
console.error(error.stderr)
|
|
618
|
+
}
|
|
619
|
+
throw error
|
|
620
|
+
}
|
|
493
621
|
}
|
|
494
622
|
|
|
495
623
|
export async function releaseNode() {
|
|
@@ -497,10 +625,10 @@ export async function releaseNode() {
|
|
|
497
625
|
const { releaseType, skipTests, skipLint, skipBuild, skipDeploy } = parseArgs()
|
|
498
626
|
const rootDir = process.cwd()
|
|
499
627
|
|
|
500
|
-
|
|
628
|
+
logStep('Reading package metadata...')
|
|
501
629
|
const pkg = await readPackage(rootDir)
|
|
502
630
|
|
|
503
|
-
|
|
631
|
+
logStep('Checking working tree status...')
|
|
504
632
|
await ensureCleanWorkingTree(rootDir)
|
|
505
633
|
|
|
506
634
|
const branch = await getCurrentBranch(rootDir)
|
|
@@ -508,7 +636,7 @@ export async function releaseNode() {
|
|
|
508
636
|
throw new Error('Unable to determine current branch.')
|
|
509
637
|
}
|
|
510
638
|
|
|
511
|
-
|
|
639
|
+
logStep(`Current branch: ${branch}`)
|
|
512
640
|
const upstreamRef = await getUpstreamRef(rootDir)
|
|
513
641
|
await ensureUpToDateWithUpstream(branch, upstreamRef, rootDir)
|
|
514
642
|
|
|
@@ -525,8 +653,8 @@ export async function releaseNode() {
|
|
|
525
653
|
|
|
526
654
|
logSuccess(`Release workflow completed for ${updatedPkg.name}@${updatedPkg.version}.`)
|
|
527
655
|
} catch (error) {
|
|
528
|
-
|
|
529
|
-
|
|
656
|
+
console.error('\nRelease failed:')
|
|
657
|
+
console.error(error.message)
|
|
530
658
|
throw error
|
|
531
659
|
}
|
|
532
660
|
}
|
|
@@ -230,8 +230,38 @@ async function runLint(skipLint, rootDir = process.cwd()) {
|
|
|
230
230
|
|
|
231
231
|
logStep('Running Laravel Pint...')
|
|
232
232
|
const pintPath = IS_WINDOWS ? 'vendor\\bin\\pint' : 'vendor/bin/pint'
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
|
|
234
|
+
let dotInterval = null
|
|
235
|
+
try {
|
|
236
|
+
// Capture output and show dots as progress
|
|
237
|
+
process.stdout.write(' ')
|
|
238
|
+
dotInterval = setInterval(() => {
|
|
239
|
+
process.stdout.write('.')
|
|
240
|
+
}, 200)
|
|
241
|
+
|
|
242
|
+
await runCommand('php', [pintPath], { capture: true, cwd: rootDir })
|
|
243
|
+
|
|
244
|
+
if (dotInterval) {
|
|
245
|
+
clearInterval(dotInterval)
|
|
246
|
+
dotInterval = null
|
|
247
|
+
}
|
|
248
|
+
process.stdout.write('\n')
|
|
249
|
+
logSuccess('Lint passed.')
|
|
250
|
+
} catch (error) {
|
|
251
|
+
// Clear dots and show error output
|
|
252
|
+
if (dotInterval) {
|
|
253
|
+
clearInterval(dotInterval)
|
|
254
|
+
dotInterval = null
|
|
255
|
+
}
|
|
256
|
+
process.stdout.write('\n')
|
|
257
|
+
if (error.stdout) {
|
|
258
|
+
console.error(error.stdout)
|
|
259
|
+
}
|
|
260
|
+
if (error.stderr) {
|
|
261
|
+
console.error(error.stderr)
|
|
262
|
+
}
|
|
263
|
+
throw error
|
|
264
|
+
}
|
|
235
265
|
}
|
|
236
266
|
|
|
237
267
|
async function runTests(skipTests, composer, rootDir = process.cwd()) {
|
|
@@ -250,13 +280,41 @@ async function runTests(skipTests, composer, rootDir = process.cwd()) {
|
|
|
250
280
|
|
|
251
281
|
logStep('Running test suite...')
|
|
252
282
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
283
|
+
let dotInterval = null
|
|
284
|
+
try {
|
|
285
|
+
// Capture output and show dots as progress
|
|
286
|
+
process.stdout.write(' ')
|
|
287
|
+
dotInterval = setInterval(() => {
|
|
288
|
+
process.stdout.write('.')
|
|
289
|
+
}, 200)
|
|
290
|
+
|
|
291
|
+
if (hasArtisanFile) {
|
|
292
|
+
await runCommand('php', ['artisan', 'test'], { capture: true, cwd: rootDir })
|
|
293
|
+
} else if (hasTestScript) {
|
|
294
|
+
await runCommand('composer', ['test'], { capture: true, cwd: rootDir })
|
|
295
|
+
}
|
|
258
296
|
|
|
259
|
-
|
|
297
|
+
if (dotInterval) {
|
|
298
|
+
clearInterval(dotInterval)
|
|
299
|
+
dotInterval = null
|
|
300
|
+
}
|
|
301
|
+
process.stdout.write('\n')
|
|
302
|
+
logSuccess('Tests passed.')
|
|
303
|
+
} catch (error) {
|
|
304
|
+
// Clear dots and show error output
|
|
305
|
+
if (dotInterval) {
|
|
306
|
+
clearInterval(dotInterval)
|
|
307
|
+
dotInterval = null
|
|
308
|
+
}
|
|
309
|
+
process.stdout.write('\n')
|
|
310
|
+
if (error.stdout) {
|
|
311
|
+
console.error(error.stdout)
|
|
312
|
+
}
|
|
313
|
+
if (error.stderr) {
|
|
314
|
+
console.error(error.stderr)
|
|
315
|
+
}
|
|
316
|
+
throw error
|
|
317
|
+
}
|
|
260
318
|
}
|
|
261
319
|
|
|
262
320
|
async function bumpVersion(releaseType, rootDir = process.cwd()) {
|