【SAP】移送をGitに載せる。gCTS+ATC+GitHub承認ゲートを実機で通した
目次
はじめに
SAPの移送(トランスポート)は、長らくSAPの中だけで完結する世界でした。誰がいつ何を承認したのかは STMS の中にあり、他の開発とは別の作法で運用されています。
これを Git に載せられないか、というのが今回のテーマです。前回建てた自分専用のSAP環境を使って、「開発機で移送をリリースしたら GitHub に push され、Pull Request で承認して、本番が取り込む」という流れが実際に動くのかを検証しました。結論から言うと、動きました。
抱えていた課題
- 承認の記録がSAPの中にしかない: 他システムの変更管理と並べて見られません。
- 品質チェックが人任せ: ABAPの静的チェック(ATC)はあるものの、レビューのたびに人が実行するかどうかに依存していました。
- 本当に動くのか誰も知らない: gCTS(Git-enabled CTS)という機能があることは知られていても、実際に一連の流れを通した話が見つかりませんでした。
目標にしたパイプライン

全体のアーキテクチャ構成と、検証した一連のCI/CDパイプラインは上の図の通りです。 SAP GUIのSTMSやSE09で移送リクエストをリリースしたことを契機に、gCTSがGitHubへ自動pushし、GitHub Actions等のCI上でATC静的検査とPR承認を経て本番機へPullされる仕組みを実機で通しました。

最初に、実現したい流れを6ステップで定義しました。
- 開発機で移送リクエストに登録する
- 移送リクエストをリリースする
- gCTSがGitHubへpushする
- GitHubでPull Requestを作る
- **承認とCI品質ゲート(ATC)**を通す
- 本番へPull / Importする
このうち1〜3が動けば「機構としては成立する」と言えます。まずそこを確認することを最初の目的にしました。
検証した内容
1. gCTSを有効化してGitHubに繋ぐ

gCTS(Git-enabled CTS)は、ABAPシステムの移送オブジェクトをGitリポジトリに同期するSAP標準機能です。gCTSのWeb UI(Fioriアプリ)からリポジトリを登録し、GitHubのHTTPS URLとパーソナルアクセストークン(PAT)を設定して連携します。
公式ドキュメントの手順と実機(CAL)のギャップ
SAP公式の導入ガイドである Prerequisites for Git-Enabled Change and Transport System や Configuring Git-Enabled Change and Transport System を確認すると、使い始める前に満たすべき前提条件やインフラ設定がずらりと並んでいます。
始める前は「インフラ基盤の設定だけで数日溶かすのではないか…」とかなり身構えていました。しかし、今回使用したSAP CALのアプライアンス(ABAP Platform 2023 developer edition)で実機検証したところ、公式手順に書かれている「必須事前設定」の多くが最初から完了しており、実際にはスキップできました。
これから個人環境等で試す人のショートカットになるよう、公式手順との対比を整理しておきます。
| 公式手順に書かれている事前設定 | 公式ドキュメントの要件 | CAL実機での結果 |
|---|---|---|
STRUST での証明書登録 | 外部Git(GitHub等)とSSL/TLS通信するため、ルート証明書(DigiCert等)のインポートが必須 | 【不要(スキップ可)】 OS/SAP側の証明書チェーンが最初から解決されており、手動インポートなしでSSL接続が成功 |
SICF でのサービス有効化 | gCTSのWeb画面やAPI通信を担うICFサービス群を手動で1つずつアクティブ化する | 【不要(スキップ可)】/sap/bc/cts_abap_vcs などの通信ノードは最初からすべて「有効」になっていた |
| 定期同期ジョブの登録 | リポジトリや移送の監視を行うバックグラウンドジョブを手動スケジュールする | 【不要(スキップ可)】 環境構築時点で自動構成済み |
| Java実行環境(JRE/Git)の配置 | OS上にSAPMachineやGitクライアントをインストール・パス指定する | 【不要(スキップ可)】 アプライアンス内に導入済み |
つまり、CALのdeveloper editionであれば、公式ガイドの長い初期設定チェックリストに怯む必要はなく、いきなりgCTSの画面を開いてリポジトリ登録に進んで問題ありませんでした。
唯一引っかかった事前注意点:GitHubリポジトリは「空」にしてはいけない
一方で、GitHub側で完全にやらかした点がありました。それはリポジトリを「完全な空(コミットが0件の状態)」で作ってはいけないということです。
GitHubで新規リポジトリを作るときに「Add a README file」にチェックを入れず、空のままgCTSにURLを登録すると、gCTS内部のGit処理がHEAD ref does not existのような状態になり、以後のPullやブランチの初期化が永久に失敗(エラーで固まる)します。
Gitは最初のコミットが打たれて初めてブランチの実体(mainなど)が作られる仕様です。gCTSで接続するリポジトリは、必ずREADMEを1本置いて初期コミットを打った状態(ブランチが存在する状態)で作成しておく必要があります。
2. 最大の落とし穴 —— /usr/sap/trans/bin が空だった

GitHub側の準備を整え、いざgCTSのWeb UIから「Create Repository」を実行したところ、何度やってもリポジトリの登録が失敗するという事態に直面しました。
画面上に返ってきたエラーログは以下のようなものです。
section: HANDLER_TP message: Error action Code:0208
section: CLIENT_TP action: CREATE_WORKSPACE ERROR
section: HANDLER_FILE action: WRITE_MANIFEST_FILE ERROR File handler cannot write file
section: REPOSITORY_FACTORY action: CREATE_REPOSITORY ERROR Repository creation error (Folder structure)
下のエラーに惑わされて原因調査が迷走
このログを見たとき、パッと目につくのは下の2行でした。
WRITE_MANIFEST_FILE ERROR: File handler cannot write file(マニフェストファイルが書き込めない)Repository creation error (Folder structure)(フォルダ構造のエラー)
「ファイルが書けない? フォルダが作れない? ということはLinuxのパーミッション(権限)か、ディスク容量不足か?」と考え、OS(SUSE Linux)に入って調べまくりました。しかし、調べれば調べるほど正常なのです。
- OSの移送ディレクトリ(
/usr/sap/trans)は存在し、所有者(sapadm/sapsys)も権限(775)も正しい - 手動で
touchやmkdirを打つと普通に書き込みができる - ディスク容量は24GB以上空いている
- SAP GUIの
STMS(移送管理システム)で接続ヘルスチェックを実行してもオール「緑(正常)」
「権限も空き容量もSTMSのステータスもすべて完璧なのに、なぜ『書き込めない』と怒られるのか?」と、ここで丸一日悩みました。
原因はエラーの1行目 —— 移送プログラム tp の設定ファイルが無かった
原因は、ログの最下部ではなく一番上の1行目にありました。
section: HANDLER_TP message: Error action Code:0208
gCTSは、裏側でSAPの標準移送制御プログラム tp(Transport Control Program) を呼び出して、Git用のワークスペースを作ったりファイルを展開したりしています。
そして、この Code:0208 というエラーコードをSAPノート等で調べたところ、「tp が動作するためのプロファイルファイルが見つからない」 という意味でした。
実際にLinux側で移送プロファイルが格納されるディレクトリを確認してみると、驚くべき結果が出ました。
ls -l /usr/sap/trans/bin
# total 0 ← プロファイル(TP_DOMAIN_<SID>.PFL 等)が1つも存在しない!
なんと、/usr/sap/trans/bin の中身が**完全な空っぽ(0件)**だったのです。
tp コマンドは起動時にここにあるプロファイルを読み込んで動作します。設定プロファイルが1枚もないため tp が起動直後にクラッシュし、その結果として「ワークスペースが作れない」「マニフェストが書けない」という後続エラーが雪崩のように発生していたのでした。
なぜSTMSが「緑」だったのにファイルが無かったのか?
ここで疑問に思うのが、「なぜSTMSの画面上では緑色(正常)だったのか?」という点です。 理由は、STMSの画面が見ているのは『データベース上の設定データ』であり、『OS上の実ファイルが存在するかどうか』までは見ていなかったからです。
このアプライアンスは、DB上には移送の設定が綺麗に登録されているものの、「DBの設定をOS上の実ファイルに書き出す」という最後の配布処理が未実行の状態で出荷されていたのです。
解決手順:STMSからプロファイルを再配布するだけ
原因さえ分かれば、対処は一瞬でした。Linuxをいじる必要すらありません。
- SAP GUIでトランザクション
STMSを開く - メニューバーの
Overview→Systemsを開く - 自システムを選択した状態で、メニューから
Extras→Distribute and Activate Configuration(構成の配布と有効化)を実行する
これで、STMSのDB情報から /usr/sap/trans/bin/TP_DOMAIN_A4H.PFL などの移送プロファイル群が一括で自動生成されました。
改めてgCTSの画面から「Create Repository」を実行すると、先ほどまでのエラーが嘘のように数秒でリポジトリが作成されました。
ここから得た2つの重要な教訓
- エラーログは必ず「一番上」から読む: 下の行にある分かりやすいエラー(File cannot writeなど)は、一番上の根本原因が引き起こした副次的・連鎖的な結果に過ぎないことが多いです。
- ヘルスチェックの「緑」を過信しない: 管理画面の信号が青や緑でも、それは「DB上の定義が揃っている」ことしか示していない場合があります。実機トラブルでは、OS上に実体(プロファイルやバイナリ)が存在しているかまで確認する視野が重要でした。
3. 承認ゲートをGitHubのPRに置く


このパイプラインを設計するにあたり、最も重要だった設計判断が**「本番適用の承認をどこで行うか(=承認の正本をどこに置くか)」**でした。
従来のSAP承認(STMS完結型)が抱えていた限界
従来のSAP運用では、開発機で移送をリリースすると、検証機や本番機のインポートキューに溜まります。そして管理者がSAP GUIで STMS を開き、画面上でインポート実行(承認)を行います。
しかし、この「SAPの中だけで完結する承認」には大きな課題がありました。
- 監査ログの分断: 誰がいつ何を理由に承認したかの履歴がSAPの内部テーブルにしか残らず、他システムの変更管理(JiraやGitHub)と一元管理できない。
- 品質ゲートの形骸化: ABAPの静的品質チェック(ATC)を実行するかどうかがレビュー担当者の裁量に依存し、チェック漏れが発生しやすい。
GitHubのPull Requestを「唯一の公式承認ゲート」にする
そこで今回の検証では、SAP側で承認するのではなく、「GitHubのPull Request(PR)のレビュー・Approve承認を唯一の公式ゲートにする」 という方針をとりました。
この設計を実現するためのキモが、「ブランチを dev と main の2本に分け、gCTSのRoleを切り分ける」 という戦略です。
なぜ gCTS の push 先を main にしてはいけないのか?
gCTSの設定を行う際、安易に開発機のpush先を main ブランチにしてしまうと破綻します。
なぜなら、開発者が開発機で移送をリリースした瞬間に、本番ブランチ(main)へ直接コードが入ってしまうからです。これではPRを作ってレビューする隙間も、ATC自動検査を挟む余地もありません。
そこで、以下のように開発機と本番機でリポジトリ登録を明確に分けました。
- SAP 開発機(DEV):
- gCTSリポジトリ登録 #1
- Role =
Development(Gitへ送り出す側) - Target Branch =
dev - 動作: 移送リリースを検知し、未承認の作業ブランチ
devへ自動push
- GitHub 上での承認ゲート:
- ブランチ合流:
dev➔mainのPull Requestを作成 - CI品質ゲート: ADT REST API経由でATCが自動起動し、「重大な指摘(優先度1)が0件」であることを自動判定
- 承認ゲート: レビュアーが差分を確認し、GitHub上で Approve(承認) して初めて
mainへマージ
- ブランチ合流:
- SAP 本番機(PRD):
- gCTSリポジトリ登録 #2
- Role =
Provided(Gitから受け取る側) - Track Branch =
main - 動作: 承認・マージされた
mainの最新コミットだけを監視し、システムへPull / Import
1つのリポジトリ登録を使い回すのではなく、「開発機用(Role: Development)」と「本番機用(Role: Provided)」で登録を分けるのが最大のポイントです。
gCTSのRoleの選択肢が Development と Provided の2つしか用意されていないこと自体が、「まさにこの構成(PRを挟んだ2システム連携)で使いなさい」というSAP側の設計意図を裏付けています。
UIのちょっとした罠:ブランチが1本だと切替ボタンが出ない
なお、gCTSのブランチ管理画面には初見殺しのUI仕様があります。リポジトリ内にブランチが1本しか無い間は、画面上にブランチ切替の操作アイコンが一切表示されません。
切り替え先が存在しないので当たり前といえば当たり前なのですが、「操作ボタンが無い=このUIからはブランチ運用ができないのか?」と勘違いしかけました。GitHub側で dev ブランチを切ってから画面をリロードすると、無事に切り替えアイコンが現れます。
4. ATCをCIから呼べるか検証する

品質ゲートには ATC(ABAP Test Cockpit)を使います。問題は、これを画面からではなくCIから呼べるかでした。
結論は「呼べる」です。ADT(ABAP Development Tools)のREST APIを使って、検査の起動から結果の取得までできました。手順は3ステップです。
- ワークリストを作る —
POST /sap/bc/adt/atc/worklists?checkVariant=...でワークリストIDを取得 - 検査を実行する —
POST /sap/bc/adt/atc/runs?worklistId=<id>に、検査対象のオブジェクトをXMLで渡す - 結果を取得する — 優先度別の件数が返ってくる
実装上で効いたのは、返却される FINDING_STATS(優先度別の指摘件数)だけで合否判定ができることでした。5,0,3 のような形で返ってくるので、「優先度1が1件でもあればFail」という判定をCIに書けます。
もうひとつ、ハマりどころとして gCTSとADTでCSRFトークンの要否が違います。gCTSは不要、ADTは必須です。同じシステムに対するAPIなのに扱いが違うので、スクリプトを書くときは分けて実装する必要があります。
5. 本番へのPullを検証する

本来なら移送先のシステムが要りますが、2台目を建てると費用が倍になります。そこで、同一システムに過去のコミットをPullして、機構とロールバックを確認するという方法を取りました。
gCTSのブランチ切替のツールチップに object difference is imported depending on configuration とあるのがヒントでした。ブランチの切替はシステムへの取り込みを伴います。つまり、本番機が main に追従する動作が、そのままPullになるわけです。
会社に提案する観点では、ステップ1〜5とこの方法まで通れば「機構が動くことを確認した」と言えます。本番機が無いことは提案上の欠陥にはなりませんでした。
得られたメリット
変更履歴が他システムと同じ土俵に乗った
誰がいつ何を変えて、誰が承認したのかがGitHub上に残ります。SAPの中だけで完結していた情報が、他の開発と同じ形で見られるようになりました。
品質チェックが自動で走る形にできた
ATCをAPIから呼べると分かったことで、「PRを出したら自動でチェックが走り、優先度1の指摘があればマージできない」という運用が現実的になりました。
「できます」と言える根拠ができた
一番大きいのはこれです。カタログ上できることになっている、ではなく、自分の環境で一通り通したという事実があると、提案の説得力がまったく違います。
使ったサービス・ツール
| サービス/ツール | 役割 | 使ってみての学び |
|---|---|---|
| gCTS (Git-enabled CTS) | 移送オブジェクトをGitに同期 | Roleが Development / Provided の2つだけ。この制約自体が想定された使い方を示している |
| GitHub + Personal Access Token | リポジトリ、承認ゲート | リポジトリを空にしてはいけない。READMEを1本置いて初期コミットを作る |
| ATC (ABAP Test Cockpit) | 静的チェックの品質ゲート | 優先度別の件数だけで合否判定ができる。CIに組み込みやすい |
| ADT REST API | ATCを外部から呼ぶ経路 | CSRFトークンが必須。gCTSは不要なので実装を分ける必要がある |
| STMS / SE09 / SE38 | 移送の設定・リリース・開発 | タスクと親リクエストの二段構造を理解していないと移送が飛ばない |
まとめ
gCTSは「使えるのか分からない機能」という印象がありましたが、実際に触ってみると、設計思想はかなりはっきりしていました。Roleが2つしかないこと、ブランチ切替が取り込みを伴うこと——制約に見える仕様が、実は想定されている使い方を示していました。
そして最大の教訓は、/usr/sap/trans/bin の件です。エラーメッセージは上から読む。当たり前のことですが、下のほうにある分かりやすい文言(権限、フォルダ構造)に引っ張られて、丸一日を溶かしました。次からは最初の1行を疑います。