Artificial Intelligence Blogs Posts
cancel
Showing results for 
Search instead for 
Did you mean: 
jakub_filak
Product and Topic Expert
Product and Topic Expert
1,525

I have recently shared an article with my objections to using git as a remote file system to get access to ABAP source code. In the article I pushed the idea of using git for versioning and using other tools for getting access to the source code - either MCP or something else (VS Code extension, command-line tool).

Today I want to share a short story backing my claims.

In our ABAP development process, we do change code in private or rather project-related systems. Yeah, sounds crazy expensive but we do that — you can save a lot of money if you do not keep the systems running 24/7 but 8/5 (also these systems are used by 1 up to 10 developers, testers, POs, etc., so they do not need the officially recommended resources — they work with half of the resources).

When the change is ready, developers commit + push to a remote git repository, open a pull request, a CI job starts, runs tools like abaplint or abap-cleaner and then deploys a fresh new ABAP system, clones the related repository into the new system, runs ABAP Units and ATCs and so on.

I hope the above explains our need to control abapGit remotely (these days, we primarily use gCTS which has its officially supported REST API but our CI pipelines are much older and abapGit is supported too). To control abapGit remotely, we developed RFC function modules which are available at

https://github.com/abapGit/abapgit-api-rfc

If you are wondering why RFC function modules and not something else, it is because it is super simple to install them with abapGit itself.

When we set up a new ABAP system with abapGit, we do install the development version, so we need to clone the remote repo and push it to the target system using our helper tool called sapcli:

git clone https://github.com/abapgit/abapgit
cd abapgit
sapcli checkin package --starting-folder src '$abapgit'

Then we need to push the abapgit-api-rfc:

git clone https://github.com/abapgit/abapgit-api-rfc
cd abapgit-api-rfc
sapcli checkin package --starting-folder src '$abapgit_api_rfc'

Here the fun part starts. That process usually fails because sapcli is often behind the abapGit format or the abapgit-api-rfc is behind abapGit interfaces and everything is behind the ABAP runtime.

Note: we haven't been using the abapgit-api-rfc for a while because of gCTS but some developers insist on using abapGit for exporting source code for agents and thus we revived our efforts with this project.

After I published my do-not-abuse-git post, I went to prepare a new system, but since I was expecting problems, I did want AI to fix them for me, so I asked Claude to install:

Please install this project written in ABAP and serialized by abapGit into my ABAP system. Use the command line tool sapcli too. The sapcli environment vars for connection are already exported in the environment. Run: sapcli checkin --starting-folder src '$abapgit_api_rfc'

By the way, I provided Claude with an invalid command but it ran --help and corrected it itself.

After successful creation and writing of the related objects, sapcli tried to activate them but the activation failed with two types of errors:

- Type BAPIRET2 is not a table type
- Method "SET" is unknown or PROTECTED or PRIVATE

Of course, Claude automatically analyzed the files of the repository and informed me about the status:

● The objects were created on the system but activation failed with two types of errors:

  Error 1: Type BAPIRET2 is not a table type (all 4 function modules)
  All function modules use TABLES RETURN STRUCTURE BAPIRET2. The target system doesn't accept BAPIRET2 (a structure) in TABLES parameters for RFC-enabled function modules. It likely needs a table type like BAPIRET2_T or BAPIRET2_TAB.

  Error 2: Method "SET" is unknown or PROTECTED or PRIVATE (LINK, PULL, SWITCHBRANCH) 
  The code calls zcl_abapgit_login_manager=>set(...) but this method doesn't exist (or isn't public) in the abapGit version installed on your system. The API may have changed.

  Would you like me to:

  1. Fix the BAPIRET2 issue by changing TABLES parameters to use a proper table type?

  2. Investigate the set method issue — do you know what version of abapGit is on the target system, or the correct method name for setting credentials?

Finally! We are getting to the point where Claude fetched the corresponding sources from the system itself.

My next prompt was:

Investigate the set method issue. You can use sapcli to get abapGit source code. For example "sapcli class read zcl_abapgit_login_manager".

If you ask why I didn’t just tell Claude the abapGit repo is in the directory ../abapgit - it is not usually the case that you have all the dependencies up to date and handy on your machine and you probably also want to check the sources on the system because who can assure that the git repo contains the same version as the one on the system?

It took Claude 30 seconds to read the class, find out the new method name, patch abapgit-api-rfc and re-run sapcli checkin to verify the fix was working.

● Bash(sapcli class read zcl_abapgit_login_manager)                                  
  ⎿  CLASS zcl_abapgit_login_manager DEFINITION                                      
       PUBLIC                                                                        
       FINAL                                                                         
     … +49 lines (ctrl+o to expand)                                                  
                                                                                     
● The old set method has been renamed to set_basic in the installed version. I'll update the three function modules that call it.                                    
                                                                                     
● Read 1 file (ctrl+o to expand)                                                     
                                                                                     
● Now I'll replace set with set_basic in all three files.  

Then Claude also asked if I wanted to fix the problem with BAPIRET2. However, since I am not primarily an ABAP developer, I had to ask it to read ABAP syntax documentation. Then Claude took off and I have no words to describe how impressive the experience was, just read the following conversation:

● Now, shall I investigate and fix the BAPIRET2 table type issue?

❯ Yes, but check ABAP syntax documentation.

● Web Search("ABAP function module TABLES parameter RFC "table type" DBSTRUCT syntax documentation site:help.sap.com")

● Fetch(https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-us/abaptables_parameters_obsolete.htm)

● Fetch(https://help.sap.com/doc/abapdocu_752_index_htm/7.52/en-US/abenrfc_limitations.htm)

● The documentation confirms TABLES parameters accept both TYPE itab_type (table type) and STRUCTURE struct (structure). The current code uses STRUCTURE BAPIRET2 which should be valid. But the error "Type BAPIRET2 is not a table type" in context "RFC/UPDATE" suggests something specific about this system.

  Let me check what BAPIRET2 looks like on the target system and if a table type exists.

● Bash(sapcli --help 2>&1 | head -40)
  ⎿  usage: sapcli [-h] [--version] [-v] [--ashost ASHOST] [--sysnr 
     … +16 lines (ctrl+o to expand)

● Bash(sapcli structure read BAPIRET2 2>&1)
  ⎿  @EndUserText.label : 'Returnparameter'
     @AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
     define structure bapiret2 {
     … +27 lines (ctrl+o to expand)

● Bash(sapcli dataelement read BAPIRET2 2>&1 || true)
  ⎿  Exception (SAPCliError):
       Object {type} does not support plain 'text' format

● Bash(sapcli table read BAPIRET2_T 2>&1 || sapcli structure read BAPIRET2_T 2>&1 || echo "BAPIRET2_T not found")
  ⎿  Exception (ExceptionResourceNotFound):
       Inactive version for TABL BAPIRET2_T does not exist
     Exception (ExceptionResourceNotFound):
     … +2 lines (ctrl+o to expand)

● Bash(sapcli table read BAPIRET2_TAB 2>&1 || echo "BAPIRET2_TAB not found")
  ⎿  Exception (ExceptionResourceNotFound):
       Inactive version for TABL BAPIRET2_TAB does not exist
     BAPIRET2_TAB not found

● Bash(sapcli datapreview --help 2>&1)
  ⎿  usage: sapcli datapreview [-h] {osql} ...

     positional arguments:
     … +5 lines (ctrl+o to expand)

● Bash(sapcli datapreview osql -q "SELECT TYPENAME FROM DD40L WHERE ROWTYPE = 'BAPIRET2'" 2>&1)
  ⎿  Error: Exit code 2
      ...
     sapcli: error: unrecognized arguments: -q

● Bash(sapcli datapreview osql "SELECT TYPENAME FROM DD40L WHERE ROWTYPE =
      'BAPIRET2'" 2>&1)
  ⎿  TYPENAME
     /BA1/F4_TAB_MESSAGE
     /BA1/F4_TAB_MSG
     … +51 lines (ctrl+o to expand)

● BAPIRET2_T exists on the system. Now I understand the full picture:

  - The ABAP documentation says TABLES parameters accept either TYPE itab_type (tabletype) or STRUCTURE struc (structure)
  - The current XML uses <DBSTRUCT>BAPIRET2</DBSTRUCT> which maps to STRUCTURE BAPIRET2
  - But for RFC-enabled function modules on this system, the TABLES parameter requires a table type, not a structure
  - BAPIRET2_T is available as a standard table type with BAPIRET2 row type I need to change the XML from <DBSTRUCT>BAPIRET2</DBSTRUCT> to <DBSTRUCT>BAPIRET2_T</DBSTRUCT> — but wait, that's still the STRUCTURE tag. Let me check how abapGit serializes a TYPE-based TABLES parameter. The correct XML tag
  should be <TYP> instead of <DBSTRUCT>.

Claude read the help of sapcli to check if the tool provides the features it needs to investigate the problem, then it used sapcli to check the existing types on the system and since sapcli does not support searching for a table type by its line type yet, Claude fell back to a brute-force approach and used sapcli’s datapreview to read ABAP types directly from the database to find the right type for the return parameter.

However, in the first attempt Claude modified the XML managed by abapGit itself. Claude did the correct modification (from DBSTRUCT to TYP) but sapcli could not process it, Claude fell back to DBSTRUCT with the new type BAPIRET2_T.

I was not sure what would happen if I tried to pull that change via abapGit into the system because BAPIRET2_T is not a table. So I reverted the change, pushed the modified function module into the system without the DBSTRUCT change (because sapcli only checks the XML but uses the source codes only) and then I checked the delta in abapGit directly. In the end, it turned out that the correct format really is <TYP>BAPIRET2_T</TYP> and not <DBSTRUCT>BAPIRET2_T</DBSTRUCT>. However, Claude would happily commit the wrong format and then a human doing git pull would probably get an error in a better case or the function would be doing something else than expected — I do not know.

Here my short story ends. I know the fixes were trivial but my intention was to show why I do not want to rely solely on git as a vehicle to deliver ABAP source code for agents. I think you can also see why I do not really use MCPs much — I create tools and scripts that can be easily enriched with the needed logic to handle specific repetitive tasks and can be reused in CI pipelines or other automations (it is like building Lego — you just need to create your own bricks too).

PS: the pull request is still under review: https://github.com/abapGit/abapgit-api-rfc/pull/8