@toptal/davinci-monorepo 8.1.4-alpha-CRT-5891-create-coverage-command-23386c1d.2 → 8.1.4-alpha-CRT-5891-create-coverage-command-c72932eb.4

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.
@@ -7,7 +7,7 @@ import { createGraphGenerateCommand } from '../src/commands/graph-generate.js'
7
7
  import metricsCommand from '../src/commands/metrics.js'
8
8
  // eslint-disable-next-line no-restricted-syntax
9
9
  import codeownersCommand from '../src/commands/codeowners/index.js'
10
- import { coverageCommand } from '../src/commands/coverage.js'
10
+ import { coverageCommand } from '../src/commands/coverage-command/index.js'
11
11
 
12
12
  cliEngine.loadCommands(
13
13
  [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toptal/davinci-monorepo",
3
- "version": "8.1.4-alpha-CRT-5891-create-coverage-command-23386c1d.2+23386c1d",
3
+ "version": "8.1.4-alpha-CRT-5891-create-coverage-command-c72932eb.4+c72932eb",
4
4
  "description": "Monorepo utility tools",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -35,13 +35,15 @@
35
35
  "dependencies": {
36
36
  "@nodelib/fs.walk": "^1.2.6",
37
37
  "@oclif/core": "^1.16.1",
38
- "@toptal/davinci-cli-shared": "2.3.1-alpha-CRT-5891-create-coverage-command-23386c1d.34+23386c1d",
38
+ "@toptal/davinci-cli-shared": "2.3.1-alpha-CRT-5891-create-coverage-command-c72932eb.36+c72932eb",
39
39
  "chalk": "^4.1.2",
40
40
  "codeowners": "5.1.1",
41
+ "commander": "^10.0.0",
41
42
  "dependency-cruiser": "^12.5.0",
42
43
  "ervy": "^1.0.7",
43
44
  "execa": "^5.1.1",
44
45
  "find-up": "5.0.0",
46
+ "find-yarn-workspace-root": "^2.0.0",
45
47
  "glob": "^8.0.3",
46
48
  "ignore": "^5.2.0",
47
49
  "is-directory": "^0.3.1",
@@ -53,5 +55,5 @@
53
55
  "devDependencies": {
54
56
  "@jest/globals": "^29.4.2"
55
57
  },
56
- "gitHead": "23386c1d709c03d921ae81f6e8ede8bbaccd64aa"
58
+ "gitHead": "c72932ebed3392a4ffb196fb2e6a21b9c5e8c3f1"
57
59
  }
@@ -62,9 +62,6 @@ Codeowners.prototype.getOwner =
62
62
  * @param {string} filePath
63
63
  */
64
64
  function getOwner(filePath) {
65
- console.log({ filePath })
66
- console.log({ entries: this.ownerEntries })
67
-
68
65
  for (const entry of this.ownerEntries) {
69
66
  if (entry.match(filePath)) {
70
67
  return entry.usernames
@@ -0,0 +1,3 @@
1
+ export const JEST_COVERAGE_PATH = 'coverage/jest'
2
+ export const CYPRESS_COVERAGE_PATH = 'coverage/cypress'
3
+ export const TEAMS_COVERAGE_PATH = 'coverage/teams'
@@ -1,24 +1,28 @@
1
1
  import path from 'path'
2
- import * as url from 'url'
3
2
  import execa from 'execa'
4
3
  import fs from 'fs'
5
4
  import { print } from '@toptal/davinci-cli-shared'
5
+ import getWorkspaceRoot from 'find-yarn-workspace-root'
6
6
 
7
- import Codeowners from './codeowners/core/codeowners/codeowners.js'
7
+ // eslint-disable-next-line no-restricted-syntax
8
+ import Codeowners from '../codeowners/core/codeowners/codeowners.js'
9
+ import { sanitizeTeamName } from './services/sanitize-team-name/sanitize-team-name.js'
10
+ import {
11
+ CYPRESS_COVERAGE_PATH,
12
+ JEST_COVERAGE_PATH,
13
+ TEAMS_COVERAGE_PATH,
14
+ } from './config.js'
8
15
 
9
- const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
10
- const rootProjectPath = path.join(__dirname, '../../')
11
-
12
- const sanitizeTeamName = team => team.replace('/', '-').replace('@', '')
16
+ const workspaceRoot = getWorkspaceRoot()
13
17
 
14
18
  const sanitizeNycPercentage = percentage =>
15
19
  percentage === 'Unknown' ? 0 : percentage
16
20
 
17
21
  // eslint-disable-next-line max-statements
18
22
  const generateTeamCoverage = async options => {
19
- print.header('generateTeamCoverage')
23
+ print.header('Generating team coverage')
20
24
 
21
- const codeowners = new Codeowners(rootProjectPath)
25
+ const codeowners = new Codeowners(workspaceRoot)
22
26
 
23
27
  const ownerEntries = codeowners.ownerEntries
24
28
  const uniqueTeams = ownerEntries
@@ -26,43 +30,40 @@ const generateTeamCoverage = async options => {
26
30
  // eslint-disable-next-line id-length
27
31
  .filter((v, i, a) => a.indexOf(v) === i)
28
32
 
29
- // eslint-disable-next-line no-console
30
- console.log('Teams:', uniqueTeams)
33
+ print.grey('Teams: ', uniqueTeams)
31
34
 
32
35
  const teams = uniqueTeams
33
36
 
34
- await execa.command(`rm -rf coverage/teams`)
35
- await execa.command(`mkdir coverage/teams`)
37
+ await execa.command(`rm -rf ${TEAMS_COVERAGE_PATH}`)
38
+ await execa.command(`mkdir ${TEAMS_COVERAGE_PATH}`)
36
39
 
37
40
  for await (const team of teams) {
38
41
  const sanitizedTeam = sanitizeTeamName(team)
42
+ const sanitizedTeamPath = path.join(TEAMS_COVERAGE_PATH, sanitizedTeam)
39
43
 
40
- await execa.command(`mkdir coverage/teams/${sanitizedTeam}`)
41
- await execa.command(`mkdir coverage/teams/${sanitizedTeam}/jest`)
42
- await execa.command(`mkdir coverage/teams/${sanitizedTeam}/cypress`)
44
+ await execa.command(`mkdir ${sanitizedTeamPath}`)
45
+ await execa.command(`mkdir ${sanitizedTeamPath}/jest`)
46
+ await execa.command(`mkdir ${sanitizedTeamPath}/cypress`)
43
47
  }
44
48
 
45
49
  for await (const team of teams) {
46
- // eslint-disable-next-line no-console
47
- console.log('Team coverage:', team)
50
+ print.gray('Team coverage: ', team)
48
51
 
49
52
  const sanitizedTeam = sanitizeTeamName(team)
53
+ const sanitizedTeamPath = path.join(TEAMS_COVERAGE_PATH, sanitizedTeam)
50
54
 
51
55
  await execa.command(
52
- `cp coverage/jest/coverage-final-${sanitizedTeam}.json coverage/teams/${sanitizedTeam}/jest/coverage-final.json`
56
+ `cp ${JEST_COVERAGE_PATH}/coverage-final-${sanitizedTeam}.json ${sanitizedTeamPath}/jest/coverage-final.json`
53
57
  )
54
-
55
- // TODO add nyc as deps?
56
58
  await execa.command(
57
- `yarn nyc report --temp-dir coverage/teams/${sanitizedTeam}/jest --reporter json-summary --reporter html --report-dir coverage/teams/${sanitizedTeam}/jest`
59
+ `yarn nyc report --temp-dir ${sanitizedTeamPath}/jest --reporter json-summary --reporter html --report-dir ${sanitizedTeamPath}/jest`
58
60
  )
59
61
 
60
62
  await execa.command(
61
- `cp coverage/cypress/coverage-final-${sanitizedTeam}.json coverage/teams/${sanitizedTeam}/cypress/coverage-final.json`
63
+ `cp ${CYPRESS_COVERAGE_PATH}/coverage-final-${sanitizedTeam}.json ${sanitizedTeamPath}/cypress/coverage-final.json`
62
64
  )
63
-
64
65
  await execa.command(
65
- `yarn nyc report --temp-dir coverage/teams/${sanitizedTeam}/cypress --reporter json-summary --reporter html --report-dir coverage/teams/${sanitizedTeam}/cypress`
66
+ `yarn nyc report --temp-dir ${sanitizedTeamPath}/cypress --reporter json-summary --reporter html --report-dir ${sanitizedTeamPath}/cypress`
66
67
  )
67
68
  }
68
69
 
@@ -71,6 +72,8 @@ const generateTeamCoverage = async options => {
71
72
 
72
73
  for await (const team of teams) {
73
74
  const sanitizedTeam = sanitizeTeamName(team)
75
+ const sanitizedTeamPath = path.join(TEAMS_COVERAGE_PATH, sanitizedTeam)
76
+
74
77
  const result = {
75
78
  created_at,
76
79
  team,
@@ -78,10 +81,7 @@ const generateTeamCoverage = async options => {
78
81
  }
79
82
 
80
83
  const jestCoverageSummary = JSON.parse(
81
- fs.readFileSync(
82
- `coverage/teams/${sanitizedTeam}/jest/coverage-summary.json`,
83
- 'utf8'
84
- )
84
+ fs.readFileSync(`${sanitizedTeamPath}/jest/coverage-summary.json`, 'utf8')
85
85
  )
86
86
 
87
87
  result.jest_lines_coverage = sanitizeNycPercentage(
@@ -99,7 +99,7 @@ const generateTeamCoverage = async options => {
99
99
 
100
100
  const cypressCoverageSummary = JSON.parse(
101
101
  fs.readFileSync(
102
- `coverage/teams/${sanitizedTeam}/cypress/coverage-summary.json`,
102
+ `${sanitizedTeamPath}/cypress/coverage-summary.json`,
103
103
  'utf8'
104
104
  )
105
105
  )
@@ -120,21 +120,19 @@ const generateTeamCoverage = async options => {
120
120
  results.push(result)
121
121
  }
122
122
 
123
- fs.writeFileSync(
124
- 'team-tests-coverage-results.json',
125
- JSON.stringify(results, null, 2)
126
- )
123
+ fs.writeFileSync(options.outputFileName, JSON.stringify(results, null, 2))
127
124
  }
128
125
 
129
- export const generateTeamCoverageCommand = program => {
130
- print.header('generateTeamCoverageCommand')
131
-
132
- return program
126
+ export const generateTeamCoverageCommand = program =>
127
+ program
133
128
  .command('generate-team-coverage')
134
129
  .description('TODO: generate-team-coverage')
135
130
  .requiredOption(
136
131
  '-r, --repository <repository_name>',
137
132
  'specify repository name'
138
133
  )
139
- .action(options => generateTeamCoverage(options))
140
- }
134
+ .requiredOption(
135
+ '-o, --output-file-name <output_file_name>',
136
+ 'specify output file name'
137
+ )
138
+ .action(generateTeamCoverage)
@@ -1,17 +1,20 @@
1
1
  import path from 'path'
2
2
  import fs from 'fs'
3
- import * as url from 'url'
4
3
  import { print } from '@toptal/davinci-cli-shared'
4
+ import getWorkspaceRoot from 'find-yarn-workspace-root'
5
5
 
6
- import Codeowners from './codeowners/core/codeowners/codeowners.js'
6
+ // eslint-disable-next-line no-restricted-syntax
7
+ import Codeowners from '../codeowners/core/codeowners/codeowners.js'
8
+ import { CYPRESS_COVERAGE_PATH, JEST_COVERAGE_PATH } from './config.js'
9
+ import { sanitizeTeamName } from './services/sanitize-team-name/sanitize-team-name.js'
7
10
 
8
- const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
9
- const rootProjectPath = path.join(__dirname, '../../')
11
+ const workspaceRoot = getWorkspaceRoot()
10
12
 
11
13
  const readJestCoverageReport = () => {
12
14
  const jestCoverageReportPath = path.join(
13
- rootProjectPath,
14
- 'coverage/jest/coverage-final-jest.json'
15
+ workspaceRoot,
16
+ JEST_COVERAGE_PATH,
17
+ 'coverage-final-jest.json'
15
18
  )
16
19
 
17
20
  const data = fs.readFileSync(jestCoverageReportPath, 'utf8')
@@ -21,8 +24,9 @@ const readJestCoverageReport = () => {
21
24
 
22
25
  const readCypressCoverageReport = () => {
23
26
  const cypressCoverageReportPath = path.join(
24
- rootProjectPath,
25
- 'coverage/cypress/coverage-final-cypress.json'
27
+ workspaceRoot,
28
+ CYPRESS_COVERAGE_PATH,
29
+ 'coverage-final-cypress.json'
26
30
  )
27
31
 
28
32
  const data = fs.readFileSync(cypressCoverageReportPath, 'utf8')
@@ -30,16 +34,19 @@ const readCypressCoverageReport = () => {
30
34
  return JSON.parse(data)
31
35
  }
32
36
 
33
- const sanitizeTeamName = team => team.replace('/', '-').replace('@', '')
34
-
35
- const splitReportIntoTeams = (reportObj, teams, codeowners, coveragePath) => {
37
+ const splitReportIntoTeams = ({
38
+ reportObj,
39
+ teams,
40
+ codeowners,
41
+ coveragePath,
42
+ }) => {
36
43
  const teamsReport = {}
37
44
 
38
45
  Object.entries(reportObj).forEach(([reportPathKey, report]) => {
39
46
  const file = report.path
40
- const relativePath = path.relative(rootProjectPath, file)
47
+ const relativeWorkspacePath = path.relative(workspaceRoot, file)
41
48
 
42
- const owners = codeowners.getOwner(relativePath)
49
+ const owners = codeowners.getOwner(relativeWorkspacePath)
43
50
 
44
51
  owners.forEach(owner => {
45
52
  teamsReport[owner] = {
@@ -54,8 +61,9 @@ const splitReportIntoTeams = (reportObj, teams, codeowners, coveragePath) => {
54
61
  const sanitizedTeamPath = sanitizeTeamName(team)
55
62
 
56
63
  const reportPath = path.join(
57
- rootProjectPath,
58
- `${coveragePath}/coverage-final-${sanitizedTeamPath}.json`
64
+ workspaceRoot,
65
+ coveragePath,
66
+ `coverage-final-${sanitizedTeamPath}.json`
59
67
  )
60
68
 
61
69
  fs.writeFileSync(reportPath, JSON.stringify(teamReport, null, 2))
@@ -69,34 +77,36 @@ const getAllTeams = codeowners => {
69
77
  // eslint-disable-next-line id-length
70
78
  .filter((v, i, a) => a.indexOf(v) === i)
71
79
 
72
- // eslint-disable-next-line no-console
73
- console.log('Teams:', uniqueTeams)
80
+ print.gray('Teams: ', uniqueTeams)
74
81
 
75
82
  return uniqueTeams
76
83
  }
77
84
 
78
85
  const groupCoverageByCodeowners = async () => {
79
- print.header('groupCoverageByCodeowners')
86
+ print.header('Grouping coverage by codeowners')
80
87
 
81
88
  const jestReport = readJestCoverageReport()
82
89
  const cypressReport = readCypressCoverageReport()
83
90
 
84
- const codeowners = new Codeowners(rootProjectPath)
91
+ const codeowners = new Codeowners(workspaceRoot)
85
92
  const teams = getAllTeams(codeowners)
86
93
 
87
- splitReportIntoTeams(jestReport, teams, codeowners, 'coverage/jest')
88
- splitReportIntoTeams(cypressReport, teams, codeowners, 'coverage/cypress')
94
+ splitReportIntoTeams({
95
+ report: jestReport,
96
+ teams,
97
+ codeowners,
98
+ coveragePath: JEST_COVERAGE_PATH,
99
+ })
100
+ splitReportIntoTeams({
101
+ report: cypressReport,
102
+ teams,
103
+ codeowners,
104
+ coveragePath: CYPRESS_COVERAGE_PATH,
105
+ })
89
106
  }
90
107
 
91
- export const groupCoverageByCodeownersCommand = program => {
92
- print.header('groupCoverageByCodeownersCommand')
93
-
94
- return program
108
+ export const groupCoverageByCodeownersCommand = program =>
109
+ program
95
110
  .command('group-coverage-by-codeowners')
96
111
  .description('TODO: group-coverage-by-codeowners')
97
- .requiredOption(
98
- '-r, --repository <repository_name>',
99
- 'specify repository name'
100
- )
101
112
  .action(groupCoverageByCodeowners)
102
- }
@@ -0,0 +1 @@
1
+ export const sanitizeTeamName = team => team.replace('/', '-').replace('@', '')
package/src/index.js CHANGED
@@ -2,7 +2,7 @@ import detectCircularityCommandCreator from './commands/detect-circularity.js'
2
2
  import metricsCommandCreator from './commands/metrics.js'
3
3
  import { createGraphGenerateCommand } from './commands/graph-generate.js'
4
4
  import codeownersCommand from './commands/codeowners/index.js'
5
- import { coverageCommand } from './commands/coverage.js'
5
+ import { coverageCommand } from './commands/coverage-command/index.js'
6
6
  import checkIfMonorepo from './utils/check-if-monorepo.js'
7
7
  import getPackages from './utils/get-packages.js'
8
8
 
@@ -4,8 +4,8 @@ import { groupCoverageByCodeownersCommand } from './group-coverage-by-codeowners
4
4
  export const coverageCommand = program => {
5
5
  const coverage = program.createCommand('coverage').description('TODO ..')
6
6
 
7
- generateTeamCoverageCommand(coverage)
8
7
  groupCoverageByCodeownersCommand(coverage)
8
+ generateTeamCoverageCommand(coverage)
9
9
 
10
10
  return coverage
11
11
  }