Skip to content

Commit 2072a1f

Browse files
authored
improve output for release proposal script (#4897)
1 parent 9de411a commit 2072a1f

3 files changed

Lines changed: 254 additions & 93 deletions

File tree

scripts/release/helpers/requirements.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
/* eslint-disable max-len */
44

5-
const { capture, fatal } = require('./terminal')
5+
const { capture, fatal, run } = require('./terminal')
66

77
const requiredScopes = ['public_repo', 'read:org']
88

99
// Check that the `git` CLI is installed.
1010
function checkGit () {
1111
try {
12-
capture('git --version')
12+
run('git --version')
1313
} catch (e) {
1414
fatal(
1515
'The "git" CLI could not be found.',
@@ -21,7 +21,7 @@ function checkGit () {
2121
// Check that the `branch-diff` CLI is installed.
2222
function checkBranchDiff () {
2323
try {
24-
capture('branch-diff --version')
24+
run('branch-diff --version')
2525
} catch (e) {
2626
const link = [
2727
'https://datadoghq.atlassian.net/wiki/spaces/DL/pages/3125511269/Node.js+Tracer+Release+Process',
@@ -47,7 +47,7 @@ function checkGitHub () {
4747
}
4848

4949
try {
50-
capture('gh --version')
50+
run('gh --version')
5151
} catch (e) {
5252
fatal(
5353
'The "gh" CLI could not be found.',
Lines changed: 117 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
11
'use strict'
22

3-
/* eslint-disable no-console */
4-
53
const { execSync, spawnSync } = require('child_process')
64

7-
// Helpers for colored output.
8-
const log = (...msgs) => msgs.forEach(msg => console.log(msg))
9-
const success = (...msgs) => msgs.forEach(msg => console.log(`\x1b[32m${msg}\x1b[0m`))
10-
const error = (...msgs) => msgs.forEach(msg => console.log(`\x1b[31m${msg}\x1b[0m`))
11-
const whisper = (...msgs) => msgs.forEach(msg => console.log(`\x1b[90m${msg}\x1b[0m`))
5+
const { params, flags } = parse()
126

13-
// Helpers for exiting with a message.
14-
const exit = (...msgs) => log(...msgs) || process.exit(0)
15-
const fatal = (...msgs) => error(...msgs) || process.exit(1)
7+
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
168

17-
// Output a command to the terminal and execute it.
18-
function run (cmd) {
19-
whisper(`> ${cmd}`)
9+
const BOLD = '\x1b[1m'
10+
const CYAN = '\x1b[36m'
11+
const ERASE = '\x1b[0K'
12+
const GRAY = '\x1b[90m'
13+
const GREEN = '\x1b[32m'
14+
const PREVIOUS = '\x1b[1A'
15+
const RED = '\x1b[31m'
16+
const RESET = '\x1b[0m'
2017

21-
const output = execSync(cmd, {}).toString()
18+
const print = (...msgs) => msgs.forEach(msg => process.stdout.write(msg))
19+
const log = (...msgs) => msgs.forEach(msg => print(`${msg}\n`))
20+
const fatal = (...msgs) => log(...msgs) || process.exit(1)
2221

23-
log(output)
22+
let timer
23+
let current
24+
25+
// Output a command to the terminal and execute it.
26+
function run (cmd) {
27+
capture(cmd)
2428
}
2529

2630
// Ask a question in terminal and return the response.
2731
function prompt (question) {
28-
process.stdout.write(`${question} `)
32+
print(`${BOLD}${CYAN}?${RESET} ${BOLD}${question}${RESET} `)
2933

3034
const child = spawnSync('bash', ['-c', 'read answer && echo $answer'], {
3135
stdio: ['inherit']
@@ -37,15 +41,110 @@ function prompt (question) {
3741
// Ask whether to continue and otherwise exit the process.
3842
function checkpoint (question) {
3943
const answer = prompt(`${question} [Y/n]`).trim()
44+
const prefix = `\r${PREVIOUS}${BOLD}${CYAN}?${RESET}`
45+
46+
question = `${BOLD}${question}${RESET}`
4047

4148
if (answer && answer.toLowerCase() !== 'y') {
49+
print(`\r${prefix} ${question} ${BOLD}${CYAN}No${RESET}${ERASE}\n`)
4250
process.exit(0)
51+
} else {
52+
print(`\r${prefix} ${question} ${BOLD}${CYAN}Yes${RESET}${ERASE}\n`)
4353
}
4454
}
4555

4656
// Run a command and capture its output to return it to the caller.
4757
function capture (cmd) {
48-
return execSync(cmd, {}).toString()
58+
if (flags.debug) {
59+
log(`${GRAY}> ${cmd}${RESET}`)
60+
}
61+
62+
const output = execSync(cmd, { encoding: 'utf8', stdio: 'pipe' }).toString().trim()
63+
64+
if (flags.debug) {
65+
log(output)
66+
}
67+
68+
return output
69+
}
70+
71+
// Start an operation and show a spinner until it reports as passing or failing.
72+
function start (title) {
73+
current = title
74+
75+
spin(0)
76+
}
77+
78+
// Show a spinner for the current operation.
79+
function spin (index) {
80+
if (flags.debug) return
81+
82+
print(`\r${CYAN}${frames[index]}${RESET} ${BOLD}${current}${RESET}`)
83+
84+
timer = setTimeout(spin, 80, index === frames.length - 1 ? 0 : index + 1)
85+
}
86+
87+
// Finish the current operation as passing.
88+
function pass (result) {
89+
if (!current) return
90+
91+
clearTimeout(timer)
92+
93+
if (!flags.debug) {
94+
print(`\r${GREEN}${RESET} ${BOLD}${current}${RESET}`)
95+
96+
if (result) {
97+
print(`: ${BOLD}${CYAN}${result}${RESET}`)
98+
}
99+
100+
print('\n')
101+
}
102+
103+
current = undefined
104+
}
105+
106+
// Finish the current operation as failing.
107+
function fail (err) {
108+
if (!current) return
109+
110+
clearTimeout(timer)
111+
112+
if (!flags.debug) {
113+
print(`\r${RED}${RESET} ${BOLD}${current}${RESET}\n`)
114+
}
115+
116+
current = undefined
117+
118+
throw err
119+
}
120+
121+
// Parse CLI arguments into parameters and flags.
122+
function parse () {
123+
const args = process.argv.slice(2)
124+
const params = []
125+
const flags = {}
126+
127+
for (const arg of args) {
128+
if (arg.startsWith('-')) {
129+
const name = arg.replace(/^-+/, '')
130+
flags[name] = true
131+
} else {
132+
params.push(arg)
133+
}
134+
}
135+
136+
return { params, flags }
49137
}
50138

51-
module.exports = { capture, checkpoint, error, exit, fatal, log, success, run, whisper }
139+
module.exports = {
140+
capture,
141+
checkpoint,
142+
fail,
143+
fatal,
144+
flags,
145+
log,
146+
params,
147+
pass,
148+
run,
149+
start
150+
}

0 commit comments

Comments
 (0)