@sap/cds-dk
Version:
Command line client and development toolkit for the SAP Cloud Application Programming Model
131 lines (112 loc) • 4.32 kB
JavaScript
module.exports = Object.assign(up, {
options: ['--to', '--namespace'],
shortcuts: ['-2', '-n'],
flags: [],
help: `
# SYNOPSIS
*cds up*
Builds and deploys the application to Cloud Foundry or Kubernetes.
# OPTIONS
*-2* | *--to* cf|k8s
The platform to deploy to. Default is 'cf'.
*-n* | *--namespace* <name>
(Kubernetes only) Target namespace. If it does not yet exist it will be
created automatically via *helm --create-namespace*.
# EXAMPLES
*cds up*
*cds up --to k8s*
*cds up --to k8s --namespace e2e-tests*
`})
const { execSync, spawn } = require('node:child_process')
const cds = require('../lib/cds')
const { highlight, bold } = require('../lib/util/term')
const { exists, fs, path } = cds.utils
const { readProject } = require('../lib/init/projectReader')
const run = cmd => {
console.log(highlight(cmd))
try {
return execSync(cmd, {
stdio: 'inherit',
env: { ...process.env, FORCE_COLOR: cds.utils.colors.enabled }
})
} catch (error) {
throw error.message
}
}
const runDetectingError = async (cmd, errorRegex) => {
console.log(highlight(cmd))
return new Promise((resolve, reject) => {
const child = spawn(cmd, { shell: true, stdio: 'pipe' })
let out = '';
['stdout', 'stderr'].forEach(key => {
child[key].on('data', data => {
process[key].write(data.toString())
out += data.toString()
})
})
child.on('close', () => {
const error = out.match(errorRegex)
if (error) {
return reject('Error in command: ' + bold(cmd) + ' → exiting')
}
resolve(out)
})
})
}
async function up() {
const { apps, appName, hasApprouter, hasXsuaa } = readProject()
for (const { app } of apps) {
const appPath = path.join(cds.root, cds.env.folders.app, app)
if (exists(path.join(appPath, 'package.json')) && !exists(path.join(appPath, 'package-lock.json'))) {
run(`npm i --package-lock-only --prefix ${appPath}`)
}
}
if (exists('mtx/sidecar') && !exists('mtx/sidecar/package-lock.json')) {
run('npm i --package-lock-only --prefix mtx/sidecar')
}
if (exists('app/router/package.json') && !exists('app/router/package-lock.json')) {
run('npm i --package-lock-only --prefix app/router')
}
if (exists('app/portal/package.json') && !exists('app/portal/package-lock.json')) {
run('npm i --package-lock-only --prefix app/portal')
}
if (exists('app/html5-deployer/package.json') && !exists('app/html5-deployer/package-lock.json')) {
run('npm i --package-lock-only --prefix app/html5-deployer')
}
if (cds.cli.options.to === 'k8s') {
if (!exists('chart')) run('cds add helm')
if (!exists('containerize.yaml')) run('cds add containerize')
} else {
if (!exists('mta.yaml')) {
run('cds add mta')
}
if (!exists('package-lock.json')) {
run('npm i --package-lock-only')
}
}
const prefix = execSync('npm prefix', { encoding: 'utf8' }).trim()
if (prefix !== cds.root) {
const source = path.join(prefix, 'package-lock.json')
const target = path.join(process.cwd(), 'package-lock.json')
if (exists(target) || fs.lstatSync(target).isSymbolicLink()) fs.unlinkSync(target)
const relative = path.relative(process.cwd(), source)
fs.symlinkSync(relative, target, 'junction')
}
if (cds.cli.options.to === 'k8s') {
const ns = cds.cli.options.namespace
const nsHelm = ns ? `--namespace ${ns} --create-namespace` : ''
const nsKubectl = ns ? `-n ${ns}` : ''
run('npm i --package-lock')
await runDetectingError('ctz containerize.yaml --log --push', /^\[?ERROR\]?.*/m)
let helmUpgrade = `helm upgrade --install ${appName} ./gen/chart ${nsHelm} --wait --wait-for-jobs`
if (hasXsuaa) helmUpgrade += ' --set-file xsuaa.jsonParameters=xs-security.json'
run(helmUpgrade)
run(`kubectl rollout status deployment ${appName}-srv ${nsKubectl} --timeout=8m`)
if (hasApprouter) run(`kubectl rollout status deployment ${appName}-approuter ${nsKubectl} --timeout=8m`)
if (exists('mtx/sidecar')) run(`kubectl rollout status deployment ${appName}-sidecar ${nsKubectl} --timeout=8m`)
} else {
run('mbt build -t gen --mtar mta.tar')
const retries = process.env.CI ? '' : '--retries 0'
run(`cf deploy gen/mta.tar -f ${retries}`)
}
}