新來的開發人員加入了大型主機團隊。她有五年使用 Git、GitHub、拉取請求、程式碼審查和 CI/CD 管線編寫 Java 微服務的經驗。她知道如何建立特性分支、提交拉取請求、觀察自動化測試的運作、獲取同事的回饋,並在測試通過後合併程式碼。然而,在加入大型主機團隊的第一天,她學習了一套工作流程:開啟 ISPF,導覽至來源 PDS,直接編輯成員,儲存,提交編譯後的 JCL,檢查 SYSOUT 輸出是否有錯誤。這裡沒有分支。除了第 1-6 列的序號之外,沒有任何歷史記錄。沒有拉取請求。沒有自動化測試門控。如果她和同事同時編輯同一個成員,第二個保存會覆蓋第一個,沒有合併,沒有警告,沒有衝突,只有靜默的資料遺失。
這正是大型主機 GitOps 旨在取代的工作流程。它並非取代 z/OS 平台、COBOL 語言,也不是取代大型主機久經考驗、可用性高達 99.9 ...
大型主機 GitOps 的真正意義
GitOps 是一種維運模型,其中 Git 是應用程式程式碼和基礎架構配置的唯一資料來源。對系統、程式碼、配置和部署定義的每一次變更都透過 Git 提交來實現。 Git 倉庫是權威記錄;運作中的系統會進行調整,以確保其內容與 Git 所記錄的一致。
對於大型主機系統而言,這意味著一系列特定的承諾:
Git 是 COBOL 原始碼的權威來源。 z /OS 上的 PDS 函式庫是一個部署工件,用於在生產環境中編譯和運行,但它並非最終的原始碼來源。最終的原始碼來源是 Git 倉庫。如果 PDS 和 Git 倉庫的內容不一致,則以 Git 為準。
所有變更都必須透過拉取請求 (Pull Request) 提交。不允許直接編輯產品定義檔 (PDS)。不允許在 Git 工作流程之外進行緊急編譯和發布。需要立即進行的變更會透過快速拉取請求提交,在真正緊急情況下,審核要求可能會降低,但最終仍需透過 Git 進行。
自動化流水線負責建置和發布。開發人員合併 PR 後,管線會編譯受影響的程序,執行自動化測試,並將編譯後的載入模組發佈到對應的程式庫中。開發人員無需手動提交編譯 JCL。
Git提交歷史記錄就是審計追蹤。生產環境中的每一次變更都可以追溯到特定的提交、特定的作者、特定的拉取請求,如果遵循拉取請求工作流程,還可以追溯到特定的一組審閱者和測試結果。
對於習慣於基於 ISPF 開發的團隊而言,這是一個重大的工作流程變革。同時,這也日益成為企業彌合人才缺口所需的工作流程:即使只懂 Git 的新開發人員無需學習 ISPF 庫管理規範,也能參與 COBOL 開發。
技術挑戰:其他文章未曾解釋的內容
將 COBOL 原始碼移轉到 Git 並非像建立倉庫並複製檔案那麼簡單。 z/OS 的四個特殊技術挑戰使遷移過程更加複雜:
1. EBCDIC 與 UTF-8 編碼對比
z/OS 使用 EBCDIC(擴展二進位編碼十進位交換碼)儲存字元數據,而 Git 使用 UTF-8 儲存檔案。所有在主機和 Git 倉庫之間傳輸的檔案都必須進行轉碼。如果轉碼處理不當、使用了錯誤的代碼頁、轉換過程不一致,或未經轉換就傳輸文件,COBOL 原始碼就會被悄悄損壞。
z/OS Unix 系統服務 (USS) 起到橋樑作用:PDS 中的 COBOL 原始碼在寫入 USS 檔案系統時會被轉碼為 UTF-8 編碼,以便 Git 可以對其進行操作。當 Git 倉庫複製到 USS 時,檔案會被標記上其編碼訊息,以便 z/OS 工具能夠正確解析它們。
打壞
# z/OS USS: correctly tag a Git-managed COBOL source file
chtag -t -c IBM-1047 CUSTPROC.cbl
# Verify the tag
ls -T CUSTPROC.cbl
# Output: t IBM-1047 T=on CUSTPROC.cbl
# The Git checkout hook should apply this automatically
# so developers don't have to tag files manually
2. 固定格式來源和列語義
COBOL 原始檔使用具有列特定語意的固定格式結構:
Columns 1-6: Sequence numbers (optional; ISPF editors fill these automatically)
Column 7: Indicator (* = comment, - = continuation, D = debug line)
Columns 8-11: Area A (division/section/paragraph names, level numbers 01/77)
Columns 12-72: Area B (executable statements, clauses)
Columns 73-80: Identification (program name, historically used for card identification)
COBOL 原始碼的 Git diff 對比結果如果顯示第 73-80 列有更改,通常反映的是序號或標識欄位的更改,而不是代碼的功能性更改。如果 diff 工具無法理解這些列的語義,就會產生幹擾訊息,掩蓋真正的改變。 COBOL 程式碼庫的 Git 配置應該包含以下內容: .gitattributes 它將 COBOL 檔案與差異驅動程式關聯起來,該驅動程式會剝離或忽略標識欄位:
INI
# .gitattributes: configure COBOL-aware diff
*.cbl diff=cobol
*.cob diff=cobol
*.cpy diff=cobol
# .gitconfig (or repo-level config): define the cobol diff driver
[diff "cobol"]
xfuncname = "^[0-9A-Z][0-9A-Z -]+"
wordRegex = "[A-Z][A-Z0-9-]+"
3. PDS 成員名稱約束
PDS成員名稱限8個字符,必須包含大寫字母、數字和加號。 $, #, @在 Git 中,檔案名稱是 PDS 成員名稱(不含副檔名,或帶有標準副檔名)。 .cbl (按慣例添加的擴展名)。 8 個字元的限製造成了命名上的約束: CUSTUPDT 完全映射到 PDS 成員; customer-account-update-processor 才不是。
實踐中行之有效的約定是:保留成員名稱作為基本檔案名稱(8 個字元),並且新增一個 .cbl 在 Git 中使用擴充功能進行來源標識,並使用 Git 中的目錄結構來提供 PDS 命名無法實現的命名空間:
repository/
├── CUSTMGMT/ # Logical application group (no PDS equivalent)
│ ├── CUSTUPDT.cbl # Maps to PDS member CUSTUPDT
│ ├── CUSTINQ.cbl
│ └── CUSTSRCH.cbl
├── COPYBOOKS/
│ ├── CUSTMSTR.cpy # Maps to PDS member CUSTMSTR
│ └── TRANREC.cpy
└── JCL/
├── CUSTNITE.jcl
└── CUSTMON.jcl
4.權威資訊來源問題
在從基於產品定義系統 (PDS) 的開發過渡到基於 Git 的開發過程中,PDS 和 Git 都包含原始碼的副本。哪個版本才是權威的?在透過新的工作流程進行任何生產環境變更之前,必須先明確這個問題的答案。
(引用索引=”42-1″>哪個系統包含權威源:Git、庫管理器,還是同步過程產生的輸出?如果答案不明確,團隊就會花時間解決系統間的差異,而不是交付價值。Git優先模型提供了一個更清晰的答案。Git包含權威源並記錄其歷史記錄。流水線使用該源工件
解決此歧義的過渡方案如下:在特定日期將 Git 倉庫確立為權威源;此日期之後,任何對 PDS 的編輯都將被視為違反策略,必須在當日工作結束前上報並回溯到 Git;緊急修復程序將通過專用的快速 PR 工作流程處理,而非 PDS 編輯例外。在兩個系統都進行維護的過渡期內,時間應盡可能短,因為雙源維護的每一天都可能導致資料不一致。
大型主機 GitOps 工具鏈
將 Git 與 z/OS 交付管道連接起來的有四類工具:
原始碼管理與整合開發環境 (IDE): IBM Developer for z/OS (IDz) 提供了一個基於 Eclipse 的傳統 IDE,支援 ISPF 風格的編輯,並整合了 Git。此外,VS Code 搭配 Zowe Explorer 擴充功能提供了一個現代化的 IDE,它透過 Zowe API 框架連接到 z/OS,無需 IDz。希望吸引熟悉現代工具的開發人員的團隊通常更傾向於選擇 VS Code。
Zowe 框架: Zowe 是一個開源框架,它為 z/OS 提供 REST API,透過標準化的 HTTP 介面公開資料集操作、作業提交和 USS 檔案訪問,這些介面可供標準的 CI/CD 工具呼叫。如果沒有 Zowe(或類似的商業框架),GitHub Actions 運行器或 Jenkins 代理程式就無法透過標準方式與 z/OS 互動。
IBM 基於依賴關係的建置 (DBB): DBB 是 IBM 專為大型主機 GitOps 提供的建置工具。它了解 COBOL 編譯依賴關係,包括每個程式包含哪些副本、IMS 程式需要哪些 DBD 和 PSB、Db2 需要哪些 BIND,並利用這些依賴關係資訊來確定在給定檔案集發生變更時需要編譯哪些內容。
變更管理和部署: ISPW(CA Brightside)、UrbanCode Deploy 和 Rocket Software ISPW 提供升級管理,將編譯後的載入模組從開發庫透過測試環境移動到生產環境,並提供受監管環境所需的審批工作流程和稽核追蹤。
| 工具鏈層 | 開源/IBM選項 | 商業替代方案 |
|---|---|---|
| IDE | VS Code + Zowe Explorer | IBM IDz、博通 IDz |
| z/OS API橋接 | Zowe CLI + API 層 | Rocket ConnectZen,CA Brightside |
| 建構編排 | IBM DBB | BMC Compuware Topaz 工作台 |
| CI/CD 運行器 | Jenkins、GitHub Actions | Azure DevOps、GitLab CI |
| 更換管理層 | Zowe + DBB 部署 | ISPW,UrbanCode部署 |
| 來源推廣 | Git 合併到主分支 | ISPW 推廣工作流程 |
流程:從公關到製作
COBOL 變更的端對端 GitOps 管線涵蓋分散式 CI/CD 平台和 z/OS 執行環境:
雅姆
# GitHub Actions: COBOL GitOps pipeline
name: Mainframe COBOL Pipeline
on:
pull_request:
paths:
- '**/*.cbl'
- '**/*.cpy'
- '**/*.jcl'
jobs:
impact-analysis:
runs-on: ubuntu-latest
outputs:
affected: ${{ steps.analyze.outputs.affected_programs }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Identify changed files
id: changes
run: |
CHANGED=$(git diff --name-only origin/main...HEAD \
| grep -E '\.(cbl|cpy|jcl)$')
echo "changed=$CHANGED" >> $GITHUB_OUTPUT
- name: Analyze dependency scope
id: analyze
# SMART TS XL or DBB dependency analysis determines
# which programs are affected by the changed files
run: |
echo "Resolving dependency scope for: ${{ steps.changes.outputs.changed }}"
# Output: the specific programs that must be compiled/tested
compile-and-test:
needs: impact-analysis
runs-on: [self-hosted, zos-runner] # Runner with z/OS connectivity
steps:
- uses: actions/checkout@v4
- name: Compile affected COBOL programs (via Zowe + DBB)
run: |
zowe dbb build \
--sourceDir ./CUSTMGMT \
--affected "${{ needs.impact-analysis.outputs.affected }}" \
--workDir /u/devops/builds/${{ github.run_id }}
- name: Run unit tests
run: |
zowe zunit run \
--programs "${{ needs.impact-analysis.outputs.affected }}" \
--results-dir /u/devops/results/${{ github.run_id }}
- name: Static compliance check (before promotion)
run: |
# Hardcoded credential check, FILE STATUS validation,
# naming convention compliance
zowe smart-ts-xl analyze \
--scope "${{ needs.impact-analysis.outputs.affected }}"
promote-to-test:
needs: compile-and-test
if: github.event_name == 'pull_request' && github.base_ref == 'main'
runs-on: [self-hosted, zos-runner]
steps:
- name: Promote to TEST library (via ISPW)
run: |
zowe ispw promote \
--programs "${{ needs.compile-and-test.outputs.compiled }}" \
--from DEV --to TEST \
--change-request ${{ github.event.pull_request.number }}
這個流程的關鍵環節是影響分析步驟:確定當 PR 修改特定原始檔集時,哪些 COBOL 程式需要編譯和測試。如果沒有這一步驟,流程要麼編譯所有檔案(速度慢且成本高),要麼只編譯明確修改的檔案(導致依賴已修改副本的程式缺失)。
依賴差距:為什麼影響分析是最困難的部分
Git 能夠準確地知道拉取要求中哪些檔案發生了變更。但 Git 並不知道這些變更會影響哪些其他程式。
修改 PR CUSTMSTR.cpy定義客戶主記錄佈局的模板,在文件數量方面沒有任何變化:只編輯了一個文件。 CUSTMSTR.cpy 47 個 COBOL 程式包含了此檔案。所有 47 個程式都必須重新編譯。如果只編譯明確修改的文件,則有 46 個程式仍會在生產環境中執行,但其副本定義與其編譯後的二進位檔案不再相符。這種不匹配現像在程式運行時才會顯現,因為程式會嘗試使用舊版面配置讀取以新版面配置寫入的資料記錄。
這就是大型主機 GitOps 中存在的依賴關係缺陷:建置系統必須了解依賴關係圖才能確定正確的編譯範圍。 IBM DBB 透過在其建置過程中建立明確依賴關係圖來解決新建程式碼庫的此問題。對於存在數千個早於 DBB 的程式的遺留環境,則必須透過對現有原始程式碼進行靜態分析來建立初始依賴關係圖。
COBOL 建置範圍中需要考慮的四種依賴類型:
COPY 語句是最常見的依賴項。任何透過 COPY 語句引入的副本檔案如果發生更改,都需要重新編譯所有包含該檔案的程式。
CALL 語句是對子程序的靜態呼叫。如果被呼叫程式的介面發生變化(參數、傳回值),則呼叫者可能需要更新並重新編譯。
SQL INCLUDE是包含 DCLGEN 成員(Db2 表的資料類產生器)的嵌入式 SQL 程式。如果 Db2 模式發生變更並產生新的 DCLGEN,則需要重新編譯包含該 DCLGEN 的所有程式。
JCL DD 資料集引用,引用不同資料集或使用不同程式名稱的 JCL 變更會影響操作管道,而不僅僅是程式編譯。
舊工作流程與 Git 工作流程
| 方面 | 基於ISPF PDS的工作流程 | 基於 Git 的 GitOps 工作流程 |
|---|---|---|
| 真理之源 | z/OS 上的 PDS 函式庫 | Git 存儲庫 |
| 編輯機制 | ISPF 編輯器,直接 PDS 成員編輯 | VS Code / IDz 與 Git 集成 |
| 變更追蹤 | 第 1-6 列的序號 | Git提交歷史記錄,包含作者、時間戳記和訊息。 |
| 同步編輯 | 第二次保存會覆蓋第一次儲存(靜默遺失) | 基於分支的開發;合併衝突偵測 |
| 代碼審查 | 非正式的,走到辦公桌前 | 帶有結構化審查和批准的拉取請求 |
| 建置觸發器 | 手動提交 JCL | 透過管道在 PR 或合併時自動執行 |
| 受影響範圍計算 | 手動操作;全部恢復預設設定 | 依賴性分析確定受影響的程序 |
| 審計追踪 | 手動更改日誌;不完整 | Git 日誌 + PR 元資料;完整且可查詢 |
| 引進新開發人員 | 需要 ISPF 培訓 | 符合 Git 標準的入門流程;現代化的整合開發環境 |
| 緊急變更 | 直接 PDS 編輯;經常未被跟踪 | 加快公關工作流程;全程追蹤 |
最下面一行是 ISPF 工作流程操作風險的集中點:直接對生產 PDS 進行緊急更改,繞過變更管理流程,是未追蹤生產變更的最常見來源,也是大型機變更控制審查中最常見的審計發現。
SMART TS XL 實現精確的大型主機 GitOps
大型主機 GitOps 中的依賴關係差距,即「Git 知道什麼發生了變化」和「管道知道要編譯什麼」之間的差距,可以透過對生成依賴關係圖的 COBOL 原始程式碼進行靜態分析來解決。
SMART TS XL“ 應用程式依賴關係映射 產生完整的 COPY 依賴關係圖:包括所有副本、包含它的每個程式、每個嵌套的 COPY 關係以及整個產品組合中的每個 CALL 依賴關係。當 PR 修改 CUSTMSTR.cpy依賴關係圖立即產生包含它的 47 個程式的列表,為 CI 管線編譯正確的組件提供了建置範圍輸入,不多不少。
正是這張依賴關係圖確保了向 Git 優先開發模式的遷移安全:在將 Git 倉庫確立為權威源之前,必須了解完整的依賴關係圖,以便初始倉庫結構能夠反映程序和副本之間的實際依賴關係。如果倉庫結構將副本與包含它們的程序分開,而沒有記錄依賴關係,那麼只有在恰好知道哪些依賴關係的情況下,倉庫才能正確構建,這違背了版本控制的初衷。
靜態程式碼分析功能提供了提交前門邏輯:檢查已更改的程式是否存在硬編碼憑證、缺少 FILE STATUS 聲明、命名約定合規性以及其他靜態品質檢查,這些檢查在 Git 工作流程中作為 PR 閘運行,而不是作為部署後發現運行。
影響分析功能可以回答 PR 審查中的問題:「此次變更的全部範圍是什麼?」修改副本的 PR 的影響範圍涵蓋所有包含該副本的程式以及執行這些程式的所有 JCL 作業。在變更合併之前,將此範圍顯示在 PR 審查環境中,有助於做出明智的審查決策、確定合適的測試範圍以及獲得適當的變更諮詢委員會批准等級。
这 企業搜索 此功能支援稽核追蹤要求:查找特定日期範圍內對特定程式的所有變更(可從 Git 日誌中查詢)、包含特定副本的每個程式(可從依賴關係對應中查詢)、以及由特定作者修改的每個程式(可從 Git 中查詢)。 Git 的提交歷史記錄和 SMART TS XL的結構分析能夠產生合規團隊和變革諮詢委員會所需的完整、可查詢的審計追蹤。
代碼倉庫應該知道代碼所知道的一切
一位擁有五年 Git 經驗的開發人員加入大型主機團隊,她並非要求大型主機轉型為雲端原生平台,而是希望它能夠支援所有現代開發團隊都在使用的工作流程:版本控制、程式碼審查、自動化測試和可追溯性。這些工作流程的存在原因對於 COBOL 和 Java 都同樣適用:防止雙重編輯覆蓋、創建每次生產變更的可審計歷史記錄、實現部署前的程式碼審查,以及自動化繁瑣的機械性工作,從而使開發人員能夠專注於實質工作。
技術挑戰確實存在,例如 EBCDIC 編碼、固定格式原始碼規格、PDS 命名限制以及權威原始碼問題。但這些挑戰並非無法解決。工具鏈(包括 Zowe、DBB、帶有 Zowe Explorer 的 VS Code 以及變更管理平台)可以應對其中大部分挑戰。剩下的困難在於依賴關係分析,它能夠確保在共享元件發生變更時,管線建構的範圍與實際情況相符。
使用 Git 管理原始程式碼、透過 CI/CD 管線建置、並透過自動化部署工作流程進行部署的大型主機,並非一台不同的大型主機。它仍然是同一台大型主機,運行著同樣經過驗證的 COBOL 程序,具有相同的 99.999% 可靠性。如今,擁有五年現代工具使用經驗的開發人員只需加入這台大型主機,即可在第一週結束前高效工作。