> ## 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.

# Demo Perform Dry run Migration of a Jenkins Job 2

> Demonstrates dry-run migration of a Jenkins Pipeline to GitHub Actions using gh actions-importer, showing converted workflows, placeholders for unsupported steps, and guidance on custom transformers and full migration.

This lesson demonstrates a dry-run migration of a Jenkins Pipeline job to GitHub Actions. It continues from the dry-run and production migration concepts typically used for Jenkins Freestyle projects and shows how the `gh actions-importer` tool translates pipeline stages and steps into a GitHub Actions workflow file.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/iRlNGmU-DLlt2Ghu/images/Migrating-Jenkins-Pipelines-to-GitHub-Actions/Automate-Migration-From-Jenkins-to-GitHub-Actions/Demo-Perform-Dry-run-Migration-of-a-Jenkins-Job-2/jenkins-dry-run-migration-slide.jpg?fit=max&auto=format&n=iRlNGmU-DLlt2Ghu&q=85&s=a054f4c318a05320560a88717f75fe3d" alt="A presentation slide with the title &#x22;Perform Dry-run Migration of a Jenkins Job - 2&#x22; centered on a blue-green gradient background. The bottom-left corner shows &#x22;© Copyright KodeKloud.&#x22;" width="1920" height="1080" data-path="images/Migrating-Jenkins-Pipelines-to-GitHub-Actions/Automate-Migration-From-Jenkins-to-GitHub-Actions/Demo-Perform-Dry-run-Migration-of-a-Jenkins-Job-2/jenkins-dry-run-migration-slide.jpg" />
</Frame>

## Source Jenkins Pipeline (pipeline portion of config.xml)

For this demo we used the Pipeline Project 2 located under `Folder One → Folder Two`. Below is the pipeline stage structure (scripted/declarative) from the job's `config.xml`:

```groovy theme={null}
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 2
            echo 'Second stage completed.'
        }
    }
}
```

## Dry-run vs Migrate

* Dry-run: translates and writes workflow files locally without modifying the target repository or creating pull requests.
* Migrate: performs a full migration and can push changes to a target repo or open PRs.

Use the `gh actions-importer` subcommands for both operations.

## Example: Full migration command

```bash theme={null}
gh actions-importer migrate jenkins \
  --target-url https://github.com/:owner/:repo \
  --output-dir tmp/migrate \
  --source-url my-jenkins-project
```

Replace `:owner` and `:repo` with your GitHub organization/user and repository.

## Example: Dry-run command used in this lesson

This dry-run writes translated workflows to `tmp/dry-run` without pushing anything:

```bash theme={null}
gh actions-importer dry-run jenkins \
  --source-url http://139.84.149.83:8080/job/folder-1/job/folder-2/job/pipeline-project-2 \
  --output-dir tmp/dry-run
```

## Actual dry-run invocation (console output)

The demo's console output shows the dry-run invocation and the generated output path:

```bash theme={null}
root@jenkins in /home
# run dry-run
gh actions-importer dry-run jenkins \
  --source-url http://139.84.149.83:8080/job/folder-1/job/folder-2/job/pipeline-project-2 \
  --output-dir tmp/dry-run

[2025-05-22 10:36:34] Logs: 'tmp/dry-run/log/valet-20250522-103634.log'
[2025-05-22 10:36:35] Output file(s):
tmp/dry-run/folder-1/folder-2/pipeline-project-2/.github/workflows/pipeline-project-2.yml

root@jenkins in /home took 23s
```

## Generated workflow (abridged)

After the dry-run, the importer created a GitHub Actions workflow YAML. The converter successfully mapped `echo` statements to `run` steps and injected a `checkout` step. Jenkins `sleep` calls did not have a built-in transformer and are emitted as commented placeholders:

```yaml theme={null}
name: folder-1/folder-2/pipeline-project-2
on:
  workflow_dispatch:

jobs:
  First_Stage:
    name: First Stage
    runs-on: ubuntu-latest
    steps:
      - name: checkout
        uses: actions/checkout@v4.1.0
      - name: echo message
        run: echo Starting the first stage...
      # This item has no matching transformer
      # - sleep:
      #   - key: time
      #     value:
      #       isLiteral: true
      #       value: 5
      - name: echo message
        run: echo First stage completed.
  Second_Stage:
    name: Second Stage
    runs-on: ubuntu-latest
    needs: First_Stage
    steps:
      - name: checkout
        uses: actions/checkout@v4.1.0
      - name: echo message
        run: echo Starting the second stage...
      # This item has no matching transformer
      # - sleep:
      #   - key: time
      #     value:
      #       isLiteral: true
      #       value: 2
      - name: echo message
        run: echo Second stage completed.
```

## What the importer did (summary)

| Jenkins construct     | Result in converted workflow                                                 | Action required                                         |
| --------------------- | ---------------------------------------------------------------------------- | ------------------------------------------------------- |
| `echo`                | Converted to `- run: echo ...` steps                                         | No action needed                                        |
| `checkout` (implicit) | Added via `actions/checkout@v4.1.0`                                          | No action needed                                        |
| `sleep`               | Emitted as commented placeholder (`# This item has no matching transformer`) | Create a custom transformer or manually update workflow |

The dry-run log reveals these internal steps: the importer fetched the job's `config.xml`, converted XML to an intermediate JSON representation, applied configured transformers, and emitted workflow YAML. Transformers were found for `echo` but not for `sleep`, so `sleep` entries appear as comments.

<Callout icon="lightbulb" color="#1CB2FE">
  The importer emits commented placeholders for Jenkins constructs that lack matching transformers. To retain or convert such steps (for example, `sleep`), create a custom transformer that maps the Jenkins keyword/function to an equivalent GitHub Actions step (for instance, `run: sleep 5`). Custom transformers let you tailor conversions for team-specific pipeline usage.
</Callout>

<Callout icon="warning" color="#FF6B6B">
  Before running a full `migrate`:

  * Validate the dry-run output under `tmp/dry-run` and manually review any commented placeholders.
  * Add or author transformers for unsupported keywords if you need automated conversions.
  * Only push or open PRs after confirming the generated workflows are functionally equivalent.
</Callout>

## Next steps

1. Implement custom transformers for unsupported Jenkins constructs (e.g., `sleep` → `run: sleep <time>`).
2. Re-run the dry-run to verify the new transformers produce the desired workflow YAML.
3. When satisfied, perform a full `migrate` to apply workflows to your target GitHub repository or open PRs.

## Links and references

* [GitHub CLI (gh)](https://cli.github.com/)
* GitHub Actions workflows documentation: [https://docs.github.com/actions](https://docs.github.com/actions)
* If you need a starting point for custom transformers, consult your `actions-importer` plugin docs or source repository for transformer templates.

That's all for this lesson — use the dry-run to iterate safely until all steps convert cleanly.

<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/a65b1d88-434f-41e3-8d2f-6e8a0644cbf9" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/migrating-jenkins-pipelines-to-github-actions/module/3b5e500f-482a-4860-9f2c-d5f9fbc95159/lesson/7d298231-8e0e-49ff-8121-9d257ffd0f5e" />
</CardGroup>
