@sap/cds-dk 9.4.3 → 9.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 +77 -0
- package/bin/compile/index.js +1 -1
- package/bin/export.js +1 -1
- package/bin/help.js +0 -1
- package/bin/import.js +8 -3
- package/bin/repl.js +7 -11
- package/bin/up.js +150 -20
- package/bin/util/containerize.js +66 -25
- package/bin/version.js +4 -4
- package/lib/bind/k8s.js +1 -1
- package/lib/build/plugins/helm/files/templates/_deployment_helpers.tpl +1 -1
- package/lib/build/plugins/helm/index.js +1 -1
- package/lib/build/provider/hana/2migration.js +16 -24
- package/lib/build/provider/hana/index.js +1 -1
- package/lib/build/provider/hana/template/.hdiconfig-all +7 -1
- package/lib/build/provider/hana/template/package.json +1 -1
- package/lib/build/provider/internalBuildPlugin.js +15 -1
- package/lib/build/provider/java/index.js +12 -1
- package/lib/build/provider/mtx-sidecar/index.js +2 -1
- package/lib/build/provider/nodejs/index.js +2 -1
- package/lib/build/util.js +3 -3
- package/lib/compile/to_openapi.js +1 -5
- package/lib/import/common.js +2 -1
- package/lib/import/odata/ParserContext.js +1 -0
- package/lib/import/odata/v4parser.js +48 -3
- package/lib/import/openapi/importOpenAPI.js +6 -1
- package/lib/init/constants.js +1 -1
- package/lib/init/index.js +15 -6
- package/lib/init/merge.js +16 -0
- package/lib/init/projectReader.js +19 -4
- package/lib/init/registries/mta.js +2 -2
- package/lib/init/template/ams/index.js +1 -1
- package/lib/init/template/app-frontend/files/app-package.json.hbs +1 -7
- package/lib/init/template/app-frontend/files/ui5.yaml.hbs +20 -1
- package/lib/init/template/app-frontend/index.js +0 -4
- package/lib/init/template/application-logging/index.js +9 -14
- package/lib/init/template/approuter/files/mta.yaml.hbs +0 -2
- package/lib/init/template/approuter/index.js +6 -7
- package/lib/init/template/cloud-logging/index.js +2 -3
- package/lib/init/template/containerize/files/containerize.yaml.hbs +17 -2
- package/lib/init/template/containerize/index.js +0 -4
- package/lib/init/template/data/as-json.js +18 -20
- package/lib/init/template/dynatrace/index.js +0 -2
- package/lib/init/template/github-actions/files/workflows/cf.yaml.hbs +16 -1
- package/lib/init/template/github-actions/files/workflows/test.yaml.hbs +20 -0
- package/lib/init/template/github-actions/index.js +5 -8
- package/lib/init/template/hana/files/db/package.json +2 -2
- package/lib/init/template/hana/files/mta.yaml.hbs +0 -4
- package/lib/init/template/hana/index.js +3 -5
- package/lib/init/template/helm/index.js +2 -7
- package/lib/init/template/helm-unified-runtime/index.js +0 -4
- package/lib/init/template/html5-repo/files/app-package.json.hbs +1 -7
- package/lib/init/template/html5-repo/files/ui5.yaml.hbs +20 -1
- package/lib/init/template/html5-repo/index.js +6 -12
- package/lib/init/template/ias/files/values.yaml.hbs +6 -6
- package/lib/init/template/ias/index.js +12 -20
- package/lib/init/template/kyma/index.js +14 -1
- package/lib/init/template/malware-scanner/files/mta.yaml.hbs +3 -1
- package/lib/init/template/malware-scanner/files/values.yaml +3 -1
- package/lib/init/template/multitenancy/files/mta.yaml.hbs +1 -3
- package/lib/init/template/multitenancy/files/values.yaml.hbs +8 -0
- package/lib/init/template/multitenancy/index.js +8 -3
- package/lib/init/template/nodejs/files/package.json.hbs +1 -1
- package/lib/init/template/pipeline/files/app-package.json.hbs +1 -7
- package/lib/init/template/pipeline/files/ui5.yaml.hbs +20 -1
- package/lib/init/template/pipeline/index.js +1 -2
- package/lib/init/template/portal/files/mta.yaml.hbs +5 -3
- package/lib/init/template/portal/index.js +3 -6
- package/lib/init/template/sample/files/_i18n/i18n_de.properties +12 -0
- package/lib/init/template/sample/files/_i18n/i18n_en.properties +21 -0
- package/lib/init/template/sample/files/_i18n/i18n_fr.properties +20 -0
- package/lib/init/template/sample/files/_i18n/messages_de.properties +34 -0
- package/lib/init/template/sample/files/_i18n/messages_en.properties +34 -0
- package/lib/init/template/sample/files/_i18n/messages_fr.properties +34 -0
- package/lib/init/template/sample/files/app/_i18n/i18n_de.properties +0 -26
- package/lib/init/template/sample/files/app/_i18n/i18n_en.properties +8 -0
- package/lib/init/template/sample/files/app/admin-authors/fiori-service.cds +52 -0
- package/lib/init/template/sample/files/app/admin-authors/webapp/Component.js.hbs +3 -0
- package/lib/init/template/sample/files/app/admin-authors/webapp/i18n/i18n.properties +11 -0
- package/lib/init/template/sample/files/app/admin-authors/webapp/manifest.json +130 -0
- package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +81 -88
- package/lib/init/template/sample/files/app/admin-books/webapp/Component.js.hbs +3 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n.properties +10 -2
- package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +24 -48
- package/lib/init/template/sample/files/app/appconfig/fioriSandboxConfig.json +54 -3
- package/lib/init/template/sample/files/app/browse/fiori-service.cds +30 -30
- package/lib/init/template/sample/files/app/browse/webapp/Component.js.hbs +3 -0
- package/lib/init/template/sample/files/app/browse/webapp/i18n/i18n.properties +10 -3
- package/lib/init/template/sample/files/app/browse/webapp/manifest.json +18 -23
- package/lib/init/template/sample/files/app/common.cds +126 -158
- package/lib/init/template/sample/files/app/fiori-apps.html +30 -0
- package/lib/init/template/sample/files/app/genres/fiori-service.cds +33 -0
- package/lib/init/template/sample/files/app/genres/tree-view.cds +42 -0
- package/lib/init/template/sample/files/app/genres/value-help.cds +6 -0
- package/lib/init/template/sample/files/app/genres/webapp/Component.js.hbs +3 -0
- package/lib/init/template/sample/files/app/genres/webapp/i18n/i18n.properties +4 -0
- package/lib/init/template/sample/files/app/genres/webapp/i18n/i18n_de.properties +2 -0
- package/lib/init/template/sample/files/app/genres/webapp/manifest.json +126 -0
- package/lib/init/template/sample/files/app/services.cds +6 -2
- package/lib/init/template/sample/files/db/currencies.cds +13 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Books.csv +5 -5
- package/lib/init/template/sample/files/db/data/{sap.capire.bookshop-Books_texts.csv → sap.capire.bookshop-Books.texts.csv} +4 -4
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Genres.csv +42 -15
- package/lib/init/template/sample/files/db/data/sap.common-Currencies.csv +12 -0
- package/lib/init/template/sample/files/db/data/sap.common-Currencies.texts.csv +15 -0
- package/lib/init/template/sample/files/db/hana/index.cds +10 -0
- package/lib/init/template/sample/files/db/schema.cds +35 -22
- package/lib/init/template/sample/files/db/sqlite/index.cds +10 -0
- package/lib/init/template/sample/files/package.json.hbs +14 -1
- package/lib/init/template/sample/files/srv/access-control.cds +3 -0
- package/lib/init/template/sample/files/srv/admin-service.cds +3 -2
- package/lib/init/template/sample/files/srv/cat-service.cds +7 -11
- package/lib/init/template/sample/index.js +26 -17
- package/lib/init/template/telemetry/index.js +1 -3
- package/lib/init/template/typescript/files/package.json +1 -1
- package/lib/init/template/workzone-standard/files/mta.yaml.hbs +0 -5
- package/lib/init/template/workzone-standard/index.js +0 -1
- package/lib/init/template/xsuaa/files/mta.yaml.hbs +4 -0
- package/lib/init/template/xsuaa/index.js +3 -5
- package/lib/lint/Linter.js +10 -4
- package/lib/lint/eslintHelp.json +1 -1
- package/lib/mtx/tenant_action.js +12 -4
- package/lib/util/checksum.js +32 -0
- package/lib/util/question.js +60 -7
- package/npm-shrinkwrap.json +59 -35
- package/package.json +2 -2
- package/lib/init/template/app-frontend/files/ui5-deploy.yaml.hbs +0 -25
- package/lib/init/template/github-actions/files/cf-setup/action.yaml +0 -53
- package/lib/init/template/html5-repo/files/ui5-deploy.yaml.hbs +0 -25
- package/lib/init/template/pipeline/files/ui5-deploy.yaml.hbs +0 -25
- package/lib/init/template/sample/files/app/_i18n/i18n.properties +0 -29
- package/lib/init/template/sample/files/app/admin-books/webapp/Component.js +0 -8
- package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n_de.properties +0 -3
- package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n_en.properties +0 -3
- package/lib/init/template/sample/files/app/browse/webapp/Component.js +0 -7
- package/lib/init/template/sample/files/app/browse/webapp/i18n/i18n_de.properties +0 -3
- package/lib/init/template/sample/files/app/browse/webapp/i18n/i18n_en.properties +0 -4
- package/lib/init/template/sample/files/app/index.html +0 -32
package/CHANGELOG.md
CHANGED
|
@@ -6,17 +6,58 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
6
6
|
|
|
7
7
|
The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
8
8
|
|
|
9
|
+
## Version 9.5.0 - 2025-12-01
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- `cds import` now accepts `--into-namespace <string>` to override the namespace entities are imported to, when importing OpenAPI definitions.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- `cds add portal` adds the correct service key configuration to the _mta.yaml_.
|
|
18
|
+
- `cds add sample` creates sample files aligned with recent versions of bookshop and bookstore in https://github.com/capire.
|
|
19
|
+
- `cds add sample` uses a matching ID in generated `manifest.json` and UI5 components.
|
|
20
|
+
- `cds build` uses `hdblogicalschema` and `hdblogicalschemaconfig` plugins in its default `.hdiconfig`.
|
|
21
|
+
- `cds add cloud-logging` adds required dependencies to _pom.xml_ for Java projects.
|
|
22
|
+
- `cds add kyma` is now the only suggested Kyma facet in `cds add help`.
|
|
23
|
+
- `cds add helm-unified-runtime` option is now deprecated; use `cds add kyma --unified-runtime` instead.
|
|
24
|
+
- `cds up --to k8s` now saves the checksum of buildpack images to determine if a rebuild is necessary.
|
|
25
|
+
- `cds up --to k8s` will interactively ask for registry credentials if they don't exist on the remote cluster.
|
|
26
|
+
- `cds build` automatically adds `contentLocalizedEdmx=true` to the java build task configuration if OData V2 is set.
|
|
27
|
+
- `cds add github-actions` has out-of-the-box support for Java projects.
|
|
28
|
+
- `cds add html5-repo` and `cds add app-frontend` do not create a separate _ui5-deploy.yaml_ but use the default _ui5.yaml_.
|
|
29
|
+
- `cds add` plugins allow merging into non-existing files with `cds.add.merge(<object>).into(<yaml-path>)`.
|
|
30
|
+
- `cds build` tasks that produce `csn.json` now emit the `compile.for.runtime` event, in alignment with other runtime CSN producers like `cds serve`. Plugins can use such events to hook into CSN creation.
|
|
31
|
+
- `cds add xsuaa` sets `credential-types: [ "binding-secret", "x509" ]` for XSUAA instances.
|
|
32
|
+
- `cds add hana` does not create an explicit `.hdiconfig` file any more as `cds build` provides defaults.
|
|
33
|
+
- `cds import` generates the on condition for a composition when the corresponding OData navigation property targets a collection, is contained (`$ContainsTarget` in OData EDM) and has a backlink (`$Partner` in OData EDM).
|
|
34
|
+
- `cds import` now considers OData contained navigation properties as compositions instead of associations.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- `cds add ias` will always add a binding to the MTX sidecar or approuter if required.
|
|
39
|
+
- `cds add ias` has improved support for multitenancy scenarios on Kyma.
|
|
40
|
+
- `cds lint` no longer fails with error code 1 and no message when loading the config fails.
|
|
41
|
+
- `cds version` no longer prints an `undefined` value for `@sap/cds-dk`.
|
|
42
|
+
- `cds compile --flavor files` no longer crashes with a `TypeError`.
|
|
43
|
+
- `cds add workzone` does not add superfluous `destinations` configuration to the `srv-api` import.
|
|
44
|
+
|
|
9
45
|
## Version 9.4.3 - 2025-10-29
|
|
10
46
|
|
|
47
|
+
### Added
|
|
48
|
+
|
|
11
49
|
### Changed
|
|
12
50
|
|
|
51
|
+
- `cds add github-actions` will use the `cap-js/cf-setup` action from GitHub marketplace instead of creating a local copy.
|
|
13
52
|
- `cds add containerize` omits the Unix-based `before_all` scripts in `containerize.yaml` in favor of a cross-platform compatible `cds up --to k8s` integration.
|
|
14
53
|
- `cds up --to k8s` now uses built-in containerization, eliminating the hard dependency on the `ctz` library.
|
|
15
54
|
- `cds up --to k8s` will interactively ask for a domain if it can't be determined from the current Kubernetes configuration.
|
|
16
55
|
- `cds build --for hana` no longer requires `.hdbgrants` and `.hdbrevokes` to be specified as a plugin in the `.hdiconfig` file.
|
|
56
|
+
- `cds import` no longer emits usage info when invoked with the dry option.
|
|
17
57
|
|
|
18
58
|
### Fixed
|
|
19
59
|
|
|
60
|
+
- `cds add data` fixes an issue where randomly generated `Decimal` and `Integer` values could exceed their defined precision or scale.
|
|
20
61
|
- `cds add pipeline` does not add UI5 template files in some cases.
|
|
21
62
|
- `cds add ias` does not write to the `mta.yaml` for non-MTA projects.
|
|
22
63
|
- `cds add ias` automatically adds the `authenticationType` to `xs-app.json` if required.
|
|
@@ -40,6 +81,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
|
40
81
|
- `cds add test` creates correct OData URLs with unqualified entity names in service paths.
|
|
41
82
|
- `cds add http` skips contained composition targets.
|
|
42
83
|
- `cds add sample` no longer comes with an error when creating a Book through Fiori.
|
|
84
|
+
- `cds build` now places the `i18n` folder in the generated output root directory instead of nested locations.
|
|
43
85
|
|
|
44
86
|
## Version 9.4.1 - 2025-10-09
|
|
45
87
|
|
|
@@ -330,6 +372,41 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
|
|
|
330
372
|
- `cds add ams` for Java adds a custom builder to the `mta.yaml` to circumvent the missing `srv/src/gen/policies`.
|
|
331
373
|
- `cds add multitenancy` requires the `srv-api` instead of the `mtx-api` for Java projects.
|
|
332
374
|
|
|
375
|
+
## Version 8.9.11 - 2025-11-21
|
|
376
|
+
|
|
377
|
+
### Fixed
|
|
378
|
+
|
|
379
|
+
- Bump dependencies in shrinkwrap.
|
|
380
|
+
|
|
381
|
+
## Version 8.9.10 - 2025-09-19
|
|
382
|
+
|
|
383
|
+
### Fixed
|
|
384
|
+
|
|
385
|
+
- Updated shrinkwrap to include `@sap/cds-compiler` version 5.9.12.
|
|
386
|
+
|
|
387
|
+
## Version 8.9.9 - 2025-09-16
|
|
388
|
+
|
|
389
|
+
### Fixed
|
|
390
|
+
|
|
391
|
+
- CVE-2025-58754: vulnerability with `axios` versions <1.12.0.
|
|
392
|
+
|
|
393
|
+
## Version 8.9.8 - 2025-07-24
|
|
394
|
+
|
|
395
|
+
### Fixed
|
|
396
|
+
|
|
397
|
+
- CVE-2025-7783: vulnerability with `form-data` versions <4.0.4.
|
|
398
|
+
|
|
399
|
+
## Version 8.9.7 - 2025-07-17
|
|
400
|
+
|
|
401
|
+
### Fixed
|
|
402
|
+
|
|
403
|
+
- Bump dependencies in shrinkwrap.
|
|
404
|
+
|
|
405
|
+
## Version 8.9.6 - 2025-06-05
|
|
406
|
+
|
|
407
|
+
### Fixed
|
|
408
|
+
|
|
409
|
+
- Bump dependencies in shrinkwrap.
|
|
333
410
|
|
|
334
411
|
## Version 8.9.5 - 2025-06-05
|
|
335
412
|
|
package/bin/compile/index.js
CHANGED
|
@@ -297,7 +297,7 @@ async function compile (models, options={}) {
|
|
|
297
297
|
throw `You must specify a model to compile.\nRun 'cds c -?' to learn more.`
|
|
298
298
|
}
|
|
299
299
|
|
|
300
|
-
let chain = model.then (m => model=m)
|
|
300
|
+
let chain = model.then?. (m => model=m) ?? Promise.resolve(model) // model could be a sync. value
|
|
301
301
|
|
|
302
302
|
// add processors for compiling
|
|
303
303
|
if (options.for) for (let each of options.for.split(',')) {
|
package/bin/export.js
CHANGED
|
@@ -111,7 +111,7 @@ class Export extends Minify {
|
|
|
111
111
|
async export (minified,o) {
|
|
112
112
|
if (this.options.to === '-') return super.print (minified)
|
|
113
113
|
if (this.options.to.endsWith('/*')) this.options.to = this.export_to()
|
|
114
|
-
console.log(`\n${this.name}ing APIs to`, this.options.to, '...\n')
|
|
114
|
+
console.log(`\n${this.name}ing APIs to`, cds.utils.local(this.options.to), '...\n')
|
|
115
115
|
const exports = []; exports.push(...this.export_models (minified))
|
|
116
116
|
if (o.texts) exports.push (...this.export_texts (minified))
|
|
117
117
|
if (o.data) exports.push (this.export_data (minified))
|
package/bin/help.js
CHANGED
|
@@ -12,7 +12,6 @@ module.exports = exports = Object.assign (help, {formatHelp, handleCompletion, h
|
|
|
12
12
|
|
|
13
13
|
*i* | *init* jump-start cds-based projects
|
|
14
14
|
*a* | *add* add a feature to an existing project
|
|
15
|
-
* * | *gen* generate models/data using a descriptive prompt [beta]
|
|
16
15
|
*m* | *import* add models from external sources
|
|
17
16
|
*c* | *compile* compile cds models to different outputs
|
|
18
17
|
*p* | *parse* parses given cds models
|
package/bin/import.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module.exports = Object.assign(_import, {
|
|
2
2
|
_name: 'import',
|
|
3
|
-
options: [ '--services', '--for', '--out', '--as', '--name', '--include-namespaces', '--dependencies', '--from', '--config', '--destination', '--group', '--data-product' ],
|
|
4
|
-
shortcuts: [ '-s',
|
|
3
|
+
options: [ '--services', '--for', '--out', '--as', '--name', '--include-namespaces', '--dependencies', '--from', '--config', '--destination', '--group', '--into-namespace', '--data-product' ],
|
|
4
|
+
shortcuts: [ '-s', '-4', '-o', '-as', '-n', '-ns', '-d',undefined, '-c', undefined, undefined, '-2', '-', '-f'],
|
|
5
5
|
flags: [ '--dry', '--force', '--no-copy', '--no-save', '--keep-namespace', '--data-product', '--edmx', '--rfc', '--odata', '--openapi', '--asyncapi' ],
|
|
6
6
|
help: `
|
|
7
7
|
# SYNOPSIS
|
|
@@ -56,10 +56,15 @@ module.exports = Object.assign(_import, {
|
|
|
56
56
|
Not supported by import types "edmx", "openapi" or "asyncapi".
|
|
57
57
|
|
|
58
58
|
*--data-product*
|
|
59
|
-
Tells cds import to import a data product. The source must be a valid
|
|
59
|
+
Tells cds import to import a data product. The source must be a valid
|
|
60
60
|
data product CSN file, e.g. as found on http://api.sap.com/dataproducts.
|
|
61
61
|
(Not released with general availability yet)
|
|
62
62
|
|
|
63
|
+
*-2 | --into-namespace* <string>
|
|
64
|
+
Specifies a custom namespace to be used for the imported service.
|
|
65
|
+
This will override the namespace that was specified via the the
|
|
66
|
+
@title annotation of the original service.
|
|
67
|
+
|
|
63
68
|
*Below options are valid for OData only*
|
|
64
69
|
|
|
65
70
|
*--keep-namespace*
|
package/bin/repl.js
CHANGED
|
@@ -35,7 +35,7 @@ module.exports = Object.assign (repl, {
|
|
|
35
35
|
*cds eval* to evaluate and execute JavaScript.
|
|
36
36
|
`})
|
|
37
37
|
|
|
38
|
-
async function repl (
|
|
38
|
+
async function repl ([project], options={}) {
|
|
39
39
|
|
|
40
40
|
const GREEN = '\x1b[32m', RESET = '\x1b[0m'
|
|
41
41
|
const cds = require('../lib/cds')
|
|
@@ -46,9 +46,9 @@ async function repl (_, options={}) {
|
|
|
46
46
|
inspect.defaultOptions.depth = 11
|
|
47
47
|
|
|
48
48
|
Object.defineProperty (cds,'repl',{value:true})
|
|
49
|
-
await cds.service.bindings
|
|
49
|
+
await cds.service.bindings // REVISIT: this pre-populates many of the cds facade's lazy properties
|
|
50
50
|
let context={}, repl = { context, displayPrompt(){} }
|
|
51
|
-
if (options.run) await _run (options.run)
|
|
51
|
+
if ((options.run ??= project)) await _run (options.run)
|
|
52
52
|
if (options.use) _export (...options.use.split(','))
|
|
53
53
|
|
|
54
54
|
repl = require('repl').start ({
|
|
@@ -94,14 +94,10 @@ async function repl (_, options={}) {
|
|
|
94
94
|
process.on = (event, listener) => event !== 'uncaughtException' && event !== 'unhandledRejection' && process.addListener(event, listener)
|
|
95
95
|
|
|
96
96
|
async function _run (project) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
} catch (e) {
|
|
102
|
-
if (e.code !== 'MODULE_NOT_FOUND') throw e
|
|
103
|
-
await cds.exec ('--project', project, '--port', '0', '--in-memory?')
|
|
104
|
-
}
|
|
97
|
+
await require('../bin/serve') ([project], { project, port: 0,
|
|
98
|
+
'in-memory?': true,
|
|
99
|
+
'with-mocks': true
|
|
100
|
+
})
|
|
105
101
|
_export ('entities', 'services')
|
|
106
102
|
}
|
|
107
103
|
|
package/bin/up.js
CHANGED
|
@@ -28,28 +28,77 @@ module.exports = Object.assign(up, {
|
|
|
28
28
|
`})
|
|
29
29
|
|
|
30
30
|
const { execSync } = require('node:child_process')
|
|
31
|
+
const { tmpdir } = require('node:os')
|
|
32
|
+
const crypto = require('node:crypto')
|
|
31
33
|
const cds = require('../lib/cds')
|
|
32
|
-
const { highlight } = require('../lib/util/term')
|
|
33
|
-
const { exists, fs, path, path: { join } } = cds.utils
|
|
34
|
+
const { highlight, warn, dim } = require('../lib/util/term')
|
|
35
|
+
const { exists, fs, path, path: { join }, read, write } = cds.utils
|
|
36
|
+
const { ask4 } = require('../lib/util/question')
|
|
34
37
|
const { readProject } = require('../lib/init/projectReader')
|
|
35
38
|
const { mkdirp, copy } = cds.utils
|
|
36
39
|
const { containerize } = require('../bin/util/containerize')
|
|
40
|
+
const { calcDirChecksum } = require('../lib/util/checksum')
|
|
37
41
|
|
|
38
|
-
const
|
|
39
|
-
|
|
42
|
+
const DEBUG = /\b(y|all|cli)\b/.test(process.env.DEBUG) ? console.debug : undefined
|
|
43
|
+
|
|
44
|
+
const run = (cmd, { continueOnFail = false, silent = false } = {}) => {
|
|
45
|
+
const redactedCmd = cmd.replace(/(--docker-password=)(['"]?)[^'"\s]+(['"]?)/, '$1[REDACTED]$3')
|
|
46
|
+
console.log(highlight(redactedCmd))
|
|
40
47
|
try {
|
|
41
48
|
return execSync(cmd, {
|
|
42
|
-
stdio: 'inherit',
|
|
49
|
+
stdio: silent ? 'pipe' : 'inherit',
|
|
43
50
|
env: { ...process.env, FORCE_COLOR: cds.utils.colors.enabled }
|
|
44
51
|
})
|
|
45
52
|
} catch (error) {
|
|
53
|
+
if (continueOnFail) {
|
|
54
|
+
if (!silent)
|
|
55
|
+
console.error(error.message)
|
|
56
|
+
return
|
|
57
|
+
}
|
|
46
58
|
throw error.message
|
|
47
59
|
}
|
|
48
60
|
}
|
|
49
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Get or create checksum file path in temp directory for UI5 apps
|
|
64
|
+
* @param {string} appName - The name of the app
|
|
65
|
+
* @returns {string} - Path to checksum file in temp directory
|
|
66
|
+
*/
|
|
67
|
+
function getChecksumFilePath(appName) {
|
|
68
|
+
const projectHash = crypto.createHash('md5').update(cds.root).digest('hex').substring(0, 8)
|
|
69
|
+
return join(tmpdir(), `cds-ui5-checksum-${projectHash}-${appName}.txt`)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Read stored checksum for an app from temp directory
|
|
74
|
+
* @param {string} appName - The name of the app
|
|
75
|
+
* @returns {string|null} - The stored checksum or null if not found
|
|
76
|
+
*/
|
|
77
|
+
function readStoredChecksum(appName) {
|
|
78
|
+
const checksumFile = getChecksumFilePath(appName)
|
|
79
|
+
if (exists(checksumFile)) {
|
|
80
|
+
try {
|
|
81
|
+
return fs.readFileSync(checksumFile, 'utf-8').trim()
|
|
82
|
+
} catch (e) {
|
|
83
|
+
// Ignore read errors and assume no checksum is stored
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return null
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Write checksum for an app to temp directory
|
|
91
|
+
* @param {string} appName - The name of the app
|
|
92
|
+
* @param {string} checksum - The checksum to store
|
|
93
|
+
*/
|
|
94
|
+
function writeStoredChecksum(appName, checksum) {
|
|
95
|
+
const checksumFile = getChecksumFilePath(appName)
|
|
96
|
+
fs.writeFileSync(checksumFile, checksum, 'utf-8')
|
|
97
|
+
}
|
|
98
|
+
|
|
50
99
|
async function up() {
|
|
51
100
|
const project = readProject()
|
|
52
|
-
const { apps, appName, hasApprouter, hasXsuaa, isMonorepoMicroservice } = project
|
|
101
|
+
const { apps, appName, hasApprouter, hasXsuaa, isMonorepoMicroservice, k8s } = project
|
|
53
102
|
|
|
54
103
|
const html5DeployerPath = join(cds.root, cds.env.folders.app, 'html5-deployer', 'resources')
|
|
55
104
|
|
|
@@ -82,18 +131,37 @@ async function up() {
|
|
|
82
131
|
}
|
|
83
132
|
|
|
84
133
|
if (cds.cli.options.to === 'k8s') {
|
|
85
|
-
if (!exists('chart')) run('cds add
|
|
86
|
-
if (apps.length > 0) {
|
|
87
|
-
await mkdirp(html5DeployerPath)
|
|
88
|
-
}
|
|
134
|
+
if (!exists('chart') || !exists('containerize.yaml')) run('cds add kyma')
|
|
89
135
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
136
|
+
if (project.hasHtml5Repo) {
|
|
137
|
+
if (apps.length > 0) {
|
|
138
|
+
await mkdirp(html5DeployerPath)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
for (const { app } of apps) {
|
|
142
|
+
const appPath = path.join(cds.root, cds.env.folders.app, app)
|
|
143
|
+
const zipPath = path.join(appPath, `dist/${app}.zip`)
|
|
144
|
+
|
|
145
|
+
// Calculate checksum for the app source folder (excluding node_modules and dist)
|
|
146
|
+
const currentChecksum = await calcDirChecksum(
|
|
147
|
+
appPath,
|
|
148
|
+
(dir) => !dir.includes('node_modules') && !dir.includes('dist')
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
const storedChecksum = readStoredChecksum(app)
|
|
152
|
+
const needsBuild = currentChecksum !== storedChecksum || !exists(zipPath)
|
|
153
|
+
|
|
154
|
+
if (needsBuild) {
|
|
155
|
+
DEBUG?.(dim(`build required for '${app}' – checksums`, { old: storedChecksum, new: currentChecksum }))
|
|
156
|
+
run(`npm run build --prefix ${appPath}`)
|
|
157
|
+
writeStoredChecksum(app, currentChecksum)
|
|
158
|
+
} else {
|
|
159
|
+
console.log(highlight(`Skipping build for UI5 app '${app}' - no changes detected (checksum: ${currentChecksum.substring(0, 8)}...)`))
|
|
160
|
+
}
|
|
95
161
|
|
|
96
|
-
|
|
162
|
+
await copy(zipPath).to(html5DeployerPath, `${app}.zip`)
|
|
163
|
+
}
|
|
164
|
+
}
|
|
97
165
|
} else {
|
|
98
166
|
if (!exists('mta.yaml')) {
|
|
99
167
|
run('cds add mta')
|
|
@@ -114,16 +182,78 @@ async function up() {
|
|
|
114
182
|
|
|
115
183
|
if (cds.cli.options.to === 'k8s') {
|
|
116
184
|
const ns = cds.cli.options.namespace
|
|
117
|
-
const nsHelm = ns ? `--namespace ${ns}
|
|
185
|
+
const nsHelm = ns ? `--namespace ${ns}` : ''
|
|
118
186
|
const nsKubectl = ns ? `-n ${ns}` : ''
|
|
119
187
|
|
|
120
188
|
run('npm i --package-lock')
|
|
121
189
|
run('cds build --production')
|
|
122
|
-
|
|
123
|
-
|
|
190
|
+
|
|
191
|
+
if (ns) {
|
|
192
|
+
const k8sNamespaceResult = run(`kubectl get namespace ${ns} -o jsonpath="{.metadata.name}"`, { continueOnFail: true, silent: true })
|
|
193
|
+
if (!k8sNamespaceResult) {
|
|
194
|
+
run(`kubectl create namespace ${ns}`)
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const isValidDomain = str => /^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(str)
|
|
199
|
+
const { image, imagePullSecret } = k8s.values.global ?? {}
|
|
200
|
+
let registry = image?.registry
|
|
201
|
+
if (!process.env.CI) {
|
|
202
|
+
if (!registry || !isValidDomain(registry)) {
|
|
203
|
+
const valuesPath = 'chart/values.yaml'
|
|
204
|
+
const [yn] = await ask4([warn(`invalid registry server '${registry}' detected, override in ${valuesPath}? (Y/n)`)])
|
|
205
|
+
if (yn?.toLowerCase() !== 'y' || process.env.CI) {
|
|
206
|
+
throw `registry parameter is invalid, please specify it in ${valuesPath}`
|
|
207
|
+
} else {
|
|
208
|
+
registry = image.registry = await ask4(['registry server (e.g. index.docker.io): '])
|
|
209
|
+
const values = (await read(valuesPath)).replace(/(registry:\s*).*/, `$1${registry}`)
|
|
210
|
+
await write(values).to(valuesPath)
|
|
211
|
+
|
|
212
|
+
const containerize = (await read('containerize.yaml')).replace(/(repository:\s*).*/, `$1${registry}`)
|
|
213
|
+
await write(containerize).to('containerize.yaml')
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (imagePullSecret?.name) {
|
|
217
|
+
const imagePullSecretResult = run(`kubectl get secret ${imagePullSecret.name} ${nsKubectl} -o jsonpath="{.metadata.name}"`, { continueOnFail: true, silent: true })
|
|
218
|
+
if (!imagePullSecretResult) {
|
|
219
|
+
const yn = await ask4([`image pull secret '${imagePullSecret.name}' not found in namespace '${ns || 'default'}' – do you want to create it? (Y/n) `])
|
|
220
|
+
if (yn?.toLowerCase() !== 'y' || process.env.CI) {
|
|
221
|
+
throw `image pull secret '${imagePullSecret.name}' is required to pull images from the registry`
|
|
222
|
+
} else {
|
|
223
|
+
const [username, email] = await ask4([
|
|
224
|
+
'registry username: ',
|
|
225
|
+
'registry email: ',
|
|
226
|
+
])
|
|
227
|
+
const password = await ask4(['registry password: '], { redacted: true })
|
|
228
|
+
run(`kubectl create secret docker-registry ${imagePullSecret.name} ${nsKubectl} --docker-server=${registry} --docker-username=${username} --docker-password='${password}' --docker-email=${email}`)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const modules = await containerize()
|
|
235
|
+
const helmArgs = []
|
|
236
|
+
modules?.forEach(m => {
|
|
237
|
+
if (m.path === 'gen/srv') {
|
|
238
|
+
helmArgs.push(`--set srv.annotations.deployment.deployment-checksum=${m.checksum}`)
|
|
239
|
+
}
|
|
240
|
+
if (m.path === 'app/router') {
|
|
241
|
+
helmArgs.push(`--set approuter.annotations.deployment.deployment-checksum=${m.checksum}`)
|
|
242
|
+
}
|
|
243
|
+
if (m.path === 'app/html5-deployer') {
|
|
244
|
+
helmArgs.push(`--set html5-apps-deployer.annotations.job.job-checksum=${m.checksum}`)
|
|
245
|
+
}
|
|
246
|
+
if (m.path === 'gen/db') {
|
|
247
|
+
helmArgs.push(`--set hana-deployer.annotations.job.job-checksum=${m.checksum}`)
|
|
248
|
+
}
|
|
249
|
+
if (m.path === 'gen/mtx/sidecar') {
|
|
250
|
+
helmArgs.push(`--set sidecar.annotations.deployment.deployment-checksum=${m.checksum}`)
|
|
251
|
+
}
|
|
252
|
+
})
|
|
124
253
|
|
|
125
254
|
let helmUpgrade = `helm upgrade --install ${appName} ./gen/chart ${nsHelm} --wait --wait-for-jobs --timeout=10m`
|
|
126
|
-
if (hasXsuaa)
|
|
255
|
+
if (hasXsuaa) helmArgs.push(' --set-file xsuaa.jsonParameters=xs-security.json')
|
|
256
|
+
if (helmArgs.length > 0) helmUpgrade += ` ${helmArgs.join(' ')}`
|
|
127
257
|
run(helmUpgrade)
|
|
128
258
|
run(`kubectl rollout status deployment ${appName}-srv ${nsKubectl} --timeout=8m`)
|
|
129
259
|
if (hasApprouter) run(`kubectl rollout status deployment ${appName}-approuter ${nsKubectl} --timeout=8m`)
|
package/bin/util/containerize.js
CHANGED
|
@@ -2,7 +2,8 @@ const cds = require('../../lib/cds')
|
|
|
2
2
|
const { path } = cds.utils
|
|
3
3
|
const { join } = path
|
|
4
4
|
const { execSync } = require('node:child_process')
|
|
5
|
-
const { highlight } = require('../../lib/util/term')
|
|
5
|
+
const { highlight, info } = require('../../lib/util/term')
|
|
6
|
+
const { calcDirChecksum } = require('../../lib/util/checksum')
|
|
6
7
|
|
|
7
8
|
const buildpacks = new Set([
|
|
8
9
|
'java', 'nodejs', 'sap-machine', 'executable-jar', 'spring-boot', 'syft'
|
|
@@ -17,15 +18,20 @@ const keyProcessorMap = {
|
|
|
17
18
|
buildpack: processBuildpack
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
const run = cmd => {
|
|
21
|
+
const run = (cmd, { continueOnFail = false, silent = false } = {}) => {
|
|
21
22
|
cmd = Array.isArray(cmd) ? cmd.join(' ') : cmd
|
|
22
23
|
console.log(highlight(cmd))
|
|
23
24
|
try {
|
|
24
25
|
return execSync(cmd, {
|
|
25
|
-
stdio: 'inherit',
|
|
26
|
+
stdio: silent ? 'pipe' : 'inherit',
|
|
26
27
|
env: { ...process.env, FORCE_COLOR: cds.utils.colors.enabled }
|
|
27
28
|
})
|
|
28
29
|
} catch (error) {
|
|
30
|
+
if (continueOnFail) {
|
|
31
|
+
if (!silent)
|
|
32
|
+
console.error(error.message)
|
|
33
|
+
return
|
|
34
|
+
}
|
|
29
35
|
throw error.message
|
|
30
36
|
}
|
|
31
37
|
}
|
|
@@ -72,41 +78,57 @@ function processBuildpack(bp, name, tag, clearCache = false) {
|
|
|
72
78
|
* @param {string} filename - The path to the YAML file to parse.
|
|
73
79
|
* @param {string} [repoOpt=''] - Optional repository override. If not provided, uses the repository defined in the YAML file.
|
|
74
80
|
* @param {boolean} [clearCache=false] - Whether to clear cache for buildpack builds.
|
|
75
|
-
* @returns {{
|
|
81
|
+
* @returns {Promise<{
|
|
76
82
|
* commands: Array<{
|
|
77
83
|
* name: string,
|
|
78
84
|
* tag: string,
|
|
79
85
|
* buildCmd: Array<string>,
|
|
80
86
|
* tagCmd: Array<string>,
|
|
81
|
-
* pushCmd: Array<string
|
|
87
|
+
* pushCmd: Array<string>,
|
|
88
|
+
* image: string,
|
|
89
|
+
* checksum: string|null
|
|
90
|
+
* path: string
|
|
82
91
|
* }>,
|
|
83
92
|
* before_all: Array<Array<string>>,
|
|
84
93
|
* repository: string
|
|
85
|
-
* }} An object containing the commands for each module, any global pre-commands, and the repository name.
|
|
94
|
+
* }>} An object containing the commands for each module, any global pre-commands, and the repository name.
|
|
86
95
|
* @throws {Error} If modules are not defined in the YAML file or if build-parameters are invalid.
|
|
87
96
|
*/
|
|
88
|
-
function parseYAML(filename, repoOpt = '', options) {
|
|
97
|
+
async function parseYAML(filename, repoOpt = '', options) {
|
|
89
98
|
const file = cds.load.yaml(join(cds.root, filename))
|
|
90
99
|
const { repository: repoFile, modules, tag: globalTag = 'latest' } = file
|
|
91
100
|
const repository = repoOpt || repoFile
|
|
92
101
|
const before_all = file['before-all'] ? file['before-all'].map(c => c.trim().split(' ')) : []
|
|
93
|
-
if (!modules) throw
|
|
94
|
-
|
|
95
|
-
const commands = modules.map(m => {
|
|
102
|
+
if (!modules) throw `no modules defined in ${filename}`
|
|
103
|
+
const commands = await Promise.all(modules.map(async (m) => {
|
|
96
104
|
const name = m.name, tag = m.tag || globalTag, bp = m['build-parameters']
|
|
97
|
-
const source = `${name}:${tag}`, repoImg = `${repository}/${source}`
|
|
105
|
+
const rawImg = `${repository}/${name}`, source = `${name}:${tag}`, repoImg = `${repository}/${source}`
|
|
98
106
|
const key = Object.keys(bp)[0]
|
|
107
|
+
let checksum = null
|
|
108
|
+
if (bp.buildpack?.path)
|
|
109
|
+
checksum = await calcDirChecksum(
|
|
110
|
+
join(cds.root, bp.buildpack.path),
|
|
111
|
+
(dir) => !dir.includes('node_modules'),
|
|
112
|
+
'sha256',
|
|
113
|
+
[
|
|
114
|
+
join(cds.root, filename),
|
|
115
|
+
join(cds.root, 'package.json')
|
|
116
|
+
]
|
|
117
|
+
)
|
|
99
118
|
const buildType = keyProcessorMap[key]
|
|
100
|
-
|
|
119
|
+
|
|
120
|
+
if (!buildType) throw `'build-parameters' ${Object.keys(bp)} in ${filename} is invalid`
|
|
101
121
|
return {
|
|
102
|
-
name,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
122
|
+
name,
|
|
123
|
+
tag,
|
|
124
|
+
buildCmd: buildType(bp, name, tag, key === 'buildpack' && options.clearCache),
|
|
125
|
+
tagCmd: [['docker', 'tag', source, repoImg]].concat(checksum ? [['docker', 'tag', source, `${rawImg}:${checksum}`]] : []),
|
|
126
|
+
pushCmd: ['docker', 'push', repoImg],
|
|
127
|
+
image: rawImg,
|
|
128
|
+
checksum,
|
|
129
|
+
path: bp.buildpack?.path
|
|
108
130
|
}
|
|
109
|
-
})
|
|
131
|
+
}))
|
|
110
132
|
return { commands, before_all, repository }
|
|
111
133
|
}
|
|
112
134
|
|
|
@@ -117,10 +139,19 @@ function parseYAML(filename, repoOpt = '', options) {
|
|
|
117
139
|
*/
|
|
118
140
|
async function executeModules(modules, options) {
|
|
119
141
|
for (const m of modules) {
|
|
120
|
-
|
|
142
|
+
if (m.checksum) {
|
|
143
|
+
try {
|
|
144
|
+
run(`docker inspect --format='{{index .RepoTags 0}}' ${m.image}:${m.checksum}`, { silent: true })
|
|
145
|
+
console.log(info(`image ${m.image}:${m.checksum} already exists – skipping build and push`))
|
|
146
|
+
continue
|
|
147
|
+
} catch (error) {
|
|
148
|
+
// ignore
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
121
152
|
for (const cmd of m.buildCmd) run(cmd)
|
|
122
153
|
if (options.push) {
|
|
123
|
-
|
|
154
|
+
for (const cmd of m.tagCmd) run(cmd)
|
|
124
155
|
run(m.pushCmd)
|
|
125
156
|
}
|
|
126
157
|
}
|
|
@@ -130,13 +161,23 @@ async function executeModules(modules, options) {
|
|
|
130
161
|
* Main function to containerize modules based on a YAML configuration file.
|
|
131
162
|
* @param {string} filename - The path to the YAML configuration file.
|
|
132
163
|
* @param {{ push: boolean, clearCache: boolean }} options - Options object, e.g., { push: true } to push images after building.
|
|
133
|
-
* @returns {Promise<
|
|
164
|
+
* @returns {Promise<Array<{
|
|
165
|
+
* name: string,
|
|
166
|
+
* tag: string,
|
|
167
|
+
* buildCmd: Array<string>,
|
|
168
|
+
* tagCmd: Array<string>,
|
|
169
|
+
* pushCmd: Array<string>,
|
|
170
|
+
* image: string,
|
|
171
|
+
* checksum: string|null
|
|
172
|
+
* path: string
|
|
173
|
+
* }>} - The list of modules that were containerized.
|
|
134
174
|
*/
|
|
135
|
-
async function containerize(filename, options = {
|
|
136
|
-
const { repository, before_all, commands: modules } = parseYAML(filename, '', options)
|
|
175
|
+
async function containerize(filename = 'containerize.yaml', options = { clearCache: !!process.env.CLEAR_CACHE, push: true }) {
|
|
176
|
+
const { repository, before_all, commands: modules } = await parseYAML(filename, '', options)
|
|
137
177
|
if (!repository || !modules) return
|
|
138
|
-
for (const cmd of before_all)
|
|
178
|
+
for (const cmd of before_all) run(cmd)
|
|
139
179
|
await executeModules(modules, options)
|
|
180
|
+
return modules
|
|
140
181
|
}
|
|
141
182
|
|
|
142
183
|
module.exports = { containerize }
|
package/bin/version.js
CHANGED
|
@@ -52,7 +52,7 @@ function list_versions (args, options) {
|
|
|
52
52
|
|
|
53
53
|
process.stdout.isTTY && console.log()
|
|
54
54
|
if (options.markdown || options.info) {
|
|
55
|
-
_markdown (versions)
|
|
55
|
+
_markdown (versions, options)
|
|
56
56
|
} else {
|
|
57
57
|
const mark = !colors ? s => s : require('../lib/util/term').info
|
|
58
58
|
for (let each of Object.keys(versions)) console.log(`${mark(each)}: ${versions[each]}`)
|
|
@@ -81,7 +81,7 @@ function info({ root: cwd = process.cwd() }) {
|
|
|
81
81
|
|
|
82
82
|
// Sort entries, with @sap/cds packages on top, followed by @cap-js packages
|
|
83
83
|
const keys = Object.keys(versions).sort(), sorted={}
|
|
84
|
-
for (let k of ['@sap/cds'
|
|
84
|
+
for (let k of ['@sap/cds']) if (!(k in sorted)) sorted[k] = versions[k]
|
|
85
85
|
for (let k of keys) if (!(k in sorted) && k.startsWith('@sap/cds')) sorted[k] = versions[k]
|
|
86
86
|
for (let k of keys) if (!(k in sorted) && k.startsWith('@cap-js')) sorted[k] = versions[k]
|
|
87
87
|
for (let k of keys) if (!(k in sorted)) sorted[k] = versions[k]
|
|
@@ -115,9 +115,9 @@ function _versions_from(pkg_path, pkg_label) {
|
|
|
115
115
|
return versions
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
function _markdown (versions) {
|
|
118
|
+
function _markdown (versions, { root: cwd = process.cwd() }) {
|
|
119
119
|
const pkg = { name:'', repository:'', version:'' }; try {
|
|
120
|
-
Object.assign (pkg, require (resolve('package.json')))
|
|
120
|
+
Object.assign (pkg, require (require.resolve('./package.json', { paths:[cwd] })))
|
|
121
121
|
} catch (e) {/* ignored */}
|
|
122
122
|
const repo = pkg.repository.url || pkg.repository || 'https://github.com/<your/repo>'
|
|
123
123
|
const valLength = Math.max(repo.length, versions.home.length)
|
package/lib/bind/k8s.js
CHANGED
|
@@ -32,7 +32,7 @@ module.exports = new class K8SBind extends require('./plugin') {
|
|
|
32
32
|
|
|
33
33
|
services4(app) {
|
|
34
34
|
const { execSync } = require('node:child_process')
|
|
35
|
-
const json = cmd => JSON.parse(execSync(cmd, { encoding: 'utf8' }))
|
|
35
|
+
const json = cmd => JSON.parse(execSync(cmd, { encoding: 'utf8', maxBuffer: 10 * 1024 * 1024 }))
|
|
36
36
|
|
|
37
37
|
const bindings = json('kubectl get servicebindings -o json').items
|
|
38
38
|
.filter(b => b.metadata.name.startsWith(app))
|
|
@@ -23,7 +23,7 @@ copied from web-application: web-application.fullname
|
|
|
23
23
|
*/}}
|
|
24
24
|
{{- define "cap.deploymentHost" -}}
|
|
25
25
|
{{- if .deployment.expose.host }}
|
|
26
|
-
{{- .deployment.expose.host }}
|
|
26
|
+
{{- tpl .deployment.expose.host . }}
|
|
27
27
|
{{- else }}
|
|
28
28
|
{{- $name := (include "cap.web-application.fullname" .) }}
|
|
29
29
|
{{- if hasPrefix $name .Release.Namespace }}
|
|
@@ -27,7 +27,7 @@ module.exports = class HelmBuildPlugin extends Plugin {
|
|
|
27
27
|
|
|
28
28
|
async build() {
|
|
29
29
|
if (!HelmBuildPlugin.hasTask()) {
|
|
30
|
-
this.pushMessage("Helm Chart not found. Execute `cds add
|
|
30
|
+
this.pushMessage("Helm Chart not found. Execute `cds add kyma` to add the helm chart.", Plugin.WARNING)
|
|
31
31
|
return
|
|
32
32
|
}
|
|
33
33
|
|