2021 Call for Code Awards: Live from New York, with SNL’s Colin Jost! Learn more

Integrate IBM z/OS platform into continuous integration pipelines with GitLab

When it comes to continuous integration (CI), orchestrators play a critical role in executing pipelines, managing various tasks that must be performed to build applications. Among the popular DevOps solutions, GitLab offers an extension to their source code management solution with the GitLab CI feature. This tutorial shows you how to set up a GitLab runner to integrate z/OS platforms into GitLab CI pipelines, and proposes a sample configuration using a multi-project pipeline to build a mainframe application with dependency-based build.

Estimated time

It should take you about 90 minutes to complete this tutorial.


GitLab is a popular solution for source code management, but it also includes several features in the DevOps space to extend its scope of activities and enhance user experience. One of these features is the CI mechanism, which provides orchestration capabilities and brings automation closer to source repositories.

The main object in GitLab is a project that combines a Git repository with project-related features like CI: With this concept, there is tight integration between the project and its automation, linking a repository with its CI pipeline. Thus, the CI pipeline is defined in the project as a YAML file stored in the repository, and it is usually called .gitlab-ci.yml.

The CI feature relies on a server-runners architecture: The GitLab server owns the pipeline definitions for each project and delegates its work to agents installed on target environments. In GitLab terminology, agents are called runners and can be customized to perform specific actions depending on the type of artifacts they are working with. The most popular executors are Docker and Shell, but other types of executors can be used to support specific configurations. Documentation related to the GitLab runners can be found at https://docs.gitlab.com/runner/.

Runners are registered in the GitLab server configuration and can be shared or dedicated to a project, depending on users’ needs. When a pipeline is triggered for execution, the GitLab server parses the pipeline definition file and pipeline actions are sent to an assigned runner for execution.

Step 1. Integrate IBM z/OS platform into GitLab CI

GitLab runners are written in Go, a language that is not yet supported by IBM z/OS (at the time of this writing), so they cannot run natively in this environment. To circumvent this situation, the best option is to use a specific type of executor, which leverages the SSH protocol.

The SSH runners are executed on a supported platform (Windows, Linux, or MacOS) and connect to a target machine through SSH for the pipeline execution. In that configuration, SSH runners act like gateways to connect platforms: The GitLab server sends the pipeline actions to the SSH runner, which in turn forwards them to the target machine (in this case the z/OS environment). The different stages of the pipeline are executed on the target z/OS machine and results are sent back to the GitLab server through the same mechanism.

With version 13.2 released in July 2020, GitLab supports the execution of runners on Linux on Z machines and proposes a Docker image of the runner for this platform. This support extends the capabilities of GitLab CI on mainframe, allowing the full GitLab CI stack to be deployed on the Linux on Z environment. The use of SSH executors, as described in this document, is applicable to Linux on Z runners.

The Docker image can also run under the control of the z/OS Container Extension (zCX) which is available with z/OS 2.4. In this configuration, the necessary components for the integration of z/OS with GitLab CI run in a single z/OS environment. The configuration of Linux on Z GitLab runners is not in scope for this tutorial, but information and guidelines on setting up zCX can be found in the IBM Redbook “Getting started with z/OS Container Extensions and Docker.”


As GitLab CI runners only support the Bash shell environment, the default shell provided by z/OS is insufficient to support this configuration. As a prerequisite, the Bash shell must be installed on z/OS. This Bash shell is provided by Rocket as part of their Open Source Languages and Tools for z/OS offering.

As the execution of the pipeline is performed through an SSH channel, it is important to have the Bash shell available for the user who will execute the build actions. More importantly, the Bash shell must be set to be the first program executed by the user when logging into z/OS Unix System Services. This parameter is controlled through the PROGRAM keyword in the RACF’s user definition, as part of the OMVS segment. To change the PROGRAM value for an existing user, please customize and use the following RACF ALTUSER command:


Where #USERID# is the user ID to be updated and #PATH_TO_BASH# is set to the path of the Bash shell executable (do not surround with quotes).

During the execution of a pipeline on the target machine, the script generated by GitLab CI is looking for the bash executable at a specific location, in /bin/bash. As Bash is not standard on z/OS, this location doesn’t exist, and a symbolic link must be created to point to the actual path of the bash executable. Please customize and use the following command to create a symbolic link to point to the correct location:

ln -s #PATH_TO_BASH# /bin/bash

The Git for z/OS client must also be installed and configured on the z/OS USS platform. It is available through the IBM Passport Advantage website or it can be obtained from Rocket’s Open Source Languages and Tools for z/OS packaging. You can find installation guidance in the IBM Knowledge Center.

Git for z/OS is free software with no support, but IBM support is available through the IBM Elite Support for Rocket Git for zOS offering.

Install the GitLab runner

First, download the gitlab-runner distribution for the appropriate platform here. In this configuration, the SSH GitLab runner is installed on a Linux x86 Red Hat distribution, but similar installation and configuration can be performed on other supported platforms.

In Linux, install the downloaded package with this command:

rpm -i gitlab-runner_amd64.rpm

Then register the runner to the GitLab server, by issuing this command:

sudo gitlab-runner register

The configurator prompts you for several pieces of information that are displayed in the GitLab server administration area (runners section):

Setting up a shared runner

Provide the GitLab server URL and the registration token to register the runner. Then provide a description for this runner and leave it empty when prompted for tags. Provide the type of executor by typing ssh, and provide the necessary information for SSH communication (IP or hostname of the target z/OS machine, port, username, and password, or path to the SSH identity file). When finished, start the runner by issuing the command:

gitlab-runner start

The runner should appear in the Runners section of the GitLab administration area:

GitLab admin - Runners

Step 2. Set up pipelines in GitLab CI

Once the GitLab SSH runner is set up for z/OS, CI pipelines can be executed on the mainframe. The definitions of pipelines in GitLab CI are done through a configuration file called .gitlab-ci.yml and stored at the root level of the project’s repository. The pipeline definition reference is available here.

The purpose of this tutorial is not to provide a complete pipeline sample, but rather to show an implementation of pipelines using available features in GitLab CI in order to build a mainframe application on z/OS. Compilation and linkage editing of mainframe source files are performed with the Dependency-Based Build (DBB) solution and the zAppBuild framework, which facilitates the orchestration of build operations.

Build a z/OS application with a simple pipeline

In this first use case, the project contains all the necessary materials to build the application: zAppBuild is part of the project and has been customized to meet the environment’s requirements. This scenario uses the sample Mortgage application, which is available in GitHub.

Sample Mortgage app

The pipeline is made up of a single operation, which is the build of the full z/OS COBOL application with zAppBuild and DBB. It only contains one step which is defined as part of the build stage:

z/OS COBOL application build

Here is the text version of the pipeline:

buildRepo: stage: build
- /usr/lpp/dbb/v1r0/bin/groovyz -Djava.library.path=/usr/lpp/dbb/v1r0/lib:/usr/lib/java_runtime64 zAppBuild/build.groovy --workspace /u/mdalbin/${CI_PROJECT_DIR} --application MortgageApplicationV2 --workDir /u/mdalbin/${CI_PROJECT_DIR} --outDir /tmp --hlq MDALBIN.PROG.MORTV2GL --fullBuild --verbose
variables: CI_DEBUG_TRACE: "true"

For convenience, the extended trace has been activated to facilitate debugging, but it is recommended that you remove it when the pipeline performs the desired actions correctly.

In the GitLab CI section of this project, the execution of this pipeline was manually triggered and finished successfully in 26 seconds:

Pipeline execution status

When drilling down and checking the output log of the buildRepo job, you’ll see that the execution of the DBB command shows that the full build of the application was performed, building eight COBOL files successfully.

Build a z/OS application with multiple projects

Mainframe applications usually communicate with each other through interfaces defined in copybooks. In order to be built correctly, an application must include the copybooks of the other applications it communicates with. With Git, this generally implies that the application’s main repository is insufficient for building, and other repositories that contain shared copybooks from other applications are needed for a successful build. In GitLab CI, this situation implies referencing other projects, which contain sources for other applications.

This situation can be managed with multi-project pipelines, a feature of GitLab CI that permits the triggering of pipelines in other projects. The reference for this feature is available here.

In this use case, the Mortgage application has been split into two components, EPSC and EPSM, and a third project contains common copybooks that are used by the two components. To be built, the EPSC component needs to reference copybooks that are owned by the EPSM project and common copybooks. A fourth project contains the zAppBuild framework, which is customized for the z/OS environment. The correct build of the EPSC component requires that the four projects be transferred to z/OS USS.

Using the multi-project pipelines feature makes it possible to trigger the execution of the external projects pipeline, which solves this complex situation. To be cloned on z/OS USS, the pipelines for the EPSM project, the Common project, and the zAppBuild project will just contain a dummy operation, as cloning is automatically generated by the GitLab server in the execution of the pipeline. The pipeline definition for the Common project is as follows:

Pipeline definition

Similar pipeline definitions are configured for the EPSM project and for the zAppBuild project.

For the EPSC project, the pipeline contains steps in the .pre stage, which is the first stage executed in the pipeline. These steps trigger downstream pipelines for the EPSM, Common, and zAppBuild projects.

  stage: .pre
    project: root/zappbuildgitlab
    strategy: depend

  stage: .pre
    project: root/gl-mortgageapplicationv2-common
    strategy: depend

  stage: .pre
    project: root/gl-mortgageapplicationv2-epsm
    strategy: depend

  stage: build
  - cd
/u/mdalbin/${CI_BUILDS_DIR}/${CI_RUNNER_SHORT_TOKEN}/${CI_CONCURRENT_ID}/root/zappbuildgit lab/
  - /usr/lpp/dbb/v1r0/bin/groovyz -Djava.library.path=/usr/lpp/dbb/v1r0/lib:/usr/lib/java_runtime64 build.groovy --workspace
/u/mdalbin/${CI_BUILDS_DIR}/${CI_RUNNER_SHORT_TOKEN}/${CI_CONCURRENT_ID}/root/ -- application gl-mortgageapplicationv2-common --workDir /u/mdalbin/${CI_PROJECT_DIR} --outDir /tmp - -hlq MDALBIN.PROG.MORTV2GL --fullBuild --verbose

  - .pre
  - build

In this configuration, the jobs zAppBuild-Update, MortgageApplicationV2-Common-Update, and MortgageApplicationV2-EPSM-Update execute first, triggering downstream pipelines for the different projects. With the keyword strategy: depend, the main pipeline waits until all the jobs in the .pre stage are finished before moving to the build stage, which contains the buildRepo job that performs the build of the EPSC component with DBB.

In the GitLab CI section of the EPSC project, the correct execution of the pipeline can be checked:

Checking pipeline execution

By selecting the pipeline, the actual sequence of downstream jobs is displayed:

Sequence of downstream jobs

Zooming in on the buildRepo job, the correct execution of the build process for the EPSC component shows that eight programs were successfully built by DBB.


This tutorial has helped you to understand and set up GitLab CI facilities to integrate z/OS platforms into a unique solution. With the multi-project pipeline feature, you are now able to orchestrate multiple builds with dependencies, enabling end-to-end delivery of multi-tier applications. You can now extend your GitLab CI pipeline with z/OS actions to include unit testing and deployment with Urban Code Deploy.