@toptal/davinci-monorepo 8.4.0 → 8.5.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 +7 -0
- package/README.md +1 -0
- package/docs/hosts.md +138 -0
- package/package.json +2 -1
- package/src/commands/hosts/filter-valid-hosts.js +87 -0
- package/src/commands/hosts/host-attributes.js +76 -0
- package/src/commands/hosts/index.js +13 -0
- package/src/index.js +2 -0
- package/src/utils/get-changed-files.js +85 -0
- package/src/utils/get-packages.js +76 -2
- package/src/utils/github/write-to-github-output.js +29 -0
- package/src/utils/graph/packages.js +2 -2
- package/src/utils/host/get-host-name-from-package-name.js +4 -0
- package/src/utils/host/print-host-attributes.mjs +24 -0
- package/src/utils/host/validate-host.js +5 -0
- package/src/utils/index.js +3 -0
- package/src/utils/logger.js +24 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# @toptal/davinci-monorepo
|
|
2
2
|
|
|
3
|
+
## 8.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#2416](https://github.com/toptal/davinci/pull/2416) [`9518893e`](https://github.com/toptal/davinci/commit/9518893ec55a03736bbaa4ec49b8dea2e6d1f46f) Thanks [@dmaklygin](https://github.com/dmaklygin)!
|
|
8
|
+
- add hosts command to davinci-monorepo package. Try it out with `yarn davinci-monorepo hosts`
|
|
9
|
+
|
|
3
10
|
## 8.4.0
|
|
4
11
|
|
|
5
12
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -13,3 +13,4 @@ Use it by installing `yarn add @toptal/davinci-monorepo` in your project.
|
|
|
13
13
|
- [`graph generate`](./docs/graph-generate.md): generate dependency graph into `monorepo-graph.svg` file
|
|
14
14
|
- [`codeowners`](./docs/codeowners.md): show list of tools available for code ownership analysis
|
|
15
15
|
- [`coverage`](./docs/coverage.md): show list of code coverage commands
|
|
16
|
+
- [`hosts`](./docs/hosts.md): get information about hosts in the monorepo
|
package/docs/hosts.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# Host functions
|
|
2
|
+
|
|
3
|
+
The `host` functions are used to get information about hosts in the monorepo.
|
|
4
|
+
|
|
5
|
+
## Filter Valid Hosts Command
|
|
6
|
+
|
|
7
|
+
This command is used to identify and validate hosts from the input.
|
|
8
|
+
|
|
9
|
+
### Description
|
|
10
|
+
|
|
11
|
+
The `davinci-monorepo hosts filter-valid-hosts` command processes an input string to determine existing hosts. It checks the input for valid host names, filters the corresponding packages, and outputs the result either to the console or GitHub.
|
|
12
|
+
|
|
13
|
+
### Usage
|
|
14
|
+
|
|
15
|
+
```shell
|
|
16
|
+
davinci-monorepo hosts filter-valid-hosts --hosts="@toptal/test-1-host @toptal/test-2-host"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Options
|
|
20
|
+
|
|
21
|
+
- `-h, --hosts [hosts]`
|
|
22
|
+
- **Description**: Input string to search for hosts in. By default, it is taken from the environment variable `HOSTS_SEQUENCE`.
|
|
23
|
+
- **Example**: `-h "@toptal/test-1-host @toptal/test-2-host"`
|
|
24
|
+
|
|
25
|
+
- `--head [head]`
|
|
26
|
+
- **Description**: HEAD commit hash. By default, it is taken from the environment variable `NX_HEAD`.
|
|
27
|
+
- **Example**: `--head abc1234`
|
|
28
|
+
|
|
29
|
+
- `--base [base]`
|
|
30
|
+
- **Description**: BASE commit hash. By default, it is taken from the environment variable `NX_BASE`.
|
|
31
|
+
- **Example**: `--base def5678`
|
|
32
|
+
|
|
33
|
+
- `-o, --output [output]`
|
|
34
|
+
- **Description**: Supported output destinations are `console` and `github`. The default is `console`.
|
|
35
|
+
- **Example**: `-o github`
|
|
36
|
+
|
|
37
|
+
- `--log-level [logLevel]`
|
|
38
|
+
- **Description**: Sets the log level. Supported values are `debug`, `info`, and `none`. The default is `none`.
|
|
39
|
+
- **Example**: `--log-level debug`
|
|
40
|
+
|
|
41
|
+
### Examples
|
|
42
|
+
|
|
43
|
+
#### Example 1: Specifying Hosts and Output to Console
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
davinci-monorepo hosts filter-valid-hosts --hosts "@toptal/test-1-host @toptal/test-2-host" --output console
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
#### Example 2: Using Environment Variables and Output to GitHub
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
export HOSTS_SEQUENCE="@toptal/test-1-host @toptal/test-2-host"
|
|
53
|
+
export NX_HEAD="abc1234"
|
|
54
|
+
export NX_BASE="def5678"
|
|
55
|
+
davinci-monorepo hosts filter-valid-hosts --output github
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Environment Variables
|
|
59
|
+
|
|
60
|
+
- `HOSTS_SEQUENCE`
|
|
61
|
+
- **Description**: Default input string to search for hosts.
|
|
62
|
+
|
|
63
|
+
- `NX_HEAD`
|
|
64
|
+
- **Description**: Default HEAD commit hash.
|
|
65
|
+
|
|
66
|
+
- `NX_BASE`
|
|
67
|
+
- **Description**: Default BASE commit hash.
|
|
68
|
+
|
|
69
|
+
- `LOGGER_LEVEL`
|
|
70
|
+
- **Description**: Sets the log level. Supported values are `debug`, `info`, and `none`.
|
|
71
|
+
|
|
72
|
+
### Exit Codes
|
|
73
|
+
|
|
74
|
+
- `0`: Successful execution.
|
|
75
|
+
- `1`: No hosts found in the input or invalid input format.
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
## Host Attributes Command
|
|
79
|
+
|
|
80
|
+
This command is used to get the attributes of a host.
|
|
81
|
+
|
|
82
|
+
### Description
|
|
83
|
+
|
|
84
|
+
The `davinci-monorepo hosts host-attributes` command retrieves the attributes of a host. It checks the host name for validity and outputs the result either to the console or GitHub. It prints the following information:
|
|
85
|
+
* Host name
|
|
86
|
+
* Host package name
|
|
87
|
+
* Jenkins name for temploy cluster
|
|
88
|
+
* Jenkins name for staging cluster
|
|
89
|
+
* Deploybot name
|
|
90
|
+
|
|
91
|
+
### Usage
|
|
92
|
+
|
|
93
|
+
```shell
|
|
94
|
+
davinci-monorepo hosts host-attributes --host="@toptal/test-1-host"
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Options
|
|
98
|
+
|
|
99
|
+
- `-h, --host [host]`
|
|
100
|
+
- **Description**: Host name to search for. By default, it is taken from the environment variable `PACKAGE_NAME`.
|
|
101
|
+
- **Example**: `-h "@toptal/test-1-host"`
|
|
102
|
+
|
|
103
|
+
- `-o, --output [output]`
|
|
104
|
+
- **Description**: Supported output destinations are `console` and `github`. The default is `console`.
|
|
105
|
+
- **Example**: `-o github`
|
|
106
|
+
|
|
107
|
+
- `--log-level [logLevel]`
|
|
108
|
+
- **Description**: Sets the log level. Supported values are `debug`, `info`, and `none`. The default is `none`.
|
|
109
|
+
- **Example**: `--log-level debug`
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
### Environment Variables
|
|
113
|
+
|
|
114
|
+
- `PACKAGE_NAME`
|
|
115
|
+
- **Description**: Default host name to search for.
|
|
116
|
+
|
|
117
|
+
- `LOGGER_LEVEL`
|
|
118
|
+
- **Description**: Sets the log level. Supported values are `debug`, `info`, and `none`.
|
|
119
|
+
|
|
120
|
+
### Examples
|
|
121
|
+
|
|
122
|
+
#### Example 1: Specifying Host and Output to Console
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
davinci-monorepo hosts host-attributes --host "@toptal/test-1-host" --output console
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### Example 2: Using Environment Variables and Output to GitHub
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
export PACKAGE_NAME="@toptal/test-1-host"
|
|
132
|
+
davinci-monorepo hosts host-attributes --output github
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Exit Codes
|
|
136
|
+
|
|
137
|
+
- `0`: Successful execution.
|
|
138
|
+
- `1`: No hosts found in the input or invalid input format.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toptal/davinci-monorepo",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.5.0",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"lint"
|
|
6
6
|
],
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"ignore": "^5.2.0",
|
|
40
40
|
"is-directory": "^0.3.1",
|
|
41
41
|
"lodash": "^4.17.21",
|
|
42
|
+
"nx": "^19.2.3",
|
|
42
43
|
"ora": "^5.4.1",
|
|
43
44
|
"ramda": "^0.28.0",
|
|
44
45
|
"true-case-path": "^1.0.3"
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { print } from '@toptal/davinci-cli-shared'
|
|
2
|
+
|
|
3
|
+
import { getPackages } from '../../utils/get-packages.js'
|
|
4
|
+
import { validateHost, writeToGithubOutput } from '../../utils/index.js'
|
|
5
|
+
|
|
6
|
+
const filterValidHostsCommand = async ({
|
|
7
|
+
hosts,
|
|
8
|
+
output,
|
|
9
|
+
head,
|
|
10
|
+
base,
|
|
11
|
+
logLevel,
|
|
12
|
+
}) => {
|
|
13
|
+
process.env.LOGGER_LEVEL = logLevel || process.env.LOGGER_LEVEL
|
|
14
|
+
const verbose = process.env.LOGGER_LEVEL !== 'none'
|
|
15
|
+
|
|
16
|
+
if (verbose) {
|
|
17
|
+
print.header('Get specified hosts in the input')
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const hostsSequence = (hosts || process.env.HOSTS_SEQUENCE || '')
|
|
21
|
+
.toString()
|
|
22
|
+
.split(' ')
|
|
23
|
+
.filter(validateHost)
|
|
24
|
+
|
|
25
|
+
if (hostsSequence.length === 0) {
|
|
26
|
+
console.error(
|
|
27
|
+
'No hosts found in the input. Please, specify the hosts sequence using the --hosts option or the HOSTS_SEQUENCE environment variable.'
|
|
28
|
+
)
|
|
29
|
+
console.error(
|
|
30
|
+
'Make sure that host names are separated by spaces and have the correct format (e.g., "@toptal/%HOST_NAME%-host").'
|
|
31
|
+
)
|
|
32
|
+
process.exit(1)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const hostPackages = await getPackages({
|
|
36
|
+
type: 'app',
|
|
37
|
+
onlyAffected: false,
|
|
38
|
+
head: head || process.env.NX_HEAD,
|
|
39
|
+
base: base || process.env.NX_BASE,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const filteredHosts = hostPackages.filter(host =>
|
|
43
|
+
hostsSequence.includes(host)
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
switch (output) {
|
|
47
|
+
case 'github':
|
|
48
|
+
writeToGithubOutput(
|
|
49
|
+
'hosts',
|
|
50
|
+
filteredHosts.length ? JSON.stringify(filteredHosts) : ''
|
|
51
|
+
)
|
|
52
|
+
break
|
|
53
|
+
case 'console':
|
|
54
|
+
default:
|
|
55
|
+
console.log(filteredHosts.length ? JSON.stringify(filteredHosts) : '')
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (verbose) {
|
|
59
|
+
print.success('Done')
|
|
60
|
+
}
|
|
61
|
+
process.exit(0)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const createFilterValidHostsCommand = program => {
|
|
65
|
+
return program
|
|
66
|
+
.createCommand('filter-valid-hosts')
|
|
67
|
+
.description('Gets the input and determines existing hosts in the input')
|
|
68
|
+
.action(filterValidHostsCommand)
|
|
69
|
+
.option(
|
|
70
|
+
'-h, --hosts [hosts]',
|
|
71
|
+
'Input string to search for hosts in. By default, it is taken from the environment variable HOSTS_SEQUENCE'
|
|
72
|
+
)
|
|
73
|
+
.option(
|
|
74
|
+
'--head [head]',
|
|
75
|
+
'HEAD commit hash. By default, it is taken from the environment variable NX_HEAD'
|
|
76
|
+
)
|
|
77
|
+
.option(
|
|
78
|
+
'--base [base]',
|
|
79
|
+
'BASE commit hash. By default, it is taken from the environment variable NX_BASE'
|
|
80
|
+
)
|
|
81
|
+
.option(
|
|
82
|
+
'-o, --output [hosts]',
|
|
83
|
+
'Supported output: console, github',
|
|
84
|
+
'console'
|
|
85
|
+
)
|
|
86
|
+
.option('--log-level [logLevel]', 'log level: debug, info, none', 'none')
|
|
87
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { print } from '@toptal/davinci-cli-shared'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
writeToGithubOutput,
|
|
5
|
+
getHostNameFromPackageName,
|
|
6
|
+
validateHost,
|
|
7
|
+
} from '../../utils/index.js'
|
|
8
|
+
|
|
9
|
+
const hostAttributesCommand = ({ host, output, logLevel }) => {
|
|
10
|
+
process.env.LOGGER_LEVEL = logLevel || process.env.LOGGER_LEVEL
|
|
11
|
+
const verbose = process.env.LOGGER_LEVEL !== 'none'
|
|
12
|
+
|
|
13
|
+
if (verbose) {
|
|
14
|
+
print.header('Prints host attributes')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const packageName = (host || process.env.PACKAGE_NAME || '').toString()
|
|
18
|
+
|
|
19
|
+
if (!validateHost(packageName)) {
|
|
20
|
+
console.error(
|
|
21
|
+
'No host found in the input. Please, specify the host using the --host option or the PACKAGE_NAME environment variable.'
|
|
22
|
+
)
|
|
23
|
+
console.error(
|
|
24
|
+
'Make sure that the host name has the correct format (e.g., "@toptal/%HOST_NAME%-host").'
|
|
25
|
+
)
|
|
26
|
+
process.exit(1)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const hostName = getHostNameFromPackageName(packageName)
|
|
30
|
+
const jenkinsTemployJobName = `${hostName}-temploy-helm-run`
|
|
31
|
+
const jenkinsStagingJobName =
|
|
32
|
+
hostName === 'client-portal'
|
|
33
|
+
? 'portal-staging-deployment'
|
|
34
|
+
: `${hostName}-portal-staging-deployment`
|
|
35
|
+
// In order to deploy to the portal, we need to replace the "host" with "portal"
|
|
36
|
+
// e.g. hire-global-client-host -> hire-global-client-portal
|
|
37
|
+
const deploybotName =
|
|
38
|
+
hostName === 'client-portal' ? 'portal' : `${hostName}-portal`
|
|
39
|
+
|
|
40
|
+
const result = JSON.stringify({
|
|
41
|
+
packageName,
|
|
42
|
+
hostName,
|
|
43
|
+
jenkinsTemployJobName,
|
|
44
|
+
jenkinsStagingJobName,
|
|
45
|
+
deploybotName,
|
|
46
|
+
sentryProject: hostName,
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
switch (output) {
|
|
50
|
+
case 'github':
|
|
51
|
+
writeToGithubOutput('attributes', result)
|
|
52
|
+
break
|
|
53
|
+
case 'console':
|
|
54
|
+
default:
|
|
55
|
+
console.log(result)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
process.exit(0)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const createHostAttributesCommand = program => {
|
|
62
|
+
return program
|
|
63
|
+
.createCommand('host-attributes')
|
|
64
|
+
.description('Prints host attributes')
|
|
65
|
+
.action(hostAttributesCommand)
|
|
66
|
+
.option(
|
|
67
|
+
'-h, --host <packageName>',
|
|
68
|
+
'Package name of the host. By default, it is taken from the environment variable PACKAGE_NAME'
|
|
69
|
+
)
|
|
70
|
+
.option(
|
|
71
|
+
'-o, --output <output>',
|
|
72
|
+
'Supported output: console, github',
|
|
73
|
+
'console'
|
|
74
|
+
)
|
|
75
|
+
.option('--log-level [logLevel]', 'log level: debug, info, none', 'none')
|
|
76
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createFilterValidHostsCommand } from './filter-valid-hosts.js'
|
|
2
|
+
import { createHostAttributesCommand } from './host-attributes.js'
|
|
3
|
+
|
|
4
|
+
export const hostsCommandFactory = program => {
|
|
5
|
+
return program
|
|
6
|
+
.createCommand('hosts')
|
|
7
|
+
.addCommand(createFilterValidHostsCommand(program))
|
|
8
|
+
.addCommand(createHostAttributesCommand(program))
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
hostsCommandFactory,
|
|
13
|
+
}
|
package/src/index.js
CHANGED
|
@@ -3,6 +3,7 @@ import { createMetricsCommand } from './commands/metrics.js'
|
|
|
3
3
|
import { createGraphGenerateCommand } from './commands/graph-generate.js'
|
|
4
4
|
import { createCodeownersCommand } from './commands/codeowners/index.js'
|
|
5
5
|
import { createCoverageCommand } from './commands/coverage-command/index.js'
|
|
6
|
+
import { hostsCommandFactory } from './commands/hosts/index.js'
|
|
6
7
|
import checkIfMonorepo from './utils/check-if-monorepo.js'
|
|
7
8
|
import getPackages from './utils/get-packages.js'
|
|
8
9
|
|
|
@@ -17,6 +18,7 @@ export const commands = [
|
|
|
17
18
|
createGraphGenerateCommand,
|
|
18
19
|
createCodeownersCommand,
|
|
19
20
|
createCoverageCommand,
|
|
21
|
+
hostsCommandFactory,
|
|
20
22
|
]
|
|
21
23
|
|
|
22
24
|
export default {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import getWorkspaceRoot from 'find-yarn-workspace-root'
|
|
2
|
+
import { execSync } from 'child_process'
|
|
3
|
+
|
|
4
|
+
import logger from './logger.js'
|
|
5
|
+
|
|
6
|
+
const workspaceRoot = getWorkspaceRoot()
|
|
7
|
+
|
|
8
|
+
const hasStashedChanges = () => {
|
|
9
|
+
try {
|
|
10
|
+
const stashList = execSync('git stash list', { cwd: workspaceRoot })
|
|
11
|
+
|
|
12
|
+
return stashList.toString().trim().length > 0
|
|
13
|
+
} catch (error) {
|
|
14
|
+
// eslint-disable-next-line no-console
|
|
15
|
+
console.error('Error checking stash list:', error)
|
|
16
|
+
|
|
17
|
+
return false
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const stashLocalChanges = () => {
|
|
22
|
+
try {
|
|
23
|
+
execSync('git stash', { cwd: workspaceRoot })
|
|
24
|
+
} catch (error) {
|
|
25
|
+
// eslint-disable-next-line no-console
|
|
26
|
+
console.error('Error stashing local changes:', error)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const restoreLocalChanges = () => {
|
|
31
|
+
if (hasStashedChanges()) {
|
|
32
|
+
try {
|
|
33
|
+
execSync('git stash pop', { cwd: workspaceRoot })
|
|
34
|
+
} catch (error) {
|
|
35
|
+
// eslint-disable-next-line no-console
|
|
36
|
+
console.error('Error restoring local changes:', error)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get list of changed files between two commits/branches
|
|
43
|
+
*/
|
|
44
|
+
const getListOfChangedFiles = ({ base = 'origin/master', head = 'HEAD' }) => {
|
|
45
|
+
const changedFilesCommand = `git diff --name-only ${base} ${head}`
|
|
46
|
+
|
|
47
|
+
const result = execSync(changedFilesCommand, { cwd: workspaceRoot })
|
|
48
|
+
|
|
49
|
+
return result.toString().split('\n').filter(Boolean)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const getChangedFiles = ({ base, head }) => {
|
|
53
|
+
stashLocalChanges()
|
|
54
|
+
|
|
55
|
+
const listOfChangedFiles = getListOfChangedFiles({ base, head })
|
|
56
|
+
|
|
57
|
+
restoreLocalChanges()
|
|
58
|
+
|
|
59
|
+
const rootChangedFiles = listOfChangedFiles.filter(filePath => {
|
|
60
|
+
// Any change that is not in these folders / files will be considered
|
|
61
|
+
// as root change and should trigger Jest & Cypress for all packages
|
|
62
|
+
const pathsWithNonRootChanges = [
|
|
63
|
+
'libs/',
|
|
64
|
+
'namespaces/',
|
|
65
|
+
'hosts/',
|
|
66
|
+
'.github/CODEOWNERS',
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
return pathsWithNonRootChanges.every(
|
|
70
|
+
ignoredPath => !filePath.startsWith(ignoredPath)
|
|
71
|
+
)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
if (rootChangedFiles.length > 0) {
|
|
75
|
+
logger.debug(
|
|
76
|
+
'[ROOT CHANGED FILES]:',
|
|
77
|
+
`Root changes detected for ${rootChangedFiles.length} files:`,
|
|
78
|
+
rootChangedFiles
|
|
79
|
+
)
|
|
80
|
+
} else {
|
|
81
|
+
logger.debug('[ROOT CHANGED FILES]:', 'No root changes detected')
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return rootChangedFiles
|
|
85
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
2
|
import glob from 'glob'
|
|
3
3
|
import fsSystem from 'fs'
|
|
4
|
+
import { execSync } from 'child_process'
|
|
5
|
+
|
|
6
|
+
import { getChangedFiles } from './get-changed-files.js'
|
|
7
|
+
import logger from './logger.js'
|
|
4
8
|
|
|
5
9
|
/**
|
|
6
10
|
* Get information about packages in monorepo
|
|
@@ -45,6 +49,76 @@ export const createGetPackages = fs => (root, cwd) => {
|
|
|
45
49
|
)
|
|
46
50
|
}
|
|
47
51
|
|
|
48
|
-
const
|
|
52
|
+
const extractPackagesAsArray = packages => {
|
|
53
|
+
const packagesArray = packages.trim().toString().split('\n').filter(Boolean)
|
|
54
|
+
|
|
55
|
+
return packagesArray.length === 0
|
|
56
|
+
? []
|
|
57
|
+
: packagesArray.map(item => item.trim())
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const performPackagesSearch = async (commandArgs = []) => {
|
|
61
|
+
const command = `npx nx show projects ${commandArgs.join(' ')}`
|
|
62
|
+
|
|
63
|
+
// Run the nx command and capture the output
|
|
64
|
+
logger.debug(`Getting list of interested projects: ${command}`)
|
|
65
|
+
const output = execSync(command, { encoding: 'utf-8' })
|
|
66
|
+
|
|
67
|
+
logger.debug('Packages:', output)
|
|
68
|
+
|
|
69
|
+
const packagesArr = extractPackagesAsArray(output)
|
|
70
|
+
|
|
71
|
+
logger.log('Number of found packages:', packagesArr.length)
|
|
72
|
+
|
|
73
|
+
return packagesArr
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const getPackages = async ({
|
|
77
|
+
base,
|
|
78
|
+
head,
|
|
79
|
+
type,
|
|
80
|
+
exclude,
|
|
81
|
+
onlyAffected = false,
|
|
82
|
+
targetCommand,
|
|
83
|
+
} = {}) => {
|
|
84
|
+
logger.debug('getPackages: onlyAffected: ', onlyAffected)
|
|
85
|
+
logger.debug('getPackages: base: ', base)
|
|
86
|
+
logger.debug('getPackages: head: ', head)
|
|
87
|
+
logger.debug('getPackages: targetCommand: ', targetCommand)
|
|
88
|
+
logger.debug('getPackages: type: ', type)
|
|
89
|
+
|
|
90
|
+
let rootChangedFiles = []
|
|
91
|
+
|
|
92
|
+
if (onlyAffected) {
|
|
93
|
+
rootChangedFiles = getChangedFiles({ base, head })
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
logger.debug('Root changes detected: ', rootChangedFiles.length > 0)
|
|
97
|
+
|
|
98
|
+
const commandArgs = []
|
|
99
|
+
const affected = rootChangedFiles.length === 0 && onlyAffected
|
|
100
|
+
|
|
101
|
+
if (targetCommand) {
|
|
102
|
+
commandArgs.push('--withTarget', targetCommand)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (type) {
|
|
106
|
+
commandArgs.push('--type', type)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (exclude) {
|
|
110
|
+
commandArgs.push('--exclude', exclude)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (affected) {
|
|
114
|
+
commandArgs.push('--affected')
|
|
115
|
+
commandArgs.push('--base', base ?? 'remotes/origin/master')
|
|
116
|
+
commandArgs.push('--head', head ?? 'HEAD')
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return await performPackagesSearch(commandArgs)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const getPackagesLegacy = createGetPackages(fsSystem)
|
|
49
123
|
|
|
50
|
-
export default
|
|
124
|
+
export default getPackagesLegacy
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fs from 'fs'
|
|
2
|
+
import os from 'os'
|
|
3
|
+
|
|
4
|
+
const writeToGithubOutput = (key, value, multiline = false) => {
|
|
5
|
+
const outputFilePath = process.env.GITHUB_OUTPUT
|
|
6
|
+
|
|
7
|
+
if (!outputFilePath) {
|
|
8
|
+
throw new Error(
|
|
9
|
+
'Unable to find environment variable for file command GITHUB_OUTPUT'
|
|
10
|
+
)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (!fs.existsSync(outputFilePath)) {
|
|
14
|
+
throw new Error(`Missing file at path: ${outputFilePath}`)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const hereDoc = Date.now()
|
|
18
|
+
const options = { encoding: 'utf8' }
|
|
19
|
+
|
|
20
|
+
if (multiline) {
|
|
21
|
+
fs.appendFileSync(outputFilePath, `${key}<<${hereDoc}${os.EOL}`, options)
|
|
22
|
+
fs.appendFileSync(outputFilePath, `${value}${os.EOL}`, options)
|
|
23
|
+
fs.appendFileSync(outputFilePath, `${hereDoc}${os.EOL}`, options)
|
|
24
|
+
} else {
|
|
25
|
+
fs.appendFileSync(outputFilePath, `${key}=${value}${os.EOL}`, options)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export default writeToGithubOutput
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import execa from 'execa'
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import getPackagesLegacy from '../get-packages.js'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Get Locations of packages in monorepo
|
|
@@ -10,7 +10,7 @@ import getPackages from '../get-packages.js'
|
|
|
10
10
|
* // => ['packages/picasso', 'packages/picasso-lab']
|
|
11
11
|
*/
|
|
12
12
|
export const getPackageLocations = () => {
|
|
13
|
-
const packages =
|
|
13
|
+
const packages = getPackagesLegacy(process.cwd())
|
|
14
14
|
|
|
15
15
|
if (packages.length === 0) {
|
|
16
16
|
throw new Error('Your project does not seem to be a monorepo.')
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { writeToGithubOutput } from './write-to-github-output.js'
|
|
2
|
+
import getHostNameFromPackageName from './get-host-name-from-package-name.mjs'
|
|
3
|
+
|
|
4
|
+
const printHostAttributes = async () => {
|
|
5
|
+
const packageName = process.env.PACKAGE_NAME
|
|
6
|
+
const hostName = getHostNameFromPackageName(packageName)
|
|
7
|
+
const jenkinsTemployJobName = `${hostName}-temploy-helm-run`
|
|
8
|
+
const jenkinsStagingJobName = `${hostName}-portal-staging-deployment`
|
|
9
|
+
const deploybotName = `${hostName}-portal`
|
|
10
|
+
|
|
11
|
+
writeToGithubOutput(
|
|
12
|
+
'attributes',
|
|
13
|
+
JSON.stringify({
|
|
14
|
+
packageName,
|
|
15
|
+
hostName,
|
|
16
|
+
jenkinsTemployJobName,
|
|
17
|
+
jenkinsStagingJobName,
|
|
18
|
+
deploybotName,
|
|
19
|
+
sentryProject,
|
|
20
|
+
})
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
printHostAttributes()
|
package/src/utils/index.js
CHANGED
|
@@ -4,3 +4,6 @@ export { default as makeWorkspacesGraph } from './make-workspaces-graph.js'
|
|
|
4
4
|
export { default as getGraphCyclePaths } from './get-graph-cycle-paths.js'
|
|
5
5
|
export { default as getCircularityErrorMessage } from './get-circularity-error-message.js'
|
|
6
6
|
export { default as getLernaGraph } from './get-lerna-graph.js'
|
|
7
|
+
export { default as validateHost } from './host/validate-host.js'
|
|
8
|
+
export { default as getHostNameFromPackageName } from './host/get-host-name-from-package-name.js'
|
|
9
|
+
export { default as writeToGithubOutput } from './github/write-to-github-output.js'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Possible log levels: info, debug
|
|
3
|
+
* @returns log level
|
|
4
|
+
*/
|
|
5
|
+
export const getLoggerLevel = () => process.env.LOGGER_LEVEL || 'info'
|
|
6
|
+
|
|
7
|
+
export const log = (...args) => {
|
|
8
|
+
// eslint-disable-next-line no-console
|
|
9
|
+
if (['debug', 'info'].includes(getLoggerLevel())) {
|
|
10
|
+
console.log('[INFO]: ', ...args)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const debug = (...args) => {
|
|
15
|
+
// eslint-disable-next-line no-console
|
|
16
|
+
if (getLoggerLevel() === 'debug') {
|
|
17
|
+
console.log('[DEBUG]: ', ...args)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default {
|
|
22
|
+
log,
|
|
23
|
+
debug,
|
|
24
|
+
}
|