News

Jenkins·Piper로 ABAP CI 자동 빌드·테스트 3단계 #shorts #SAP #ABAP

▶ YouTube에서 보기

1. 개요 및 이 글에서 다룰 것

ABAP 개발도 이제 자바·자바스크립트 진영처럼 Git 기반 버전 관리CI(Continuous Integration) 파이프라인을 통해 빌드·테스트를 자동화할 수 있습니다. 핵심 도구는 세 가지입니다. abapGit은 ABAP 오브젝트를 Git 저장소와 동기화해 주고, Jenkins는 파이프라인 오케스트레이션을 담당하며, SAP Piper는 SAP 환경에 특화된 Jenkins 공유 라이브러리(공식 오픈소스 프로젝트)로서 ABAP/BTP/Fiori 전용 스텝을 제공합니다.

이 글에서 다룰 것:

  • abapGit으로 ABAP 패키지를 GitHub/Azure Repos에 연결
  • Jenkinsfile에 abapEnvironmentCloneGitRepo 스텝으로 BTP ABAP 환경에 코드 풀
  • abapEnvironmentRunAUnitTest로 ABAP Unit을 자동 실행하고 JUnit 리포트 수집
  • 인증·범위·실패 처리 등 실무 트러블슈팅
대상 독자: ABAP 개발자 또는 BTP ABAP Environment 운영자 중 CI 파이프라인을 처음 구축하는 분.

2. 사전 가정

이 글은 다음을 알고 있다고 가정합니다.

  • abapGit 기본 사용: SE80/ADT에서 패키지를 abapGit 저장소에 연결하고 stage/commit을 수행해 본 경험
  • Jenkins 설치/운영: Jenkins LTS를 도커 또는 VM에 띄우고 Multibranch Pipeline 잡을 만들어 본 경험
  • ABAP Unit: FOR TESTING 클래스 작성과 로컬 실행(Ctrl+Shift+F10) 경험
  • YAML/Groovy 문법에 대한 기본 이해

3. 환경 / 버전 / 준비물

일반적으로 권장되는 조합은 다음과 같습니다(2026년 6월 기준).

  • SAP BTP ABAP Environment (Steampunk) 또는 SAP S/4HANA on-premise 2022/2023 + gCTS 활성화
  • abapGit: 최신 standalone 버전 또는 ABAP 1909+ 내장 버전
  • Jenkins LTS 2.426.x 이상 (Pipeline, Git, Credentials Binding 플러그인 필수)
  • project "Piper" Jenkins library: master 또는 v1.400 이상 고정 권장
  • Communication Arrangement: BTP ABAP 환경의 SAP_COM_0510(Software Component Test Integration) 또는 SAP_COM_0948
  • Service Key (JSON): cf create-service-key로 발급, Jenkins Credentials에 secret file로 등록
  • Git 호스팅: GitHub Enterprise, Azure Repos, 또는 자체 GitLab

Jenkins 컨트롤러에는 도커가 설치돼 있어야 합니다. Piper의 ABAP 스텝은 내부적으로 ppiper/cf-cli 도커 이미지를 사용해 Cloud Foundry CLI 호출을 격리합니다.

4. 핵심 개념

CI/CD와 ABAP

전통적인 ABAP 개발은 Transport Request(CTS)를 통해 DEV → QAS → PRD로 이동했습니다. CI/CD 관점에서 보면 운반 자체는 배포(CD)에 가깝지만, "커밋 시점에 자동으로 빌드·테스트가 돌아가는" CI 단계가 비어 있었습니다. abapGit과 Piper가 이 구멍을 메웁니다.

abapGit의 역할

abapGit은 ABAP 리포지토리 오브젝트(클래스, 인터페이스, DDIC, CDS 뷰 등)를 직렬화해 .abap/.xml 파일로 만들고 Git 저장소에 푸시합니다. 비유하자면 ABAP 시스템과 Git 사이의 번역기입니다. 반대로 pull하면 Git의 직렬화된 파일을 다시 SAP 시스템에 활성화합니다.

SAP Piper 구조

Piper는 두 부분으로 구성됩니다.

  • Jenkins Library (Groovy): library 'piper-lib-os'로 로드되며 piperPipeline, abapEnvironmentPipeline 같은 상위 오케스트레이터를 제공
  • Piper Go binary: 실제 스텝 로직은 Go로 작성돼 컨테이너에서 실행. Jenkins-독립적이라 GitHub Actions에서도 동일 스텝 사용 가능

도식으로 표현하면 다음과 같습니다.

Developer Push (Git)
      |
      v
Jenkins Webhook ----> Jenkinsfile
                          |
                          v
                 piper-lib-os (Groovy)
                          |
                          v
                 Piper Go binary (Docker)
                          |
           +--------------+--------------+
           v                             v
  abapEnvironmentCloneGitRepo   abapEnvironmentRunAUnitTest
           |                             |
           v                             v
     BTP ABAP Env                  JUnit XML

주요 스텝

  • abapEnvironmentCreateSystem: 일회성 테스트 시스템 프로비저닝
  • abapEnvironmentCloneGitRepo: Software Component를 시스템에 pull
  • abapEnvironmentRunAUnitTest: ABAP Unit 실행 후 JUnit 결과 다운로드
  • abapEnvironmentRunATCCheck: ABAP Test Cockpit 정적 분석

5. 실전 코드 3단계

1단계: abapGit으로 ABAP 패키지를 Git에 연결

먼저 SAP 시스템 측에서 패키지 ZCI_DEMO를 만들고 abapGit Online Repository로 등록합니다. ADT에서 Ctrl+Shift+A > "abapGit Repositories" > + 버튼으로 신규 저장소를 추가하면 다음과 같이 .abapgit.xml 메타파일이 자동 생성됩니다.

<?xml version="1.0" encoding="utf-8"?>
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
 <asx:values>
  <DATA>
   <MASTER_LANGUAGE>E</MASTER_LANGUAGE>
   <STARTING_FOLDER>/src/</STARTING_FOLDER>
   <FOLDER_LOGIC>PREFIX</FOLDER_LOGIC>
   <IGNORE>
    <item>/.gitignore</item>
    <item>/LICENSE</item>
    <item>/README.md</item>
   </IGNORE>
  </DATA>
 </asx:values>
</asx:abap>

다음으로 첫 번째 ABAP Unit 클래스를 작성합니다. 단순 계산 로직과 테스트입니다.

CLASS zcl_ci_calc DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    METHODS add IMPORTING iv_a TYPE i iv_b TYPE i
                RETURNING VALUE(rv_sum) TYPE i.
ENDCLASS.

CLASS zcl_ci_calc IMPLEMENTATION.
  METHOD add.
    rv_sum = iv_a + iv_b.
  ENDMETHOD.
ENDCLASS.

CLASS ltc_calc DEFINITION FOR TESTING
  DURATION SHORT RISK LEVEL HARMLESS FINAL.
  PRIVATE SECTION.
    METHODS add_two_plus_three FOR TESTING.
ENDCLASS.

CLASS ltc_calc IMPLEMENTATION.
  METHOD add_two_plus_three.
    DATA(lo_calc) = NEW zcl_ci_calc( ).
    cl_abap_unit_assert=>assert_equals(
      act = lo_calc->add( iv_a = 2 iv_b = 3 )
      exp = 5 ).
  ENDMETHOD.
ENDCLASS.

abapGit에서 stage > commit > push 하면 Git 저장소에 src/zcl_ci_calc.clas.abap이 생성됩니다.

2단계: Jenkinsfile + SAP Piper 파이프라인

Jenkins Multibranch Pipeline에서 읽어 들일 Jenkinsfile을 리포지토리 루트에 둡니다. Piper 라이브러리는 @Library로 로드합니다.

# .pipeline/config.yml
general:
  cfCredentialsId: 'cfDeployUser'
  abapCredentialsId: 'abapCommUser'
stages:
  Prepare System:
    cfApiEndpoint: 'https://api.cf.eu10.hana.ondemand.com'
    cfOrg: 'mycompany_prod'
    cfSpace: 'CI'
    cfServiceInstance: 'abap-ci-system'
    cfServiceKeyName: 'ci-key'
  Clone Repositories:
    repositories:
      - name: '/DMO/ZCI_DEMO'
        branch: 'main'
  ATC:
    atcConfig: 'atcConfig.yml'
  AUnit:
    aUnitConfig: 'aUnitConfig.yml'
@Library('piper-lib-os') _

node('linux') {
  stage('Init') {
    checkout scm
    setupCommonPipelineEnvironment script: this
  }

  stage('Prepare System') {
    abapEnvironmentCreateSystem script: this,
      includeAddon: false
  }

  stage('Clone Repositories') {
    abapEnvironmentCloneGitRepo script: this
  }

  stage('ATC') {
    abapEnvironmentRunATCCheck script: this
  }

  stage('AUnit') {
    abapEnvironmentRunAUnitTest script: this
  }

  stage('Cleanup') {
    cloudFoundryDeleteService script: this
  }
}

여기서 setupCommonPipelineEnvironment.pipeline/config.yml을 읽어 모든 스텝에 공통 파라미터를 주입합니다. Jenkins Credentials에는 cfDeployUser(Cloud Foundry 사용자), abapCommUser(Communication User basic auth)를 미리 등록해 둡니다.

3단계: AUnit 자동 실행 + JUnit 결과 수집

실행 범위를 정의하는 aUnitConfig.yml을 작성합니다. 패키지 단위로 테스트 범위를 좁히는 것이 일반적입니다.

title: AUnit run for ZCI_DEMO
context: AUnit run
options:
  measurements: none
  scope:
    ownTests: true
    foreignTests: false
  riskLevel:
    harmless: true
    dangerous: true
    critical: false
  duration:
    short: true
    medium: true
    long: false
objectSet:
  type: unionSet
  set:
    type: componentSet
    component:
      - name: /DMO/ZCI_DEMO

스텝 실행 결과는 AUnitResults.xml(JUnit 호환)로 작업공간에 떨어집니다. Jenkins의 표준 junit 스텝으로 수집하면 트렌드 그래프와 실패 알림이 자동으로 활성화됩니다.

stage('AUnit') {
  try {
    abapEnvironmentRunAUnitTest script: this,
      aUnitResultsFileName: 'AUnitResults.xml'
  } finally {
    junit testResults: 'AUnitResults.xml',
          allowEmptyResults: false
    archiveArtifacts artifacts: 'AUnitResults.xml',
                    fingerprint: true
  }
}

프로덕션에서는 다음을 추가로 권장합니다.

  • Secret 분리: 서비스 키 JSON은 withCredentials([file(...)])로만 노출, 로그 마스킹 활성화
  • 병렬 실행: ATC와 AUnit을 parallel { } 블록으로 동시 실행해 파이프라인 시간 단축
  • 실패 게이팅: unstable 임계값을 aUnitConfig.yml에 정의해 PR 머지 차단
  • 리트라이: BTP 시스템 프로비저닝은 가끔 타임아웃이 나므로 retry(2)로 감싸기

6. 흔한 실수 / 트러블슈팅

FAQ 1. 401 Unauthorized가 떨어진다

대부분 Communication Arrangement(SAP_COM_0510) 사용자의 비밀번호 만료 또는 Jenkins Credentials ID 오타입니다. cfServiceKeyName이 실제 서비스 키 이름과 정확히 일치하는지, 공백·줄바꿈이 섞이지 않았는지 확인하세요. curl -u user:pass https://<host>/sap/opu/odata/...로 직접 호출해 격리 테스트하는 것이 빠릅니다.

FAQ 2. AUnit이 0건만 실행된다

aUnitConfig.ymlobjectSet 범위가 잘못된 경우입니다. componentSetname은 Software Component(예: /DMO/ZCI_DEMO)지 일반 패키지가 아닙니다. 패키지로 좁히려면 packageSet 타입과 includeSubpackages: true를 함께 지정해야 합니다. 또한 ownTests: false로 두면 자체 테스트도 제외되니 주의하세요.

FAQ 3. 테스트는 통과했는데 빌드가 unstable이다

Piper는 riskLevel.critical: true로 설정된 테스트가 한 건이라도 있으면 위험 등급 정책에 따라 결과를 unstable로 마킹할 수 있습니다. CI 단계에서는 critical을 제외하고 별도 nightly 잡에서 돌리는 것이 일반적입니다. 또한 JUnit 플러그인의 healthScaleFactor가 너무 민감하게 설정돼 있을 수 있으니 함께 점검하세요.

기타 자주 만나는 문제

  • 도커 권한 오류: Jenkins 에이전트가 docker.sock에 접근하지 못하면 Piper Go 바이너리 실행 실패. usermod -aG docker jenkins 후 재시작
  • Software Component 미등록: BTP ABAP 환경의 "Manage Software Components" Fiori 앱에서 먼저 컴포넌트를 등록해야 abapEnvironmentCloneGitRepo가 동작
  • 네트워크 프록시: 사내망에서는 HTTP_PROXY/NO_PROXY를 Jenkins 글로벌 환경변수와 도커 이미지 양쪽에 모두 설정

7. 다음 단계 / 관련 주제

CI 파이프라인이 안정화되면 다음 영역으로 확장하세요.

  • ABAP Test Cockpit(ATC): 정적 코드 품질 검사. abapEnvironmentRunATCCheck 스텝으로 동일 파이프라인에 추가 가능
  • Code Inspector(SCI): 온프렘 시스템에서 변수명 규칙·성능 패턴 검사. 체크 변형을 미리 만들어 두면 ATC와 결과 공유
  • gCTS(Git-enabled CTS): 온프렘 S/4HANA에서 transport와 Git을 양방향 동기화. abapGit 대안으로 검토
  • SAP Cloud Transport Management(cTMS): CI 통과 후 QAS/PRD 자동 배포로 CD 단계 완성
  • Trunk-based development: short-lived feature branch + PR 머지 시 자동 ATC/AUnit 게이팅

8. 참고 자료

댓글 0

아직 댓글이 없습니다.