Technical Articles
Setting up CI/CD for SAP Cloud Foundry on GitLab for a SAPUI5 application built with UI5 Tooling
For my latest project I had to develop several SAPUI5 applications as a side-by-side extension to SAP S/4HANA Public Cloud. As our S/4HANA Public Cloud landscape consists out of two tenants (testing and production) we also have two separate SAP Cloud Platform Cloud Foundry sub-accounts.
At the beginning of the project we didn’t have any CI/CD in place for our GIT repositories. So for each release (+/- every 2 weeks) we manually deployed our applications to production. As you can imagine this becomes quite a hassle if you need to deploy a lot of applications (each release contains bug fixes to existing applications and/or new applications) and there is quite some chance for human mistakes when doing everything manually.
So I thought to myself, wouldn’t it be so much easier to be able to deploy these applications with a push of a button (or even automatically)?! Let’s try out CI/CD!
For the sake of the walk-through I created a demo GIT repository and mimicked the SAP Cloud Platform landscape on a trial account.
SAP Cloud Platform Landscape
I’m not going into detail on how to setup the SAP Cloud Platform landscape since this is not the purpose of this blog. (and there are a lot of guides describing how to set this up)
Basically my setup looks like this (sub-accounts):
Sub-account trial-dev:
Subaccount trial-prd:
The SAPUI5 application
Well, for this walk-through we’ll deploy a very simple application generated with easy-ui5 (created by Marius Obert ). I won’t go in to detail on how to generate such an application, a good guide can be found here.
When you generate the application, the only important thing to watch out for is to choose “Cloud Foundry HTML5 Application Repository” when asked the question “On which platform would you like to host the application?“.
To make the karma-ci tests work in the docker image, one small adaption (browser and customLauncher section) to the file karma-ci.conf.js needs to be done so it reflects like following:
module.exports = function(config) {
require("./karma.conf")(config);
config.set({
// test results reporter to use
// possible values: 'dots', 'progress', 'coverage'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress'],
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['ChromeHeadlessNoSandbox'],
customLaunchers: {
ChromeHeadlessNoSandbox: {
base: 'ChromeHeadless',
flags: [
'--no-sandbox', // required to run without privileges in docker
'--user-data-dir=/tmp/chrome-test-profile',
'--disable-web-security'
]
}
},
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true
});
};
Empty template looks like:
GitLab repository configuration
My repository consists out of 2 stable branches develop and master. These are protected against direct commits, so changes to these branches can only be made using merge requests. Merge requests are protected so they can only be created if the pipeline of the branch succeeded. This means that for each new change we create so-called feature branches.
In the actual project we’re using a gitflow-like setup, but for this walk-through that’s a little over-complicated. For now we’ll work with following setup:
Branch | Continuous Integration | Continuous Delivery (+ deployment) |
Master | Yes (ESLint + Karma-ci) | Yes (to prd space) |
Develop | Yes (ESLint + Karma-ci) | Yes (to dev space) |
my-super-cool-feature1 | Yes (ESLint + Karma-ci) | No |
To facilitate the CI/CD process in GitLab, I created a docker image (can be found here) containing the necessary tools. Basically the tools are:
- Node.js
- npm
- CF CLI
- CF Multiapps plugin
- Chrome browser
To activated CI/CD on the repository in GitLab, the only thing that needs to be done is create a .gitlab-ci.yml file inside the root of your project. For our project we’ll have 3 stages:
- test (runs ESLint and Karma-ci)
- build (creates an MTA package)
- deploy (deploys MTA package to SAP Cloud Foundry)
Our .gitlab-ci.yml file will look like this:
image: geertjanklaps/node-cf-cli:latest
cache:
paths:
- node_modules/
stages:
- test
- build
- deploy
ESLint:
stage: test
before_script:
- npm install
script:
- npm run test
MTA:
stage: build
before_script:
- npm install
script:
- npm run build:mta
only:
- develop
- master
deploy_dev:
stage: deploy
before_script:
- npm install
- cf login -a $API_ENDPOINT -u $USER -p $PASSWORD -o $ORGANIZATION_DEV -s $SPACE_DEV
script:
- npm run deploy
after_script:
- cf logout
only:
- develop
deploy_prd:
stage: deploy
before_script:
- npm install
- cf login -a $API_ENDPOINT -u $USER -p $PASSWORD -o $ORGANIZATION_PRD -s $SPACE_PRD
script:
- npm run deploy
after_script:
- cf logout
only:
- master
To get this script working you’ll need to define following variables in your CI/CD settings of you GitLab repository:
Variable | Value | Masked |
API_ENDPOINT | API url for your environment | No |
USER | e-mail address | No |
PASSWORD | password | Yes! |
ORGANIZATION_DEV | organization name dev space | No |
ORGANIZATION_PRD | organization name prd space | No |
SPACE_DEV | space name within dev organization | No |
SPACE_PRD | space name within prd organization | No |
Now we’re all set! If we push changes to our my-super-cool-feature1 branch this will result in following pipeline:
After merging our feature branch into the development branch:
After merging our development branch into the master branch:
Well that’s basically all it takes for setting up a continuous integration / continuous delivery pipeline with continuous deployment to your SAP Cloud Platform Cloud Foundry environments. I hope this saves you a lot of time and figuring things out! Feel free to try it out and leave your comments / remarks!
Hi Geert-Jan,
why did you choose this setup instead of other options? It would be great if you could elaborate on that on your article. Especially, because there are a lot of community posts on the various options. I am thinking of Project Piper, GitHub Actions or the likes.
Kind regards
Martin
Hi Martin,
Well basically the choice wasn't really ours, the customer was using GitLab so we needed to integrate the CI/CD process in GitLab. So GitHub actions are for sure not an option and Project Piper is focused on GitHub / Jenkins.
One option could have been to setup a Jenkins server and integrate GitLab instead of GitHub and try to use Project Piper, but I'm not really sure if that's possible. Anyway, that option would have required us to setup a separate CI server (Jenkins) while we have an integrated CI server on GitLab.
Another point why we didn't even try to use Project Piper is that the currently provided scenario of deploying SAPUI5 apps to the SAP Cloud Platform is focused on the NEO environment, while we are using the SAP Cloud Platform Cloud Foundry environment. (Scenario can be found here).
Best regards,
Geert-Jan Klaps
Hi Geert-Jan,
That was very insightful. Thanks a lot for the thorough comment.
Kind regards
Martin
Good Article
Hi,
I tried to implement the solution and I have an error with the script
which is not recognized.
It seems the Business Application Studio is using now the command MBT to build the project.
May be it should be better to use this command ?
Regards,
David Bizien
Hi,
Sure, in the meanwhile a lot has changed. The build process now uses mbt as you mention, so you can for sure replace the build command with the new mbt build command.
Best regards,
Geert-Jan
That means, we need to update the docker image in order to install the lastest version of MBT. Correct ?
Best regards,
David Bizien
Here you can find image with cf8-cli, latest npm and node v14 with preinstalled mbt.
https://hub.docker.com/r/aaugmentum/node-cf-cli
Dockerfile: