Making an OnPremise ABAP CI/CD with Github Actions

Let’s say you are ready to release a new update to your ABAP library, used by most of your customers: what’s your current approach to dispatch the release from your internal development system to the customer’s?

In other environments, like Node.Js, this would be as easy as a publish command of the new release and an update command on every consumer project; even better, if I can take advantage of a CI/CD pipeline those steps become automatic, and I just have to check if the new release works properly. 

If you are an ABAP developer with no experience in other programming languages, you might not fully understand what I’m referring to. The concept of modularity may be something you’re not very familiar with, given its limited practical use in the SAP environment.

These are probably the steps you would follow to deliver the latest release of your library:

  1. the library is available on your central development system;
  2. develop the new features and prepare the latest release on this system;
  3. prepare a transport request with the whole library;
  4. manually check that the customer’s system is compliant with the new release (e.g. no braking changes, ABAP version compatibility, no syntax/runtime errors on external dependant objects);

Now imagine repeating the same steps for each library, for each customer… it is pretty clear that it would be overwhelming! And what if you are not the only contributor to those libraries? And what if you are not able to easily access the target systems?

Set aside the problems described above for a minute (we’ll find a solution later 😉) modular programming is a really important concept, especially for companies that can gain benefit from reusable code. The concept is to separate your work into smaller, independent packages, making it well organized, maintainable, and, most importantly, reusable.

1629546268915.jfif

 

Let me introduce you to the dotabap index website: throughout the years, many open source projects were created by the community to improve the ABAP programming experience.

In this blog, we’re going to see how to benefit from a few of these projects:

  • abapGit
  • abapLint
  • ADASH
  • TRM (Transport Request Manager)

Making use of open source projects

In this article, I will show you how to solve the problem described above:

making new releases of ABAP libraries in S4, ready to be delivered, installed and used on customer’s systems, effortlessly and in compliance with any other popular programming language procedure.

Continuous integration and Continuous delivery

The following procedure can help you solve the problems described above:

Stage 1 (Plan & Code): Developers code the software updates (depending on your organization, there could be more than one developer working on the same task)

Stage 2 (Test): The software is tested in the staging environment. Tests can be automated (syntax checks, mocking data, unit tests…) but sometimes they must be performed manually by a quality assurance team.

Stage 3 (Deploy): Once all tests get the green flag, we can safely release the update. This means packing our developments and making them ready to install to any system compliant with the requirements.

Stage 4 (Deliver): Install the new update to a subset or to all the systems involved. This assures that all the systems run the latest (and greatest) version of your software!.

These steps are known as CI/CD (continuous integration and continuous delivery):

 

CICDBlog.png

 

Of course, a little adaptation is required to make it work with ABAP, but the goal is to put in place everything that is needed to code, test, and deliver a new software release based on the CI/CD approach.

We will use Github Actions, a CI/CD platform inside of Github that allows us to automate most of the steps above.

Branching strategy

Git (and Github) is the starting point for this CI/CD. The GitHub platform offers many tools such as pull requests, issues, discussion and projects; in our case we’ll focus on branches and pull requests, as they are the triggers of our actions: with that being said, I will set up my branching strategy this way(keep in mind there are many others to choose from).

git_branching.png

 

  • Features and fixes are developed in their own specific branch (i.e. branch1, branch2)
  • When a feature/defect branch is considered done, I’ll create a pull request to main
  • When one (or more) feature/defect is merged into main, I’ll manually create a new release

Let’s take a look at this branching strategy at work with ABAP, along with some automation using Github Actions:

For demonstration purposes, I set up two Nuve ABAP Platform 1909 instances. The first one represents the development environment (source), and it will also act as testing environment (it would be better to set up a fresh instance for testing, but let’s keep it simple). The second instance is the target for the deployment of the new release (in a real world scenario you may not have access to the target instance: in that case, the following workflow would still be valid).

workflow.jpg

 

The next paragraphs will explain in detail what the actions mentioned above.

abapGit

abapGit is the most established ABAP open source project. abapGit is the git client in the SAP world: since 2014, the lack of git for ABAP has been compensated/overcome by this tool.

There are lots of articles and tutorials about abapGit, getting started is as easy as looking into its documentation.

abapGit becomes essential in a CI/CD development stage, as git pushes are often the triggers of events.

If commits are done with the right frequency, it’s also very handy in situations where code needs to be reverted.

abapLint Github app

Its installation is very easy: all you need to do is enable its Github application to access your repository and abapLint will run on each commit.

abapLint is a linter: if any of your code isn’t compliant with the rules established on the project, you’ll be notified on the commit.

abapLint comes with a set of default rules, and you can add your own too.

All the available check runs are described on the official website.

You can read more about abapLint here, as there are many more use cases (in this article we are only interested in the Github app).

ADASH

ADASH is a hidden gem among open source projects: it runs ABAP unit tests from the command line.

A single CLI command is enough to run all of the unit tests available in a package: this enables automated tests as a step of a CI/CD pipeline.

You can read more about ADASH in this article.

TRM (Transport Request Manager)

TRM is an open-source project I launched in 2023.

At the beginning, TRM was an internal tool developed for the company I work for, and its purpose was to simplify the delivery of new releases of our ABAP libraries. We later figured out this could be a project the community could benefit from.

Our first approach was solely based on abapGit, however we initially misinterpreted some of its capabilities (check the differences below), and we realized that we needed a custom solution in order to achieve our goals.

TRM is a manager for transport requests: it works via CLI installed on your machine and has commands inspired by package managers like NPM.

The two fundamental commands of TRM are publish and install.

  • trm publish <package name> packs up everything you developed  into one (or more) transport request(s) and stores the result into a registry (most likely in cloud).
  • trm install <package name> retrieves the transport request(s) from the registry and automatically imports them into a system

A manifest file is generated when TRM packs up a transport request (and is used during unpacking): information about the package is stored inside the manifest file, such as its version, authors, required dependencies, and required standard objects.

TRM is made up of two main components: trm-server and trm-client.

trm-server (ABAP package that exposes RFC APIs) is installed on your source SAP system and all your target development SAP systems. trm-client (Node.js CLI) is installed on your machine.

Once a TRM package is installed into a target development system, it can be transported across its landscape (DEV -> QLT -> PRD) as usual.

In addition, a TRM transport has a linked manifest, and this allows you to keep track of its package descriptor (e.g. find out which version is installed on any system in the landscape).

trm-server is not required on any of your target landscape systems except development, where packages are installed.

trm_install_landscape.png

 

To learn more about TRM, visit its documentation.

Main differences between TRM and abapGit

  • Both can work on their own: you don’t need TRM to make abapGit push/pulls and you don’t need abapGit to publish/install TRM packages;
  • in the development phase, using abapGit to push/pull commits is the best approach: push/pull is fast, commits are reversible, different branches/tags can be used. A version control tool such as git is necessary in this phase, regardless of the programming language;
  • in the deploy/install phase, using TRM is the best approach: TRM uses TMS behind the scenes, which is the SAP standard way to deliver developments across different systems. TMS is reliable and supports every development object. TRM keeps track of package versions installed across your landscape, as well as ensuring dependencies are met;
  • both projects are open source, documented and open to fixes/features from the community;
  • abapGit needs a git repository , TRM needs a TRM registry (eg. trmregistry.com);
  • abapGit is used via SAP GUI (transaction or SA38), TRM is used via CLI on your machine;
  • TRM supports everything that can be put inside of a transport (development objects, translations, customizing…) while abapGit supports whatever can be serialized/deserialized (check its documentation for the full list)

Example of CI/CD on S4 with Github

What I used

Github

I made a Github repository with the abapLint app (https://github.com/marketplace/abaplint) and I created three Github Actions.

The repository is also configured to block pull requests in case of failing checks(abapLint and ADASH).

As a general rule of the repository, direct push to the main branch is not allowed: you must use a pull request.

abapGit

I installed abapGit on both the source and target systems: on the target system, it is only needed for the initial install of trm-server.

TRM Registry

I have a TRM Registry account (https://trmregistry.com/) and I’ll use it to publish the public package that will be created.

A TRM account is not required to install the package since it is public.

Github Actions self-hosted runner

I set up a self-hosted runner following this documentation.

This is necessary because:

  1. TRM needs to be installed and it is easier/faster to use my own pc as a runner instead of installing all of the necessary components on a Github runner
  2. In a real-world scenario, unlike this demo where I’m setting up temporary ABAP Platform 1909 instances, my internal systems and customer systems are only accessible through my VPN, so GitHub runners wouldn’t be able to reach them.

Nuve Platform

As a proof of concept, I decided to use Nuve Platform as the provider of my systems.

As I said earlier, it would be possible to use internal systems with the self-hosted runner technique, however a fresh instance is better for demo purposes.

After setting everything up, I started doing some commits with abapGit and a custom Z package.

You can check the demo repository here: https://github.com/RegestaItalia/abapcicd

Example of failing code

The first test I did was checking if the failing conditions actually work.

I created a new class inside my Z package:

1_failingcode.png

As a rule of my repository, I decided to avoid spaces before a dot.

I then added some unit tests to this class that will also fail:

2_classtest.png

I pushed the code to the repo, and the feedback of the CI/CD were just as expected:

3_adashfail.png

If I try to make a pull request with errors it will be blocked, because of the repository rules I set up:

4_prblock.png

You can check the repository in this state here:

https://github.com/RegestaItalia/abapcicd/tree/d95e915f8597c033870c82fc335ce5b5d98cb19a

Also, the test workflow run here: https://github.com/RegestaItalia/abapcicd/actions/runs/9805690513

Example of code that does not fail

I then fixed the errors I made earlier: I removed the space before the dot in the class and fixed the expected result of 1+1 in its unit test class.

Pushing the fixing commit, the pull request was updated with the OK status 🙂

5_checkok.png

 

With working code, I am able to merge my feature branch into main.

You can check the success test workflow run here: https://github.com/RegestaItalia/abapcicd/actions/runs/9805742193

Triggering a new release

If you take a look at my demo repository, you will see that the creation of a new Github release triggers a Github Action to publish a new TRM release.

So I created a new Github release and at the end I was notified via email that a new TRM release was published.

You can see the release on the registry here: https://trmregistry.com/#/package/abapcicd.

The last step of the Github release workflow is the deployment to target systems, and sure enough my new release was imported correctly.

6_trmrun.PNG

You can check the publish/distribute workflow run here:

https://github.com/RegestaItalia/abapcicd/actions/runs/9805896703

Conclusion

By setting up this Github Actions CI/CD, I was able to create a new release of an ABAP library that ensures:

  • Working unit tests
  • ABAP syntax compliant to abapLint rule set

On top of that, I have all the benefits given by Github/abapGit during the code phase (issues, branch/pull requests…) and TRM during the deploy/distribute phase (dependencies, versioning).

You can check TRM benefits in the install and publish documentation.

 

And that’s all, folks! Thanks for diving into this topic with us.

As always, feel free to share your thoughts or reach out if you have any questions.

Scroll to Top