Skip to main content
In this lesson we demonstrate how to use a custom transformer to add, map, or remove environment variables while converting Jenkins pipelines into GitHub Actions workflows. The transformer lets you:
  • Map Jenkins env vars to GitHub Actions env vars
  • Convert Jenkins variables into GitHub Actions secrets
  • Remove variables from the generated workflow
A presentation slide with the title "Custom Transformer — environment variables" centered on a blue-green gradient background. A small "© Copyright KodeKloud" appears in the bottom-left corner.
Overview
  • The custom transformer runs during the import/dry-run and modifies the resulting workflow’s env section.
  • You author rules in a small Ruby DSL file that the importer evaluates to translate or remove variables.
  • This process is especially useful for mapping credential references to GitHub Actions secrets.
Transformer syntax examples Below are common transformer directives used in the Ruby DSL. You can place these in a transformer file (e.g., ss-pipeline-transformer.rb).
env "OCTO", "CAT"                 # map OCTO -> CAT (literal)
env "MONA_LISA", nil              # remove MONA_LISA from output
env "MONALISA", secret("OCTOCAT") # map MONALISA -> secret named OCTOCAT
You can match multiple variables using regular expressions:
env /.*/, nil                     # remove all environment variables
Quick reference
Transformer directivePurposeExample
env "NAME", "value"Map a literal valueenv "MONGO_USERNAME", "superuser"
env "NAME", secret("KEY")Use a GitHub Actions secretenv "MONGO_PASSWORD", secret("mongo_db_password")
env "NAME", nilRemove a variable from outputenv "MONGO_DB_CREDS", nil
Jenkins pipeline example This is the Jenkinsfile we will convert — a simple two-stage pipeline triggered by poll SCM:
stages {
  stage('First Stage') {
    steps {
      echo 'Starting the first stage...'
      sleep 5
      echo 'First stage completed.'
    }
  }

  stage('Second Stage') {
    steps {
      echo 'Starting the second stage...'
      sleep 20
      echo 'Second stage completed.'
    }
  }
}
Dry-run conversion (initial) First, run a dry-run conversion without any custom transformer to inspect the base output and see which environment variables remain unresolved:
gh actions-importer dry-run jenkins \
  --source-url http://139.84.149.83:8080/job/ci-pipeline-poll-scm/ \
  --output-dir tmp/dry-run
Example dry-run output (summarized):
[2025-05-22 12:54:02] Logs: 'tmp/dry-run/log/valet-20250522-125402.log'
[2025-05-22 12:54:06] Output file(s):
    tmp/dry-run/ci-pipeline-poll-scm/.github/workflows/ci-pipeline-poll-scm.yml
Generated workflow (excerpt) The importer generates a workflow that often requires manual tuning. Here are representative excerpts to show where env vars appear and how some items may be left as commented placeholders when the importer doesn’t have a mapping. Example job (Trivy scan):
Trivy Vulnerability Scanner:
  name: Trivy Vulnerability Scanner
  runs-on:
    - self-hosted
    - us-west-1-ubuntu-22
  needs: Build_Publish_Image
  steps:
    - name: checkout
      uses: actions/checkout@v4.1.0
    - name: sh
      shell: bash
      run: trivy image siddharth67/solar-system:$GIT_COMMIT --severity CRITICAL --exit-code 1 --quiet --format json -o trivy-image-CR
    - name: sh
      shell: bash
      run: trivy convert --format template --template "@/usr/local/share/trivy/templates/html.tpl" --output trivy-image-CRITICAL-resu
    - name: Upload Artifacts
      uses: actions/upload-artifact@v4.1.0
      with:
        if-no-files-found: ignore
        name: Trivy Image Critical Vul Report
        path: "."
Workflow header, triggers and environment (note the converted cron and partially converted env vars):
name: ci-pipeline-poll-scm
on:
  push:
    branches:
      - main
  schedule:
    - cron: "0 0 * * *"
env:
  MONGO_URI: mongodb+srv://supercluster.d83jj.mongodb.net/superData
#  # This item has no matching transformer
# MONGO_DB_CREDS:
#  # This item has no matching transformer
# MONGO_USERNAME:
#  # This item has no matching transformer
# MONGO_PASSWORD:
jobs:
  Installing_Dependencies:
    name: Installing Dependencies
    runs-on:
      - self-hosted
      - us-west-1-ubuntu-22
    container:
      image: node:24
    steps:
      - name: checkout
        uses: actions/checkout@v4.1.0
      - name: sh
        shell: bash
        run: npm install --no-audit
Why some env vars were not transformed
  • The importer converts SCM polling to a GitHub Actions cron schedule automatically.
  • Credential references stored in Jenkins credential stores are typically not transformed by default. Those appear as commented placeholders with the message # This item has no matching transformer.
  • Use a custom transformer to explicitly map these variables to literals or secrets.
Creating a custom transformer to handle environment variables Create a transformer file (for example ss-pipeline-transformer.rb) and use env directives to add mappings, mark values as secrets, or remove variables. Example transformer (Ruby DSL):
# ss-pipeline-transformer.rb
env "MONGO_USERNAME", "superuser"
env "MONGO_PASSWORD", secret("mongo_db_password")
env "MONGO_DB_CREDS", nil
  • secret("mongo_db_password") indicates the importer should reference the GitHub Actions secret named mongo_db_password.
  • Setting a variable to nil removes it from the generated workflow.
Run dry-run with the custom transformer Re-run the importer specifying the transformer file:
gh actions-importer dry-run jenkins \
  --source-url http://139.84.149.83:8080/job/ci-pipeline-poll-scm/ \
  --output-dir tmp/dry-run \
  --custom-transformers ss-pipeline-transformer.rb
If you see a message such as:
[2025-05-22 12:58:53] No custom transformers found at path: /data/ss-pipeline-transformer.rb
it usually means the transformer path is incorrect relative to your current working directory. Verify the file exists (for example ls ss-pipeline-transformer.rb) and either run the command from that directory or supply an absolute path to --custom-transformers.
Resulting transformed workflow (excerpt) After applying the custom transformer, the env section reflects the mappings and secrets:
name: ci-pipeline-poll-scm
on:
  push:
    branches:
      - main
  schedule:
    - cron: "0 0 * * *"
env:
  MONGO_URI: mongodb+srv://supercluster.d83jj.mongodb.net/superData
  MONGO_USERNAME: superuser
  MONGO_PASSWORD: "${{ secrets.mongo_db_password }}"
jobs:
  Installing_Dependencies:
    name: Installing Dependencies
    runs-on:
      - self-hosted
      - us-west-1-ubuntu-22
    container:
      image: node:14
    ...
Best practices and tips
  • Keep transformer files in your project repository and reference them with a relative or absolute path to avoid “not found” errors.
  • Prefer mapping credentials to GitHub Actions secrets rather than hard-coding sensitive values.
  • Use regular expressions cautiously to avoid accidentally removing environment variables you need.
Summary
  • Use env "NAME", "value" to map literals, env "NAME", secret("KEY") to map to GitHub Actions secrets, and env "NAME", nil to remove variables from the generated workflow.
  • If the importer cannot find your custom transformer, verify the path and working directory or use an absolute path.
  • This article focuses on env var transformation; other Jenkins-specific constructs (e.g., complex credential bindings or specialized plugins) may require additional custom handling and are covered separately.
Links and references

Watch Video