Skip to Content
Technical Articles
Author's profile photo Daniel Mieg

CI/CD Tools for SAP BTP ABAP Environment

In the on-premise ABAP world, lifecycle and quality processes can be controlled by the ABAP systems themselves. Think of transport routes and jobs to execute different checks. In the SAP BTP ABAP Environment aka Steampunk, this is no longer possible. Steampunk systems are independent of each other, and source code is “transported” with git-based solutions: gCTS and abapGit. While different systems in one global account are connected to the same repositories (read: “software components”), they do not know of each other. Due to this, the driver of lifecycle and quality processes needs to shift from the ABAP system itself to an external driver – for example: a classic Continuous Integration / Continuous Delivery (CI/CD) server like Jenkins. Of course, the Steampunk systems need to expose the functionality via APIs so that a CI/CD server can control those processes.


Components of Jenkins driven Steampunk CI/CD processes

In the next sections, I want to introduce the released APIs regarding gCTS and ABAP Test Cockpit (ATC), as well as all the functionality we built on top of these APIs to make your life easier: reusable functions using these endpoints and a predefined pipeline which lets you easily create CI/CD processes for Steampunk.

To make the consumption of our pipeline and functions (or “steps” in the context of a pipeline) as convenient as possible, we decided to contribute them to the Project Piper. This open-source project is the home of different steps and pipelines related to the SAP Ecosystem.

Let’s start with the easiest way to create a pipeline and drill our way down to the APIs.


ABAP Environment Pipeline

The “ABAP Environment Pipeline” is a predefined pipeline usable on a Jenkins server. It covers most use cases and is ready to use: no programming is required – only the configuration of the pipeline is necessary. The pipeline consists of several stages. A stage groups a set of steps together, which are related in content. One stage, for example, is called “Prepare System”. As the name indicates, this stage takes care of preparing a system that is usable within the pipeline. It includes creating a Steampunk system and configuring the communication.


Layers of a predefined Jenkins Pipeline

The ABAP Environment Pipeline supports various use cases. A simple scenario that can be realized with this predefined pipeline is running nightly ATC checks on the released source code. (Of course, you will benefit most from such a pipeline if you release your Transport Requests early and often.) This pipeline would consist of the following stages:

  • Prepare System: This stage creates the Steampunk system and configures the communication to the system
  • Clone Repositories: This stage clones your repositories (software components) to the system
  • ATC: This stage executes ATC checks on the configured repositories
  • Post: This stage is automatically executed in the end and will delete the Steampunk system



Diagram of the ABAP Environment Pipeline. The Post stage is not displayed. Stages that are not configured are skipped.


While the “ABAP Environment Pipeline” itself is predefined, you still have the option to customize it via configuration and extension. In principle, a stage of this pipeline will only be executed if it is configured. This means that, if I do not want to create a new Steampunk instance for every pipeline execution, I just do not configure the “Prepare System” stage. In case a specific stage does not quite fit my needs, I can create an extension file for this stage and add missing functionality (or even rewrite the whole stage). A popular example is to extend the ATC stage with the “CheckStyle” Plugin, which creates helpful diagrams out of the XML output of the ATC API.


Example set of CheckStyle diagrams

As you can imagine, there is a lot of room for creativity. You can head to the documentation to learn more about the pipeline or check out some examples in this repository.

If this pipeline does not quite fit your needs, you still have the option to reuse our steps to create your own pipeline. Let’s have a look in the next section.


Pipeline Steps

I want to start this section by highlighting the pipeline steps’ design pattern in Project Piper. Some years ago, Piper’s focus was on the CI server Jenkins: The pipeline steps were written in the language “Groovy” and could only run on this technology. Nowadays, while Jenkins is still widespread, other technologies are gaining popularity. Therefore, the decision was made to switch the implementation of pipeline steps over to “Go” (or “Golang”). This language compiles the source code to a binary, which can be executed on different CI servers. Here is an example of how the “clone” step can be called via the piper binary:

abapEnvironmentCloneGitRepo --host --username myUser --password myPassword --repositoryName  “/DMO/GIT_REPOSITORY” --branchName master

Of course, for users of a Jenkins CI server, a Jenkins step implementation is built on top of the Golang implementation. So, the full picture is as follows: several WebAPI endpoints of Steampunk are called by the Golang implementation and the resulting binary is then used by the Jenkins step.

Layers of a Piper step


Before looking at the WebAPI, let me show you an example of a Jenkinsfile defining a custom pipeline and reusing the Jenkins step “abapEnvironmentCloneGitRepo”.

@Library(['piper- lib-os']) _
pipeline {
  agent any
    stage("Pull Git Repository"){
      steps {
        abapEnvironmentCloneGitRepo(script: this) 

The annotation “@Library([‘piper-lib-os’]) _” is a reference to the Project Piper jenkins-library (, which would have been configured on the Jenkins server with the ID ‘piper-lib-os’. The reused step is part of a pipeline stage and simply called with the statement “abapEnvironmentCloneGitRepo(script: this)”. The parameters for this step (e.g. endpoints, credential IDs etc.) would be provided in a separate configuration file.

The documentation of our example step for the action “Clone” can be found here. Other available steps can then be found in the documentation menu under “Library steps”.

Now that you know how to use the steps in Jenkins or via the Golang binary, what are they actually doing? Let’s have a look at our example step: the action of cloning a repository. At first, the step authenticates on the system (and fetches the X-Csrf-Token, which is required for a POST request). After triggering the “clone” action, the step polls the status of the action to find out, when the repository is finally cloned successfully. As you can see, the steps implement a simple series of API requests to achieve a single task (“clone a git repository”).

Of course, if you really want to control every detail of your pipeline (or want to run it on a CI server that is not able to support the Golang binary), you can use the released APIs for gCTS and ABAP Test Cockpit directly. Let’s have a look at them in the next section.


The goal of the gCTS API is to enable you to automate the most crucial functions that you may know from the “Manage Software Components” app: cloning a repository, pulling a repository, and checking out a branch. The service, including those endpoints, is documented here.

For example, the following request would clone the software component “/DMO/GIT_REPOSITORY” to the system, with the branch “master” being checked out.


POST/sap/opu/odata/sap/MANAGE_GIT_REPOSITORY/Clones HTTP/1.1
Content-Type: application/json
Accept: application/json

        "sc_name": "/DMO/GIT_REPOSITORY"
        "branch_name": "master"


A second service would then allow you to execute a check run with the ABAP Test Cockpit (ATC). You can specify the check variant and the software component or package to be checked in the request body. Here is an example:


POST https://<>:<port>/sap/bc/adt/api/atc/runs?clientWait=false
Content-Type: application/

<?xml version="1.0" encoding="UTF-8"?>
<atc:runparameters xmlns:atc="" xmlns:obj="">
        <obj:softwarecomponent value="/DMO/GIT_REPOSITORY"/>


The full documentation can be found here.


What’s next?

In the future, the ABAP Environment Pipeline will support the build process of ABAP Add-ons for Steampunk. This scenario is intended for SAP partners who want to build Software as a Service (SaaS) solutions for the SAP BTP. Some stages and steps are already contributed and part of the ABAP Environment Pipeline. While this is currently our focus, we are still continuously improving the existing pipeline and steps, and we are hoping to support more tools in the future.

Please let me know if you have feedback or questions and feel free to post in the comment section below (or head to the Answer Hub for general questions).


Notice: images are my own.

Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Thomas Schneider
      Thomas Schneider

      Hi Daniel, a very cool blog. I really appreciate ist

      Author's profile photo Andre Fischer
      Andre Fischer

      Very well explained !
      I was waiting for such a comprehensive explanation so that I can share it with customers and partners.

      Author's profile photo Lars Hvam
      Lars Hvam

      Thanks, few questions/comments,


      A: Can this be tested in the ABAP Steampunk trial systems?

      B: According to, the system is not created automatically ? Following [1] the automation part is important for CI/CD, I guess this will be fixed in a upcoming release?

      D: What would the typical flow/trigger/lifecycle be of this pipeline? With one development system I guess there will not be feature branches? So the integration will not be for "each person"/"each integration" [1], but a set of integrations by a set of developers?

      C: for "Executing ABAP Test Cockpit (ATC) Check Runs", , it looks like it is not possible to configure the variant? Or am I missing something?

      E: "Keep the build fast" in [1], any experiences on the time taken to execute the pipeline?



      Author's profile photo Daniel Mieg
      Daniel Mieg
      Blog Post Author

      Thanks for your comment!

      Regarding your questions:

      A: I don't think this is possible as both the software component lifecycle and the communication is restricted (see this blog post). 

      B: The system itself is created automatically, but we have currently no easily accessible API to check when the system is ready. But, hopefully this will be solved soon.

      D: Branches are generally supported. Currently, they are intended to be used as “release branches”, e.g. to split up the development into a “development” and “maintenance” code line. Personally, I’m a big fan of “feature branch” development (or via forks), but I think there are a few missing pieces to do this with Steampunk systems. For now, it is also only possible to have a scheduled pipeline.

      So, to answer your question: the typical case would be a single development system and a scheduled pipeline supplying different systems with the released development and/or running checks.

      C: As far as I know, this should be possible (see last example in this documentation).

      E: The most time consuming part is creating a Steampunk system (see also point B). When this can be done fully automated – hopefully soon – I would estimate that the pipeline takes about one hour to run (probably a bit faster). It is, of course, also possible to use a static Steampunk system. Then, I assume, the deciding factor would be the size of the software component. Our tests (with small software components) took around five minutes.

      Author's profile photo Lars Hvam
      Lars Hvam

      Thanks, sorry about the letter sequence(ABDCE), but guess its easier to keep it that way 🙂

      D: Does this mean Steampunk will, in the future, support having one development system where each developer can work on their own branch within the same software component at the same time?

      I think there is a large difference between having a scheduled job running and Continuous Integration, with a scheduled job it is difficult to figure out where some changes broke, assuming multiple developers have made changes since last scheduled job.


      E: Its difficult, a static system could potentially produce incorrect results, eg. with unit tests modifying database contents or calling XCO framework. Its not a correct unit test if it does this, but in a generic setup it might be worth making some compromise depending on the nature of the development.

      from [1],

      Most of my colleagues consider a build that takes an hour to be totally unreasonable

      Another compromise, not sure if its possible(?), would be to have systems on stand-by, ready to accept pipeline jobs.

      And also front load as much as possible to run before it reaches an actual ABAP system, see "Scenario 9" in [2]





      Author's profile photo Daniel Mieg
      Daniel Mieg
      Blog Post Author

      D: Does this mean Steampunk will, in the future, support having one development system where each developer can work on their own branch within the same software component at the same time?

      No, I did not want to imply that.

      I think there is a large difference between having a scheduled job running and Continuous Integration, with a scheduled job it is difficult to figure out where some changes broke, assuming multiple developers have made changes since last scheduled job.

      I agree.

      Another compromise, not sure if its possible(?), would be to have systems on stand-by, ready to accept pipeline jobs.

      I think this could be possible. But this is not planned on our side and has to be done by the consumer. This would be a reason to choose a custom made pipeline (and only reusing the steps) over the predefine ABAP Environment Pipeline.

      Author's profile photo Muhammad Ilyas
      Muhammad Ilyas

      D: one system for all developer working on different branches? I believe this can't be achieved on common data dictionary.

      Author's profile photo Felipe Silva
      Felipe Silva

      Great to see things moving forward towards a CI/CD approach! For sure there will be several technical challenges to fully get there. Keep it up!

      Not to mention all other barriers that typically relegates technical excellence to a lower role. Or the huge skills set (and mindset) gap that makes it possible and relevant in a customer code base.

      Anyway! I had a question: what is the ideia for running AUNIT tests in the pipeline, through some ATC check? Sorry if it is a dumb question, I still didn't.go through all the documentation.


      Felipe S.


      Author's profile photo Daniel Mieg
      Daniel Mieg
      Blog Post Author

      Thanks for your comment - and sorry for the late response.

      Yes, currently we recommend to execute AUNIT via the ATC functionality.


      Kind regards,


      Author's profile photo Karan Chopra
      Karan Chopra

      Hi Daniel,

      while initializing  the Cx Server it returns error in the windows cmd for below command

      docker run -it --rm -u $(id -u):$(id -g) -v "${PWD}":/cx-server/mount/ ppiper/cx-server-companion:latest init-cx-server

      error - unknown shorthand flag: 'g' in -g

      Are there some shortcoming while using windows?


      Author's profile photo Sijin Chandran
      Sijin Chandran

      Hi Daniel,

      Am very new to this CI/CD based Software Lifecycle Management and even 'ABAP Environment for BTP' and majority of my experience yet is with BTP Trial account only, hence please bear with me if my ask is too basic.

      When we have CI/CD tools based code migration and deployment setup then what is the relevance of TRs getting generated in Steampunk environment ?

      Does this both go hand in hand and TR concept is still there as a Versioning provision for ABAP objects or is there some other relevance, kindly enlighten on this.



      Author's profile photo Thomas Fiedler
      Thomas Fiedler

      Hi Sijin,

      in the development system of SAP BTP you are still working with transport tasks and requests. Once you have finshed your developments you release the transport request exactly the same as in on-premise development. BUT the transport requests will not reach any other ABAP system directly. The objects are commited to a GIT repository. The software artifacts are then deployed from the Git repository into the test and production systems.



      Author's profile photo Sijin Chandran
      Sijin Chandran

      Thanks a lot for your time and precise answer.

      So that means once a Transport is moved using gCTS (Git-enabled Change and Transport System ) to a next landscape say QA, there the Object would be having that TR in the version right ? Only the way it got Transported from one Landscape to another got changed with gCTS.



      Author's profile photo Thomas Fiedler
      Thomas Fiedler


      Small remark: Up to now customers do not have access to the Git repository directly and hence cannot use the version control of Git. This is planned for upcoming releases that you can manage the Git repository on your own.



      Author's profile photo Sijin Chandran
      Sijin Chandran

      This was a great help for getting clarity on gCTS, me being very novice into 'ABAP Environment for BTP' related developments.

      Much appreciated!