# GitHub Actions Importer: what it converts and what it leaves for you

> GitHub Actions Importer audits, forecasts and converts pipelines from seven CI systems. See each command, what it converts, and what stays manual.

Source: https://latchkey.dev/learn/migrate/github-actions-importer  
Updated: 2026-11-12

GitHub Actions Importer is a GitHub CLI extension, `gh actions-importer`, that runs in Docker and converts pipelines from Azure DevOps, Bamboo, Bitbucket Pipelines, CircleCI, GitLab, Jenkins and Travis CI into GitHub Actions workflows. Its `audit`, `forecast`, `dry-run` and `migrate` commands inventory a CI server, estimate Actions usage, convert one pipeline to local files and open a pull request, while secrets, runners and unknown plugins or orbs remain manual.

You have more pipelines than you want to convert by hand, and you want to know which ones will convert cleanly before you promise a date. That is the job the Importer does best: it reads the CI server, converts every pipeline it can, and writes a report that sorts them by how much is left to do.

It is not a finished migration. GitHub's documentation sets the goal at 80% conversion per workflow and says every converted workflow should be inspected before it runs production work. This page covers each command, the files they write, the per-platform manual work, and the mapping details that change behavior.

## Install it and configure credentials

The Importer is a container image plus a `gh` extension that drives it, so it needs Docker running and the GitHub CLI installed. It does not have to run on the CI server; it talks to it over the API.

`configure` prompts for a GitHub personal access token (classic) with the `repo` and `workflow` scopes, which `migrate` uses to open pull requests, plus the URL and token for your CI system, and writes them to `.env.local`. `update` pulls the latest image. The extension itself last tagged a release, v1.3.6, in October 2023; the converter ships in the image, so run `update` before each session.

```Terminal
gh extension install github/gh-actions-importer
gh actions-importer update
gh actions-importer configure
gh actions-importer version
```

## Which platforms, and how each names a pipeline

All seven platforms support all four planning and conversion commands. What differs is the subcommand and the flag that identifies one pipeline for `dry-run` and `migrate`.

| Platform | Subcommand | Names one pipeline with |
| --- | --- | --- |
| Jenkins | `jenkins` | `--source-url` (the job URL) |
| GitLab, cloud or self-managed | `gitlab` | `--namespace` and `--project` |
| CircleCI | `circle-ci` | `--circle-ci-project` |
| Azure DevOps | `azure-devops pipeline` or `release` | `--pipeline-id` |
| Bamboo | `bamboo build` or `deployment` | `--plan-slug` or `--deployment-project-id` |
| Bitbucket Pipelines | `bitbucket` | `--workspace` and `--repository` |
| Travis CI | `travis-ci` | `--travis-ci-repository` |

> From each platform's "Migrating from ... with GitHub Actions Importer" page on docs.github.com, read 2026-11-12. For GitLab and CircleCI, `audit` needs an organization account; `dry-run` and `migrate` also work with a user account.

## Audit, then forecast

`audit` fetches every project on the server, converts each one and writes `audit_summary.md` beside the converted files. Pipelines land in four buckets: successful (everything converted), partially successful (the structure converted, some items did not), unsupported, and failed, which usually means the original was invalid or the token could not read it. Build steps are counted as known, unknown or unsupported, and a Manual tasks section lists the secrets and self-hosted runner labels you have to create. `workflow_usage.csv` lists the actions, secrets and runners each pipeline uses, which is the list a security review wants.

`forecast` reads completed runs, the previous seven days by default, and reports job count, execution time, queue time and concurrent jobs. Execution time is your minutes estimate and concurrent jobs is your runner count. On Jenkins it needs the `paginated-builds` plugin installed first.

```Terminal
gh actions-importer audit jenkins --output-dir tmp/audit
gh actions-importer audit gitlab --output-dir tmp/audit --namespace my-group
gh actions-importer audit circle-ci --output-dir tmp/audit --include-from repositories.txt
gh actions-importer forecast jenkins --output-dir tmp/forecast
```

## What it converts, and what it leaves for you

Each platform guide on docs.github.com publishes a supported-syntax table and a list of constructs you must migrate manually. The manual lists are short and worth reading before the audit, because they predict most of the Manual steps section in every pull request.

| Platform | Converts | Left for you |
| --- | --- | --- |
| Jenkins | Declarative `stage`, `docker`; partially `agent`, `environment`, `steps`, `triggers`, `when`. Not `matrix`, `options`, `parameters` or `input` | Scripted pipelines, secrets, self-hosted runners, unknown plugins, mandatory build tools |
| GitLab | `script`, `needs`, `stages`, `tags`, `variables`, `image`, `resource_group`, `schedule`; partially `rules`, `only`/`except`, `include`, `services`, `parallel`, `environment` | Masked project or group variable values, artifact reports; no caching between jobs of different workflows |
| CircleCI | Jobs, steps, executors to `runs-on`, `matrix`, `when`/`unless`, cron; partially orbs, `container` and `services` | Contexts, project-level environment variables, unknown job properties, unknown orbs; self-hosted executors unsupported |

## Dry run with custom transformers

`dry-run` converts one pipeline and writes the workflow to disk. This is where you shape the output before anything reaches a repository. Custom transformers are Ruby files passed with `--custom-transformers`: `runner` maps a source label to an Actions label, `env` rewrites or removes a variable or points it at a secret, and `transform` replaces an unknown build step, such as a Jenkins shared library call, with steps you define.

Map runners first. The documentation states that a label the Importer cannot map becomes `ubuntu-latest`, and `runner :default` changes that fallback.

```transformers.rb
# transformers.rb
runner "linux", "ubuntu-latest"
runner "big-agent", ["self-hosted", "xl", "linux"]
runner :default, "ubuntu-latest"

env "REGISTRY_PASSWORD", secret("REGISTRY_PASSWORD")

transform "deployService" do |item|
  { name: "deploy", run: "./scripts/deploy.sh" }
end

# then:
# gh actions-importer dry-run jenkins --source-url https://jenkins.example.com/job/app \
#   --output-dir tmp/dry-run --custom-transformers transformers.rb
```

## Migrate, and the mappings to check by hand

`migrate` runs the same conversion and opens a pull request against `--target-url`. Its description carries a Manual steps section, usually the secrets to create. Merge only after the first run on a branch is green.

Read the environment variable mappings before you trust a converted condition. The Importer maps Jenkins `BUILD_NUMBER` to `github.run_id`, a large unique id, not the per-workflow counter `github.run_number`, so image tags change shape. It maps GitLab `CI_COMMIT_BRANCH` and CircleCI `CIRCLE_BRANCH` to `github.ref`, which is `refs/heads/main`, so a comparison against `main` silently goes false. GitHub's sample `list-features` output also shows `actions/cache` and `reusable-workflows` disabled; check yours and turn them on with `--enable-features` if your target supports them.

```Terminal
gh actions-importer list-features
gh actions-importer migrate jenkins \
  --source-url https://jenkins.example.com/job/app \
  --target-url https://github.com/my-org/app \
  --output-dir tmp/migrate \
  --custom-transformers transformers.rb \
  --enable-features actions/cache
```

## FAQ

### Which CI platforms does GitHub Actions Importer support?

Azure DevOps, Bamboo, Bitbucket Pipelines, CircleCI, GitLab (cloud and self-managed), Jenkins and Travis CI. Each has its own subcommand and its own guide on docs.github.com listing supported syntax and manual tasks.

### Does GitHub Actions Importer migrate secrets?

No. The audit and the migration pull request list the secrets the converted workflows reference, and you create them in GitHub yourself. For GitLab, masked variable values are explicitly a manual task, and for CircleCI so are contexts and project-level environment variables.

### Can GitHub Actions Importer convert scripted Jenkins pipelines?

No. GitHub lists scripted pipelines among the Jenkins constructs you must migrate manually. Declarative Jenkinsfiles and Freestyle jobs convert, fully or partially, and the audit tells you which.

### Does the Importer need to run on my CI server?

No. It needs Docker and the GitHub CLI on any Linux-container-capable machine, plus API access to the CI server with a token that can read every job you want to audit. For Jenkins, folders that do not inherit permissions need explicit access for that token.

## References

- [GitHub Docs: Automating migration with GitHub Actions Importer (read 2026-11-12)](https://docs.github.com/en/actions/tutorials/migrate-to-github-actions/automated-migrations/use-github-actions-importer)
- [GitHub Docs: Extending GitHub Actions Importer with custom transformers](https://docs.github.com/en/actions/reference/github-actions-importer/custom-transformers)
- [GitHub Docs: Supplemental arguments and settings, including --features and --allowed-actions](https://docs.github.com/en/actions/reference/github-actions-importer/supplemental-arguments-and-settings)
- [github/gh-actions-importer repository and releases](https://github.com/github/gh-actions-importer)

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
