gCTS & CI/CD dans ABAP Cloud : Mettre en place un pipeline DevOps

Catégorie
DevOps
Publié
Auteur
Johannes

gCTS (Git-enabled Change and Transport System) et les pipelines CI/CD apportent les pratiques DevOps modernes dans le monde ABAP. Dans cet article, vous apprendrez comment mettre en place un pipeline DevOps complet pour ABAP Cloud - de l’integration Git jusqu’au pipeline de deploiement automatise.

Qu’est-ce que gCTS ?

gCTS connecte le systeme de transport SAP classique avec les repositories Git. Au lieu de deplacer manuellement les ordres de transport entre les systemes, les objets ABAP sont stockes sous forme de fichiers dans Git et synchronises via des operations Git.

Concept principal

+-----------------------------------------------------------------------+
| Paysage de developpement avec gCTS |
| |
| +-------------+ +-------------+ +-------------+ |
| | DEV | | QAS | | PRD | |
| | Systeme | | Systeme | | Systeme | |
| | +-------+ | | +-------+ | | +-------+ | |
| | | gCTS | | | | gCTS | | | | gCTS | | |
| | |Client | | | |Client | | | |Client | | |
| | +---+---+ | | +---+---+ | | +---+---+ | |
| +------+------+ +------+------+ +------+------+ |
| | | | |
| +--------+---------+--------+---------+ |
| Push | | Pull |
| v v |
| +-------------------------------+ |
| | Repository Git | |
| | (GitHub / GitLab / Azure) | |
| +-------------------------------+ |
+-----------------------------------------------------------------------+

CTS classique vs. gCTS

AspectCTS classiquegCTS
VersionnementOrdres de transportCommits Git
BranchingImpossibleBranching complet
ComparaisonLimiteeDiff entre commits
CollaborationLimiteePull Requests, Code Review
HistoriqueLogs de transportHistorique Git complet
RollbackManuelGit Revert/Reset
CI/CDDifficileIntegration native
OutillageSpecifique SAPOutils Git standard

gCTS vs. abapGit : Quand utiliser lequel ?

Une question frequente dans la communaute ABAP : Quelle est la difference entre gCTS et abapGit ?

CriteregCTSabapGit
OrigineProduit SAP (officiel)Open-Source (Communaute)
Public cibleOperations IT & EnterpriseDeveloppeurs & Equipes
FocusAutomatisation des transportsVersionnement du code
Integration GitPush & PullComplete (bidirectionnelle)
CoutLicence SAP requiseGratuit
Complexite de setupPlus elevee (setup Enterprise)Plus faible (demarrage rapide)
Pipeline CI/CDIntegration SAP nativeConfigurable manuellement
Integration transportCompletement integreAucune
Support SAPOui, support officielSupport communautaire

Recommandation

  • Choisir gCTS : Environnements Enterprise avec paysages systemes productifs, lorsqu’un support SAP officiel est necessaire
  • Choisir abapGit : Projets open-source, equipes de developpement, demarrage rapide, flexibilite maximale
  • Combinaison : Les deux outils peuvent etre combines - abapGit pour le developpement, gCTS pour les deploiements Enterprise

Pour une introduction detaillee a abapGit, voir l’article tutoriel abapGit.


Concepts CI/CD pour ABAP

L’Integration Continue (CI) et la Livraison Continue (CD) apportent des pratiques DevOps eprouvees dans le developpement ABAP :

PhaseSans CI/CDAvec CI/CD
TestsManuels, souvent oubliesAutomatiques a chaque commit
Qualite du codeVerifications ATC sporadiquesVerification continue
DeploiementTransport manuelAutomatise & reproductible
FeedbackDiffere, apres des joursImmediat, en minutes
RisqueGrandes releases, risque elevePetits changements, faible risque
RollbackComplexe, manuelSimple, automatise

Le pipeline CI/CD pour ABAP

+-----------------------------------------------------------------------------+
| Pipeline CI/CD pour ABAP Cloud |
| |
| +---------+ +---------+ +---------+ +---------+ +---------+ |
| | Code | | Build | | Test | | Quality | | Deploy | |
| | Push |-->| Check |-->| Stage |-->| Gate |-->| Stage | |
| +---------+ +---------+ +---------+ +---------+ +---------+ |
| | | | | | |
| v v v v v |
| Git Push Syntaxe & ABAP Unit ATC Checks gCTS Pull |
| Trigger Activation Tests Code Review Transport |
| Integration Coverage |
| Tests Securite |
+-----------------------------------------------------------------------------+

Configurer gCTS : Guide de setup

Prerequis

  • SAP S/4HANA ou SAP BTP ABAP Environment
  • Repository Git (GitHub, GitLab, Azure DevOps)
  • Certificats SSL pour le serveur Git
  • Autorisations : S_CTS_ADMI, S_CTS_SADM

Etape 1 : Importer les certificats SSL

Transaction: STRUST
1. Ouvrir SSL Client (Standard)
2. Importer le certificat:
- GitHub: github.com
- GitLab: gitlab.com (ou votre propre domaine)
3. Actualiser la liste des certificats
4. Sauvegarder

Etape 2 : Creer un repository gCTS

Dans la transaction GCTS_MAINT ou via l’application Fiori :

+--------------------------------------------------------------+
| Configuration du Repository |
+--------------------------------------------------------------+
| Nom du Repository: Z_MY_PROJECT |
| URL Distante: https://github.com/company/project.git |
| Branche: main |
| |
| Authentification: |
| * Base sur token (recommande) |
| |
| Nom d'utilisateur: github-service-user |
| Token: ghp_xxxxxxxxxxxx |
| |
| vSID (Virtual System ID): DEV |
+--------------------------------------------------------------+

Etape 3 : Creer un repository via API (optionnel)

CLASS zcl_gcts_setup DEFINITION
PUBLIC FINAL CREATE PUBLIC.
PUBLIC SECTION.
METHODS create_repository
IMPORTING
iv_repository_name TYPE string
iv_remote_url TYPE string
iv_branch TYPE string DEFAULT 'main"
RAISING
cx_web_http_client_error.
ENDCLASS.
CLASS zcl_gcts_setup IMPLEMENTATION.
METHOD create_repository.
DATA(lo_destination) = cl_http_destination_provider=>create_by_url(
i_url = |http://localhost:50000/sap/bc/cts_abapvcs/repository| ).
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination(
i_destination = lo_destination ).
DATA: BEGIN OF ls_request,
repository TYPE string,
url TYPE string,
branch TYPE string,
role TYPE string VALUE 'SOURCE',
END OF ls_request.
ls_request-repository = iv_repository_name.
ls_request-url = iv_remote_url.
ls_request-branch = iv_branch.
DATA(lv_json) = /ui2/cl_json=>serialize(
data = ls_request
compress = abap_true
pretty_name = /ui2/cl_json=>pretty_mode-camel_case ).
DATA(lo_request) = lo_client->get_http_request( ).
lo_request->set_header_field( i_name = 'Content-Type' i_value = 'application/json' ).
lo_request->set_text( lv_json ).
DATA(lo_response) = lo_client->execute( if_web_http_client=>post ).
IF lo_response->get_status( )-code <> 201.
RAISE EXCEPTION TYPE cx_web_http_client_error.
ENDIF.
lo_client->close( ).
ENDMETHOD.
ENDCLASS.

Etape 4 : Lier le package ABAP au repository

Apres la creation du repository, le package ABAP doit etre lie :

" Dans SE80 ou via ADT:
" Package Z_MY_PACKAGE -> Properties -> Attribuer le repository gCTS

Pipeline GitHub Actions pour ABAP

GitHub Actions offre une flexibilite maximale pour le CI/CD ABAP. Voici un pipeline complet, pret pour la production :

Configuration complete du pipeline

.github/workflows/abap-cicd.yml
name: ABAP CI/CD Pipeline
on:
push:
branches: [ main, develop, 'release/**' ]
pull_request:
branches: [ main, develop ]
workflow_dispatch:
inputs:
deploy_target:
description: 'Deployer vers environnement"
required: true
default: 'dev"
type: choice
options:
- dev
- qas
- prd
env:
ABAP_PACKAGE: ${{ vars.ABAP_PACKAGE }}
ATC_VARIANT: ${{ vars.ATC_VARIANT || 'DEFAULT' }}
jobs:
# Job 1: Verification syntaxe et activation
build:
name: Build & Syntax Check
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20"
- name: Verify ABAP Syntax
run: |
curl -X POST \
"${{ secrets.ABAP_ENDPOINT }}/sap/bc/adt/programs/checks" \
-u "${{ secrets.ABAP_USER }}:${{ secrets.ABAP_PASSWORD }}" \
-H "Content-Type: application/json" \
--fail
# Job 2: Tests unitaires ABAP
unit-tests:
name: ABAP Unit Tests
needs: build
runs-on: ubuntu-latest
steps:
- name: Run ABAP Unit Tests
id: aunit
run: |
curl -X POST \
"${{ secrets.ABAP_ENDPOINT }}/sap/bc/adt/abapunit/testruns" \
-u "${{ secrets.ABAP_USER }}:${{ secrets.ABAP_PASSWORD }}" \
-H "Content-Type: application/vnd.sap.adt.abapunit.testruns.config.v4+xml" \
-H "Accept: application/vnd.sap.adt.abapunit.testruns.result.v1+xml" \
-d @- << 'EOF' > aunit_results.xml
<?xml version="1.0" encoding="UTF-8"?>
<aunit:runConfiguration xmlns:aunit="http://www.sap.com/adt/aunit">
<external>
<coverage active="true" branchCoverage="true"/>
</external>
<options>
<uriType value="semantic"/>
<testDeterminationStrategy sameProgram="true"/>
<testRiskCoverage>
<harmless active="true"/>
<dangerous active="true"/>
<critical active="true"/>
</testRiskCoverage>
<durationCoverage short="true" medium="true" long="true"/>
</options>
<adtcore:objectSets xmlns:adtcore="http://www.sap.com/adt/core">
<objectSet kind="inclusive">
<adtcore:objectReferences>
<adtcore:objectReference adtcore:uri="/sap/bc/adt/vit/wb/object_type/devck/object_name/${{ env.ABAP_PACKAGE }}"/>
</adtcore:objectReferences>
</objectSet>
</adtcore:objectSets>
</aunit:runConfiguration>
EOF
- name: Parse Test Results
run: |
if grep -q 'alerts severity="error"' aunit_results.xml; then
echo "::error::Les tests unitaires ABAP ont echoue!"
exit 1
fi
echo "Tous les tests unitaires ABAP ont reussi"
- name: Upload Test Results
uses: actions/upload-artifact@v4
with:
name: aunit-results
path: aunit_results.xml
# Job 3: Verifications qualite ATC
atc-checks:
name: ATC Quality Checks
needs: build
runs-on: ubuntu-latest
steps:
- name: Run ATC Checks
id: atc
run: |
# Demarrer ATC Run
RUN_ID=$(curl -X POST \
"${{ secrets.ABAP_ENDPOINT }}/sap/bc/adt/atc/runs" \
-u "${{ secrets.ABAP_USER }}:${{ secrets.ABAP_PASSWORD }}" \
-H "Content-Type: application/vnd.sap.atc.run.parameters.v1+xml" \
-d @- << EOF | grep -oP 'id="\K[^"]+' | head -1
<?xml version="1.0" encoding="UTF-8"?>
<atc:run xmlns:atc="http://www.sap.com/adt/atc">
<checkVariant>${{ env.ATC_VARIANT }}</checkVariant>
<objectSets>
<objectSet name="run">
<softwareComponent name="${{ env.ABAP_PACKAGE }}"/>
</objectSet>
</objectSets>
</atc:run>
EOF
)
echo "ATC Run ID: $RUN_ID"
sleep 30
# Recuperer les resultats
curl -X GET \
"${{ secrets.ABAP_ENDPOINT }}/sap/bc/adt/atc/runs/$RUN_ID/results" \
-u "${{ secrets.ABAP_USER }}:${{ secrets.ABAP_PASSWORD }}" \
-H "Accept: application/vnd.sap.atc.checkresult.v1+xml" \
> atc_results.xml
- name: Evaluate ATC Results
run: |
ERRORS=$(grep -c 'priority="1"' atc_results.xml || true)
WARNINGS=$(grep -c 'priority="2"' atc_results.xml || true)
echo "Resultats ATC: $ERRORS erreurs, $WARNINGS avertissements"
if [ "$ERRORS" -gt 0 ]; then
echo "::error::ATC a trouve $ERRORS problemes critiques!"
exit 1
fi
echo "Les verifications ATC ont reussi"
- name: Upload ATC Results
uses: actions/upload-artifact@v4
with:
name: atc-results
path: atc_results.xml
# Job 4: Deployer vers DEV
deploy-dev:
name: Deploy to DEV
needs: [unit-tests, atc-checks]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/develop"
environment: development
steps:
- name: Pull to DEV System via gCTS
run: |
curl -X POST \
"${{ secrets.DEV_ENDPOINT }}/sap/bc/cts_abapvcs/repository/${{ vars.GCTS_REPO }}/pull" \
-u "${{ secrets.DEPLOY_USER }}:${{ secrets.DEPLOY_PASSWORD }}" \
-H "Content-Type: application/json" \
-d '{"branch": "develop"}"
echo "Deploye vers DEV"
# Job 5: Deployer vers QAS
deploy-qas:
name: Deploy to QAS
needs: [unit-tests, atc-checks]
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main"
environment: quality-assurance
steps:
- name: Pull to QAS System via gCTS
run: |
curl -X POST \
"${{ secrets.QAS_ENDPOINT }}/sap/bc/cts_abapvcs/repository/${{ vars.GCTS_REPO }}/pull" \
-u "${{ secrets.DEPLOY_USER }}:${{ secrets.DEPLOY_PASSWORD }}" \
-H "Content-Type: application/json" \
-d '{"branch": "main"}"
echo "Deploye vers QAS"
# Job 6: Deployer vers PRD (Approbation manuelle)
deploy-prd:
name: Deploy to PRD
needs: deploy-qas
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main' && github.event_name == 'workflow_dispatch"
environment: production
steps:
- name: Pull to PRD System via gCTS
run: |
curl -X POST \
"${{ secrets.PRD_ENDPOINT }}/sap/bc/cts_abapvcs/repository/${{ vars.GCTS_REPO }}/pull" \
-u "${{ secrets.DEPLOY_USER }}:${{ secrets.DEPLOY_PASSWORD }}" \
-H "Content-Type: application/json" \
-d '{"branch": "main", "tag": "${{ github.sha }}"}"
echo "Deploye vers PRD"

Integrer des tests automatises

Classe de test ABAP Unit pour CI/CD

CLASS zcl_customer_test DEFINITION
FOR TESTING
RISK LEVEL HARMLESS
DURATION SHORT.
PRIVATE SECTION.
CLASS-DATA:
mo_environment TYPE REF TO if_cds_test_environment.
CLASS-METHODS:
class_setup,
class_teardown.
METHODS:
setup,
teardown,
test_create_customer_success FOR TESTING,
test_create_customer_invalid_email FOR TESTING,
test_update_customer_status FOR TESTING.
ENDCLASS.
CLASS zcl_customer_test IMPLEMENTATION.
METHOD class_setup.
" CDS Test Double Framework pour tests isoles
mo_environment = cl_cds_test_environment=>create_for_multiple_cds(
VALUE #(
( i_for_entity = 'ZI_CUSTOMER' )
( i_for_entity = 'ZI_ORDER' )
)
).
ENDMETHOD.
METHOD class_teardown.
mo_environment->destroy( ).
ENDMETHOD.
METHOD setup.
mo_environment->clear_doubles( ).
" Inserer des donnees mock
DATA(lt_customers) = VALUE zt_customer_t(
( customer_id = '1' name = 'Test GmbH' email = '[email protected]' status = 'A' )
).
mo_environment->insert_test_data( lt_customers ).
ENDMETHOD.
METHOD teardown.
ROLLBACK WORK.
ENDMETHOD.
METHOD test_create_customer_success.
" Given
DATA(lo_cut) = NEW zcl_customer_service( ).
DATA(ls_input) = VALUE zs_customer_create(
name = 'New Customer"
).
" When
DATA(ls_result) = lo_cut->create_customer( ls_input ).
" Then
cl_abap_unit_assert=>assert_not_initial(
act = ls_result-customer_id
msg = 'L ID client devrait etre genere"
).
ENDMETHOD.
METHOD test_create_customer_invalid_email.
" Given
DATA(lo_cut) = NEW zcl_customer_service( ).
DATA(ls_input) = VALUE zs_customer_create(
name = 'Invalid Customer"
email = 'not-an-email"
).
" When / Then
TRY.
lo_cut->create_customer( ls_input ).
cl_abap_unit_assert=>fail( 'Exception attendue' ).
CATCH zcx_customer_error INTO DATA(lx_error).
cl_abap_unit_assert=>assert_equals(
act = lx_error->error_code
exp = 'INVALID_EMAIL"
).
ENDTRY.
ENDMETHOD.
METHOD test_update_customer_status.
" Given
DATA(lo_cut) = NEW zcl_customer_service( ).
" When
lo_cut->set_customer_status( iv_customer_id = '1' iv_status = 'I' ).
" Then
DATA(ls_customer) = lo_cut->get_customer( '1' ).
cl_abap_unit_assert=>assert_equals(
act = ls_customer-status
exp = 'I"
msg = 'Le statut devrait etre mis a jour"
).
ENDMETHOD.
ENDCLASS.

Resume des bonnes pratiques

ThemeRecommandation
Isolation des testsCDS Test Environment pour les tests unitaires
Donnees de testDonnees mock dans les methodes setup
Variante ATCPropre variante CI/CD avec verifications pertinentes
SecretsUtiliser GitHub Secrets / Azure Key Vault
ParallelisationExecuter les jobs independants en parallele
EnvironmentsGitHub Environments pour les workflows d’approbation
Messages de commitCommits conventionnels (feat:, fix:, etc.)
Code ReviewPull Requests avant chaque merge
TaggingReleases avec versionnement semantique
MonitoringIntegration Slack/Teams pour les notifications

Conclusion

gCTS et CI/CD transforment le developpement ABAP des processus de transport manuels vers des workflows DevOps automatises :

  1. gCTS permet une gestion des transports basee sur Git avec historique complet et branching
  2. Les pipelines CI/CD automatisent les tests, verifications de qualite et deploiements
  3. Les tests unitaires ABAP dans le pipeline assurent la qualite du code a chaque commit
  4. Les verifications ATC empechent les failles de securite ou problemes de performance d’atteindre la production

Prochaines etapes :

  1. Configurer un repository gCTS pour votre projet ABAP
  2. Configurer un pipeline GitHub Actions ou Azure DevOps
  3. Ecrire des tests unitaires ABAP pour la logique metier critique
  4. Creer une variante ATC personnalisee pour CI/CD
  5. Former l’equipe aux workflows Git

Articles complementaires