@toptal/davinci-workflow 1.8.1-alpha-chore-upgrade-babel-core.3 → 1.8.1

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 CHANGED
@@ -1,5 +1,14 @@
1
1
  # @toptal/davinci-workflow
2
2
 
3
+ ## 1.8.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1309](https://github.com/toptal/davinci/pull/1309) [`e3aac3fc`](https://github.com/toptal/davinci/commit/e3aac3fc5603664e5b2a49fca96d794e229cf498) Thanks [@dmaklygin](https://github.com/dmaklygin)! - - set up proper secrets to deployment GH Workflows
8
+ - autogenerate secrets from yaml file
9
+ - Updated dependencies [[`e3aac3fc`](https://github.com/toptal/davinci/commit/e3aac3fc5603664e5b2a49fca96d794e229cf498)]:
10
+ - @toptal/davinci-skeleton@6.2.1
11
+
3
12
  ## 1.8.0
4
13
 
5
14
  ### Minor Changes
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@toptal/davinci-workflow",
3
+ "version": "1.8.1",
4
+ "description": "GH Workflow generator package for frontend applications",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "keywords": [
9
+ "Github Actions",
10
+ "GH Workflows",
11
+ "generator"
12
+ ],
13
+ "author": "Toptal",
14
+ "homepage": "https://github.com/toptal/davinci/tree/master/packages/workflow#readme",
15
+ "license": "ISC",
16
+ "bin": {
17
+ "davinci-workflow": "./bin/davinci-workflow.js"
18
+ },
19
+ "main": "./src/index.js",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/toptal/davinci.git"
23
+ },
24
+ "scripts": {
25
+ "build:package": "../../bin/build-package.js",
26
+ "prepublishOnly": "../../bin/prepublish.js",
27
+ "test": "echo \"Error: run tests from root\" && exit 1"
28
+ },
29
+ "bugs": {
30
+ "url": "https://github.com/toptal/davinci/issues"
31
+ },
32
+ "dependencies": {
33
+ "@toptal/davinci-cli-shared": "1.5.1",
34
+ "@toptal/davinci-skeleton": "6.2.1",
35
+ "fs-extra": "^9.0.1",
36
+ "lodash.kebabcase": "^4.1.1",
37
+ "ora": "^5.4.1",
38
+ "chalk": "^4.1.2"
39
+ }
40
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toptal/davinci-workflow",
3
- "version": "1.8.1-alpha-chore-upgrade-babel-core.3+0b7b1ccf",
3
+ "version": "1.8.1",
4
4
  "description": "GH Workflow generator package for frontend applications",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -30,12 +30,11 @@
30
30
  "url": "https://github.com/toptal/davinci/issues"
31
31
  },
32
32
  "dependencies": {
33
- "@toptal/davinci-cli-shared": "1.5.2-alpha-chore-upgrade-babel-core.96+0b7b1ccf",
34
- "@toptal/davinci-skeleton": "6.2.1-alpha-chore-upgrade-babel-core.3+0b7b1ccf",
35
- "chalk": "^4.1.2",
33
+ "@toptal/davinci-cli-shared": "1.5.1",
34
+ "@toptal/davinci-skeleton": "6.2.1",
36
35
  "fs-extra": "^9.0.1",
37
36
  "lodash.kebabcase": "^4.1.1",
38
- "ora": "^5.4.1"
39
- },
40
- "gitHead": "0b7b1ccfe086e0714360aa12d422257236444de6"
37
+ "ora": "^5.4.1",
38
+ "chalk": "^4.1.2"
39
+ }
41
40
  }
@@ -3,15 +3,21 @@ const path = require('path')
3
3
  const fs = require('fs-extra')
4
4
  const ora = require('ora')
5
5
  const kebabCase = require('lodash.kebabcase')
6
- const {WORKFLOWS_DIR, GITHUB_DIR} = require('../constants')
7
- const {copyWorkflowFromSkeleton} = require('../utils/skeleton')
6
+
7
+ const { WORKFLOWS_DIR, GITHUB_DIR } = require('../constants')
8
+ const {
9
+ copyWorkflowFromSkeleton,
10
+ getWorkflowSourceFilepath
11
+ } = require('../utils/skeleton')
12
+ const { readYMLSecrets } = require('../utils/read-secrets')
13
+ const generateMessageFromSecrets = require('../utils/generate-command-message')
8
14
 
9
15
  /**
10
16
  * Check whether github directory exists
11
17
  * @param rootDir
12
18
  * @returns {Promise<void>}
13
19
  */
14
- const checkGithubDirectory = async (rootDir) => {
20
+ const checkGithubDirectory = async rootDir => {
15
21
  const spinner = ora(`Searching for ${GITHUB_DIR} directory...`).start()
16
22
  const githubDir = path.join(rootDir, GITHUB_DIR)
17
23
 
@@ -19,7 +25,9 @@ const checkGithubDirectory = async (rootDir) => {
19
25
  const doesGithubDirExist = await fs.stat(githubDir)
20
26
 
21
27
  if (!doesGithubDirExist) {
22
- throw new Error('It looks like you run Davinci command not in a root of the project.')
28
+ throw new Error(
29
+ 'It looks like you run Davinci command not in a root of the project.'
30
+ )
23
31
  }
24
32
 
25
33
  spinner.succeed('Github directory exists!')
@@ -35,7 +43,7 @@ const checkGithubDirectory = async (rootDir) => {
35
43
  * Returns workflows directory. If the directory structure does not exist, it is created.
36
44
  * @param githubDir
37
45
  */
38
- const getWorkflowsDirectory = async (githubDir) => {
46
+ const getWorkflowsDirectory = async githubDir => {
39
47
  const spinner = ora('Searching for workflows directory...').start()
40
48
 
41
49
  const workflowsDir = path.join(githubDir, WORKFLOWS_DIR)
@@ -57,48 +65,48 @@ const getWorkflowsDirectory = async (githubDir) => {
57
65
  * @param workflowName
58
66
  * @returns {*}
59
67
  */
60
- const getWorkflowFilename = (workflowName) => {
68
+ const getWorkflowFilename = workflowName => {
61
69
  return kebabCase(`davinci-${workflowName}`) + '.yml'
62
70
  }
63
71
 
64
- const getWorkflowPostBuildFilename = (workflowName) => {
72
+ const getWorkflowPostBuildFilename = workflowName => {
65
73
  return kebabCase(workflowName) + '.js'
66
74
  }
67
75
 
68
76
  const performPostBuildProcedure = async (filename, destDir) => {
69
- const spinner = ora('Post build procedure...').start()
70
- const postBuildFilePathname = path.join(require.resolve('@toptal/davinci-workflow'), '../', 'post-build', filename)
71
-
72
- try {
73
- const doesFileExist = await fs.exists(postBuildFilePathname)
74
- if (!doesFileExist) {
75
- spinner.succeed('No post-build procedure')
76
- return
77
- }
77
+ const postBuildFilePathname = path.join(
78
+ require.resolve('@toptal/davinci-workflow'),
79
+ '../',
80
+ 'post-build',
81
+ filename
82
+ )
83
+ const doesFileExist = await fs.exists(postBuildFilePathname)
78
84
 
79
- const executePostBuild = require(postBuildFilePathname)
80
- if (typeof executePostBuild !== 'function') {
81
- throw new Error('post build file must export a function')
82
- }
85
+ if (!doesFileExist) {
86
+ return
87
+ }
83
88
 
84
- await executePostBuild({
85
- print,
86
- destDir
87
- })
89
+ const executePostBuild = require(postBuildFilePathname)
88
90
 
89
- spinner.succeed('Post-build procedure has been executed!')
90
- } catch (err) {
91
- spinner.fail()
92
- throw err
91
+ if (typeof executePostBuild !== 'function') {
92
+ throw new Error('post build file must export a function')
93
93
  }
94
+
95
+ await executePostBuild({
96
+ print,
97
+ destDir
98
+ })
94
99
  }
95
100
 
96
- const createCommand = async (workflowName) => {
97
- print.green(
98
- 'Creating',
99
- workflowName,
100
- '...'
101
- )
101
+ const printMandatorySecretsList = async fileName => {
102
+ const workflowFilepath = getWorkflowSourceFilepath(fileName)
103
+ const secrets = readYMLSecrets(workflowFilepath)
104
+
105
+ print.grey(generateMessageFromSecrets(secrets))
106
+ }
107
+
108
+ const createCommand = async workflowName => {
109
+ print.green('Creating', workflowName, '...')
102
110
 
103
111
  const rootDir = process.cwd()
104
112
 
@@ -109,12 +117,18 @@ const createCommand = async (workflowName) => {
109
117
  const workflowsDir = await getWorkflowsDirectory(githubDir)
110
118
  // get filename
111
119
  const fileName = getWorkflowFilename(workflowName)
120
+
112
121
  // copy workflow to an appropriate directory
113
122
  await copyWorkflowFromSkeleton(fileName, workflowsDir)
123
+ // print successfull result
124
+ print.green('Workflow has been created.\n')
114
125
  // execute a possible post-build procedure
115
- await performPostBuildProcedure(getWorkflowPostBuildFilename(workflowName), workflowsDir)
116
-
117
- print.green('Workflow has been created.')
126
+ await performPostBuildProcedure(
127
+ getWorkflowPostBuildFilename(workflowName),
128
+ workflowsDir
129
+ )
130
+ // read and print mandatory ENV secrets that must be installed beforehand
131
+ await printMandatorySecretsList(fileName)
118
132
  } catch (err) {
119
133
  print.red(err)
120
134
  process.exit(1)
package/src/constants.js CHANGED
@@ -1,7 +1,31 @@
1
1
  const GITHUB_DIR = '.github'
2
2
  const WORKFLOWS_DIR = 'workflows'
3
3
 
4
+ const SECRET_DEFINITION = {
5
+ // common
6
+ TOPTAL_DEVBOT_TOKEN:
7
+ 'GH access token to checkout and publish comments/reactions in PRs',
8
+ GCR_ACCOUNT_KEY: 'Google Cloud Account Key. Necessary to upload Docker image',
9
+ SENTRY_SOURCEMAP_UPLOAD_TOKEN:
10
+ 'Sentry Token. Necessary to upload source files to Sentry',
11
+ // production
12
+ TOPTAL_BOT_JENKINS_DEPLOYMENT_TOKEN:
13
+ 'Jenkins Deploy Token. Necessary to execute deploy to PRODUCTION Jenkins job',
14
+ HTTP_PROXY:
15
+ 'Jenkins Proxy. Necessary to execute deploy to production Jenkins job',
16
+ // staging
17
+ TOPTAL_BOT_JENKINS_API_TOKEN:
18
+ 'Jenkins Deploy Token. Necessary to execute deploy to STAGING Jenkins job',
19
+ // temploy
20
+ TOPTAL_JENKINS_BUILD_TOKEN:
21
+ 'Jenkins Build Token. Necessary to execute Jenkins job',
22
+ // alpha-package
23
+ NPM_TOKEN_PUBLISH: 'NPM publish access token',
24
+ NPM_TOKEN_READ_ONLY: 'NPM read token'
25
+ }
26
+
4
27
  module.exports = {
5
28
  GITHUB_DIR,
6
- WORKFLOWS_DIR
29
+ WORKFLOWS_DIR,
30
+ SECRET_DEFINITION
7
31
  }
@@ -1,9 +1,11 @@
1
1
  const chalk = require('chalk')
2
- const skeleton = require('../utils/skeleton')
3
2
  const path = require('path')
4
3
 
5
- const executePostBuild = ({destDir}) => {
6
- const logText = chalk.red.bold
4
+ const skeleton = require('../utils/skeleton')
5
+ const yellowBoldText = chalk.yellow.bold
6
+ const logText = chalk.red.bold
7
+
8
+ const executePostBuild = ({ destDir }) => {
7
9
  let isScriptExist = false
8
10
 
9
11
  try {
@@ -13,7 +15,8 @@ const executePostBuild = ({destDir}) => {
13
15
  const config = skeleton.readPackageJson(rootDir)
14
16
 
15
17
  if (!config.scripts['build:package']) {
16
- config.scripts['build:package'] = 'lerna run build:package --stream --parallel'
18
+ config.scripts['build:package'] =
19
+ 'lerna run build:package --stream --parallel'
17
20
  } else {
18
21
  isScriptExist = true
19
22
  }
@@ -24,15 +27,16 @@ const executePostBuild = ({destDir}) => {
24
27
  }
25
28
 
26
29
  console.log(
27
- chalk.green('\r\nPublish Alpha Package (alpha-package) GH Workflow has been generated! \n'),
28
- '———————————————————————————————————————————————————————————————————————————————————————————————— \n',
29
- logText('@toptal-bot run package:alpha-release'), ' it performs build & release of a new alpha package \n',
30
- 'The following GH secrets ', logText('must'), ' be specified in repo to properly execute the command: \n',
31
- logText('NPM_TOKEN_PUBLISH'), ' — NPM publish access token\n',
32
- logText('TOPTAL_DEVBOT_TOKEN'), ' GH access token to checkout and publish comments/reactions in PRs\n',
33
- '———————————————————————————————————————————————————————————————————————————————————————————————— \n',
34
- isScriptExist ? logText('Script "build:package" exists in package.json! \n') : logText('New "build:package" script was added in package.json! \n'),
35
-
30
+ [
31
+ chalk.green(
32
+ '\nPublish Alpha Package (alpha-package) GH Workflow has been generated! \n\n'
33
+ ),
34
+ yellowBoldText('@toptal-bot run package:alpha-release'),
35
+ ' — it performs build&release of a new alpha package \n',
36
+ !isScriptExist
37
+ ? logText('New "build:package" script was added in package.json! \n')
38
+ : ''
39
+ ].join('')
36
40
  )
37
41
  }
38
42
 
@@ -1,8 +1,10 @@
1
1
  const chalk = require('chalk')
2
- const skeleton = require('../utils/skeleton')
3
2
  const path = require('path')
4
3
 
5
- const executePostBuild = ({destDir}) => {
4
+ const skeleton = require('../utils/skeleton')
5
+ const yellowBoldText = chalk.yellow.bold
6
+
7
+ const executePostBuild = ({ destDir }) => {
6
8
  const logText = chalk.red.bold
7
9
  let isScriptExist = false
8
10
 
@@ -24,15 +26,16 @@ const executePostBuild = ({destDir}) => {
24
26
  }
25
27
 
26
28
  console.log(
27
- chalk.green('\r\nDeploy Temploy (deploy-temploy) GH Workflow has been generated! \n'),
28
- '———————————————————————————————————————————————————————————————————————————————————————————————— \n',
29
- logText('@toptal-bot run temploy'), ' it performs build & deploy a new temploy \n',
30
- 'The following GH secrets ', logText('must'), ' be specified in repo to properly execute the command: \n',
31
- logText('GCR_ACCOUNT_KEY'), ' — Google Cloud Account Key. Necessary to upload Docker image\n',
32
- logText('TOPTAL_DEVBOT_TOKEN'), ' GH access token to checkout and publish comments/reactions in PRs\n',
33
- logText('TOPTAL_JENKINS_BUILD_TOKEN'), ' — Jenkins Build Token. Necessary to execute Jenkins job\n',
34
- '———————————————————————————————————————————————————————————————————————————————————————————————— \n',
35
- isScriptExist ? logText('Script "build" exists in package.json! \n') : logText('New "build" script was added in package.json! \n'),
29
+ [
30
+ chalk.green(
31
+ '\r\nDeploy Temploy (deploy-temploy) GH Workflow has been generated! \n\n'
32
+ ),
33
+ yellowBoldText('@toptal-bot run temploy'),
34
+ ' — it performs build & deploy a new temploy \n',
35
+ !isScriptExist
36
+ ? logText('New "build" script was added in package.json! \n')
37
+ : ''
38
+ ].join('')
36
39
  )
37
40
  }
38
41
 
@@ -2,14 +2,14 @@ const chalk = require('chalk')
2
2
  const path = require('path')
3
3
 
4
4
  const skeleton = require('../utils/skeleton')
5
-
5
+ const logText = chalk.red.bold
6
+ const yellowBoldText = chalk.yellow.bold
6
7
  const deployWorkflows = [
7
8
  'davinci-deploy-production.yml',
8
9
  'davinci-deploy-staging.yml'
9
10
  ]
10
11
 
11
12
  const executePostBuild = async ({ destDir }) => {
12
- const logText = chalk.red.bold
13
13
  let isScriptExist = false
14
14
 
15
15
  const rootDir = path.resolve(destDir, '../../')
@@ -40,37 +40,21 @@ const executePostBuild = async ({ destDir }) => {
40
40
  }
41
41
 
42
42
  console.log(
43
- chalk.green('\r\nDeploy GH Workflow has been generated! \n'),
44
- 'Three workflows have been created - ',
45
- chalk.green(
46
- 'davinci-deploy.yml, davinci-deploy-staging.yml and davinci-deploy-production.yml'
47
- ),
48
- '\n',
49
- 'davinci-deploy.yml builds and pushes image & release image and according to settings in davinci.yml it triggers deploy to staging and/or production\n',
50
- '———————————————————————————————————————————————————————————————————————————————————————————————— \n',
51
- logText('@toptal-bot run deploy-staging'),
52
- ' it performs build & deploy to staging for the latest commit in the PR branch \n',
53
- 'The following GH secrets ',
54
- logText('must'),
55
- ' be specified in the repo to properly execute the command: \n',
56
- logText('GCR_ACCOUNT_KEY'),
57
- ' — Google Cloud Account Key. Necessary to upload Docker image\n',
58
- logText('TOPTAL_DEVBOT_TOKEN'),
59
- ' — GH access token to checkout and publish comments/reactions in PRs\n',
60
- logText('TOPTAL_JENKINS_BUILD_TOKEN'),
61
- ' — Jenkins Build Token. Necessary to execute Jenkins jobs\n',
62
- logText('TOPTAL_BOT_JENKINS_DEPLOYMENT_TOKEN'),
63
- ' — Jenkins Deploy Token. Necessary to execute deploy to production Jenkins job\n',
64
- logText('TOPTAL_BOT_USERNAME'),
65
- ' — Jenkins User Name. Necessary to execute deploy to production Jenkins job\n',
66
- logText('HTTP_PROXY'),
67
- ' — Jenkins Proxy. Necessary to execute deploy to production Jenkins job\n',
68
- logText('NPM_TOKEN'),
69
- ' — NPM Token. Necessary to load private NPM packages\n',
70
- '———————————————————————————————————————————————————————————————————————————————————————————————— \n',
71
- isScriptExist
72
- ? logText('Script "build" already exists in package.json! \n')
73
- : logText('New "build" script was added in package.json! \n')
43
+ [
44
+ chalk.green('\nDeploy GH Workflow has been generated!\n\n'),
45
+ 'Three workflows have been created — ',
46
+ chalk.green(
47
+ 'davinci-deploy.yml, davinci-deploy-staging.yml and davinci-deploy-production.yml'
48
+ ),
49
+ '\n\n',
50
+ chalk.green('davinci-deploy.yml'),
51
+ ' GH Workflow builds&pushes Docker image and according to settings in davinci.yml it triggers deploy to staging and/or production\n\n',
52
+ yellowBoldText('@toptal-bot run deploy-staging'),
53
+ ' it performs build & deploy to staging for the latest commit in the PR branch \n',
54
+ !isScriptExist
55
+ ? logText('New "build" script was added in package.json! \n')
56
+ : ''
57
+ ].join('')
74
58
  )
75
59
  }
76
60
 
@@ -1,23 +1,25 @@
1
1
  const chalk = require('chalk')
2
2
 
3
- const CONFLUENCE_PAGE = 'https://toptal-core.atlassian.net/l/c/qtXKBzvs#Generated-IT-Workflow'
4
-
5
- const redBoldText = chalk.red.bold
3
+ const CONFLUENCE_PAGE =
4
+ 'https://toptal-core.atlassian.net/l/c/qtXKBzvs#Generated-IT-Workflow'
6
5
  const yellowBoldText = chalk.yellow.bold
7
6
 
8
7
  const executePostBuild = () => {
9
8
  console.log(
10
- chalk.green('\r\nIntegration tests (integration-tests) GH Workflow has been generated! \n\n'),
11
- 'Workflow is located in ', chalk.green.bold('.github/workflows/davinci-integration-tests.yml'), '\n',
12
- 'But it likely won\'t work out of the box and will ', yellowBoldText('require little bit of adjusting'), ' to make it work in your CI\n',
13
- 'Read more about customization here ', chalk.grey.bold(CONFLUENCE_PAGE), '\n',
14
- '———————————————————————————————————————————————————————————————————————————————————————————————— \n',
15
- 'The following GH secrets ', redBoldText('must'), ' be specified in repo to properly execute the command: \n',
16
- redBoldText('TOPTAL_DEVBOT_TOKEN'), ' — GH access token to checkout and publish comments/reactions in PRs\n',
17
- '———————————————————————————————————————————————————————————————————————————————————————————————— \n',
18
- 'The following GH secrets are ', yellowBoldText('optional'), ': \n',
19
- yellowBoldText('NPM_TOKEN_READ_ONLY'), ' needed when your project has private dependencies\n',
20
- '———————————————————————————————————————————————————————————————————————————————————————————————— \n',
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('')
21
23
  )
22
24
  }
23
25
 
@@ -0,0 +1,38 @@
1
+ const chalk = require('chalk')
2
+
3
+ const { SECRET_DEFINITION } = require('../constants')
4
+ const logText = chalk.red.bold
5
+
6
+ /**
7
+ * Function gather necessary secrets to a command message
8
+ * @type {Array} list of secrets
9
+ */
10
+ const generateMessageFromSecrets = secretsList => {
11
+ if (secretsList.length === 0) {
12
+ return ''
13
+ }
14
+
15
+ let message = [
16
+ '————————————————————————————————————————————————————————————————————————————————————————————————\n',
17
+ 'The following GH secrets',
18
+ logText('must'),
19
+ 'be specified in the repo to properly execute the command: \n\n'
20
+ ].join(' ')
21
+
22
+ message += secretsList.reduce((message, secret) => {
23
+ if (!SECRET_DEFINITION[secret]) {
24
+ throw new Error(`the definition for the secret: ${secret} is not found`)
25
+ }
26
+
27
+ message += ' ' + logText(secret) + ' — ' + SECRET_DEFINITION[secret] + '\n'
28
+
29
+ return message
30
+ }, '')
31
+
32
+ message +=
33
+ '————————————————————————————————————————————————————————————————————————————————————————————————\n'
34
+
35
+ return message
36
+ }
37
+
38
+ module.exports = generateMessageFromSecrets
@@ -0,0 +1,42 @@
1
+ const fs = require('fs')
2
+
3
+ const reg = /\$\{\{\s*secrets\.([A-Za-z_\-0-9]+)\s*\}\}/g
4
+
5
+ /**
6
+ * Pick up secrets from string
7
+ * @param document
8
+ * @returns {String[]}
9
+ */
10
+ const readSecrets = document => {
11
+ let match
12
+
13
+ const secrets = []
14
+
15
+ // eslint-disable-next-line no-cond-assign
16
+ while ((match = reg.exec(document))) {
17
+ secrets.push(match[1])
18
+ }
19
+
20
+ return secrets
21
+ }
22
+
23
+ /**
24
+ * Read YML file's secrets and return a list of them
25
+ * @param pathname
26
+ * @returns {String[]}
27
+ */
28
+ const readYMLSecrets = pathname => {
29
+ try {
30
+ const file = fs.readFileSync(pathname, 'utf8')
31
+
32
+ return readSecrets(file)
33
+ } catch (e) {
34
+ console.log('readYMLSecrets Error: ', e)
35
+ throw e
36
+ }
37
+ }
38
+
39
+ module.exports = {
40
+ readSecrets,
41
+ readYMLSecrets
42
+ }
@@ -19,17 +19,22 @@ const writePackageJson = (folder, config) => {
19
19
  fs.writeFileSync(packageJsonFile, modifiedConfigData)
20
20
  }
21
21
 
22
+ const getWorkflowSourceFilepath = fileName => {
23
+ const skeletonPath = require.resolve('@toptal/davinci-skeleton')
24
+
25
+ return path.join(skeletonPath, '../..', GITHUB_DIR, WORKFLOWS_DIR, fileName)
26
+ }
27
+
22
28
  const copyWorkflowFromSkeleton = async (fileName, destDir) => {
23
29
  const spinner = ora('Copying workflow...').start()
24
30
 
25
- const skeletonPath = require.resolve('@toptal/davinci-skeleton')
26
- const srcFilepath = path.join(skeletonPath, '../..', GITHUB_DIR, WORKFLOWS_DIR, fileName)
31
+ const srcFilepath = getWorkflowSourceFilepath(fileName)
27
32
  const destFilepath = path.join(destDir, fileName)
28
33
 
29
34
  try {
30
35
  await fs.copy(srcFilepath, destFilepath)
31
36
 
32
- spinner.succeed('Workflow copied!')
37
+ spinner.succeed('Workflow has been copied!')
33
38
  } catch (err) {
34
39
  spinner.fail()
35
40
  throw err
@@ -39,5 +44,6 @@ const copyWorkflowFromSkeleton = async (fileName, destDir) => {
39
44
  module.exports = {
40
45
  readPackageJson,
41
46
  writePackageJson,
42
- copyWorkflowFromSkeleton,
47
+ getWorkflowSourceFilepath,
48
+ copyWorkflowFromSkeleton
43
49
  }