async function run()

in compiler/run-validations.js [62:216]


async function run () {
  const options = minimist(process.argv.slice(2), {
    string: ['api', 'type', 'branch'],
    boolean: ['cache'],
    default: { cache: true }
  })

  spinner.text = 'Checking requirements'

  const noCache = options.cache === false
  const metadata = await readMetadata()
  const lastRun = metadata.lastRun ? new Date(metadata.lastRun) : new Date(0)
  const isStale = lastRun.getTime() + DAY < Date.now()

  if (options.api === '') {
    spinner.fail('You must specify the api, for example: \'make validate api=index type=request branch=main\'')
    process.exit(1)
  }

  if (!apis.includes(options.api)) {
    spinner.fail(`The api '${options.api}' does not exists, did you mean '${closest(options.api, apis)}'?`)
    process.exit(1)
  }
  // if the empty string it's because the make target wasn't configured with a type argument
  if (options.type !== '' && options.type !== 'request' && options.type !== 'response') {
    spinner.fail('You must specify the type (request or response), for example: \'make validate api=index type=request branch=main\'')
    process.exit(1)
  }

  if (options.branch === '') {
    spinner.fail('You must specify the branch, for example: \'make validate api=index type=request branch=main\'')
    process.exit(1)
  }


  const isFlightRecorderCloned = await $`[[ -d ${path.join(__dirname, '..', '..', 'clients-flight-recorder')} ]]`.exitCode === 0
  if (!isFlightRecorderCloned) {
    spinner.text = 'It looks like you didn\'t clone the flight recorder, doing that for you'
    await $`git clone https://github.com/elastic/clients-flight-recorder.git ${path.join(__dirname, '..', '..', 'clients-flight-recorder')}`
  } else if (isStale) {
    spinner.text = 'Pulling the latest flight recorder changes'
    cd(path.join(__dirname, '..', '..', 'clients-flight-recorder'))
    await $`git pull`
    cd(path.join(compilerPath, '..'))
  }

  const isCompilerInstalled = await $`[[ -d ${path.join(compilerPath, 'node_modules')} ]]`.exitCode === 0
  const isTsGeneratorInstalled = await $`[[ -d ${path.join(tsGeneratorPath, 'node_modules')} ]]`.exitCode === 0
  if (noCache || !isCompilerInstalled || !isTsGeneratorInstalled) {
    spinner.text = "It looks like you didn't install the project dependencies, doing that for you"
    await $`npm install --prefix ${compilerPath}`
    await $`npm install --prefix ${tsGeneratorPath}`
  }

  const isCloneEsInstalled = await $`[[ -d ${path.join(cloneEsPath, 'node_modules')} ]]`.exitCode === 0
  const isUploadRecordingInstalled = await $`[[ -d ${path.join(uploadRecordingsPath, 'node_modules')} ]]`.exitCode === 0
  const isTypesValidatorInstalled = await $`[[ -d ${path.join(tsValidationPath, 'node_modules')} ]]`.exitCode === 0

  if (noCache || !isCloneEsInstalled || !isUploadRecordingInstalled || !isTypesValidatorInstalled) {
    spinner.text = 'It looks like you didn\'t installed the flight recorder project dependencies, doing that for you'
    await $`npm install --prefix ${cloneEsPath}`
    await $`npm install --prefix ${uploadRecordingsPath}`
    await $`npm install --prefix ${tsValidationPath}`
  }

  const isCompilerBuilt = await $`[[ -d ${path.join(compilerPath, 'lib')} ]]`.exitCode === 0
  if (noCache || isStale || !isCompilerBuilt) {
    spinner.text = 'Optimizing the compiler'
    await $`npm run build --prefix ${compilerPath}`
  }

  const isTsGeneratorBuilt = await $`[[ -d ${path.join(tsGeneratorPath, 'lib')} ]]`.exitCode === 0
  if (noCache || isStale || !isTsGeneratorBuilt) {
    spinner.text = 'Optimizing the ts generator'
    await $`npm run build --prefix ${tsGeneratorPath}`
  }

  {
    spinner.text = 'Compiling specification'
    const Process = await nothrow($`npm run compile:specification --prefix ${compilerPath}`)
    if (Process.exitCode !== 0) {
      spinner.fail(removeHeader(Process.stdout))
      process.exit(1)
    }
  }

  {
    spinner.text = 'Generating schema'
    const Process = await nothrow($`node ${path.join(compilerPath, 'lib', 'index.js')} --spec ${specPath} --output ${outputPath}`)
    if (Process.exitCode !== 0) {
      spinner.fail(removeHeader(Process.stdout))
      console.log(Process.stderr)
      process.exit(1)
    }
  }

  {
    spinner.text = 'Generating typescript view'
    const Process = await nothrow($`node ${path.join(tsGeneratorPath, 'lib', 'index.js')}`)
    if (Process.exitCode !== 0) {
      spinner.fail(removeHeader(Process.toString()))
      process.exit(1)
    }
  }

  {
    spinner.text = 'Validating typescript view'
    const Process = await nothrow($`npm run validate-ts-view --prefix ${compilerPath}`)
    if (Process.exitCode !== 0) {
      spinner.fail(removeHeader(Process.toString()))
      process.exit(1)
    }
  }

  spinner.text = 'Running validations'

  const branchName = options.branch.startsWith('7.') ? '7.x' : options.branch

  if (noCache || isStale || metadata.branchName !== branchName) {
    metadata.lastRun = new Date()
    metadata.branchName = branchName

    spinner.text = 'Downloading recordings'
    await $`node ${path.join(uploadRecordingsPath, 'download.js')} --branch ${branchName} --git`

    spinner.text = 'Fetching artifacts'
    await $`node ${path.join(cloneEsPath, 'index.js')} --branch ${branchName}`
  }

  cd(tsValidationPath)
  spinner.text = 'Validating endpoints'
  // the ts validator will copy types.ts and schema.json autonomously
  const flags = ['--verbose']
  if (options.type === '') {
    flags.push('--request')
    flags.push('--response')
  } else {
    flags.push(`--${options.type}`)
  }
  const output = await $`node ${path.join(tsValidationPath, 'index.js')} --api ${options.api} --branch ${branchName} ${flags}`

  cd(path.join(compilerPath, '..'))
  if (output.exitCode === 0) {
    spinner.stop()
    console.log(output.toString())
  } else {
    spinner.fail(output.toString())
  }

  await writeFile(
    path.join(compilerPath, '..', '.validation.json'),
    JSON.stringify(metadata),
    'utf8'
  )
}