@toptal/davinci-workflow 1.9.0 → 1.10.0
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/CHANGELOG.md +14 -0
- package/bin/davinci-workflow.js +4 -1
- package/dist-package/package.json +6 -3
- package/package.json +6 -3
- package/src/commands/new-workflow.js +11 -3
- package/src/post-build/{alpha-package.js → alpha-package/alpha-package.js} +1 -1
- package/src/post-build/alpha-package/index.js +1 -0
- package/src/post-build/{deploy.js → deploy/deploy.js} +1 -1
- package/src/post-build/deploy/index.js +1 -0
- package/src/post-build/{deploy-temploy.js → deploy-temploy/deploy-temploy.js} +1 -1
- package/src/post-build/deploy-temploy/index.js +1 -0
- package/src/post-build/integration-tests/index.js +1 -0
- package/src/post-build/integration-tests/integration-tests.js +126 -0
- package/src/post-build/integration-tests/nyc.js +22 -0
- package/src/post-build/integration-tests/prompts.js +82 -0
- package/src/utils/filter-packages-by-commands.js +29 -0
- package/src/utils/get-program-config.js +42 -0
- package/src/utils/prompts.js +74 -0
- package/src/utils/set-root-env.js +17 -0
- package/src/post-build/integration-tests.js +0 -26
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @toptal/davinci-workflow
|
|
2
2
|
|
|
3
|
+
## 1.10.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1341](https://github.com/toptal/davinci/pull/1341) [`2d5479da`](https://github.com/toptal/davinci/commit/2d5479dab2cedf0133da1a47e91b2bde5b6b019d) Thanks [@OndrejTuma](https://github.com/OndrejTuma)! - ### new-workflow integration-tests
|
|
8
|
+
|
|
9
|
+
- collects additional information during generation and updates the workflow
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`2d5479da`](https://github.com/toptal/davinci/commit/2d5479dab2cedf0133da1a47e91b2bde5b6b019d), [`5410a3b7`](https://github.com/toptal/davinci/commit/5410a3b73e3dbbc96ad8dbeca0bdde03d8d2d676)]:
|
|
14
|
+
- @toptal/davinci-monorepo@6.6.0
|
|
15
|
+
- @toptal/davinci-skeleton@7.1.1
|
|
16
|
+
|
|
3
17
|
## 1.9.0
|
|
4
18
|
|
|
5
19
|
### Minor Changes
|
package/bin/davinci-workflow.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
const inquirer = require('inquirer')
|
|
3
3
|
const cliEngine = require('@toptal/davinci-cli-shared')
|
|
4
4
|
|
|
5
5
|
const newWorkflowCommandCreator = require('../src/commands/new-workflow')
|
|
6
6
|
|
|
7
|
+
// register 'table' prompt type https://npmjs.com/package/inquirer-table-prompt
|
|
8
|
+
inquirer.registerPrompt('table', require('inquirer-table-prompt'))
|
|
9
|
+
|
|
7
10
|
cliEngine.loadCommands([newWorkflowCommandCreator])
|
|
8
11
|
|
|
9
12
|
cliEngine.bootstrap()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toptal/davinci-workflow",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "GH Workflow generator package for frontend applications",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -31,10 +31,13 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@toptal/davinci-cli-shared": "1.5.2",
|
|
34
|
-
"@toptal/davinci-monorepo": "^6.
|
|
35
|
-
"@toptal/davinci-skeleton": "7.1.
|
|
34
|
+
"@toptal/davinci-monorepo": "^6.6.0",
|
|
35
|
+
"@toptal/davinci-skeleton": "7.1.1",
|
|
36
36
|
"chalk": "^4.1.2",
|
|
37
|
+
"cosmiconfig": "^7.0.1",
|
|
37
38
|
"fs-extra": "^9.0.1",
|
|
39
|
+
"inquirer": "^8.2.4",
|
|
40
|
+
"inquirer-table-prompt": "^0.2.1",
|
|
38
41
|
"js-yaml": "^4.1.0",
|
|
39
42
|
"lodash.kebabcase": "^4.1.1",
|
|
40
43
|
"ora": "^5.4.1"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toptal/davinci-workflow",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "GH Workflow generator package for frontend applications",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -31,10 +31,13 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@toptal/davinci-cli-shared": "1.5.2",
|
|
34
|
-
"@toptal/davinci-monorepo": "^6.
|
|
35
|
-
"@toptal/davinci-skeleton": "7.1.
|
|
34
|
+
"@toptal/davinci-monorepo": "^6.6.0",
|
|
35
|
+
"@toptal/davinci-skeleton": "7.1.1",
|
|
36
36
|
"chalk": "^4.1.2",
|
|
37
|
+
"cosmiconfig": "^7.0.1",
|
|
37
38
|
"fs-extra": "^9.0.1",
|
|
39
|
+
"inquirer": "^8.2.4",
|
|
40
|
+
"inquirer-table-prompt": "^0.2.1",
|
|
38
41
|
"js-yaml": "^4.1.0",
|
|
39
42
|
"lodash.kebabcase": "^4.1.1",
|
|
40
43
|
"ora": "^5.4.1"
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
const { print } = require('@toptal/davinci-cli-shared')
|
|
2
|
+
const {
|
|
3
|
+
utils: { checkIfMonorepo },
|
|
4
|
+
} = require('@toptal/davinci-monorepo')
|
|
2
5
|
const path = require('path')
|
|
3
6
|
const fs = require('fs-extra')
|
|
4
7
|
const ora = require('ora')
|
|
@@ -74,10 +77,10 @@ const getWorkflowFilename = workflowName => {
|
|
|
74
77
|
}
|
|
75
78
|
|
|
76
79
|
const getWorkflowPostBuildFilename = workflowName => {
|
|
77
|
-
return kebabCase(workflowName)
|
|
80
|
+
return path.join(kebabCase(workflowName), 'index.js')
|
|
78
81
|
}
|
|
79
82
|
|
|
80
|
-
const performPostBuildProcedure = async (filename, destDir) => {
|
|
83
|
+
const performPostBuildProcedure = async (filename, destDir, workflowName) => {
|
|
81
84
|
const postBuildFilePathname = path.join(
|
|
82
85
|
require.resolve('@toptal/davinci-workflow'),
|
|
83
86
|
'../',
|
|
@@ -96,9 +99,13 @@ const performPostBuildProcedure = async (filename, destDir) => {
|
|
|
96
99
|
throw new Error('post build file must export a function')
|
|
97
100
|
}
|
|
98
101
|
|
|
102
|
+
const isMonorepo = checkIfMonorepo()
|
|
103
|
+
|
|
99
104
|
await executePostBuild({
|
|
100
105
|
print,
|
|
101
106
|
destDir,
|
|
107
|
+
workflowName,
|
|
108
|
+
isMonorepo,
|
|
102
109
|
})
|
|
103
110
|
}
|
|
104
111
|
|
|
@@ -129,7 +136,8 @@ const createCommand = async workflowName => {
|
|
|
129
136
|
// execute a possible post-build procedure
|
|
130
137
|
await performPostBuildProcedure(
|
|
131
138
|
getWorkflowPostBuildFilename(workflowName),
|
|
132
|
-
workflowsDir
|
|
139
|
+
workflowsDir,
|
|
140
|
+
fileName
|
|
133
141
|
)
|
|
134
142
|
// read and print mandatory ENV secrets that must be installed beforehand
|
|
135
143
|
await printMandatorySecretsList(fileName)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./alpha-package')
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const chalk = require('chalk')
|
|
2
2
|
const path = require('path')
|
|
3
3
|
|
|
4
|
-
const skeleton = require('
|
|
4
|
+
const skeleton = require('../../utils/skeleton')
|
|
5
5
|
const logText = chalk.red.bold
|
|
6
6
|
const yellowBoldText = chalk.yellow.bold
|
|
7
7
|
const deployWorkflows = [
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./deploy')
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./deploy-temploy')
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
module.exports = require('./integration-tests')
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const chalk = require('chalk')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const {
|
|
5
|
+
utils: { getPackages },
|
|
6
|
+
} = require('@toptal/davinci-monorepo')
|
|
7
|
+
|
|
8
|
+
const filterPackagesByCommands = require('../../utils/filter-packages-by-commands')
|
|
9
|
+
const setRootEnv = require('../../utils/set-root-env')
|
|
10
|
+
const { readPackageJson } = require('../../utils/skeleton')
|
|
11
|
+
const {
|
|
12
|
+
promptCodeCoverage,
|
|
13
|
+
promptParallelWorkersForMonorepo,
|
|
14
|
+
promptParallelWorkersForSPA,
|
|
15
|
+
} = require('./prompts')
|
|
16
|
+
const { getCoverageReportDir } = require('./nyc')
|
|
17
|
+
|
|
18
|
+
const CONFLUENCE_PAGE =
|
|
19
|
+
'https://toptal-core.atlassian.net/l/c/qtXKBzvs#Generated-IT-Workflow'
|
|
20
|
+
const yellowBoldText = chalk.yellow.bold
|
|
21
|
+
|
|
22
|
+
const getEnvForMonorepo = async (rootDir, commands) => {
|
|
23
|
+
const packages = getPackages(rootDir)
|
|
24
|
+
|
|
25
|
+
const filteredWorkspaces = filterPackagesByCommands(
|
|
26
|
+
rootDir,
|
|
27
|
+
packages,
|
|
28
|
+
commands
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
if (filteredWorkspaces.length === 0) {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`There are no packages to run integration tests in. Following commands were not found: ${JSON.stringify(
|
|
34
|
+
commands
|
|
35
|
+
)}`
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const parallelMatrix = JSON.stringify(
|
|
40
|
+
await promptParallelWorkersForMonorepo(filteredWorkspaces)
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
const { command, location } = filteredWorkspaces[0]
|
|
44
|
+
|
|
45
|
+
const coverageReportDir = await getCoverageReportDir(
|
|
46
|
+
path.join(rootDir, location)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
PARALLEL_MATRIX: parallelMatrix,
|
|
51
|
+
COMMAND: command,
|
|
52
|
+
COVERAGE_REPORT_DIR: coverageReportDir,
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const getEnvForSPA = async (rootDir, commands) => {
|
|
57
|
+
const pkg = readPackageJson(rootDir)
|
|
58
|
+
const command = Object.keys(pkg.scripts).find(script =>
|
|
59
|
+
commands.includes(script)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
if (!command) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`No command for integration tests was found. Searched for: ${JSON.stringify(
|
|
65
|
+
commands
|
|
66
|
+
)}`
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const parallelGroups = await promptParallelWorkersForSPA()
|
|
71
|
+
const coverageReportDir = await getCoverageReportDir(rootDir)
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
PARALLEL_GROUPS: parallelGroups,
|
|
75
|
+
COMMAND: command,
|
|
76
|
+
COVERAGE_REPORT_DIR: coverageReportDir,
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const executePostBuild = async ({ destDir, workflowName, isMonorepo }) => {
|
|
81
|
+
const workflowPath = path.join(destDir, workflowName)
|
|
82
|
+
const rootDir = path.resolve(destDir, '../../')
|
|
83
|
+
// to support backward compatibility
|
|
84
|
+
const supportedCommands = ['test:integration:ci', 'test:ui:ci', 'test:e2e:ci']
|
|
85
|
+
|
|
86
|
+
try {
|
|
87
|
+
const dynamicEnv = isMonorepo
|
|
88
|
+
? await getEnvForMonorepo(rootDir, supportedCommands)
|
|
89
|
+
: await getEnvForSPA(rootDir, supportedCommands)
|
|
90
|
+
|
|
91
|
+
const printCoverage = await promptCodeCoverage()
|
|
92
|
+
|
|
93
|
+
setRootEnv(
|
|
94
|
+
{
|
|
95
|
+
...dynamicEnv,
|
|
96
|
+
PRINT_COVERAGE: printCoverage,
|
|
97
|
+
},
|
|
98
|
+
workflowPath
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
console.log(chalk.green('\nWorkflow has been updated.'))
|
|
102
|
+
} catch (e) {
|
|
103
|
+
fs.unlinkSync(workflowPath)
|
|
104
|
+
console.error(e.stack)
|
|
105
|
+
throw new Error(`Workflow failed to be generated: ${e.message}`)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log(
|
|
109
|
+
[
|
|
110
|
+
chalk.green(
|
|
111
|
+
'\nIntegration tests (integration-tests) GH Workflow has been generated! \n\n'
|
|
112
|
+
),
|
|
113
|
+
'Workflow is located in ',
|
|
114
|
+
chalk.green.bold('.github/workflows/davinci-integration-tests.yml'),
|
|
115
|
+
'\n',
|
|
116
|
+
"But it likely won't work out of the box and will ",
|
|
117
|
+
yellowBoldText('require little bit of adjusting'),
|
|
118
|
+
' to make it work in your CI\n',
|
|
119
|
+
'Read more about customization here ',
|
|
120
|
+
chalk.grey.bold(CONFLUENCE_PAGE),
|
|
121
|
+
'\n',
|
|
122
|
+
].join('')
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
module.exports = executePostBuild
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const getProgramConfig = require('../../utils/get-program-config')
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {string} root
|
|
5
|
+
* @return {Promise<string>}
|
|
6
|
+
*/
|
|
7
|
+
const getCoverageReportDir = async root => {
|
|
8
|
+
const config = await getCoverageConfig(root)
|
|
9
|
+
|
|
10
|
+
return config?.['report-dir'] ?? 'coverage'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {string} root
|
|
15
|
+
* @return {Promise<Object<string, any>>}
|
|
16
|
+
*/
|
|
17
|
+
const getCoverageConfig = root => getProgramConfig('nyc', root)
|
|
18
|
+
|
|
19
|
+
module.exports = {
|
|
20
|
+
getCoverageConfig,
|
|
21
|
+
getCoverageReportDir,
|
|
22
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const {
|
|
2
|
+
promptTable,
|
|
3
|
+
promptNumber,
|
|
4
|
+
promptConfirm,
|
|
5
|
+
} = require('../../utils/prompts')
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Return custom message for parallel workers prompt
|
|
9
|
+
* @param {string} [customMessage]
|
|
10
|
+
* @return {string}
|
|
11
|
+
* @private
|
|
12
|
+
*/
|
|
13
|
+
const getMessageForParallelWorkers = customMessage => {
|
|
14
|
+
const message = customMessage ? [customMessage] : []
|
|
15
|
+
|
|
16
|
+
message.push(
|
|
17
|
+
'Here are packages that support integration tests. Select how many parallel workers you want in which package.'
|
|
18
|
+
)
|
|
19
|
+
message.push(
|
|
20
|
+
"If you don't choose anything, package won't be included in integration testing"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
return message.join('\n')
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Show table prompt with selection of parallel workers for each package
|
|
28
|
+
* @param {Array<{ name: string, location: string }>} packages
|
|
29
|
+
* @param {string} [customMessage]
|
|
30
|
+
* @return {Promise<Array<{ pkg: string, location: string, parallelGroups: number }>>}
|
|
31
|
+
*/
|
|
32
|
+
const promptParallelWorkersForMonorepo = async (
|
|
33
|
+
packages,
|
|
34
|
+
customMessage = ''
|
|
35
|
+
) => {
|
|
36
|
+
const message = getMessageForParallelWorkers(customMessage)
|
|
37
|
+
const columns = Array.from({ length: 10 }, (_, index) => index + 1)
|
|
38
|
+
const rows = packages.map(({ name }) => name)
|
|
39
|
+
|
|
40
|
+
const parallelWorkers = await promptTable(message, {
|
|
41
|
+
columns,
|
|
42
|
+
rows,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
// At least one package needs to be selected for integration tests
|
|
46
|
+
// so if none is selected, show the prompt again
|
|
47
|
+
if (!parallelWorkers.some(Boolean)) {
|
|
48
|
+
return promptParallelWorkersForMonorepo(
|
|
49
|
+
packages,
|
|
50
|
+
'At least one package needs to be selected for integration tests!'
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return packages
|
|
55
|
+
.map(({ name, location }, index) => ({
|
|
56
|
+
pkg: name,
|
|
57
|
+
location,
|
|
58
|
+
parallelGroups: parallelWorkers[index],
|
|
59
|
+
}))
|
|
60
|
+
.filter(({ parallelGroups }) => parallelGroups)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const promptParallelWorkersForSPA = () =>
|
|
64
|
+
promptNumber(
|
|
65
|
+
'Input how many parallel workers you want for integration tests',
|
|
66
|
+
{
|
|
67
|
+
validate: input => input > 0 || 'Please provide a number > 0',
|
|
68
|
+
filter: input => (Number.isNaN(input) || Number(input) <= 0 ? '' : input),
|
|
69
|
+
}
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
const promptCodeCoverage = () =>
|
|
73
|
+
promptConfirm(
|
|
74
|
+
'Do you want to print code coverage info in your PR? \nYour project must support code-coverage generation',
|
|
75
|
+
false
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
module.exports = {
|
|
79
|
+
promptCodeCoverage,
|
|
80
|
+
promptParallelWorkersForMonorepo,
|
|
81
|
+
promptParallelWorkersForSPA,
|
|
82
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Return workspace packages that have specified
|
|
5
|
+
* command(s) in their package.json scripts
|
|
6
|
+
* @param {string} rootDir
|
|
7
|
+
* @param {Array<{ name: string, location: string }>} packages
|
|
8
|
+
* @param {Array<string>} commands
|
|
9
|
+
* @return {Array<{ name: string, location: string, command: string }>}
|
|
10
|
+
*/
|
|
11
|
+
const filterPackagesByCommands = (rootDir, packages, commands) => {
|
|
12
|
+
return packages
|
|
13
|
+
.map(({ name, location }) => {
|
|
14
|
+
const packageJsonPath = path.join(rootDir, location, 'package.json')
|
|
15
|
+
|
|
16
|
+
const pkg = require(packageJsonPath)
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
name,
|
|
20
|
+
location,
|
|
21
|
+
command: Object.keys(pkg.scripts).find(script =>
|
|
22
|
+
commands.includes(script)
|
|
23
|
+
),
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
.filter(({ command }) => command)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = filterPackagesByCommands
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const { cosmiconfig } = require('cosmiconfig')
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Searches for and loads configuration for your program
|
|
6
|
+
* Looks for:
|
|
7
|
+
* - a package.json property
|
|
8
|
+
* - a JSON or YAML, extensionless "rc file"
|
|
9
|
+
* - an "rc file" with the extensions .json, .yaml, .yml, .js, or .cjs
|
|
10
|
+
* - a .config.js or .config.cjs CommonJS module
|
|
11
|
+
* @param program
|
|
12
|
+
* @param [defaultDir] - search up the directory tree from this folder
|
|
13
|
+
* @return {Promise<any|{extends}>}
|
|
14
|
+
*/
|
|
15
|
+
const getProgramConfig = async (program, defaultDir) => {
|
|
16
|
+
const explorer = cosmiconfig(program)
|
|
17
|
+
|
|
18
|
+
const defaultConfig = await explorer.search(defaultDir)
|
|
19
|
+
|
|
20
|
+
if (!defaultConfig) {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (!defaultConfig.config.extends) {
|
|
25
|
+
return defaultConfig.config
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const extendedConfig = await explorer.load(
|
|
29
|
+
path.join(defaultDir, defaultConfig.config.extends)
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
if (!extendedConfig) {
|
|
33
|
+
return defaultConfig.config
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
...defaultConfig.config,
|
|
38
|
+
...extendedConfig.config,
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
module.exports = getProgramConfig
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const inquirer = require('inquirer')
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef Choices
|
|
5
|
+
* @type {object}
|
|
6
|
+
* @property {string} name
|
|
7
|
+
* @property {string|Object<string, any>} [value]
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Show table prompt
|
|
12
|
+
* @param {string} message
|
|
13
|
+
* @param {Object} additionalProps
|
|
14
|
+
* @param {Array<string | Choices>} additionalProps.columns
|
|
15
|
+
* @param {Array<string | Choices>} additionalProps.rows
|
|
16
|
+
* @return {Promise<Array<any|undefined>>}
|
|
17
|
+
*/
|
|
18
|
+
const promptTable = async (message, { columns, rows }) => {
|
|
19
|
+
const { result } = await inquirer.prompt([
|
|
20
|
+
{
|
|
21
|
+
type: 'table',
|
|
22
|
+
name: 'result',
|
|
23
|
+
message,
|
|
24
|
+
columns,
|
|
25
|
+
rows,
|
|
26
|
+
},
|
|
27
|
+
])
|
|
28
|
+
|
|
29
|
+
return result
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Show number prompts
|
|
34
|
+
* @param {string} message
|
|
35
|
+
* @param {Object} [additionalProps]
|
|
36
|
+
* @return {Promise<number>}
|
|
37
|
+
*/
|
|
38
|
+
const promptNumber = async (message, additionalProps) => {
|
|
39
|
+
const { numberValue } = await inquirer.prompt([
|
|
40
|
+
{
|
|
41
|
+
type: 'number',
|
|
42
|
+
name: 'numberValue',
|
|
43
|
+
message,
|
|
44
|
+
...additionalProps,
|
|
45
|
+
},
|
|
46
|
+
])
|
|
47
|
+
|
|
48
|
+
return numberValue
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Show confirmation prompt
|
|
53
|
+
* @param {string} message
|
|
54
|
+
* @param {boolean} [defaultValue]
|
|
55
|
+
* @return {Promise<boolean>}
|
|
56
|
+
*/
|
|
57
|
+
const promptConfirm = async (message, defaultValue) => {
|
|
58
|
+
const { confirmValue } = await inquirer.prompt([
|
|
59
|
+
{
|
|
60
|
+
type: 'confirm',
|
|
61
|
+
name: 'confirmValue',
|
|
62
|
+
message,
|
|
63
|
+
default: defaultValue,
|
|
64
|
+
},
|
|
65
|
+
])
|
|
66
|
+
|
|
67
|
+
return confirmValue
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = {
|
|
71
|
+
promptTable,
|
|
72
|
+
promptNumber,
|
|
73
|
+
promptConfirm,
|
|
74
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const yaml = require('js-yaml')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Set/replace root ENV variables in the workflow
|
|
6
|
+
* @param {Object<string, any>} env
|
|
7
|
+
* @param {string} workflowPath
|
|
8
|
+
*/
|
|
9
|
+
const setRootEnv = (env, workflowPath) => {
|
|
10
|
+
const workflow = yaml.load(fs.readFileSync(workflowPath, 'utf8'))
|
|
11
|
+
|
|
12
|
+
Object.assign(workflow.env, env)
|
|
13
|
+
|
|
14
|
+
fs.writeFileSync(workflowPath, yaml.dump(workflow))
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = setRootEnv
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const chalk = require('chalk')
|
|
2
|
-
|
|
3
|
-
const CONFLUENCE_PAGE =
|
|
4
|
-
'https://toptal-core.atlassian.net/l/c/qtXKBzvs#Generated-IT-Workflow'
|
|
5
|
-
const yellowBoldText = chalk.yellow.bold
|
|
6
|
-
|
|
7
|
-
const executePostBuild = () => {
|
|
8
|
-
console.log(
|
|
9
|
-
[
|
|
10
|
-
chalk.green(
|
|
11
|
-
'\nIntegration tests (integration-tests) GH Workflow has been generated! \n\n'
|
|
12
|
-
),
|
|
13
|
-
'Workflow is located in ',
|
|
14
|
-
chalk.green.bold('.github/workflows/davinci-integration-tests.yml'),
|
|
15
|
-
'\n',
|
|
16
|
-
"But it likely won't work out of the box and will ",
|
|
17
|
-
yellowBoldText('require little bit of adjusting'),
|
|
18
|
-
' to make it work in your CI\n',
|
|
19
|
-
'Read more about customization here ',
|
|
20
|
-
chalk.grey.bold(CONFLUENCE_PAGE),
|
|
21
|
-
'\n',
|
|
22
|
-
].join('')
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
module.exports = executePostBuild
|