> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Dry run

> Explains how to perform a dry-run conversion of Jenkins pipelines to GitHub Actions workflows, generating workflows locally for review without modifying the repository.

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.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/iRlNGmU-DLlt2Ghu/images/Migrating-Jenkins-Pipelines-to-GitHub-Actions/Automate-Migration-From-Jenkins-to-GitHub-Actions/Dry-run/dry-run-jenkins-to-github-actions.jpg?fit=max&auto=format&n=iRlNGmU-DLlt2Ghu&q=85&s=b43e807c6c34421c456844fe0e728864" alt="A presentation slide titled &#x22;Dry-run&#x22; with a highlighted line reading: &#x22;A safe, non-disruptive way to simulate converting a Jenkins pipeline into a GitHub Actions workflow.&#x22; A small &#x22;© Copyright KodeKloud&#x22; appears in the bottom-left." width="1920" height="1080" data-path="images/Migrating-Jenkins-Pipelines-to-GitHub-Actions/Automate-Migration-From-Jenkins-to-GitHub-Actions/Dry-run/dry-run-jenkins-to-github-actions.jpg" />
</Frame>

<Callout icon="lightbulb" color="#1CB2FE">
  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.
</Callout>

<Callout icon="warning" color="#FF6B6B">
  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.
</Callout>

## Command usage

Provide the Jenkins job URL and an output directory to write the generated workflows:

```bash theme={null}
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):

```groovy theme={null}
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.

```yaml theme={null}
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 construct  |    GitHub Actions equivalent | Example                                                                           |
| ------------------ | ---------------------------: | --------------------------------------------------------------------------------- |
| `agent` (label)    |                    `runs-on` | `label 'TeamARunner'` → `runs-on: ['self-hosted', 'TeamARunner']`                 |
| `environment`      |                        `env` | `DISABLE_AUTH = 'true'` → `env: DISABLE_AUTH: 'true'`                             |
| `stages` / `steps` |             `jobs` / `steps` | `stage('build') { steps { ... } }` → `jobs.build.steps: [...]`                    |
| Test publishing    | Actions or community actions | `junit '**/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

* [GitHub Actions documentation](https://docs.github.com/actions)
* [Jenkins documentation](https://www.jenkins.io/doc/)
* [GitHub Actions Importer (gh actions-importer)](https://github.com/github/gh-actions-importer)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/migrating-jenkins-pipelines-to-github-actions/module/3b5e500f-482a-4860-9f2c-d5f9fbc95159/lesson/8c88e5f7-609c-431e-9d7b-013ae5380f32" />
</CardGroup>
