@sap/cds-dk 9.1.2 → 9.2.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 +35 -0
- package/bin/cds.js +2 -0
- package/bin/repl.js +4 -2
- package/bin/up.js +11 -1
- package/bin/util/log.js +8 -1
- package/bin/version.js +20 -15
- package/lib/bind/shared.js +3 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/Chart.yaml +1 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/templates/_helpers.tpl +1 -1
- package/lib/build/plugins/helm/files/subcharts/web-application/templates/deployment.yaml +8 -0
- package/lib/build/plugins/helm/files/subcharts/web-application/templates/virtual-service.yaml +38 -0
- package/lib/build/plugins/helm/files/subcharts/web-application/values.schema.json +15 -0
- package/lib/build/plugins/helm/files/subcharts/web-application/values.yaml +12 -9
- package/lib/build/plugins/helm/index.js +1 -1
- package/lib/build/provider/hana/index.js +5 -4
- package/lib/build/provider/hana/template/.hdiconfig-all +6 -0
- package/lib/compile/to-xsuaa.js +3 -2
- package/lib/init/constants.js +5 -3
- package/lib/init/index.js +6 -1
- package/lib/init/merge.js +7 -3
- package/lib/init/projectReader.js +4 -1
- package/lib/init/registries/mta.js +6 -0
- package/lib/init/template/ams/files/values.yaml.hbs +5 -0
- package/lib/init/template/approuter/files/containerize.yaml.hbs +1 -1
- package/lib/init/template/approuter/files/values.yaml.hbs +1 -5
- package/lib/init/template/data/as-json.js +4 -3
- package/lib/init/template/data/index.js +1 -0
- package/lib/init/template/destination/files/mta.yaml.hbs +1 -20
- package/lib/init/template/extension/index.js +1 -1
- package/lib/init/template/github-actions/files/cf-github-deploy/action.yaml +48 -0
- package/lib/init/template/github-actions/files/cf-setup/action.yaml +53 -0
- package/lib/init/template/github-actions/files/kyma-info/action.yaml +37 -0
- package/lib/init/template/github-actions/files/kyma-setup/action.yaml +64 -0
- package/lib/init/template/github-actions/files/workflows/cf.yaml.hbs +48 -0
- package/lib/init/template/github-actions/files/workflows/kyma.yaml.hbs +39 -0
- package/lib/init/template/github-actions/files/workflows/test.yaml.hbs +21 -0
- package/lib/init/template/github-actions/index.js +73 -0
- package/lib/init/template/helm/index.js +5 -1
- package/lib/init/template/html5-repo/files/containerize.yaml.hbs +4 -4
- package/lib/init/template/html5-repo/files/mta.yaml.hbs +24 -0
- package/lib/init/template/html5-repo/files/values.yaml.hbs +2 -1
- package/lib/init/template/html5-repo/index.js +9 -3
- package/lib/init/template/http/index.js +4 -4
- package/lib/init/template/ias/files/package.json.hbs +7 -0
- package/lib/init/template/ias/files/values.yaml.hbs +1 -4
- package/lib/init/template/ias/index.js +2 -1
- package/lib/init/template/kyma/index.js +10 -0
- package/lib/init/template/malware-scanner/index.js +1 -1
- package/lib/init/template/multitenancy/files/values.yaml.hbs +53 -1
- package/lib/init/template/multitenancy/index.js +0 -13
- package/lib/init/template/pipeline/files/Jenkinsfile +2 -2
- package/lib/init/template/pipeline/index.js +1 -1
- package/lib/init/template/portal/files/containerize.yaml.hbs +15 -0
- package/lib/init/template/portal/files/values.yaml.hbs +1 -1
- package/lib/init/template/portal/index.js +9 -1
- package/lib/init/template/sample/index.js +1 -1
- package/lib/init/template/test/index.js +1 -1
- package/lib/init/template/tiny-sample/index.js +1 -1
- package/lib/init/template/typescript/index.js +1 -1
- package/lib/init/template/workzone-standard/index.js +13 -4
- package/lib/init/template/xsuaa/files/mta.yaml.hbs +8 -0
- package/lib/init/template/xsuaa/index.js +11 -0
- package/lib/init/template.js +38 -26
- package/lib/lint/eslintHelp.json +1 -1
- package/lib/watch/watched.js +1 -1
- package/npm-shrinkwrap.json +15 -15
- package/package.json +1 -1
- /package/lib/init/template/html5-repo/files/{ui-resources/package.json.hbs → html5-deployer.package.json.hbs} +0 -0
|
@@ -228,9 +228,10 @@ function dataForField(element, artifact, csn, record, data, parent, depth, refer
|
|
|
228
228
|
return randomIntInRange(range)
|
|
229
229
|
}
|
|
230
230
|
case 'cds.hana.REAL':
|
|
231
|
-
case 'cds.Decimal': { // Decimal(9,5), Decimal(9), Decimal(precision:5)
|
|
231
|
+
case 'cds.Decimal': { // Decimal(9,5), Decimal(9), Decimal(precision:5), Decimal(2,2)
|
|
232
232
|
const scale = element.scale ?? (element.precision ? 0 : 2) // scale is 0 if only precision is given
|
|
233
|
-
|
|
233
|
+
//10^x would allow one digit more than allowed, that's why -1
|
|
234
|
+
const prec = element.precision ? Math.min(Math.pow(10, element.precision - scale) - 1, Number.MAX_SAFE_INTEGER) : 100
|
|
234
235
|
const range = { from: 0, to: prec }
|
|
235
236
|
annotatedIntRange(element, range)
|
|
236
237
|
return +(randomDecimalInRange(range).toFixed(scale))
|
|
@@ -550,7 +551,7 @@ function randomDateInRange(dateRange) {
|
|
|
550
551
|
function randomDecimalInRange(decimalRange) {
|
|
551
552
|
const max = decimalRange.to
|
|
552
553
|
const min = decimalRange.from
|
|
553
|
-
const num = min + (randomNumber() % (max - min))
|
|
554
|
+
const num = max === 0 ? 0 : min + (randomNumber() % (max - min))
|
|
554
555
|
let dec = randomNumber()
|
|
555
556
|
const divider = Math.pow(10, dec.toString().length)
|
|
556
557
|
dec = dec / divider
|
|
@@ -82,6 +82,7 @@ module.exports = class DataTemplate extends require('../../plugin') {
|
|
|
82
82
|
|
|
83
83
|
if (contentType === 'csv') {
|
|
84
84
|
const headerOnly = !cds.cli.options['records'] // compat to old behavior which only creates headers
|
|
85
|
+
if (headerOnly) console.log(`${dim('adding headers only, use --records to create random entries')}`)
|
|
85
86
|
await asCsv(data, csn, Object.assign({ headerOnly }, dataForParams))
|
|
86
87
|
}
|
|
87
88
|
|
|
@@ -22,23 +22,4 @@ resources:
|
|
|
22
22
|
type: org.cloudfoundry.managed-service
|
|
23
23
|
parameters:
|
|
24
24
|
service: destination
|
|
25
|
-
service-plan: lite
|
|
26
|
-
config:
|
|
27
|
-
HTML5Runtime_enabled: true
|
|
28
|
-
init_data:
|
|
29
|
-
instance:
|
|
30
|
-
existing_destinations_policy: update
|
|
31
|
-
destinations:
|
|
32
|
-
- Name: srv-api
|
|
33
|
-
URL: ~{srv-api/srv-url}
|
|
34
|
-
Authentication: NoAuthentication
|
|
35
|
-
Type: HTTP
|
|
36
|
-
ProxyType: Internet
|
|
37
|
-
HTML5.ForwardAuthToken: true
|
|
38
|
-
HTML5.DynamicDestination: true
|
|
39
|
-
- Name: ui5
|
|
40
|
-
URL: https://ui5.sap.com
|
|
41
|
-
Authentication: NoAuthentication
|
|
42
|
-
Type: HTTP
|
|
43
|
-
ProxyType: Internet
|
|
44
|
-
{{/hasHtml5Repo}}
|
|
25
|
+
service-plan: lite
|
|
@@ -8,7 +8,7 @@ const npmPackageRegex = /^(@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/
|
|
|
8
8
|
module.exports = class ExtensionProjectTemplate extends require('../../plugin') {
|
|
9
9
|
|
|
10
10
|
static help() {
|
|
11
|
-
return '
|
|
11
|
+
return 'extension project'
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
options() {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: GitHub Deployment for Cloud Foundry
|
|
2
|
+
description: "Creates a GitHub deployment for your Cloud Foundry app"
|
|
3
|
+
|
|
4
|
+
inputs:
|
|
5
|
+
app-name:
|
|
6
|
+
description: "Base name of the deployed CAP app"
|
|
7
|
+
required: true
|
|
8
|
+
|
|
9
|
+
runs:
|
|
10
|
+
using: "composite"
|
|
11
|
+
steps:
|
|
12
|
+
- name: Get deployed server URL
|
|
13
|
+
id: get-url
|
|
14
|
+
shell: bash
|
|
15
|
+
run: |
|
|
16
|
+
raw=$(cf app "${{ inputs.app-name }}" | awk '/routes:/ {print $2}')
|
|
17
|
+
raw=$(echo "$raw" | sed -E 's#^https?://##')
|
|
18
|
+
echo "url=https://$raw" >> "$GITHUB_OUTPUT"
|
|
19
|
+
|
|
20
|
+
- name: Create GitHub Deployment
|
|
21
|
+
uses: actions/github-script@v7
|
|
22
|
+
env:
|
|
23
|
+
URL: ${{ steps.get-url.outputs.url }}
|
|
24
|
+
with:
|
|
25
|
+
script: |
|
|
26
|
+
const { owner, repo } = context.repo
|
|
27
|
+
const ref = context.ref
|
|
28
|
+
const url = process.env.URL
|
|
29
|
+
|
|
30
|
+
const deployment = await github.rest.repos.createDeployment({
|
|
31
|
+
owner,
|
|
32
|
+
repo,
|
|
33
|
+
ref,
|
|
34
|
+
required_contexts: [],
|
|
35
|
+
environment: 'Production',
|
|
36
|
+
auto_merge: false,
|
|
37
|
+
description: 'Deployed to Cloud Foundry',
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
await github.rest.repos.createDeploymentStatus({
|
|
41
|
+
owner,
|
|
42
|
+
repo,
|
|
43
|
+
deployment_id: deployment.data.id,
|
|
44
|
+
state: 'success',
|
|
45
|
+
environment_url: url,
|
|
46
|
+
log_url: `https://github.com/${owner}/${repo}/actions/runs/${context.runId}`,
|
|
47
|
+
description: 'CAP app is live',
|
|
48
|
+
})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: Cloud Foundry Setup
|
|
2
|
+
description: "Installs dependencies for Cloud Foundry deployment"
|
|
3
|
+
|
|
4
|
+
inputs:
|
|
5
|
+
cf-version:
|
|
6
|
+
description: "The version of the Cloud Foundry CLI to install"
|
|
7
|
+
required: false
|
|
8
|
+
default: "8.8.3"
|
|
9
|
+
cf-api:
|
|
10
|
+
description: "The Cloud Foundry API endpoint to connect to"
|
|
11
|
+
required: true
|
|
12
|
+
cf-org:
|
|
13
|
+
description: "The Cloud Foundry organization to target"
|
|
14
|
+
required: true
|
|
15
|
+
cf-space:
|
|
16
|
+
description: "The Cloud Foundry space to target"
|
|
17
|
+
required: true
|
|
18
|
+
cf-username:
|
|
19
|
+
description: "The Cloud Foundry username to authenticate with"
|
|
20
|
+
required: true
|
|
21
|
+
cf-password:
|
|
22
|
+
description: "The Cloud Foundry password to authenticate with"
|
|
23
|
+
required: true
|
|
24
|
+
|
|
25
|
+
runs:
|
|
26
|
+
using: composite
|
|
27
|
+
steps:
|
|
28
|
+
- shell: bash
|
|
29
|
+
run: |
|
|
30
|
+
set -e
|
|
31
|
+
echo "Using CF_VERSION=${{ inputs.cf-version }}"
|
|
32
|
+
echo "Using CF_API=${{ inputs.cf-api }}"
|
|
33
|
+
curl -L "https://packages.cloudfoundry.org/stable?release=linux64-binary&version=${{ inputs.cf-version }}&source=github" -o cf-cli.tgz
|
|
34
|
+
mkdir cf-cli && tar -xzf cf-cli.tgz -C cf-cli
|
|
35
|
+
chmod +x cf-cli/cf
|
|
36
|
+
echo "${PWD}/cf-cli" >> $GITHUB_PATH
|
|
37
|
+
|
|
38
|
+
- shell: bash
|
|
39
|
+
run: |
|
|
40
|
+
echo "Installing MBT..."
|
|
41
|
+
npm install -g mbt
|
|
42
|
+
|
|
43
|
+
- shell: bash
|
|
44
|
+
run: |
|
|
45
|
+
echo "Installing CF CLI multiapps plugin..."
|
|
46
|
+
cf install-plugin multiapps -f
|
|
47
|
+
|
|
48
|
+
- shell: bash
|
|
49
|
+
run: |
|
|
50
|
+
echo "Authenticating to Cloud Foundry..."
|
|
51
|
+
cf api "${{ inputs.cf-api }}"
|
|
52
|
+
cf auth "${{ inputs.cf-username }}" "${{ inputs.cf-password }}"
|
|
53
|
+
cf target -o "${{ inputs.cf-org }}" -s "${{ inputs.cf-space }}"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Kyma Info
|
|
2
|
+
|
|
3
|
+
description: "Prints post-deployment information for Kyma applications"
|
|
4
|
+
|
|
5
|
+
inputs:
|
|
6
|
+
app:
|
|
7
|
+
description: App Name
|
|
8
|
+
required: true
|
|
9
|
+
|
|
10
|
+
runs:
|
|
11
|
+
using: "composite"
|
|
12
|
+
steps:
|
|
13
|
+
- name: Get Events
|
|
14
|
+
shell: bash
|
|
15
|
+
run: kubectl get events --sort-by='.lastTimestamp' | tail -n 10
|
|
16
|
+
- name: Get Pods
|
|
17
|
+
shell: bash
|
|
18
|
+
run: kubectl get pods
|
|
19
|
+
- name: Get Secrets
|
|
20
|
+
shell: bash
|
|
21
|
+
run: kubectl get secrets
|
|
22
|
+
- name: Get Service Instances
|
|
23
|
+
shell: bash
|
|
24
|
+
run: kubectl get serviceinstances
|
|
25
|
+
- name: Get Service Bindings
|
|
26
|
+
shell: bash
|
|
27
|
+
run: kubectl get servicebindings
|
|
28
|
+
- shell: bash
|
|
29
|
+
run: |
|
|
30
|
+
echo "::group::Kyma Logs for ${{ inputs.app }}-srv"
|
|
31
|
+
kubectl get pods --no-headers | awk '{print $1}' | grep "${{ inputs.app }}.*-srv" | xargs -r -I % kubectl logs % --since=10m
|
|
32
|
+
echo "::endgroup::"
|
|
33
|
+
- shell: bash
|
|
34
|
+
run: |
|
|
35
|
+
echo "::group::Kyma Logs for ${{ inputs.app }}-approuter"
|
|
36
|
+
kubectl get pods --no-headers | awk '{print $1}' | grep "${{ inputs.app }}.*-approuter" | xargs -r -I % kubectl logs % --since=10m
|
|
37
|
+
echo "::endgroup::"
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
name: Kyma Setup
|
|
2
|
+
|
|
3
|
+
description: "Installs dependencies for Kyma deployment"
|
|
4
|
+
|
|
5
|
+
inputs:
|
|
6
|
+
registry:
|
|
7
|
+
description: Image Registry
|
|
8
|
+
required: true
|
|
9
|
+
user:
|
|
10
|
+
description: Registry User
|
|
11
|
+
required: true
|
|
12
|
+
password:
|
|
13
|
+
description: Registry Password
|
|
14
|
+
required: true
|
|
15
|
+
kube-config:
|
|
16
|
+
description: Base64-encoded Kubernetes Config
|
|
17
|
+
required: true
|
|
18
|
+
|
|
19
|
+
runs:
|
|
20
|
+
using: "composite"
|
|
21
|
+
steps:
|
|
22
|
+
- run: apt-get update -y
|
|
23
|
+
shell: bash
|
|
24
|
+
- run: apt-get install software-properties-common -y
|
|
25
|
+
shell: bash
|
|
26
|
+
- run: apt-get install curl ca-certificates -y
|
|
27
|
+
shell: bash
|
|
28
|
+
- run: apt install sudo
|
|
29
|
+
shell: bash
|
|
30
|
+
- run: curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
|
|
31
|
+
shell: bash
|
|
32
|
+
- run: echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
|
|
33
|
+
shell: bash
|
|
34
|
+
- run: apt-get update -y
|
|
35
|
+
shell: bash
|
|
36
|
+
- run: apt-get install make -y
|
|
37
|
+
shell: bash
|
|
38
|
+
- run: apt-get install maven -y
|
|
39
|
+
shell: bash
|
|
40
|
+
- run: apt-get install docker.io -y
|
|
41
|
+
shell: bash
|
|
42
|
+
- run: (curl -sSL "https://github.com/buildpacks/pack/releases/download/v0.31.0/pack-v0.31.0-linux.tgz" | sudo tar -C /usr/local/bin/ --no-same-owner -xzv pack)
|
|
43
|
+
shell: bash
|
|
44
|
+
- run: apt-get install kubectl -y
|
|
45
|
+
shell: bash
|
|
46
|
+
- run: curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null
|
|
47
|
+
shell: bash
|
|
48
|
+
- run: sudo apt-get install apt-transport-https --yes
|
|
49
|
+
shell: bash
|
|
50
|
+
- run: echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
|
|
51
|
+
shell: bash
|
|
52
|
+
- run: sudo apt-get update
|
|
53
|
+
shell: bash
|
|
54
|
+
- run: sudo apt-get install helm
|
|
55
|
+
shell: bash
|
|
56
|
+
- run: npm install -g ctz
|
|
57
|
+
shell: bash
|
|
58
|
+
- shell: bash
|
|
59
|
+
run: |
|
|
60
|
+
mkdir ${HOME}/kyma-binaries
|
|
61
|
+
export PATH=${HOME}/kyma-binaries/:$PATH
|
|
62
|
+
echo "${{ inputs.password }}" | docker login "${{ inputs.registry }}" -u "${{ inputs.user }}" --password-stdin
|
|
63
|
+
mkdir ${HOME}/.kube
|
|
64
|
+
echo "${{ inputs.kube-config }}" | base64 --decode > ${HOME}/.kube/config
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: Cloud Foundry
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
workflow_dispatch:
|
|
6
|
+
merge_group:
|
|
7
|
+
push:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: {{#literal}}cf-${{ github.workflow }}-${{ github.head_ref || github.run_id }}{{/literal}}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
env:
|
|
16
|
+
APP_NAME: {{ appName }}
|
|
17
|
+
jobs:
|
|
18
|
+
deploy:
|
|
19
|
+
runs-on: {{#sap}}[self-hosted, solinas]{{/sap}}{{^sap}}ubuntu-latest{{/sap}}
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: actions/setup-node@v4
|
|
23
|
+
with:
|
|
24
|
+
node-version: 22
|
|
25
|
+
- uses: ./.github/actions/cf-setup # cap-js/cf-setup@v1
|
|
26
|
+
with:
|
|
27
|
+
cf-api: {{#literal}}${{ vars.CF_API }}{{/literal}}
|
|
28
|
+
cf-org: {{#literal}}${{ vars.CF_ORG }}{{/literal}}
|
|
29
|
+
cf-space: {{#literal}}${{ vars.CF_SPACE }}{{/literal}}
|
|
30
|
+
cf-username: {{#literal}}${{ vars.CF_USERNAME }}{{/literal}}
|
|
31
|
+
cf-password: {{#literal}}${{ secrets.CF_PASSWORD }}{{/literal}}
|
|
32
|
+
- run: npm install
|
|
33
|
+
- run: npx cds up
|
|
34
|
+
|
|
35
|
+
- uses: ./.github/actions/cf-github-deploy
|
|
36
|
+
with:
|
|
37
|
+
app-name: {{#literal}}${{ env.APP_NAME }}{{/literal}}
|
|
38
|
+
|
|
39
|
+
{{#hasApprouter}}
|
|
40
|
+
- run: cf logs "${{ env.APP_NAME }}" --recent
|
|
41
|
+
{{/hasApprouter}}
|
|
42
|
+
- run: cf logs "${{ env.APP_NAME }}-srv" --recent
|
|
43
|
+
{{^hasMultitenancy}}
|
|
44
|
+
- run: cf logs "${{ env.APP_NAME }}-db-deployer" --recent
|
|
45
|
+
{{/hasMultitenancy}}
|
|
46
|
+
{{#hasMultitenancy}}
|
|
47
|
+
- run: cf logs "${{ env.APP_NAME }}-mtx" --recent
|
|
48
|
+
{{/hasMultitenancy}}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: Kyma
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
workflow_dispatch:
|
|
6
|
+
merge_group:
|
|
7
|
+
push:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
|
|
11
|
+
concurrency:
|
|
12
|
+
group: {{#literal}}deploy-${{ github.workflow }}-${{ github.head_ref || github.run_id }}{{/literal}}
|
|
13
|
+
cancel-in-progress: true
|
|
14
|
+
|
|
15
|
+
env:
|
|
16
|
+
APP_NAME: {{ appName }}
|
|
17
|
+
jobs:
|
|
18
|
+
deploy:
|
|
19
|
+
runs-on: [self-hosted, {{#sap}}solinas{{/sap}}{{^sap}}ubuntu-latest{{/sap}}]
|
|
20
|
+
container:
|
|
21
|
+
image: public.int.repositories.cloud.sap/ubuntu:24.04
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v4
|
|
24
|
+
- uses: actions/setup-node@v4
|
|
25
|
+
with:
|
|
26
|
+
node-version: 22
|
|
27
|
+
- uses: ./.github/actions/kyma-setup
|
|
28
|
+
with:
|
|
29
|
+
registry: {{#literal}}${{ vars.DOCKER_REGISTRY }}{{/literal}}
|
|
30
|
+
user: {{#literal}}${{ vars.DOCKER_USERNAME }}{{/literal}}
|
|
31
|
+
password: {{#literal}}${{ secrets.DOCKER_PASSWORD }}{{/literal}}
|
|
32
|
+
kube-config: {{#literal}}${{ secrets.KUBE_CONFIG }}{{/literal}}
|
|
33
|
+
- run: npm clean-install
|
|
34
|
+
- run: npx cds up --to k8s
|
|
35
|
+
|
|
36
|
+
- uses: ./.github/actions/kyma-info
|
|
37
|
+
if: always()
|
|
38
|
+
with:
|
|
39
|
+
app: {{#literal}}${{ env.APP_NAME }}{{/literal}}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
workflow_dispatch:
|
|
6
|
+
pull_request:
|
|
7
|
+
merge_group:
|
|
8
|
+
push:
|
|
9
|
+
branches:
|
|
10
|
+
- main
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
tests:
|
|
14
|
+
runs-on: [self-hosted, {{#sap}}solinas{{/sap}}{{^sap}}ubuntu-latest{{/sap}}]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/setup-node@v4
|
|
17
|
+
with:
|
|
18
|
+
node-version: 22
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- run: npm install
|
|
21
|
+
- run: npm test
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const path = require('node:path')
|
|
2
|
+
const { readProject } = require('../../projectReader')
|
|
3
|
+
const { renderAndCopy } = require('../../template')
|
|
4
|
+
const cds = require('../../../cds')
|
|
5
|
+
const { exists, copy } = cds.utils
|
|
6
|
+
|
|
7
|
+
module.exports = class GitHubActionTemplate extends require('../../plugin') {
|
|
8
|
+
|
|
9
|
+
static hasInProduction() {
|
|
10
|
+
return exists('.github/workflows/test.yaml')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
options() {
|
|
14
|
+
return {
|
|
15
|
+
'sap': {
|
|
16
|
+
type: 'boolean'
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static help() {
|
|
22
|
+
return 'CI/CD pipeline via GitHub Actions'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async run() {
|
|
26
|
+
const out = '.github/workflows/test.yaml'
|
|
27
|
+
if (!exists(out) || cds.cli.options.force) {
|
|
28
|
+
await renderAndCopy(path.join(__dirname, 'files/workflows/test.yaml.hbs'), out, { sap: cds.cli.options.sap })
|
|
29
|
+
} else {
|
|
30
|
+
console.log('> skipping ' + out)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async combine() {
|
|
35
|
+
const project = readProject()
|
|
36
|
+
const { hasMta, hasHelm } = project, { force } = cds.cli.options
|
|
37
|
+
project.literal = () => text => text
|
|
38
|
+
project.sap = cds.cli.options.sap
|
|
39
|
+
if (hasMta) {
|
|
40
|
+
const cf = '.github/workflows/cf.yaml'
|
|
41
|
+
if (!exists(cf) || force) {
|
|
42
|
+
await renderAndCopy(path.join(__dirname, 'files/workflows/cf.yaml.hbs'), cf, project)
|
|
43
|
+
}
|
|
44
|
+
const cfSetup = '.github/actions/cf-setup'
|
|
45
|
+
if (!exists(cfSetup) || force) {
|
|
46
|
+
await copy(path.join(__dirname, 'files/cf-setup'), cfSetup)
|
|
47
|
+
}
|
|
48
|
+
const cfGithub = '.github/actions/cf-github-deploy'
|
|
49
|
+
if (!exists(cfGithub) || force) {
|
|
50
|
+
await copy(path.join(__dirname, 'files/cf-github-deploy'), cfGithub)
|
|
51
|
+
}
|
|
52
|
+
const cfInfo = '.github/actions/cf-info'
|
|
53
|
+
if (!exists(cfInfo) || force) {
|
|
54
|
+
await copy(path.join(__dirname, 'files/cf-info'), cfInfo)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (hasHelm) {
|
|
58
|
+
const kyma = '.github/workflows/kyma.yaml'
|
|
59
|
+
if (!exists(kyma) || force) {
|
|
60
|
+
await renderAndCopy(path.join(__dirname, 'files/workflows/kyma.yaml.hbs'), kyma, project)
|
|
61
|
+
}
|
|
62
|
+
const kymaSetup = '.github/actions/kyma-setup'
|
|
63
|
+
if (!exists(kymaSetup) || force) {
|
|
64
|
+
await copy(path.join(__dirname, 'files/kyma-setup'), kymaSetup)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const kymaInfo = '.github/actions/kyma-info'
|
|
68
|
+
if (!exists(kymaInfo) || force) {
|
|
69
|
+
await copy(path.join(__dirname, 'files/kyma-info'), kymaInfo)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -101,7 +101,11 @@ module.exports = class HelmTemplate extends require('../../plugin') {
|
|
|
101
101
|
}
|
|
102
102
|
if (hasMultitenancy) {
|
|
103
103
|
await this._mergeDependency('web-application', 'sidecar')
|
|
104
|
-
|
|
104
|
+
if (hasXsuaa) {
|
|
105
|
+
await this._mergeDependency('service-instance', 'saas-registry')
|
|
106
|
+
} else {
|
|
107
|
+
await this._mergeDependency('service-instance', 'subscription-manager')
|
|
108
|
+
}
|
|
105
109
|
}
|
|
106
110
|
if (hasDestination) {
|
|
107
111
|
await this._mergeDependency('service-instance', 'destination')
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
before-all:
|
|
3
3
|
{{#hasUI5}}
|
|
4
|
-
- mkdir -p
|
|
4
|
+
- mkdir -p app/html5-deployer/resources
|
|
5
5
|
{{#apps}}
|
|
6
6
|
- npm i --prefix app/{{app}}
|
|
7
7
|
- npm run build --prefix app/{{app}}
|
|
8
8
|
# zip filename should match the archiveName specified in ui5-deploy.yaml
|
|
9
|
-
- cp -f app/{{app}}/dist/{{app}}.zip
|
|
9
|
+
- cp -f app/{{app}}/dist/{{app}}.zip app/html5-deployer/resources/{{app}}.zip
|
|
10
10
|
{{/apps}}
|
|
11
11
|
{{/hasUI5}}
|
|
12
12
|
modules:
|
|
@@ -20,6 +20,6 @@ modules:
|
|
|
20
20
|
type: nodejs
|
|
21
21
|
builder: builder-jammy-base
|
|
22
22
|
{{/hasHelmUnifiedRuntime}}
|
|
23
|
-
path:
|
|
23
|
+
path: app/html5-deployer
|
|
24
24
|
env:
|
|
25
|
-
BP_NODE_RUN_SCRIPTS: ""
|
|
25
|
+
BP_NODE_RUN_SCRIPTS: ""
|
|
@@ -25,9 +25,14 @@ modules:
|
|
|
25
25
|
type: com.sap.application.content
|
|
26
26
|
path: {{#isNodejs}}gen{{/isNodejs}}{{#isJava}}.{{/isJava}}
|
|
27
27
|
requires:
|
|
28
|
+
- name: {{appName}}-auth
|
|
29
|
+
- name: srv-api
|
|
28
30
|
- name: {{appName}}-html5-repo-host
|
|
29
31
|
parameters:
|
|
30
32
|
content-target: true
|
|
33
|
+
config:
|
|
34
|
+
HTML5Runtime_enabled: true{{#hasIas}}
|
|
35
|
+
IASDependencyName: {{appName}}-api{{/hasIas}}
|
|
31
36
|
build-parameters:
|
|
32
37
|
build-result: {{#isNodejs}}{{& appPath }}{{/isNodejs}}{{#isJava}}resources{{/isJava}}
|
|
33
38
|
requires:
|
|
@@ -37,6 +42,25 @@ modules:
|
|
|
37
42
|
- {{app}}.zip
|
|
38
43
|
target-path: {{#isNodejs}}{{& appPath }}{{/isNodejs}}{{#isJava}}resources{{/isJava}}
|
|
39
44
|
{{/apps}}
|
|
45
|
+
parameters:
|
|
46
|
+
config:
|
|
47
|
+
HTML5Runtime_enabled: true
|
|
48
|
+
init_data:
|
|
49
|
+
instance:
|
|
50
|
+
existing_destinations_policy: update
|
|
51
|
+
destinations:
|
|
52
|
+
- Name: srv-api
|
|
53
|
+
URL: ~{srv-api/srv-url}
|
|
54
|
+
Authentication: NoAuthentication
|
|
55
|
+
Type: HTTP
|
|
56
|
+
ProxyType: Internet
|
|
57
|
+
HTML5.ForwardAuthToken: true
|
|
58
|
+
HTML5.DynamicDestination: true
|
|
59
|
+
- Name: ui5
|
|
60
|
+
URL: https://ui5.sap.com
|
|
61
|
+
Authentication: NoAuthentication
|
|
62
|
+
Type: HTTP
|
|
63
|
+
ProxyType: Internet
|
|
40
64
|
|
|
41
65
|
{{#apps}}
|
|
42
66
|
- name: {{strippedAppName}}{{strippedApp}}
|
|
@@ -16,10 +16,11 @@ html5-apps-deployer:
|
|
|
16
16
|
serviceInstanceName: xsuaa
|
|
17
17
|
{{/hasXsuaa}}
|
|
18
18
|
{{#hasIas}}
|
|
19
|
-
|
|
19
|
+
identity:
|
|
20
20
|
serviceInstanceName: identity
|
|
21
21
|
parameters:
|
|
22
22
|
credential-type: X509_GENERATED
|
|
23
|
+
app-identifier: html5-deployer
|
|
23
24
|
{{/hasIas}}
|
|
24
25
|
destination:
|
|
25
26
|
serviceInstanceName: destination
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const { join } = require('path')
|
|
2
2
|
const { readProject } = require('../../projectReader')
|
|
3
3
|
const { merge } = require('../../merge')
|
|
4
|
-
const { srv4, html5RepoHost, html5Runtime, appDeployer, approuter, mtxSidecar4 } = require('../../registries/mta')
|
|
4
|
+
const { srv4, html5RepoHost, html5Runtime, xsuaa, appDeployer, approuter, mtxSidecar4 } = require('../../registries/mta')
|
|
5
5
|
const { odataApi } = require('../../registries/xs-app')
|
|
6
6
|
const { exists } = require('../../../cds').utils
|
|
7
7
|
const { renderAndCopy } = require('../../template')
|
|
@@ -51,7 +51,7 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
|
|
|
51
51
|
|
|
52
52
|
async combine() {
|
|
53
53
|
const project = readProject()
|
|
54
|
-
const { isJava, srvPath, appPath, hasMta, hasMultitenancy, hasWorkzoneStandard, hasHelm, hasHelmUnifiedRuntime, hasApprouter, hasContainerize, apps } = project
|
|
54
|
+
const { isJava, srvPath, appPath, hasMta, hasXsuaa, hasMultitenancy, hasWorkzoneStandard, hasHelm, hasHelmUnifiedRuntime, hasApprouter, hasContainerize, apps } = project
|
|
55
55
|
|
|
56
56
|
await Promise.all(apps.map(async ({ app }) => {
|
|
57
57
|
project.app = app
|
|
@@ -97,6 +97,12 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
|
|
|
97
97
|
into: [isJava ? srv : mtxSidecar4('gen/mtx/sidecar'), 'requires', 'name']
|
|
98
98
|
})
|
|
99
99
|
}
|
|
100
|
+
if (hasXsuaa) {
|
|
101
|
+
relationships.push({
|
|
102
|
+
insert: [xsuaa, 'name'],
|
|
103
|
+
into: [appDeployer, 'requires']
|
|
104
|
+
})
|
|
105
|
+
}
|
|
100
106
|
await merge(__dirname, 'files/mta.yaml.hbs').into('mta.yaml', {
|
|
101
107
|
with: project,
|
|
102
108
|
additions,
|
|
@@ -111,7 +117,7 @@ module.exports = class Html5RepoTemplate extends require('../../plugin') {
|
|
|
111
117
|
await merge(__dirname, '/files/containerize.yaml.hbs').into('containerize.yaml', { with: project, additions })
|
|
112
118
|
}
|
|
113
119
|
if (hasHelm || hasHelmUnifiedRuntime) {
|
|
114
|
-
await renderAndCopy(join(__dirname, 'files/
|
|
120
|
+
await renderAndCopy(join(__dirname, 'files/html5-deployer.package.json.hbs'), 'app/html5-deployer/package.json', project)
|
|
115
121
|
await merge(__dirname, 'files/values.yaml.hbs').into('chart/values.yaml', { with: project })
|
|
116
122
|
}
|
|
117
123
|
}
|
|
@@ -163,7 +163,7 @@ module.exports = class HttpTemplate extends require('../../plugin') {
|
|
|
163
163
|
const key = Object.keys(e.keys)[0] // draft keys are always single
|
|
164
164
|
delete entityData[key] // draft keys should always by auto generated (either UUID or through custom logic), so remove them from the payload
|
|
165
165
|
const postBody = JSON.stringify(entityData, null, 2)
|
|
166
|
-
generateDraftRequests(requests, requestTitle, url, headers, headerAuth, postBody, key)
|
|
166
|
+
generateDraftRequests(requests, requestTitle, url, headers, headerAuth, postBody, key, service)
|
|
167
167
|
}
|
|
168
168
|
else {
|
|
169
169
|
const postBody = JSON.stringify(entityData, null, 2)
|
|
@@ -198,14 +198,14 @@ module.exports = class HttpTemplate extends require('../../plugin') {
|
|
|
198
198
|
this.#write(requests, serviceName)
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
-
function generateDraftRequests(requests, title, url, headers, headerAuth, postBody, key) {
|
|
201
|
+
function generateDraftRequests(requests, title, url, headers, headerAuth, postBody, key, service) {
|
|
202
202
|
const nameDraftsCreate = slug(title+'_Draft_POST')
|
|
203
203
|
requests.push(`${title} Drafts GET\n# @name ${slug(title+'_Drafts_GET')}\nGET ${url}?$filter=(IsActiveEntity eq false)\n${headerAuth}\n`) // unencoded URL for better readability (client can handle this)
|
|
204
204
|
requests.push(`${title} Draft POST\n# @name ${nameDraftsCreate}\nPOST ${url}\n${headers}\n\n${postBody}\n`)
|
|
205
205
|
requests.push(`\n### Result from POST request above\n@draftID={{${nameDraftsCreate}.response.body.$.${key}}}\n`)
|
|
206
206
|
requests.push(`${title} Draft PATCH\n# @name ${slug(title+'_Draft_Patch')}\nPATCH ${url}(${key}={{draftID}},IsActiveEntity=false)\n${headers}\n\n${postBody}\n`)
|
|
207
|
-
requests.push(`${title} Draft Prepare\n# @name ${slug(title+'_Draft_Prepare')}\nPOST ${url}(${key}={{draftID}},IsActiveEntity=false)
|
|
208
|
-
requests.push(`${title} Draft Activate\n# @name ${slug(title+'_Draft_Activate')}\nPOST ${url}(${key}={{draftID}},IsActiveEntity=false)
|
|
207
|
+
requests.push(`${title} Draft Prepare\n# @name ${slug(title+'_Draft_Prepare')}\nPOST ${url}(${key}={{draftID}},IsActiveEntity=false)/${service.name}.draftPrepare\n${headers}\n\n{}\n`)
|
|
208
|
+
requests.push(`${title} Draft Activate\n# @name ${slug(title+'_Draft_Activate')}\nPOST ${url}(${key}={{draftID}},IsActiveEntity=false)/${service.name}.draftActivate\n${headers}\n\n{}\n`)
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
function slug(str) {
|
|
@@ -9,13 +9,20 @@
|
|
|
9
9
|
{{#profile}}
|
|
10
10
|
"[{{profile}}]": {
|
|
11
11
|
{{/profile}}
|
|
12
|
+
{{#shortcut}}
|
|
13
|
+
"auth": "ias"
|
|
14
|
+
{{/shortcut}}
|
|
15
|
+
{{^shortcut}}
|
|
12
16
|
"auth": {
|
|
13
17
|
"kind": "ias"
|
|
14
18
|
}
|
|
19
|
+
{{/shortcut}}
|
|
20
|
+
|
|
15
21
|
{{#profile}}
|
|
16
22
|
}
|
|
17
23
|
{{/profile}}
|
|
18
24
|
}
|
|
25
|
+
|
|
19
26
|
{{#isNodejs}}
|
|
20
27
|
}
|
|
21
28
|
{{/isNodejs}}
|
|
@@ -29,10 +29,6 @@ identity:
|
|
|
29
29
|
servicePlanName: application
|
|
30
30
|
parameters:
|
|
31
31
|
display-name: {{appName}}
|
|
32
|
-
{{#hasAms}}
|
|
33
|
-
authorization:
|
|
34
|
-
enabled: true
|
|
35
|
-
{{/hasAms}}
|
|
36
32
|
{{#hasMultitenancy}}
|
|
37
33
|
multi-tenant: true
|
|
38
34
|
{{/hasMultitenancy}}
|
|
@@ -50,3 +46,4 @@ identity:
|
|
|
50
46
|
- https://*.{{ tpl .Values.global.domain . }}/*/logout.html
|
|
51
47
|
<%={{ }}=%>
|
|
52
48
|
{{/hasApprouter}}
|
|
49
|
+
|