Blog

Modernizing CI/CD: Migrating Bash and Jenkins Pipelines to GitHub Actions

12.05.2026
Reading time: 4 mins.
Last Updated: 12.05.2026

Table of Contents

In earlier posts Migrating Bitbucket Repositories and Pipelines to GitHub Actions and Secure Dependency Updates During Bitbucket to GitHub Migration , we covered how repositories were migrated from Bitbucket Cloud to GitHub and how project dependencies were securely updated to ensure builds continued to run reliably. With source control and dependencies in place, the next step in the migration journey is to modernize the CI/CD layer itself.

This article focuses on modernizing continuous integration workflows by translating existing Bash scripts and Jenkins pipelines into GitHub Actions, creating a unified, maintainable automation model.

bash

In this project, one of the pipelines was implemented using a Bash script, with Jenkins orchestrating and executing the build process. The goal of the migration was to map the existing script logic and pipeline behavior into a GitHub Actions workflow without changing the build outcome.

Below is an example of the original build.sh script:

#!/bin/bash
set -e
set -x

branch=$1
commit=$2

# Clean previous builds
make -f docker.mk cleanup DOWNLOAD_DIR=/path/to/downloads

# Run the build
make -f docker.mk DOWNLOAD_DIR=/path/to/downloads

# Copy build artifacts
mkdir -p output/${branch}_${commit}
cp build/* output/${branch}_${commit}/

# Publish build artifacts to a remote server
pscp -i /path/to/private_key -P REMOTE_PORT -q -r output/${branch}_${commit} REMOTE_USER@REMOTE_HOST:REMOTE_PATH

This script encapsulates the core build logic: cleaning previous outputs, running the build, and collecting artifacts into a structured output directory.

The Jenkins pipeline responsible for running this script was defined as follows:

import java.text.SimpleDateFormat;

def builders = [:]

builders['linux-builder'] = {
    node('linux-node') {
        build_project()
    }
}

parallel builders

void build_project() {
    stage('Build') {
        def scmVars = checkout scm
        def commit = scmVars.GIT_COMMIT.take(8)
        sh "./build.sh ${scmVars.GIT_BRANCH} ${commit}"
    }
}

Jenkins handled repository checkout, extracted branch and commit metadata, and executed the Bash script on a specific build node.

To migrate this setup, a workflow file is defined under .github/workflows/. This file describes when the pipeline runs, which runner executes it, and which steps are required.

In the Jenkins setup, pipelines were triggered via Bitbucket webhooks and could be restricted to specific branches. This behavior is mapped in GitHub Actions using branch-based triggers:

on:
  push:
    branches:
      - main
      - 'release/*'
  workflow_dispatch:

This configuration ensures the workflow runs automatically on pushes to the specified branches, while workflow_dispatch enables manual execution similar to Jenkins’ “Build Now” functionality.

In GitHub Actions, the execution environment is defined using the runs-on keyword:

runs-on: [self-hosted, us-east-1, X64, yocto]

This instructs GitHub Actions to run the job on a self-hosted runner matching these tags (see our deep dive on deploying self‑hosted GitHub runners on Kubernetes). Conceptually, this maps directly to node(‘linux-node’) in Jenkins, ensuring the build runs on the appropriate machine.

In Jenkins, repository checkout and metadata extraction were handled using:

def scmVars = checkout scm

In GitHub Actions, this is achieved using the checkout action and built-in context variables:

- name: Checkout repository
  uses: actions/checkout@v4
env:
  DOWNLOAD_DIR: /path/to/downloads
  BRANCH: ${{ github.ref_name }}

The repository is checked out into $GITHUB_WORKSPACE, while branch and commit information is exposed through ${{ github.ref_name }} and ${{ github.sha }}. This provides the same inputs previously passed to the Bash script in Jenkins.

Using the run keyword allows shell commands to execute without modification, making the migration straightforward and low risk.

To collect build outputs, GitHub Actions provides a built-in artifact upload action:

- name: Upload artifacts
  uses: actions/upload-artifact@v4
  with:
    name: build-artifacts
    path: output/**

In the original Jenkins setup, artifacts were uploaded to a remote server using tools like pscp. With GitHub Actions, artifacts are stored directly within GitHub, eliminating the need for external servers while keeping artifacts easily accessible from the workflow run.

The fully migrated workflow looks like this:

name: Build Pipeline

on:
  push:
    branches:
      - main
      - 'release/*'
  workflow_dispatch:

env:
  DOWNLOAD_DIR: /path/to/downloads
  BRANCH: ${{ github.ref_name }}

jobs:
  build:
    runs-on: [self-hosted, us-east-1, X64, yocto]

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Clean build
        run: make -f docker.mk cleanup DOWNLOAD_DIR=$DOWNLOAD_DIR

      - name: Build project
        run: make -f docker.mk DOWNLOAD_DIR=$DOWNLOAD_DIR

      - name: Upload artifacts
        uses: actions/upload-artifact@v4
        with:
          name: build-artifacts
          path: output/**

When moving from a Jenkins and Bash based setup to GitHub Actions, the objective is not to replicate scripts line by line. Instead, the focus is on preserving pipeline logic and outcomes ensuring clean builds, correct artifacts, and reliable execution-while improving maintainability and reducing operational overhead.

With CI workflows modernized and consolidated under GitHub Actions, the final step is to migrate native Bitbucket Pipelines. The next article will focus on translating YAML based Bitbucket Pipelines into GitHub Actions workflows, completing the transition to a fully standardized CI/CD platform.

Stay tuned for the next part of the series.

Check out more of our blog posts here.

More Posts

The ITGix AWS Landing Zone continues to evolve with a clear goal: enabling organizations to build secure, compliant, and scalable AWS environments with less operational overhead. Across recent releases (v1.2.0...
Reading
In earlier articles, we covered migrating repositories from Bitbucket Cloud, securely updating project dependencies, and modernizing CI/CD workflows by translating Jenkins and Bash-based pipelines to GitHub Actions. With those foundations...
Reading
Get In Touch
ITGix provides you with expert consultancy and tailored DevOps services to accelerate your business growth.
Newsletter for
Tech Experts
Join 12,000+ business leaders and engineers who receive blogs, e-Books, and case studies on emerging technology.