How to Migrate from Jenkins to GitLab CI Without Stopping Delivery
Most Jenkins migrations stall for the same reason: someone tries to translate the most complicated pipeline first, discovers it depends on four plugins and a shared library nobody understands, and the project quietly dies. Migrate in the opposite order. Start with the simplest service, prove the pattern, and let the hard pipelines come last when you have a working idiom and confidence.
Steps
Inventory every job and who owns it: List all Jenkins jobs, what each builds, how it is triggered, which plugins it depends on and — critically — whether anyone still uses it. Jenkins instances accumulate dead jobs. A significant share of most inventories can simply be deleted rather than migrated, and finding that out first shrinks the project.
Set up GitLab Runners: Runners execute your pipelines. Decide between GitLab-hosted runners, which are simplest, and self-managed runners on your own infrastructure, which you will need if builds must reach internal resources or stay inside India. Register at least one runner and confirm a trivial pipeline executes before migrating anything real.
Migrate secrets and credentials first: Jenkins credentials move to GitLab CI/CD variables, ideally masked and protected so they are only exposed to protected branches. Do this before pipelines, because a translated pipeline that fails on a missing secret looks like a translation problem and wastes hours. Rotate anything that has been sitting in Jenkins for years while you are at it.
Translate one simple pipeline as the reference: Pick your least complicated service. Write its .gitlab-ci.yml with clear stages — build, test, deploy. Get it green. This becomes the template every other team copies, so spend time making it clean and commented rather than merely working. A good reference pipeline is the highest-leverage artefact of the whole migration.
Run both systems in parallel: For each migrated service, let Jenkins and GitLab CI build the same commits for a couple of weeks. Compare outputs and durations. This is how you find the environment assumption baked into the Jenkins agent that nobody documented — a tool installed by hand three years ago that your new runner does not have.
Replace shared libraries with CI templates: Jenkins shared libraries usually become GitLab CI templates included with the include: keyword, or components. Resist recreating the library exactly — it accumulated complexity for reasons that may no longer apply. Rebuild the behaviour you still need, not the code you happen to have.
Handle the plugin-dependent pipelines last: The jobs leaning on unusual Jenkins plugins are the hard ones. By now you have a working idiom and a team that knows GitLab CI, so tackle them with the right tools. Some plugins map to a GitLab feature directly, some become a script step, and a few represent behaviour worth dropping entirely.
Decommission Jenkins deliberately: Once nothing builds on Jenkins, put it in read-only mode rather than deleting it. Keep it for a month so historical build logs remain reachable, then archive and shut down. Deleting immediately is how you lose the build artefact somebody needed for an audit.
Frequently Asked Questions
How long does a Jenkins to GitLab CI migration take?
For 20-40 pipelines, typically six to twelve weeks running alongside normal delivery. The variable is not pipeline count but how much undocumented environment state lives on your Jenkins agents. Teams with containerised builds move fastest; teams with hand-configured agents move slowest.
Can we migrate pipelines automatically?
Partially. There are converters that produce a starting .gitlab-ci.yml from a Jenkinsfile, and they are useful for simple declarative pipelines. Anything using shared libraries, plugin-specific steps or scripted Groovy needs human translation. Treat automated output as a first draft.
Do we need self-managed runners?
Only if builds must reach internal resources, require specific hardware, or must run inside India for data-residency reasons. Otherwise GitLab-hosted runners remove an entire category of maintenance. Many Indian teams end up with both — hosted for most work, self-managed for deployments touching internal networks.
What happens to our build history?
It stays in Jenkins. Build history does not migrate, which is why you keep Jenkins read-only for a period rather than deleting it. If you need long-term retention of specific artefacts or logs, export them deliberately before decommissioning.
Is it worth moving if Jenkins works?
If Jenkins genuinely works and nobody maintains it under protest, there is no urgency. The usual triggers are maintenance burden, plugin security updates, the desire for pipelines defined in the repository next to the code, and wanting security scanning integrated into merge requests rather than bolted on.
We plan and run Jenkins to GitLab CI migrations for Indian engineering teams — inventory, reference pipeline, parallel run and decommissioning.