Skip to main content
A dry-run simulates converting a Jenkins pipeline into GitHub Actions workflows without changing your repository. It writes the generated workflow files to an output directory you specify but does not open pull requests or modify existing configuration. This is a safe way to inspect the importer’s translation of Jenkins constructs into GitHub Actions before applying any changes.
A presentation slide titled "Dry-run" with a highlighted line reading: "A safe, non-disruptive way to simulate converting a Jenkins pipeline into a GitHub Actions workflow." A small "© Copyright KodeKloud" appears in the bottom-left.
Use dry-run to verify how Jenkins pipeline constructs (agents, environment, stages/steps) are mapped to GitHub Actions concepts (runs-on, env, jobs/steps) before committing any changes.
Always provide the full Jenkins job URL and an output directory you control. The dry-run will not change your repo, but incorrect URLs or output paths can cause confusing results or missed files.

Command usage

Provide the Jenkins job URL and an output directory to write the generated workflows:
gh actions-importer dry-run jenkins --url "https://jenkins.example.com/job/my-job/" --output-dir "./output"
Be sure to use the full Jenkins job URL (including /job/<name>/ where applicable) and an output directory path that you control.

What the dry-run produces

The dry-run generates files representing the GitHub Actions workflows equivalent to the given Jenkins pipeline. It preserves any items that the importer cannot automatically translate as commented entries in the YAML output so you can review them and implement custom handling. Below is an example showing an original Jenkins Declarative Pipeline and the generated GitHub Actions workflow produced by a dry-run. Original Jenkins pipeline (Declarative Pipeline syntax):
pipeline {
    agent {
        label 'TeamARunner'
    }

    environment {
        DISABLE_AUTH = 'true'
        DB_ENGINE = 'sqlite'
    }

    stages {
        stage('build') {
            steps {
                echo "Database engine is ${DB_ENGINE}"
                sleep 80
                echo "DISABLE_AUTH is ${DISABLE_AUTH}"
            }
        }
        stage('test') {
            steps {
                junit '**/target/*.xml'
            }
        }
    }
}
Generated GitHub Actions workflow (YAML). Notice how environment and agent.label map to env and runs-on. Items the importer could not translate (for example, sleep 80) are left as commented placeholders near where they would have been handled.
name: test_pipeline
on:
  push:
env:
  DISABLE_AUTH: 'true'
  DB_ENGINE: sqlite
jobs:
  build:
    runs-on:
      - self-hosted
      - TeamARunner
    steps:
      - name: checkout
        uses: actions/checkout@v2
      - name: echo message
        run: echo "Database engine is ${{ env.DB_ENGINE }}"
# This item has no matching transformer
# - sleep:
#   - key: time
#     value:
#       isLiteral: true
#       value: 80
      - name: echo message
        run: echo "DISABLE_AUTH is ${{ env.DISABLE_AUTH }}"

  test:
    runs-on:
      - self-hosted
      - TeamARunner
    needs: build
    steps:
      - name: checkout
        uses: actions/checkout@v2
      - name: Publish test results
        uses: EnricoMi/publish-unit-test-result-action@v1.7
        if: always()
        with:
          files: "**/target/*.xml"

Common mappings

The importer converts many Jenkins constructs to GitHub Actions equivalents. The table below summarizes typical mappings and examples.
Jenkins constructGitHub Actions equivalentExample
agent (label)runs-onlabel 'TeamARunner'runs-on: ['self-hosted', 'TeamARunner']
environmentenvDISABLE_AUTH = 'true'env: DISABLE_AUTH: 'true'
stages / stepsjobs / stepsstage('build') { steps { ... } }jobs.build.steps: [...]
Test publishingActions or community actionsjunit '**/target/*.xml'uses: EnricoMi/publish-unit-test-result-action@v1.7

Notes on partial conversions

  • Many Jenkins constructs map directly to GitHub Actions concepts (agents -> runs-on, environment -> env, stages/steps -> jobs/steps).
  • When a Jenkins construct has no matching transformer (for example, sleep 80), the importer leaves a commented representation in the generated YAML so you can review and implement the desired behavior manually.
  • Commented placeholders in the YAML make it clear where custom handling is required and where to add your own steps or actions.
  • The generated workflow includes best-effort substitutions (for example, self-hosted + label for custom runners) but you should review runs-on and runner labels to ensure they match your GitHub-hosted or self-hosted runner setup.

Next steps

  • Review the generated files in the --output-dir and confirm the mappings for env, runs-on, job dependencies (needs), and test publishing.
  • Create custom transformers for Jenkins constructs that need automatic translation (for example, converting sleep into an equivalent step using timeout or a small script).
  • When satisfied with the dry-run output, run the importer without dry-run to generate real workflow files and open a pull request.
Links and references

Watch Video