Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
atsybulsky
Active Participant
Merry Christmas !

This post is not about ABAP directly but about tooling around it. You probably know about abapGit written by Lars Hvam (regards!). You might also know about another tool from him called abaplint - a static code analyzer. In a nutshell, it is a kind of SCI but written in javascript and so can be run outside of an SAP system. I won't describe abaplint itself in detail. You can search a couple of posts here at SCN and also visit homepage of the product for this. The post is about automatic running of it using CI tools.

Since the availability of abapGit more and more CI scenarios becomes possible for ABAP. Keeping ABAP code in git repositories slowly becomes the mainstream. As well as different CI (continuous integration) scenarios around it. One of scenarios is automatic code check which abaplint makes possible.

Let's focus on 2 popular git providers - Github and Gitlab.

Github is widely used for open-source. Recently there have been a rise of open-source ABAP packages (thanks to abapGit). Open-source projects are open for everyone to contribute, but how to ensure that the coding style for the project remain unified. Like variable naming conventions, indentation, case of key words, etc. This can be heavily assisted by automatic CI script which would run for each pull request from a contributor.

Gitlab is more enterprise oriented. It supports free private repositories and also a possibility to install it on premises. This makes it a good candidate for local git system role for teams and companies who are willing to embrace and benefit from modern development practices.

In this post I'll share a sample configuration of how to run abaplint automatically for your repositories in both providers.

Github


First let's start from Github. The service itself does not have a CI functionality, you have to use external one. Most popular is probably Travis.

1. let's assume you have a repository with some code. Example github repo can be found here.

2. Create an account in Travis and link it to you Github account. If you don't have it - all you need to go to https://travis-ci.org (or better https://travis-ci.com, see UPD2 at the bottom) and press sign-in with Github. On the way it will ask to authorize Travis for certain operations and monitoring of you code - you can allow it - this is how Travis automatically finds out about changes to your repositories and makes it's job.



In your Github account you can see this connection in your account setting - Application settings. Here you can revoke the access if you would like to stop it later.



Travis will automatically find all your repositories and propose to choose ones to do the CI builds for. But let's first prepare our repo files for this.

3. In order to run abaplint for your repository you have to add 2 additional files there.

abaplint.json - the configuration for abaplint so it knows what to check. Some documentation can be found on abaplint homepage. But let's focus on our example. The given rules are checking: indentation, capital keywords and maximal length of the line (there are more rules available but let's focus these for simplicity).
{
"global": {
"version": "v702"
},
"rules": {
"keywords_upper": {
"enabled": true,
"ignoreExceptions": true
},
"line_length": {
"enabled": true,
"length": 80
},
"start_at_tab": {
"enabled": true
}
}
}

Let's also consider our repository files. There is a program and an include for it. Include contains this code
CLASS lcl_name_factory DEFINITION FINAL.
PUBLIC SECTION.
CLASS-METHODS get_greeting
IMPORTING
iv_name TYPE string
RETURNING
value(rv_greeting) TYPE string.
ENDCLASS.
CLASS lcl_name_factory IMPLEMENTATION.
METHOD get_greeting.
rv_greeting = |Hello { iv_name }|.
ENDMETHOD.
ENDCLASS.

And if you look attentively you would find 2 violation of the rules defined above: value keyword is in lower case and wrong indentation of method code (just one space at the beginning). This is expected to be found by our test scenario. Stay tuned.

Second file to add to the repo is .travis.yml - this is a configuration for Travis so that it knows how to check the code.
language: node_js
node_js:
- "10"
notifications:
email: false
before_script:
- npm install -g abaplint
script:
- abaplint "src/**/*.*"
branches:
only:
- master

In a nutshell it specifies that:

  • in order to run the check it uses node.js environment. Abaplint is written on javascript (typescript to be more precise, but it does not matter for the example)

  • Travis does not send email on check (or maybe you want - then set true)

  • before starting the script it installs abaplint globally with node package manager (npm)

  • the check script itself contains just one command - abaplint - which is runs over all files in all subdirectories of "src" folder in the repository

  • the check is executed just for the master branch (so writing draft code in other branches will not generate annoying errors)


4. After you committed the above files to your repository let's get back to Travis configuration page we left at point 2. It list all your repositories and allows you to enable Travis for each repository individually. Let's do this for our repository



Let's double check the settings



There is nothing to change here for our example, however one setting to notice - build pushed pull requests - above we limited the check to the master branch only. How about pull requests? They are not the master yet! This setting forces Travis build for pull requests to master although they were not explicitly mentioned in the configuration file.

These are all settings! Now try pushing something to the repository right to the master branch.Travis sees the new push to master automatically and runs the job according to the configuration file. You can find it in Build history tab.



The build has failed as we intended. Let's check the details



The log show output of the script with the abaplint messages. You can see the files and lines where the errors had been detected.

OK, but it does not seem very convenient to always go to the Travis site to see the result, should I always do it? Not exactly.

  • Well, Firstly you can enable emails we blocked above - the report will come to your mailbox

  • Secondly you can add a special banner to you repo readme. In order to do it click on the banner in Travis near your repository name - it will open a nice dialog which gives you the banner code. Choose Markdown format. And copy-paste the chunk at the beginning of your readme file in the repository





  • After commit the banner will be rendered automatically based on last build status





  • And the last but not the least. The linter will be executed for pull requests. Let's try to create a pull request with some mistakes. Upon created pull request the Travis will automatically re-run the test and if it failed it would display it right there, in the pull request flow.





  • ... and the log ...



"So sorry, but cannot merge, please fix your code first". This is probably the most useful part of this CI script - Travis and abaplint controls the basic quality of the code with no effort from your side. Programming can and must be convenient.

Gitlab


If you're not tired from reading yet let's see how this works in Gitlab. Most of the flow is the same so it will be briefer, just some details differ. First of all Gitlab has own CI out of the box, no need to connect with external tools. See the example gitlab repository here.

The CI is enabled by default. You don't need to activate anything. But just in case check that Shared runners in Runners subsections of CD/CI settings are not disabled. In the enterprise environment you will probably have dedicated runners setup in the left part of this screen. But this is a different story for next times.





In order instruct Gitlab CI what how to run the check you have to commit CI configuration file. The file is called .gitlab-ci.yml and should contain this.
image: node:10-alpine
cache:
paths:
- node_modules/
stages:
- lint
run_abaplint:
stage: lint
only:
- master
before_script:
- npm install -g abaplint
script:
- abaplint "src/**/*.*"

It looks very similar to Travis config. But let's skim through:

  • same node.js environment (alpine is a special tiny sized docker container, I won't stop on it here)

  • cache specifies that node-modules folder should be preserved between builds for performance reason

  • stages allow to specify several steps of the test pipeline. For the example we just need one, let's call it "lint"

  • finally the script "run_abaplint" have very similar attributes to the Travis one. It runs only for master, installs abaplint globally at start and then runs it for all files in "src" folder


One note: abaplint is being actively developed and new features/improvements come often. Maybe you don't want to use the cache above and always use the latest version - then just remove the cache section. Or maybe in opposite, you want to fix the version you know works well and avoid newborn bugs - then you can pin the version adding it to the end of install command e.g. "npm install -g abaplint@1.5.1"

After file commit you will see the build status icon near the repo header.



Our build predictably failed. Clicking on the status icon will show the reasons (you'll have to drill down twice - to stages).



I hope you find this useful for your development flow.

Happy automatic code checking !

UPD: there are plans to lint not only abap code in the future but also data elements, structures and table types. So the latest recommendation is to mask all the available files for the check: abaplint "src/**/*.*"

UPD2: Travis is migrating their open source part of the service from https://travis-ci.org to https://travis-ci.com. So their official recommendation is to use "com" address for new repositories. See more here and here. The screenshots in this post are done from "org" so pictures may look just a bit different at "com" version.

 
8 Comments
nabheetscn
Active Contributor
0 Kudos
Great and interesting stuff!
peter_langner
Active Contributor
0 Kudos
Thank you for figuring it out. If works like a charm ...

 
former_member608301
Discoverer
0 Kudos

I am just starting to get familiar with all those tools and I am really like that on the web it’s possible to find so much useful info like your article. Otherwise I don’t even know what would I do…

sdfraga
Participant
0 Kudos
Hello atsy

Thank you for this great post!

I was playing around to create a rule that checks if there are unused variables in the code when submitting a PR.

Do you know how to achieve this with abaplint + Travis?

Thanks again

 
larshp
Active Contributor
the command line interface has been moved to package "@abaplint/cli", install it instead of "abaplint"
gregorw
Active Contributor
Hi atsy,

would be great if you can update the package. Otherwise everyone following your blog will not benefit from the improvements made until Lars switched.

Best regards
Gregor
atsybulsky
Active Participant
0 Kudos
Will try to find time for this. And probably also for a new post for github actions (if noone posted it yet ...)
ŁukaszPęgiel
Contributor
0 Kudos

YAML for Azure DevOps Pipeline

trigger:
- main

pool:
  vmImage: ubuntu-latest

steps:
- task: NodeTool@0
  inputs:
    versionSpec: '16.x'
  displayName: 'Install Node.js'
    
- task: Npm@1
  inputs:
   command: 'custom'
   customCommand: 'install -g @abaplint/cli'
  displayName: 'Install AbapLint'
   
- bash: |
      abaplint "src/**/*.*"
     displayName: 'Calling AbapLint'