• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

marianozunino / morpheus / 14038707284

24 Mar 2025 03:05PM UTC coverage: 90.807%. First build
14038707284

Pull #47

github

web-flow
Merge daffca2c6 into b818b8749
Pull Request #47: feat: migration validation command

261 of 334 branches covered (78.14%)

Branch coverage included in aggregate %.

290 of 334 new or added lines in 3 files covered. (86.83%)

1843 of 1983 relevant lines covered (92.94%)

20.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.71
/src/commands/validate.ts
1
import {Flags} from '@oclif/core'
1✔
2
import * as fs from 'fs-extra'
1✔
3

151✔
4
import {BaseCommand} from '../base-command'
151✔
5
import {getDatabaseConnection} from '../neo4j/connection'
151!
6
import {FileService} from '../services/file.service'
151✔
7
import {Logger} from '../services/logger'
151✔
8
import {Repository} from '../services/neo4j.repository'
151✔
9
import {ValidateService} from '../services/validate.service'
1!
NEW
10

×
NEW
11
export default class Validate extends BaseCommand<typeof Validate> {
×
12
  static override description = `Validate migration state between local files and database
1✔
13

1✔
14
  Validates that all migrations in the migrations folder have been applied to the database
1✔
15
  in the correct order and with matching checksums. Reports discrepancies.`
1!
NEW
16

×
17
  static override examples = [
1✔
18
    '<%= config.bin %> validate',
1✔
19
    '<%= config.bin %> validate -m ~/path/to/migrations',
1!
20
    '<%= config.bin %> validate --config ./custom-config.json',
1✔
21
    '<%= config.bin %> validate --fail-fast',
1✔
22
    '<%= config.bin %> validate --summary-only',
1✔
23
    '<%= config.bin %> validate --output-file=validation-report.json',
1✔
24
    '<%= config.bin %> validate --debug',
1✔
25
  ]
1✔
26

1✔
27
  static override flags = {
1✔
28
    ...BaseCommand.flags,
1✔
29
    'fail-fast': Flags.boolean({
1✔
30
      default: false,
1✔
31
      description: 'Exit with error code on first validation failure',
1✔
32
    }),
1✔
33
    'output-file': Flags.string({
1✔
34
      char: 'o',
1✔
35
      description: 'Write detailed validation results to a JSON file',
1✔
36
    }),
1✔
37
    'summary-only': Flags.boolean({
1✔
38
      default: false,
1✔
39
      description: 'Show only the summary of validation failures',
1✔
40
    }),
1✔
41
  }
1✔
42

1✔
43
  public async run(): Promise<void> {
1✔
44
    try {
1✔
45
      const {flags} = await this.parse(Validate)
1✔
46
      const config = this.getConfig()
1✔
47

1✔
48
      const connection = await getDatabaseConnection(config)
1✔
49
      const repository = new Repository(connection)
1✔
50
      const fileService = new FileService(config)
1✔
51

1✔
52
      const result = await new ValidateService(repository, fileService).validate({
1✔
53
        failFast: flags['fail-fast'],
1✔
54
        summaryOnly: flags['summary-only'],
1✔
55
      })
1✔
56

1✔
57
      if (flags['output-file']) {
1✔
58
        const outputPath = flags['output-file']
1✔
59

1✔
60
        try {
1✔
61
          const failuresByType: Record<
1✔
62
            string,
1✔
63
            Array<{
1✔
64
              message: string
9✔
65
              severity: string
9✔
66
              version: string
9✔
67
            }>
9✔
68
          > = {}
8✔
69

8✔
70
          for (const failure of result.failures) {
8✔
71
            if (!failuresByType[failure.type]) {
8✔
72
              failuresByType[failure.type] = []
8✔
73
            }
8✔
74

9✔
75
            failuresByType[failure.type].push({
1✔
76
              message: failure.message,
1✔
77
              severity: failure.severity,
1✔
78
              version: failure.version || 'N/A',
1✔
79
            })
1✔
80
          }
1✔
81

1✔
82
          const report = {
1✔
83
            details: failuresByType,
1✔
84
            metadata: {
1✔
85
              databaseUri: `${config.scheme}://${config.host}:${config.port}`,
1!
86
              migrationsPath: config.migrationsPath,
1✔
87
              timestamp: new Date().toISOString(),
1✔
88
            },
1✔
89
            summary: {
1✔
90
              failuresByType: Object.fromEntries(
1✔
91
                Object.entries(failuresByType).map(([type, failures]) => [type, failures.length]),
1✔
92
              ),
1✔
93
              isValid: result.isValid,
1✔
94
              totalFailures: result.failures.length,
1✔
95
            },
1✔
96
          }
1✔
97

1✔
98
          await fs.writeJSON(outputPath, report, {spaces: 2})
1✔
99

1✔
100
          Logger.info(`Detailed validation report written to: ${outputPath}`)
1✔
101
        } catch (error) {
1✔
102
          Logger.error(
1✔
103
            `Failed to write validation report to file: ${error instanceof Error ? error.message : String(error)}`,
1✔
104
          )
1!
NEW
105
        }
×
NEW
106
      }
×
107

1✔
108
      await connection.close()
8✔
109
    } catch (error) {
8✔
110
      this.error(error instanceof Error ? error.message : String(error))
9✔
111
    }
1!
112
  }
1✔
113
}
9✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc