Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

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.20.0 - 17-August-2026

### Added

- Added support for SAP Build Work Zone, Standard Edition (`workzone-standard`). Generates a `build-workzone-standard` service instance (`local-entry-point` plan) and binding, with workloads updated as required.

## Version 0.19.0 - 31-July-2026

### Added
Expand Down
8 changes: 8 additions & 0 deletions files/approuter.yaml.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,17 @@ workloads:
{{#hasHTML5Repo}}
- {{appName}}-html5-repo-runtime-bind
{{/hasHTML5Repo}}
{{#hasWorkzoneStandard}}
- {{appName}}-workzone-bind
{{/hasWorkzoneStandard}}
deploymentDefinition:
type: Router
image:
ports:
- name: router-port
port: 5000
{{#hasWorkzoneStandard}}
env:
- name: OWN_SAP_CLOUD_SERVICE
value: '["{{strippedAppName}}.service"]'
Comment thread
anirudhprasad-sap marked this conversation as resolved.
{{/hasWorkzoneStandard}}
3 changes: 3 additions & 0 deletions files/workloads.yaml.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ workloads:
{{#hasHtml5Repo}}
- {{appName}}-html5-repo-host-bind
{{/hasHtml5Repo}}
{{#hasWorkzoneStandard}}
- {{appName}}-workzone-bind
{{/hasWorkzoneStandard}}
jobDefinition:
type: Content
image:
Expand Down
15 changes: 15 additions & 0 deletions files/workzone.yaml.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
serviceInstances:
workzone:
name: {{appName}}-workzone-service
serviceOfferingName: build-workzone-standard
servicePlanName: local-entry-point
parameters:
providerId: {{workzoneProviderId}}
exposureId: "{{strippedAppName}}.service"
serviceBindings:
workzone:
name: {{appName}}-workzone-bind
serviceInstanceName: {{appName}}-workzone-service
secretName: {{appName}}-workzone-bind-secret
secretKey: credentials
parameters: {}
9 changes: 8 additions & 1 deletion lib/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,11 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin {
const project = this.readProject(isServiceOnly)
const {
hasDestination, hasHtml5Repo, hasXsuaa, hasApprouter,
hasMultitenancy, hasIas
hasMultitenancy, hasIas, hasWorkzoneStandard
} = project
Comment thread
anirudhprasad-sap marked this conversation as resolved.

if (hasWorkzoneStandard) project.workzoneProviderId = project.strippedAppName.slice(0, 20)

Comment on lines +128 to +129

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: project.workzoneProviderId is assigned twice. The first assignment at line 128 runs immediately after destructuring (outside any guard), and the identical assignment is repeated inside the if (hasWorkzoneStandard) block at line 146. The outer assignment is redundant dead code and should be removed. The inner assignment (inside the if) is the correct, guarded one.

Suggested change
if (hasWorkzoneStandard) project.workzoneProviderId = project.strippedAppName.slice(0, 20)

Double-check suggestion before committing. Edit this comment for amendments.


Please provide feedback on the review comment by checking the appropriate box:

  • 🌟 Awesome comment, a human might have missed that.
  • ✅ Helpful comment
  • 🤷 Neutral
  • ❌ This comment is not helpful

const valuesPath = join(cds.root, 'chart/values.yaml')
const valuesYaml = yaml.parse(await read(valuesPath))

Expand All @@ -140,6 +142,11 @@ module.exports = class CapOperatorAddPlugin extends cds.add.Plugin {
await addIf(hasIas, '../files/ias.yaml.hbs')
await addIf(!hasIas && hasXsuaa, '../files/xsuaa.yaml.hbs')

if (hasWorkzoneStandard) {
project.workzoneProviderId = project.strippedAppName.slice(0, 20)
await addIf(true, '../files/workzone.yaml.hbs')
}

if (hasMultitenancy) {
await addIf(hasIas, '../files/subscription-manager.yaml.hbs')
await addIf(!hasIas && hasXsuaa, '../files/saas-registry.yaml.hbs')
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cap-js/cap-operator-plugin",
"version": "0.19.0",
"version": "0.20.0",
"description": "Add/Build Plugin for CAP Operator",
"homepage": "https://github.com/cap-js/cap-operator-plugin/blob/main/README.md",
"repository": {
Expand Down
32 changes: 32 additions & 0 deletions test/add.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { join } = require('node:path')
const { execSync } = require('node:child_process')
const { expect } = require('chai')
const fs = require('node:fs')
const yaml = require('yaml')

const TempUtil = require('./tempUtil')
const tempUtil = new TempUtil(__filename, { local: true })
Expand Down Expand Up @@ -321,4 +322,35 @@ describe('cds add cap-operator', () => {

expect(log).to.not.include("'btp.provider'")
})

it('Add cap-operator chart with workzone-standard', async () => {
execSync(`cds add workzone-standard`, { cwd: bookshop })
execSync(`cds add cap-operator`, { cwd: bookshop })
Comment thread
anirudhprasad-sap marked this conversation as resolved.

const parsed = yaml.parse(fs.readFileSync(join(bookshop, 'chart/values.yaml'), 'utf8'))

// service instance
const wzInstance = parsed.serviceInstances.workzone
expect(wzInstance.serviceOfferingName).to.equal('build-workzone-standard')
expect(wzInstance.servicePlanName).to.equal('local-entry-point')
expect(wzInstance.parameters.providerId).to.equal('bookshop')
expect(wzInstance.parameters.providerId.length).to.be.at.most(20)
expect(wzInstance.parameters.exposureId).to.equal('bookshop.service')

// service binding
const wzBinding = parsed.serviceBindings.workzone
expect(wzBinding.name).to.equal('bookshop-workzone-bind')
expect(wzBinding.serviceInstanceName).to.equal('bookshop-workzone-service')

// appRouter: workzone binding in consumedBTPServices + OWN_SAP_CLOUD_SERVICE env var
const appRouter = parsed.workloads.appRouter
expect(appRouter.consumedBTPServices).to.include('bookshop-workzone-bind')
const ownSapCloudService = appRouter.deploymentDefinition.env?.find(e => e.name === 'OWN_SAP_CLOUD_SERVICE')
expect(ownSapCloudService).to.exist
expect(ownSapCloudService.value).to.include('bookshop.service')

// contentDeploy: workzone binding in consumedBTPServices
const contentDeploy = parsed.workloads.contentDeploy
expect(contentDeploy.consumedBTPServices).to.include('bookshop-workzone-bind')
})
})