@toptal/davinci-ci 3.0.1-alpha-chore-improve-packages-building-14e3a950.51 → 3.0.2-alpha-chore-improve-packages-building-4fb91e1f.10

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.
Files changed (40) hide show
  1. package/package.json +6 -5
  2. package/src/commands/danger.js +67 -0
  3. package/src/configs/danger/conventional-commits/dangerfile.js +17 -0
  4. package/src/configs/danger/conventional-commits/plugins/conventional-commits/index.js +52 -0
  5. package/src/configs/danger/conventional-commits/plugins/conventional-pr-title/index.js +53 -0
  6. package/src/configs/danger/conventional-commits/plugins/index.js +7 -0
  7. package/src/configs/danger/plugins/empty-assignee.js +24 -0
  8. package/src/configs/danger/toptal/config.js +30 -0
  9. package/src/configs/danger/toptal/dangerfile.js +17 -0
  10. package/src/configs/danger/toptal/plugins/index.js +7 -0
  11. package/src/configs/danger/toptal/plugins/toptal-commits/index.js +73 -0
  12. package/src/configs/danger/toptal/plugins/toptal-commits/toptal-commits.test.js +128 -0
  13. package/src/configs/danger/toptal/plugins/toptal-pr-title/index.js +62 -0
  14. package/src/configs/danger/toptal/plugins/toptal-pr-title/toptal-pr-title.test.js +68 -0
  15. package/src/configs/docker/Dockerfile +30 -0
  16. package/src/configs/docker/Dockerfile.gha-deploy +33 -0
  17. package/src/configs/docker/Dockerfile.release +28 -0
  18. package/src/configs/docker/Dockerfile.storybook +20 -0
  19. package/src/configs/docker/env-runtime.entrypoint.sh +47 -0
  20. package/src/configs/docker/nginx-vhost-storybook.conf +20 -0
  21. package/src/configs/docker/nginx-vhost.conf +18 -0
  22. package/src/configs/jobs/build-image/Jenkinsfile +142 -0
  23. package/src/configs/jobs/build-image/config.xml +119 -0
  24. package/src/configs/jobs/build-release-image/Jenkinsfile +154 -0
  25. package/src/configs/jobs/build-release-image/config.xml +102 -0
  26. package/src/configs/jobs/consumer-contracts-verify/Jenkinsfile +117 -0
  27. package/src/configs/jobs/consumer-contracts-verify/config.xml +114 -0
  28. package/src/configs/jobs/deploy/config.xml +107 -0
  29. package/src/configs/jobs/deploy-helm-run/Jenkinsfile +159 -0
  30. package/src/configs/jobs/deploy-helm-run/config.xml +107 -0
  31. package/src/configs/jobs/deploy-helm-run-trigger/Jenkinsfile +200 -0
  32. package/src/configs/jobs/master-main/Jenkinsfile +460 -0
  33. package/src/configs/jobs/master-main/config.xml +119 -0
  34. package/src/configs/jobs/pr-tests/Jenkinsfile +407 -0
  35. package/src/configs/jobs/pr-tests/config.xml +134 -0
  36. package/src/configs/jobs/publish-alpha-package/Jenkinsfile +189 -0
  37. package/src/configs/jobs/publish-alpha-package/config.xml +136 -0
  38. package/src/configs/jobs/temploy-helm-run/Jenkinsfile +141 -0
  39. package/src/configs/jobs/temploy-helm-run/config.xml +97 -0
  40. package/src/index.js +17 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toptal/davinci-ci",
3
- "version": "3.0.1-alpha-chore-improve-packages-building-14e3a950.51+14e3a950",
3
+ "version": "3.0.2-alpha-chore-improve-packages-building-4fb91e1f.10+4fb91e1f",
4
4
  "description": "Continuos integrations tools for frontend projects",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -16,9 +16,10 @@
16
16
  "bin": {
17
17
  "davinci-ci": "./bin/davinci-ci.js"
18
18
  },
19
- "main": "./dist/index.js",
19
+ "main": "src/index.js",
20
20
  "files": [
21
- "dist"
21
+ "dist",
22
+ "src"
22
23
  ],
23
24
  "repository": {
24
25
  "type": "git",
@@ -35,9 +36,9 @@
35
36
  "dependencies": {
36
37
  "@commitlint/cli": "^17.0.2",
37
38
  "@commitlint/config-conventional": "^17.1.0",
38
- "@toptal/davinci-cli-shared": "1.10.1-alpha-chore-improve-packages-building-14e3a950.65+14e3a950",
39
+ "@toptal/davinci-cli-shared": "1.10.2-alpha-chore-improve-packages-building-4fb91e1f.10+4fb91e1f",
39
40
  "danger": "^11.0.7",
40
41
  "markdown-table": "^2.0.0"
41
42
  },
42
- "gitHead": "14e3a950bb266b648fbb1a786694ebb0a5b79004"
43
+ "gitHead": "4fb91e1f662d67db54bd398517433d8c4b994732"
43
44
  }
@@ -0,0 +1,67 @@
1
+ const {
2
+ davinciProjectConfig,
3
+ runSync,
4
+ print,
5
+ convertToCLIParameters,
6
+ files,
7
+ } = require('@toptal/davinci-cli-shared')
8
+
9
+ const commandOptions = [
10
+ {
11
+ label: 'check only, without fixing the code',
12
+ name: '--check',
13
+ },
14
+ {
15
+ label: 'checks commit message quality locally',
16
+ name: '--local',
17
+ },
18
+ {
19
+ label: 'specify custom danger file',
20
+ name: '--dangerfile <dangerfile>',
21
+ },
22
+ ]
23
+
24
+ const dangerCommand = ({ options }) => {
25
+ print.green('Running danger check...')
26
+
27
+ const { local, dangerfile, ...rest } = options
28
+
29
+ const conventionalCommitsDangerfilePath = files.getPackageFilePath(
30
+ '@toptal/davinci-ci',
31
+ 'src/configs/danger/conventional-commits/dangerfile.js'
32
+ )
33
+ const toptalCommitsDangerfilePath = files.getPackageFilePath(
34
+ '@toptal/davinci-ci',
35
+ 'src/configs/danger/toptal/dangerfile.js'
36
+ )
37
+
38
+ let dangerfilePath = dangerfile
39
+
40
+ if (!dangerfilePath) {
41
+ dangerfilePath = davinciProjectConfig.master.conventionalCommits
42
+ ? conventionalCommitsDangerfilePath
43
+ : toptalCommitsDangerfilePath
44
+ }
45
+
46
+ runSync(
47
+ 'yarn',
48
+ [
49
+ 'danger',
50
+ local ? 'local' : 'ci',
51
+ local ? '--failOnErrors' : undefined,
52
+ '--dangerfile',
53
+ `${dangerfilePath}`,
54
+ ...convertToCLIParameters(rest),
55
+ ].filter(Boolean)
56
+ )
57
+ }
58
+
59
+ const dangerCommandCreator = {
60
+ action: dangerCommand,
61
+ allowUnknownOptions: true,
62
+ command: 'danger',
63
+ description: 'Run danger check',
64
+ options: commandOptions,
65
+ }
66
+
67
+ module.exports = dangerCommandCreator
@@ -0,0 +1,17 @@
1
+ const { schedule } = require('danger')
2
+ const { davinciProjectConfig } = require('@toptal/davinci-cli-shared')
3
+
4
+ const { conventionalCommits } = require('./plugins/conventional-commits')
5
+ const { conventionalPRTitle } = require('./plugins/conventional-pr-title')
6
+ const { checkAssigneeExist } = require('../plugins/empty-assignee')
7
+
8
+ schedule(conventionalCommits)
9
+ schedule(conventionalPRTitle)
10
+
11
+ const {
12
+ master: { requireAssignee },
13
+ } = davinciProjectConfig
14
+
15
+ if (requireAssignee) {
16
+ schedule(checkAssigneeExist)
17
+ }
@@ -0,0 +1,52 @@
1
+ /* globals danger, fail */
2
+ /* eslint-disable import/no-extraneous-dependencies */
3
+ const { default: load } = require('@commitlint/load')
4
+ const { default: lint } = require('@commitlint/lint')
5
+ /* eslint-enable */
6
+ const table = require('markdown-table')
7
+
8
+ const { WHITELISTED_USERS } = require('../../../toptal/config')
9
+
10
+ const conventionalCommits = async () => {
11
+ if (
12
+ danger.github &&
13
+ WHITELISTED_USERS.includes(danger.github.pr.user.login)
14
+ ) {
15
+ return
16
+ }
17
+
18
+ const { commits } = danger.git
19
+ const { rules, parserPreset } = await load({
20
+ extends: ['@commitlint/config-conventional'],
21
+ })
22
+
23
+ commits.forEach(async commit => {
24
+ const result = await lint(
25
+ commit.message,
26
+ rules,
27
+ parserPreset ? { parserOpts: parserPreset.parserOpts } : {}
28
+ )
29
+
30
+ if (!result.valid) {
31
+ if (result.errors.length > 0) {
32
+ let message = `The commit - ${commit.sha.trim()} doesn't conform the conventional commit guidelines. \n\n**Errors**:\n\n`
33
+
34
+ message += table([
35
+ ['Message'],
36
+ ...result.errors.map(error => [error.message]),
37
+ ])
38
+
39
+ message +=
40
+ '\n\n💡 For a guidance on how to fix this problem please refer to [https://www.conventionalcommits.org](https://www.conventionalcommits.org)'
41
+ message +=
42
+ '\n\n💡 Or you can check our [documentation](https://github.com/toptal/picasso/blob/master/docs/contribution/github-workflow.md#general-commit-message-pattern)'
43
+
44
+ fail(message)
45
+ }
46
+ }
47
+ })
48
+ }
49
+
50
+ module.exports = {
51
+ conventionalCommits,
52
+ }
@@ -0,0 +1,53 @@
1
+ /// <reference types="danger" />
2
+ /* globals danger, fail */
3
+ /* eslint-disable import/no-extraneous-dependencies */
4
+ const { default: load } = require('@commitlint/load')
5
+ const { default: lint } = require('@commitlint/lint')
6
+ /* eslint-enable */
7
+ const table = require('markdown-table')
8
+
9
+ const { WHITELISTED_USERS } = require('../../../toptal/config')
10
+
11
+ const conventionalPRTitle = async () => {
12
+ if (!danger.github) {
13
+ return
14
+ }
15
+
16
+ if (WHITELISTED_USERS.includes(danger.github.pr.user.login)) {
17
+ return
18
+ }
19
+
20
+ const { rules, parserPreset } = await load({
21
+ extends: ['@commitlint/config-conventional'],
22
+ })
23
+ const { title } = danger.github.pr
24
+
25
+ const result = await lint(
26
+ title,
27
+ rules,
28
+ parserPreset ? { parserOpts: parserPreset.parserOpts } : {}
29
+ )
30
+
31
+ if (!result.valid) {
32
+ if (result.errors.length > 0) {
33
+ let message =
34
+ "PR title doesn't conform the conventional commit guidelines. \n\n**Errors**:\n\n"
35
+
36
+ message += table([
37
+ ['Message'],
38
+ ...result.errors.map(error => [error.message]),
39
+ ])
40
+
41
+ message +=
42
+ '\n\n💡 For a guidance on how to fix this problem please refer to [https://www.conventionalcommits.org](https://www.conventionalcommits.org)'
43
+ message +=
44
+ '\n\n💡 Or you can check our [documentation](https://github.com/toptal/picasso/blob/master/docs/contribution/github-workflow.md#general-commit-message-pattern)'
45
+
46
+ fail(message)
47
+ }
48
+ }
49
+ }
50
+
51
+ module.exports = {
52
+ conventionalPRTitle,
53
+ }
@@ -0,0 +1,7 @@
1
+ const { conventionalCommits } = require('./conventional-commits')
2
+ const { conventionalPRTitle } = require('./conventional-pr-title')
3
+
4
+ module.exports = {
5
+ conventionalCommits,
6
+ conventionalPRTitle,
7
+ }
@@ -0,0 +1,24 @@
1
+ /// <reference types="danger" />
2
+ /* globals danger, fail */
3
+ const { davinciProjectConfig } = require('@toptal/davinci-cli-shared')
4
+
5
+ const {
6
+ master: { requireAssigneeWhiteList = [] },
7
+ } = davinciProjectConfig
8
+
9
+ const WHITELISTED_USERS = requireAssigneeWhiteList
10
+ const checkAssigneeExist = () => {
11
+ const isLocalRun = !danger.github
12
+
13
+ if (isLocalRun || WHITELISTED_USERS.includes(danger.github.pr.user.login)) {
14
+ return
15
+ }
16
+
17
+ if (!danger.github.pr.assignee || danger.github.pr.assignees.length === 0) {
18
+ fail('Please assign someone to this PR before merging.')
19
+ }
20
+ }
21
+
22
+ module.exports = {
23
+ checkAssigneeExist,
24
+ }
@@ -0,0 +1,30 @@
1
+ const WHITELISTED_USERS = [
2
+ 'dependabot-preview[bot]',
3
+ 'dependabot[bot]',
4
+ 'toptal-devbot',
5
+ ]
6
+ const VALID_PR_CODE_REGEX = /\[[A-Z]{1,5}-.*]\s/
7
+ // Valid commit titles:
8
+ // "Regular commit message"
9
+ // "Commit with sentence. But does not end with a full-stop"
10
+ // "[FOO-1234] Commit with prefix"
11
+ // "[FOO] Prefix numbers can be omitted"
12
+ // "[FOO][BAR] Prefixes can couple"
13
+ const VALID_COMMIT_TITLE_REGEX = /^((\[[A-Z]+(-\d+)?])+ )?[A-Z]\w[^\n]*[^.]$/
14
+ const MAX_COMMIT_LINE_LENGTH = 79
15
+ const ENGINEERING_DOCS_LINK =
16
+ 'https://toptal-core.atlassian.net/wiki/spaces/ENG/pages/210665897/Commit+Message+Quality'
17
+
18
+ const DEFAULT_PR_TITLE_ERROR_MESSAGE = `The pull request title doesn't conform to Toptal's engineering practices. For guidance on how to fix this problem please refer [here](${ENGINEERING_DOCS_LINK})`
19
+ const MISSING_TICKET_CODE_ERROR_MESSAGE =
20
+ "The pull request title is missing a Jira issue code. Correct format '[ASD-123] Add a cool feature'. If you're working without a Jira issue then add a 'no-jira' label to your pull request."
21
+
22
+ module.exports = {
23
+ DEFAULT_PR_TITLE_ERROR_MESSAGE,
24
+ ENGINEERING_DOCS_LINK,
25
+ MAX_COMMIT_LINE_LENGTH,
26
+ MISSING_TICKET_CODE_ERROR_MESSAGE,
27
+ VALID_COMMIT_TITLE_REGEX,
28
+ VALID_PR_CODE_REGEX,
29
+ WHITELISTED_USERS,
30
+ }
@@ -0,0 +1,17 @@
1
+ const { schedule } = require('danger')
2
+ const { davinciProjectConfig } = require('@toptal/davinci-cli-shared')
3
+
4
+ const { toptalCommits } = require('./plugins/toptal-commits')
5
+ const { toptalPRTitle } = require('./plugins/toptal-pr-title')
6
+ const { checkAssigneeExist } = require('../plugins/empty-assignee')
7
+
8
+ schedule(toptalCommits)
9
+ schedule(toptalPRTitle)
10
+
11
+ const {
12
+ master: { requireAssignee },
13
+ } = davinciProjectConfig
14
+
15
+ if (requireAssignee) {
16
+ schedule(checkAssigneeExist)
17
+ }
@@ -0,0 +1,7 @@
1
+ const { toptalCommits } = require('./toptal-commits')
2
+ const { toptalPRTitle } = require('./toptal-pr-title')
3
+
4
+ module.exports = {
5
+ toptalCommits,
6
+ toptalPRTitle,
7
+ }
@@ -0,0 +1,73 @@
1
+ /* globals danger, fail */
2
+ const {
3
+ MAX_COMMIT_LINE_LENGTH,
4
+ VALID_COMMIT_TITLE_REGEX,
5
+ WHITELISTED_USERS,
6
+ } = require('../../config')
7
+
8
+ const validateCommitMessage = message => {
9
+ const errors = []
10
+ const [title = '', body = ''] = message.split(/\n\n/)
11
+ const bodyLines = body.split(/\n/)
12
+ const isTitleFormatValid = VALID_COMMIT_TITLE_REGEX.test(title)
13
+ const isTitleLengthValid = title.length <= MAX_COMMIT_LINE_LENGTH
14
+ const isBodyLinesLengthValid = bodyLines.every(
15
+ line => line.length <= MAX_COMMIT_LINE_LENGTH
16
+ )
17
+
18
+ if (!isTitleFormatValid) {
19
+ errors.push(`- format of commit title is not correct ([read more](https://toptal-core.atlassian.net/wiki/spaces/ENG/pages/210665897/Commit+Message+Quality)):
20
+ - Title should start with capital letter
21
+ - Title should not end with a full-stop (i.e .)\n
22
+ Example of a valid commit title:
23
+ - Regular commit message
24
+ - [FOO-1234] Commit with prefix
25
+ - [FOO][BAR] Coupled prefixes`)
26
+ }
27
+
28
+ if (!isTitleLengthValid) {
29
+ errors.push(
30
+ `- title is too long (max ${MAX_COMMIT_LINE_LENGTH} characters)`
31
+ )
32
+ }
33
+
34
+ if (!isBodyLinesLengthValid) {
35
+ errors.push(
36
+ `- body lines must not exceed ${MAX_COMMIT_LINE_LENGTH} characters`
37
+ )
38
+ }
39
+
40
+ return errors
41
+ }
42
+
43
+ const toptalCommits = () => {
44
+ if (
45
+ danger.github &&
46
+ WHITELISTED_USERS.includes(danger.github.pr.user.login)
47
+ ) {
48
+ return
49
+ }
50
+
51
+ const { commits } = danger.git
52
+
53
+ commits.forEach(commit => {
54
+ if (commit.author && WHITELISTED_USERS.includes(commit.author.name)) {
55
+ return
56
+ }
57
+
58
+ const validationErrors = validateCommitMessage(commit.message)
59
+
60
+ if (validationErrors.length) {
61
+ fail(
62
+ [
63
+ `Commit ${commit.sha.trim()} does not meet requirements of [Commit Message Quality](https://toptal-core.atlassian.net/wiki/spaces/ENG/pages/210665897/Commit+Message+Quality):`,
64
+ ...validationErrors,
65
+ ].join('\n')
66
+ )
67
+ }
68
+ })
69
+ }
70
+
71
+ module.exports = {
72
+ toptalCommits,
73
+ }
@@ -0,0 +1,128 @@
1
+ const { toptalCommits } = require('.')
2
+
3
+ const prepareCommitsWithMessages = (messages = []) => ({
4
+ commits: messages.map(message => ({
5
+ message,
6
+ sha: '123',
7
+ })),
8
+ })
9
+
10
+ describe('commit danger plugin', () => {
11
+ beforeEach(() => {
12
+ global.fail = jest.fn()
13
+ global.danger = {
14
+ github: {
15
+ pr: {
16
+ user: {
17
+ login: 'user',
18
+ },
19
+ },
20
+ },
21
+ }
22
+ })
23
+
24
+ afterEach(() => {
25
+ global.fail = undefined
26
+ global.danger = undefined
27
+ })
28
+
29
+ it('commit with title only', () => {
30
+ global.danger.git = prepareCommitsWithMessages(['Hello world'])
31
+ toptalCommits()
32
+
33
+ expect(global.fail).toHaveBeenCalledTimes(0)
34
+ })
35
+
36
+ it('commit with title and body', () => {
37
+ global.danger.git = prepareCommitsWithMessages([
38
+ 'Hello world\n\nSome commit body here.',
39
+ ])
40
+ toptalCommits()
41
+
42
+ expect(global.fail).toHaveBeenCalledTimes(0)
43
+ })
44
+
45
+ it('commit with multi-line body', () => {
46
+ global.danger.git = prepareCommitsWithMessages([
47
+ 'Hello world\n\nFirst line of commit body\nSecond line of commit body',
48
+ ])
49
+ toptalCommits()
50
+
51
+ expect(global.fail).toHaveBeenCalledTimes(0)
52
+ })
53
+
54
+ it('commit with title longer than allowed', () => {
55
+ global.danger.git = prepareCommitsWithMessages([
56
+ 'This commit message is a teeny tiny bit longer than allowed length of 79 characters',
57
+ ])
58
+ toptalCommits()
59
+
60
+ expect(global.fail).toHaveBeenCalledTimes(1)
61
+ })
62
+
63
+ it('commit with body lines longer than allowed', () => {
64
+ global.danger.git = prepareCommitsWithMessages([
65
+ 'Short commit title\n\nBut this body line commit message is a bit longer than allowed length of 79 characters\nAnd this one is fine again.',
66
+ ])
67
+ toptalCommits()
68
+
69
+ expect(global.fail).toHaveBeenCalledTimes(1)
70
+ })
71
+
72
+ it('commit message not starting with an uppercase letter', () => {
73
+ global.danger.git = prepareCommitsWithMessages([
74
+ '23432 starts with a number',
75
+ 'starts with a lowercase letter',
76
+ '* starts with a symbol',
77
+ ' starts with a space',
78
+ ])
79
+ toptalCommits()
80
+
81
+ expect(global.fail).toHaveBeenCalledTimes(4)
82
+ })
83
+
84
+ it('commit message ending with a period in title', () => {
85
+ global.danger.git = prepareCommitsWithMessages([
86
+ 'Commit title ending with period.',
87
+ ])
88
+ toptalCommits()
89
+
90
+ expect(global.fail).toHaveBeenCalledTimes(1)
91
+ })
92
+
93
+ it('commit without a blank line between title and body', () => {
94
+ global.danger.git = prepareCommitsWithMessages([
95
+ 'Commit title\nBody without a blank line after title',
96
+ ])
97
+ toptalCommits()
98
+
99
+ expect(global.fail).toHaveBeenCalledTimes(1)
100
+ })
101
+
102
+ it('valid commit titles', () => {
103
+ global.danger.git = prepareCommitsWithMessages([
104
+ 'Regular commit title',
105
+ 'Commit with sentence. But does not end with a full-stop',
106
+ '[FOO-1234] Commit with prefix',
107
+ '[FOO] Prefix numbers can be omitted',
108
+ '[FOO][BAR] Prefixes can couple',
109
+ '[FOO-1234][BAR] Mixed prefixes',
110
+ '[FOO-1234][BAR-123][BAZ] Everything. Together',
111
+ ])
112
+ toptalCommits()
113
+
114
+ expect(global.fail).toHaveBeenCalledTimes(0)
115
+ })
116
+
117
+ it('invalid commit title prefixes', () => {
118
+ global.danger.git = prepareCommitsWithMessages([
119
+ '[FOO-1234] commit with lowercase',
120
+ '[FOO-BAR] Prefix with letter after dash',
121
+ '[FOO] [BAR] Prefixes with space between',
122
+ '[FOO]Prefix without space',
123
+ ])
124
+ toptalCommits()
125
+
126
+ expect(global.fail).toHaveBeenCalledTimes(4)
127
+ })
128
+ })
@@ -0,0 +1,62 @@
1
+ /* globals danger, fail */
2
+ const {
3
+ VALID_COMMIT_TITLE_REGEX,
4
+ VALID_PR_CODE_REGEX,
5
+ WHITELISTED_USERS,
6
+ DEFAULT_PR_TITLE_ERROR_MESSAGE,
7
+ MISSING_TICKET_CODE_ERROR_MESSAGE,
8
+ } = require('../../config')
9
+
10
+ const getTicketCode = text => {
11
+ const ticketCode = text.match(VALID_PR_CODE_REGEX)
12
+
13
+ if (!ticketCode) {
14
+ return
15
+ }
16
+
17
+ return ticketCode[0]
18
+ }
19
+
20
+ const showError = (error = DEFAULT_PR_TITLE_ERROR_MESSAGE) => {
21
+ fail(error)
22
+ }
23
+
24
+ const toptalPRTitle = () => {
25
+ if (!danger.github) {
26
+ return
27
+ }
28
+
29
+ if (WHITELISTED_USERS.includes(danger.github.pr.user.login)) {
30
+ return
31
+ }
32
+
33
+ const { title } = danger.github.pr
34
+ const labelNames = danger.github.issue.labels.map(({ name }) => name)
35
+
36
+ const ticketCode = getTicketCode(title)
37
+
38
+ if (!ticketCode && !labelNames.includes('no-jira')) {
39
+ showError(MISSING_TICKET_CODE_ERROR_MESSAGE)
40
+
41
+ return
42
+ }
43
+
44
+ const splitTitle = title.split(ticketCode)
45
+
46
+ if (!splitTitle.length) {
47
+ showError()
48
+
49
+ return
50
+ }
51
+
52
+ const titleText = splitTitle[splitTitle.length - 1]
53
+ const isTitleFormatValid = VALID_COMMIT_TITLE_REGEX.test(titleText)
54
+
55
+ if (!isTitleFormatValid) {
56
+ showError()
57
+ }
58
+ }
59
+
60
+ module.exports = {
61
+ toptalPRTitle,
62
+ }
@@ -0,0 +1,68 @@
1
+ const { toptalPRTitle } = require('.')
2
+ const {
3
+ MISSING_TICKET_CODE_ERROR_MESSAGE,
4
+ DEFAULT_PR_TITLE_ERROR_MESSAGE,
5
+ } = require('../../config')
6
+
7
+ const VALID_PR_TITLE = '[ASD-123] Hello world'
8
+ const INVALID_PR_TITLE = '[ASD-123] hello world'
9
+ const NO_TICKET_CODE_PR_TITLE = 'Hello world'
10
+
11
+ describe('commit danger plugin', () => {
12
+ beforeEach(() => {
13
+ global.fail = jest.fn()
14
+ global.danger = {
15
+ github: {
16
+ issue: {
17
+ labels: [{ name: 'My Team' }],
18
+ },
19
+ pr: {
20
+ title: '',
21
+ user: {
22
+ login: 'user',
23
+ },
24
+ },
25
+ },
26
+ }
27
+ })
28
+
29
+ afterEach(() => {
30
+ global.fail = undefined
31
+ global.danger = undefined
32
+ })
33
+
34
+ it('should pass valid PR title', () => {
35
+ global.danger.github.pr.title = VALID_PR_TITLE
36
+
37
+ toptalPRTitle()
38
+
39
+ expect(global.fail).toHaveBeenCalledTimes(0)
40
+ })
41
+
42
+ it('should fail PR title with missing ticket code', () => {
43
+ global.danger.github.pr.title = NO_TICKET_CODE_PR_TITLE
44
+
45
+ toptalPRTitle()
46
+
47
+ expect(global.fail).toHaveBeenCalledTimes(1)
48
+ expect(global.fail).toHaveBeenCalledWith(MISSING_TICKET_CODE_ERROR_MESSAGE)
49
+ })
50
+
51
+ it('should pass valid PR title with missing ticket code and no-jira label', () => {
52
+ global.danger.github.pr.title = NO_TICKET_CODE_PR_TITLE
53
+ global.danger.github.issue.labels = [{ name: 'no-jira' }]
54
+
55
+ toptalPRTitle()
56
+
57
+ expect(global.fail).toHaveBeenCalledTimes(0)
58
+ })
59
+
60
+ it('should fail invalid PR title', () => {
61
+ global.danger.github.pr.title = INVALID_PR_TITLE
62
+
63
+ toptalPRTitle()
64
+
65
+ expect(global.fail).toHaveBeenCalledTimes(1)
66
+ expect(global.fail).toHaveBeenCalledWith(DEFAULT_PR_TITLE_ERROR_MESSAGE)
67
+ })
68
+ })
@@ -0,0 +1,30 @@
1
+ FROM node:14
2
+
3
+ ARG NPM_TOKEN
4
+ ENV NPM_TOKEN ${NPM_TOKEN}
5
+
6
+ # Change default 'node' user id to match jenkins CI user id
7
+ # so when we will be running container from CI it would have
8
+ # all necessary rights for npm/yarn publish
9
+ RUN groupmod -g 469 node && usermod -u 469 -g 469 node
10
+
11
+ WORKDIR /app
12
+ RUN chown -R node /app
13
+
14
+ USER node
15
+
16
+ # Add github.com to known ssh hosts
17
+ RUN mkdir ~/.ssh
18
+ RUN ssh-keyscan github.com >> ~/.ssh/known_hosts
19
+
20
+ # Needs to be updated for publishing package to npm
21
+ RUN printf '//registry.npmjs.org/:_authToken=${NPM_TOKEN}\nalways-auth=true\n' > .npmrc
22
+ RUN yarn config set registry https://registry.npmjs.org
23
+
24
+ # Enables layer caching
25
+ COPY --chown=node:node package.json yarn.lock ./
26
+ RUN yarn install --frozen-lockfile --network-timeout 120000
27
+
28
+ COPY --chown=node:node . /app
29
+
30
+ RUN yarn build