Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deployment to CF using cds up #1712

Merged
merged 8 commits into from
Mar 24, 2025
Merged
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
4 changes: 2 additions & 2 deletions guides/databases-hana.md
Original file line number Diff line number Diff line change
@@ -36,7 +36,7 @@ Package `@cap-js/hana` uses the [`hdb`](https://www.npmjs.com/package/hdb) drive

::: tip Prefer `cds add`

... as documented in the [deployment guide](deployment/to-cf#_1-using-sap-hana-database), which also does the equivalent of `npm add @cap-js/hana` but in addition cares for updating `mta.yaml` and other deployment resources.
... as documented in the [deployment guide](deployment/to-cf#_1-sap-hana-database), which also does the equivalent of `npm add @cap-js/hana` but in addition cares for updating `mta.yaml` and other deployment resources.

:::

@@ -202,7 +202,7 @@ No further configuration is necessary for Node.js. For Java, see the [Use SAP HA

`cds deploy` lets you deploy _just the database parts_ of the project to an SAP HANA instance. The server application (the Node.js or Java part) still runs locally and connects to the remote database instance, allowing for fast development roundtrips.

Make sure that you're [logged in to Cloud Foundry](deployment/to-cf#deploy) with the correct target, that is, org and space.
Make sure that you're [logged in to Cloud Foundry](deployment/to-cf#build-and-deploy) with the correct target, that is, org and space.
Then in the project root folder, just execute:

```sh
2 changes: 1 addition & 1 deletion guides/databases-postgres.md
Original file line number Diff line number Diff line change
@@ -352,7 +352,7 @@ cds add postgres

### Deploy

You can package and deploy that application, for example using [MTA-based deployment](deployment/to-cf#build-mta).
You can package and deploy that application, for example using [MTA-based deployment](deployment/to-cf#add-mta-yaml).

## Automatic Schema Evolution { #schema-evolution }

10 changes: 5 additions & 5 deletions guides/databases.md
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ npm add @cap-js/hana
<!-- REVISIT: A bit confusing to prefer the non-copiable variant that doesn't get its own code fence -->
::: details Prefer `cds add hana` ...

... which also does the equivalent of `npm add @cap-js/hana` but in addition cares for updating `mta.yaml` and other deployment resources as documented in the [deployment guide](deployment/to-cf#_1-using-sap-hana-database).
... which also does the equivalent of `npm add @cap-js/hana` but in addition cares for updating `mta.yaml` and other deployment resources as documented in the [deployment guide](deployment/to-cf#_1-sap-hana-database).

:::

@@ -371,9 +371,9 @@ This set of functions are by large the same as specified in OData:
* `endswith(x,y)` — checks whether `y` ends with `x`
* `matchespattern(x,y)` — checks whether `x` matches regex `y`
* `substring(x,i,n?)` <sup>1</sup> —
Extracts a substring from `x` starting at index `i` (0-based) with optional length `n`.
* **`i`**: Positive starts at `i`, negative starts `i` before the end.
* **`n`**: Positive extracts `n` items; omitted extracts to the end; negative is invalid.
Extracts a substring from `x` starting at index `i` (0-based) with optional length `n`.
* **`i`**: Positive starts at `i`, negative starts `i` before the end.
* **`n`**: Positive extracts `n` items; omitted extracts to the end; negative is invalid.
* `indexof(x,y)` <sup>1</sup> — returns the index of the first occurrence of `y` in `x`
* `length(x)` — returns the length of string `x`
* `tolower(x)` — returns all-lowercased `x`
@@ -1050,7 +1050,7 @@ Once you have 2 non-HANA local databases you need to have 2 distinct database co
```
In case you use 2 different databases you also need to make sure that you have the JDBC drivers configured (on the classpath).

:::
:::

</div>

155 changes: 75 additions & 80 deletions guides/deployment/to-cf.md
Original file line number Diff line number Diff line change
@@ -65,7 +65,6 @@ cd bookshop
[Learn more about Setting Up Local Development.](../../java/getting-started#local){.learn-more}
</div>

<br>
<br>

In addition, you need to prepare the following:
@@ -133,14 +132,18 @@ If you followed CAP's grow-as-you-go approach so far, you've developed your appl

We'll use the `cds add <facets>` CLI command for that, which ensures the required services are configured correctly and corresponding package dependencies are added to your _package.json_.

### 1. Using SAP HANA Database
### 1. SAP HANA Database

<div class="impl node">
While we used SQLite as a low-cost stand-in during development, we're going to use a managed SAP HANA database for production:

While we used SQLite as a low-cost stand-in during development, we're going to use an SAP HANA Cloud database for production:

</div>

<div class="impl java">
While we used SQLite or H2 as a low-cost stand-in during development, we're going to use a managed SAP HANA database for production:

While we used SQLite or H2 as a low-cost stand-in during development, we're going to use an SAP HANA Cloud database for production:

</div>

```sh
@@ -149,7 +152,7 @@ cds add hana --for production

[Learn more about using SAP HANA for production.](../databases-hana){.learn-more}

### 2. Using XSUAA-Based Authentication
### 2. Authorization/Authentication

Configure your app for XSUAA-based authentication:

@@ -174,7 +177,7 @@ Add the following snippet to your _xs-security.json_ and adapt it to the landsca

[Learn more about SAP Authorization and Trust Management/XSUAA.](https://discovery-center.cloud.sap/serviceCatalog/authorization-and-trust-management-service?region=all){.learn-more}

### 3. Using MTA-Based Deployment { #add-mta-yaml}
### 3. MTA-Based Deployment { #add-mta-yaml}

We'll be using the [Cloud MTA Build Tool](https://sap.github.io/cloud-mta-build-tool/) to execute the deployment. The modules and services are configured in an `mta.yaml` deployment descriptor file, which we generate with:

@@ -184,15 +187,15 @@ cds add mta

[Learn more about MTA-based deployment.](https://help.sap.com/products/BTP/65de2977205c403bbc107264b8eccf4b/d04fc0e2ad894545aebfd7126384307c.html?locale=en-US){.learn-more}

### 4. Using App Router as Gateway { #add-app-router}
### 4. App Router as Gateway { #add-app-router}

The _App Router_ acts as a single point-of-entry gateway to route requests to. In particular, it ensures user login and authentication in combination with XSUAA.

Two deployment options are available:

- **Managed App Router**: for SAP Build Work Zone, the Managed App Router provided by SAP Fiori Launchpad is available. See the [end-to-end tutorial](https://developers.sap.com/tutorials/integrate-with-work-zone.html) for the necessary configuration in `mta.yaml` and on each _SAP Fiori application_.
- **Custom App Router**: for scenarios without SAP Fiori Launchpad, the App Router needs to be deployed along with your application.
Use the following command to enhance the application configuration:
- **Managed App Router**: for SAP Build Work Zone, the Managed App Router provided by SAP Fiori Launchpad is available.
- **Custom App Router**: for custom scenarios without SAP Fiori Launchpad, the App Router needs to be deployed along with your application.
In this case, use the following command to enhance the application configuration:

```sh
cds add approuter
@@ -202,151 +205,144 @@ Two deployment options are available:

### 5. User Interfaces { #add-ui }

#### SAP Cloud Portal
#### Option A: SAP Cloud Portal

If you intend to deploy user interface applications, you also need to set up the [HTML5 Application Repository](https://discovery-center.cloud.sap/serviceCatalog/html5-application-repository-service) in combination with the [SAP Cloud Portal service](https://discovery-center.cloud.sap/serviceCatalog/cloud-portal-service):

```sh
cds add portal
```

#### SAP Build Work Zone, Standard Edition <Beta />
#### Option B: SAP Build Work Zone, Standard Edition <Beta />

For **single-tenant applications**, you can use [SAP Build Work Zone, Standard Edition](https://discovery-center.cloud.sap/serviceCatalog/sap-build-work-zone-standard-edition):

```sh
cds add workzone
```

### 6. Optional: Add Multitenancy { #add-multitenancy }
### 6. Optional: Multitenancy { #add-multitenancy }

To enable multitenancy for production, run the following command:

```sh
cds add multitenancy --for production
```

> If necessary, modifies deployment descriptors such as _mta.yaml_ for Cloud Foundry.

[Learn more about MTX services.](../multitenancy/#behind-the-scenes){.learn-more}

<br>

::: tip You're set!
The previous steps are required _only once_ in a project's lifetime. With that done, we can repeatedly deploy the application.
:::

<br>

### 7. Freeze Dependencies { #freeze-dependencies }

<div class="impl node">
## Build and Deploy

Deployed applications should freeze all their dependencies, including transient ones. Create a _package-lock.json_ file for that:
You can now freeze dependencies, build, and deploy the application:

```sh
npm update --package-lock-only
cds up
```

</div>

If you use multitenancy, also freeze dependencies for the MTX sidecar:

```sh
npm update --package-lock-only --prefix mtx/sidecar
```
[You need to be logged in to Cloud Foundry.](https://help.sap.com/products/BTP/65de2977205c403bbc107264b8eccf4b/7a37d66c2e7d401db4980db0cd74aa6b.html){.learn-more}

In addition, you need install and freeze dependencies for your UI applications:
<!-- ::: info Prepare monorepo setups
The CAP samples repository on GitHub has a more advanced (monorepo) structure, so tell the `mbt` tool to find the `package-lock.json` on top-level:

```sh
npm i --prefix app/browse
npm i --prefix app/admin-books
ln -sf ../package-lock.json
```

[Learn more about dependency management for Node.js](../../node.js/best-practices#dependencies){.learn-more}

::: tip Regularly update your `package-lock.json` to consume latest versions and bug fixes
Do so by running this command again, for example each time you deploy a new version of your application.
:::

## Build & Assemble { #build-mta }
::: -->

### Build Deployables with `cds build`

Run `cds build` to generate additional deployment artifacts and prepare everything for production in a local `./gen` folder as a staging area. While `cds build` is included in the next step `mbt build`, you can also run it selectively as a test, and to inspect what is generated:
::: details Essentially, this automates the following steps...

```sh
cds build --production
```

[Learn more about running and customizing `cds build`.](custom-builds){.learn-more}
# Installing app dependencies, e.g.
npm i app/browse
npm i app/admin-books

### Assemble with `mbt build`
# If project is multitenant
npm i --package-lock-only mtx/sidecar

::: info Prepare monorepo setups
The CAP samples repository on GitHub has a more advanced (monorepo) structure, so tell the `mbt` tool to find the `package-lock.json` on top-level:
# If package-lock.json doesn't exist
npm i --package-lock-only

```sh
ln -sf ../package-lock.json
# Final assembly and deployment...
mbt build -t gen --mtar mta.tar
cf deploy gen/mta.tar -f
```

:::

Now, we use the `mbt` build tool to assemble everything into a single `mta.tar` archive:
::: details Test with `cds build`

While `cds build` is already ran as part of `mbt build` in `cds up`, you can also run it standalone to inspect what is generated for production:

```sh
mbt build -t gen --mtar mta.tar
cds build --production
```

[Got errors? See the troubleshooting guide.](../../get-started/troubleshooting#mta){.learn-more}

[Learn how to reduce the MTA archive size during development.](../../get-started/troubleshooting#reduce-mta-size){.learn-more}

## Deploy to Cloud {#deploy}
[Learn more about running and customizing `cds build`.](custom-builds){.learn-more style="margin-top: 10px"}

Finally, we can deploy the generated archive to Cloud Foundry:

```sh
cf deploy gen/mta.tar
```
:::

[You need to be logged in to Cloud Foundry.](https://help.sap.com/products/BTP/65de2977205c403bbc107264b8eccf4b/7a37d66c2e7d401db4980db0cd74aa6b.html){.learn-more}
[Got errors? See the troubleshooting guide.](../../get-started/troubleshooting#mta){.learn-more style="margin-top: 10px"}
[Learn how to reduce the MTA archive size **during development**.](../../get-started/troubleshooting#reduce-mta-size){.learn-more}

This process can take some minutes and finally creates a log output like this:
This process can take some minutes and finally logs an output like this:

```log
[…]
Application "bookshop" started and available at
"[org]-[space]-bookshop.landscape-domain.com"
"[org]-[space]-bookshop.<landscape-domain>.com"
[…]
```

Copy and open this URL in your web browser. It's the URL of your App Router application.
You can use this URL to access the approuter as the entry point of your application.

For **multitenant applications**, you have to subscribe a tenant first. The application is accessible via a tenant-specific URL after subscription.

::: tip For multitenant applications, you have to subscribe a tenant first
In this case, the application is accessible via a tenant-specific URL after onboarding.
::: tip No index page and SAP Fiori preview in the cloud
The default index page and [SAP Fiori preview](../../advanced/fiori#sap-fiori-preview), that you are used to see from local development, are only available for the development profile and not available in the cloud. For productive applications, you should add a proper SAP Fiori Elements application through on of the [user interface options](#add-ui) outlined before.
:::

### Inspect Apps in BTP Cockpit

Visit the "Applications" section in your [SAP BTP cockpit](https://help.sap.com/docs/BTP/65de2977205c403bbc107264b8eccf4b/144e1733d0d64d58a7176e817fa6aeb3.html) to see the deployed apps:

![The screenshot shows the SAP BTP cockpit, when a user navigates to his dev space in the trial account and looks at all deployed applications.](./assets/apps-cockpit.png){.mute-dark}
![The screenshot shows the SAP BTP cockpit, when a user navigates to his dev space in the trial account and looks at all deployed applications.](./assets/apps-cockpit.png)

::: tip Assign the _admin_ role
We didn't do the _admin_ role assignment for the `AdminService`. You need to create a role collection and [assign the role and your user](https://developers.sap.com/tutorials/btp-app-role-assignment.html) to get access.
::: tip Next up: Assign the _admin_ role
In order to access the admin APIs you need to assign the _admin_ role required by `AdminService`. Create a role collection and [assign the role and your user](https://developers.sap.com/tutorials/btp-app-role-assignment.html) to get access.
:::

[Got errors? See the troubleshooting guide.](../../get-started/troubleshooting#cflogs-recent){.learn-more}

### Upgrade Tenants {.java}

## Keep Dependencies Up-to-date { #freeze-dependencies }

Deployed applications should freeze all their dependencies, including transient ones. Therefore, on first execution, `cds up` creates a _package-lock.json_ file for all application modules.

It is **essential to regularly update dependencies** to consume latest bug fixes and improvements. Not doing so will increase the risk of **security vulnerabilities**, expose your application to **known bugs**, and make future upgrades significantly harder and more time-consuming.

We recommend setting up [Dependabot](https://docs.github.com/en/code-security/dependabot), [Renovate](https://docs.renovatebot.com/) or similar automated solutions to update dependencies **one-by-one** to easily identify breaking changes, minimize risks, and ensure continuous compatibility and **stability of your application**.


## Upgrade Tenants {.java}

The CAP Java SDK offers `main` methods for Subscribe/Unsubscribe in the classes `com.sap.cds.framework.spring.utils.Subscribe/Unsubscribe` that can be called from the command line. This way, you can run the tenant subscribe/unsubscribe for the specified tenant. This would trigger also your custom handlers, which is useful for the local testing scenarios.

In order to register all handlers of the application properly during the execution of a tenant operation `main` method, the component scan package must be configured. To set the component scan, the property <Config java>cds.multitenancy.component-scan</Config> must be set to the package name of your application.

The handler registration provides additional information that is used for the tenant subscribe, for example, messaging subscriptions that are created.

::: warning
You can stop the CAP Java back end when you call this method, but the _MTX Sidecar_ application must be running!
::: warning The MTX sidecar must be running
You can stop the CAP Java backend when you call this method, but the MTX sidecar application must be running!
:::

This synchronization can also be automated, for example using [Cloud Foundry Tasks](https://docs.cloudfoundry.org/devguide/using-tasks.html) on SAP BTP and [Module Hooks](https://help.sap.com/products/BTP/65de2977205c403bbc107264b8eccf4b/b9245ba90aa14681a416065df8e8c593.html) in your MTA.
@@ -355,10 +351,10 @@ The `main` method optionally takes tenant ID (string) as the first input argumen

The method returns the following exit codes.

| Exit Code | Result |
| --------- | ------------------------------------------------------------------------------------------------ |
| 0 | Tenant subscribed/unsubscribed successfully. |
| 3 | Failed to subscribe/unsubscribe the tenant. Rerun the procedure to make sure the tenant is subscribed/unsubscribed. |
| Exit Code | Result |
|-----------:|---------------------------------------------------------------------------------------------------------------------|
| 0 | Tenant subscribed/unsubscribed successfully. |
| 3 | Failed to subscribe/unsubscribe the tenant. Rerun the procedure to make sure the tenant is subscribed/unsubscribed. |

To run this method locally, use the following command where `<jar-file>` is the one of your applications:

@@ -392,6 +388,7 @@ sed -i 's/org.springframework.boot.loader.JarLauncher/-Dloader.main=com.sap.cds.

:::

<!--
---
{style="margin-top:11em"}

@@ -471,12 +468,10 @@ cf logs <app-name>-db-deployer --recent

to ensure that SAP HANA deployment was successful. The application itself is by default in state `started` after HDI deployment has finished, even if the HDI deployer returned an error. To save resources, you can explicitly stop the deployer application afterwards.
:::
::: tip No Fiori preview in the cloud
The [SAP Fiori Preview](../../advanced/fiori#sap-fiori-preview), that you are used to see from local development, is only available for the development profile and not available in the cloud. For productive applications, you should add a proper SAP Fiori application.
:::


::: warning
Multitenant applications are not supported yet as multitenancy-related settings are not added to the generated descriptors. The data has to be entered manually.
:::

[Got errors? See the troubleshooting guide.](../../get-started/troubleshooting#aborted-deployment-with-the-create-service-push-plugin){.learn-more}
[Got errors? See the troubleshooting guide.](../../get-started/troubleshooting#aborted-deployment-with-the-create-service-push-plugin){.learn-more} -->
Loading
Oops, something went wrong.