From 8d88c2488deef9c5d3d187242d35a3233d6d17b1 Mon Sep 17 00:00:00 2001 From: i325261 Date: Tue, 28 Apr 2026 11:17:17 +0200 Subject: [PATCH 1/7] [Misc] Migrate 'globalAccountId' to 'providerSubaccountId' in chart files Co-authored-by: Copilot --- lib/add.js | 34 ++++++++++++++++++++++++++++- test/add.test.js | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/lib/add.js b/lib/add.js index 0f09902..b606ac9 100644 --- a/lib/add.js +++ b/lib/add.js @@ -189,6 +189,36 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { throw new Error(`Option '--with-service-only' cannot be used with '--with-mta' or '--with-mta-extensions'`) } + async adoptIncompactibleChanges(isConfigurable) { + const valuesPath = join(cds.root, 'chart/values.yaml') + const valuesYaml = yaml.parse(await read(valuesPath)) + + if (valuesYaml.btp?.globalAccountId === undefined) return + + console.log("⚠️ 'globalAccountId' is deprecated — replacing with 'providerSubaccountId' in chart files") + + delete valuesYaml.btp.globalAccountId + valuesYaml.btp.providerSubaccountId = '' + await write(yaml.stringify(valuesYaml)).to(valuesPath) + console.log("⚠️ Updated values.yaml") + + const croPath = join(cds.root, 'chart/templates/cap-operator-cros.yaml') + if (exists(croPath)) { + const croContent = await read(croPath) + await write(croContent.replace( + 'globalAccountId: {{ .Values.btp.globalAccountId }}', + 'providerSubaccountId: {{ .Values.btp.providerSubaccountId }}' + )).to(croPath) + console.log("⚠️ Updated chart/templates/cap-operator-cros.yaml") + } + + const valuesSchemaPath = isConfigurable + ? '../files/configurableTemplatesChart/values.schema.json' + : '../files/chart/values.schema.json' + await copy(join(__dirname, valuesSchemaPath)).to('chart/values.schema.json') + console.log("⚠️ Updated values.schema.json") + } + async handleExistingChart(project) { const isConfigurable = isConfigurableTemplateChart('chart') let loggingDone = false @@ -202,6 +232,8 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { loggingDone = true } + await this.adoptIncompactibleChanges(isConfigurable) + if (!isConfigurable && cds.cli.options['with-configurable-templates']) console.log("CAP Operator chart already present. If you want to convert the existing chart to a configurable template chart, run 'npx cap-op-plugin convert-to-configurable-template-chart'") @@ -271,7 +303,7 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { .filter(binding => { const serviceInstance = serviceInstances.values().find(instance => instance.name === binding.serviceInstanceName) return !(serviceInstance?.serviceOfferingName === 'html5-apps-repo' && - serviceInstance?.servicePlanName === 'app-host') + serviceInstance?.servicePlanName === 'app-host') }) .map(binding => binding.name) diff --git a/test/add.test.js b/test/add.test.js index fb155ba..8f8fa51 100644 --- a/test/add.test.js +++ b/test/add.test.js @@ -209,4 +209,60 @@ describe('cds add cap-operator', () => { expect(getFileHash(join(__dirname, '../files/commonTemplates/service-binding.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-binding.yaml'))) expect(getFileHash(join(__dirname, '../files/commonTemplates/service-instance.yaml'))).to.equal(getFileHash(join(bookshop, 'chart/templates/service-instance.yaml'))) }) + + it('Migrates globalAccountId to providerSubaccountId in simple chart', async () => { + execSync(`cds add cap-operator`, { cwd: bookshop }) + + const valuesPath = join(bookshop, 'chart/values.yaml') + fs.writeFileSync(valuesPath, fs.readFileSync(valuesPath, 'utf8').replace(' providerSubaccountId:', ' globalAccountId:')) + + const log = execSync(`cds add cap-operator`, { cwd: bookshop }).toString() + + expect(log).to.include("'globalAccountId' is deprecated") + expect(log).to.include('Updated values.yaml') + expect(log).to.include('Updated values.schema.json') + + const updatedValues = fs.readFileSync(valuesPath, 'utf8') + expect(updatedValues).to.include(' providerSubaccountId:') + expect(updatedValues).to.not.include('globalAccountId:') + }) + + it('Migrates globalAccountId to providerSubaccountId in configurable template chart', async () => { + fs.writeFileSync(join(bookshop, 'xs-security.json'), orignalXsSecurityJson) + execSync(`cds add cap-operator --with-configurable-templates`, { cwd: bookshop }) + + const valuesPath = join(bookshop, 'chart/values.yaml') + fs.writeFileSync(valuesPath, fs.readFileSync(valuesPath, 'utf8').replace(' providerSubaccountId:', ' globalAccountId:')) + + const croPath = join(bookshop, 'chart/templates/cap-operator-cros.yaml') + fs.writeFileSync(croPath, fs.readFileSync(croPath, 'utf8').replace( + 'providerSubaccountId: {{ .Values.btp.providerSubaccountId }}', + 'globalAccountId: {{ .Values.btp.globalAccountId }}' + )) + + const log = execSync(`cds add cap-operator`, { cwd: bookshop }).toString() + + expect(log).to.include("'globalAccountId' is deprecated") + expect(log).to.include('Updated values.yaml') + expect(log).to.include('Updated chart/templates/cap-operator-cros.yaml') + expect(log).to.include('Updated values.schema.json') + + const updatedValues = fs.readFileSync(valuesPath, 'utf8') + expect(updatedValues).to.include(' providerSubaccountId:') + expect(updatedValues).to.not.include('globalAccountId:') + + const updatedCro = fs.readFileSync(croPath, 'utf8') + expect(updatedCro).to.include('providerSubaccountId: {{ .Values.btp.providerSubaccountId }}') + expect(updatedCro).to.not.include('globalAccountId: {{ .Values.btp.globalAccountId }}') + }) + + it('Skips globalAccountId migration when chart is already up to date', async () => { + execSync(`cds add cap-operator`, { cwd: bookshop }) + + const log = execSync(`cds add cap-operator`, { cwd: bookshop }).toString() + + expect(log).to.not.include("'globalAccountId' is deprecated") + expect(log).to.not.include('Updated values.yaml') + expect(log).to.not.include('Updated values.schema.json') + }) }) From 48bc19d70b42dd8f847d0be090d00a3a4b7442fb Mon Sep 17 00:00:00 2001 From: i325261 Date: Tue, 28 Apr 2026 12:51:12 +0200 Subject: [PATCH 2/7] [Misc] Update handling of 'globalAccountId' deprecation in values.yaml Co-authored-by: Copilot --- lib/add.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/add.js b/lib/add.js index b606ac9..eafdc1c 100644 --- a/lib/add.js +++ b/lib/add.js @@ -193,12 +193,12 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { const valuesPath = join(cds.root, 'chart/values.yaml') const valuesYaml = yaml.parse(await read(valuesPath)) - if (valuesYaml.btp?.globalAccountId === undefined) return + if (valuesYaml.btp?.globalAccountId === undefined) return false console.log("⚠️ 'globalAccountId' is deprecated — replacing with 'providerSubaccountId' in chart files") delete valuesYaml.btp.globalAccountId - valuesYaml.btp.providerSubaccountId = '' + valuesYaml.btp.providerSubaccountId = null await write(yaml.stringify(valuesYaml)).to(valuesPath) console.log("⚠️ Updated values.yaml") @@ -217,6 +217,8 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { : '../files/chart/values.schema.json' await copy(join(__dirname, valuesSchemaPath)).to('chart/values.schema.json') console.log("⚠️ Updated values.schema.json") + + return true } async handleExistingChart(project) { @@ -232,7 +234,7 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { loggingDone = true } - await this.adoptIncompactibleChanges(isConfigurable) + loggingDone = loggingDone || await this.adoptIncompactibleChanges(isConfigurable) if (!isConfigurable && cds.cli.options['with-configurable-templates']) console.log("CAP Operator chart already present. If you want to convert the existing chart to a configurable template chart, run 'npx cap-op-plugin convert-to-configurable-template-chart'") From af673bacb81a9596aeeb692deebcbe4e61b64803 Mon Sep 17 00:00:00 2001 From: i325261 Date: Tue, 28 Apr 2026 12:54:34 +0200 Subject: [PATCH 3/7] [Fix] Ensure 'chart' directory is not empty before handling existing chart --- lib/add.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/add.js b/lib/add.js index eafdc1c..bd63caf 100644 --- a/lib/add.js +++ b/lib/add.js @@ -89,7 +89,7 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { // If chart folder exists, read the chart.yaml to determine if it's a service only chart const project = this.readProject(isServiceOnly || isServiceOnlyChart('chart')) - if (exists('chart')) { + if (exists('chart') && require('fs').readdirSync('chart').length > 0) { await this.handleExistingChart(project) return } From 9ee5867855eedc932efa573ed2e1e231df0467bd Mon Sep 17 00:00:00 2001 From: i325261 Date: Tue, 28 Apr 2026 14:03:21 +0200 Subject: [PATCH 4/7] [Misc] Update README and CHANGELOG for globalAccountId deprecation; add migration instructions and default values Co-authored-by: Copilot --- CHANGELOG.md | 5 ++++- README.md | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9275fcb..8f1458e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,14 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). The format is based on [Keep a Changelog](http://keepachangelog.com/). -## Version 0.15.0 - 21-April-2026 +## Version 0.15.0 - 28-April-2026 ### Changed - Deprecated `globalAccountId` in favor of `providerSubaccountId` in the `values.yaml` file. This change is part of the latest CAP Operator version `v0.28.0`. **Use this version with CAP Operator `v0.28.0` or later to avoid any compatibility issues.** +- Defaulting `ttlSecondsAfterFinished` to 300 seconds for job workloads. +- Added `sme.sap.com/enable-cleanup-monitoring: "true"` as a default annotation on the CAPApplication resource. +- `serviceExposures` restriction removed in from CAPApplicationVersion template to allow users to configure it as per their needs. - Updated `values.schema.json` to align with the latest CAP Operator version `v0.28.0` and BTP Service Operator version `v0.10.5`. - Replaced `readline` based prompt with [`enquirer`](https://github.com/enquirer/enquirer) for improved interactive prompt experience during runtime values generation. Required fields are now marked with `*` and validated inline. diff --git a/README.md b/README.md index da4dafe..fe3a3b5 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,14 @@ The CAP Operator Plugin offers a simple method for generating [CAP Operator](https://sap.github.io/cap-operator/) resources, which are essential for deploying multi-tenant CAP Applications. +> [!WARNING] +> ## Action Required: +> The `globalAccountId` field in the `CAPApplication` spec is [deprecated](https://github.com/SAP/cap-operator/discussions/343) since CAP Operator v0.28.0 and will be removed in a future release. +> +> **To migrate**, upgrade to CAP Operator Plugin v0.15.0 or later and run `cds add cap-operator`. This updates `values.yaml`, `values.schema.json`, and `templates/cap-operator-cros.yaml` to use `providerSubaccountId` instead. +> +> If you have already migrated, you can ignore this message. + ## Before You Start The CAP Operator plugin requires `@sap/cds-dk: ">=8.2.1"`. If you've installed @sap/cds-dk globally, ensure that the installed version is `8.2.1` or higher. From 5039721c00d49a5b7d4d16078996e92fcd4abb0b Mon Sep 17 00:00:00 2001 From: i325261 Date: Tue, 28 Apr 2026 14:07:57 +0200 Subject: [PATCH 5/7] [Fix] Correct typo in adoptIncompatibleChanges method name --- lib/add.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/add.js b/lib/add.js index bd63caf..103dfea 100644 --- a/lib/add.js +++ b/lib/add.js @@ -189,7 +189,7 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { throw new Error(`Option '--with-service-only' cannot be used with '--with-mta' or '--with-mta-extensions'`) } - async adoptIncompactibleChanges(isConfigurable) { + async adoptIncompatibleChanges(isConfigurable) { const valuesPath = join(cds.root, 'chart/values.yaml') const valuesYaml = yaml.parse(await read(valuesPath)) @@ -234,7 +234,7 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { loggingDone = true } - loggingDone = loggingDone || await this.adoptIncompactibleChanges(isConfigurable) + loggingDone = loggingDone || await this.adoptIncompatibleChanges(isConfigurable) if (!isConfigurable && cds.cli.options['with-configurable-templates']) console.log("CAP Operator chart already present. If you want to convert the existing chart to a configurable template chart, run 'npx cap-op-plugin convert-to-configurable-template-chart'") From 9aadee4c31ec1b2426982bf8ae170e361db051fe Mon Sep 17 00:00:00 2001 From: Anirudh Prasad Date: Tue, 28 Apr 2026 14:14:10 +0200 Subject: [PATCH 6/7] Apply suggestions from code review Co-authored-by: hyperspace-insights[bot] <209611008+hyperspace-insights[bot]@users.noreply.github.com> --- lib/add.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/add.js b/lib/add.js index 103dfea..a00f704 100644 --- a/lib/add.js +++ b/lib/add.js @@ -89,7 +89,7 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin { // If chart folder exists, read the chart.yaml to determine if it's a service only chart const project = this.readProject(isServiceOnly || isServiceOnlyChart('chart')) - if (exists('chart') && require('fs').readdirSync('chart').length > 0) { + if (exists('chart') && require('fs').readdirSync(join(cds.root, 'chart')).length > 0) { await this.handleExistingChart(project) return } From 4d8c661249c713c7ac0dac9c52f2e7bc4e36a2db Mon Sep 17 00:00:00 2001 From: i325261 Date: Wed, 29 Apr 2026 09:47:42 +0200 Subject: [PATCH 7/7] [Fix] Update release date for version 0.15.0 in CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f1458e..dcce4ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). The format is based on [Keep a Changelog](http://keepachangelog.com/). -## Version 0.15.0 - 28-April-2026 +## Version 0.15.0 - 29-April-2026 ### Changed