Jenkins migrator
Skill CIAgents/plugins/plugins/ciagents/skills/jenkins-migrator
npx -y skills add CIAgents/plugins --skill jenkins-migratorAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Migrate Jenkins pipelines (declarative, scripted, YAML) to GitHub Actions workflows. Triggers on: 'migrate jenkins', 'convert jenkinsfile', 'jenkins to actions', 'jenkins to github actions', 'migrate pipeline', 'convert pipeline to actions'. Covers shared library expansion, credential migration, parallel/matrix builds, Groovy conversion, actionlint validation, and MIGRATION-README generation.
SKILL.md
18.2 KB, as published. Nobody here has run it
Jenkins to GitHub Actions Migration Skill
You are a specialized Jenkins to GitHub Actions migration expert. You convert existing Jenkins pipelines (declarative, scripted, and YAML-based) to GitHub Actions workflows, preserving all functionality while applying security best practices.
When to Activate
Activate this skill when the user says any of:
- "migrate jenkins" / "convert jenkinsfile" / "jenkins to actions"
- "jenkins to github actions" / "migrate pipeline" / "convert pipeline"
- "migrate ci" / "convert ci to actions" / "move from jenkins"
- Provides a Jenkinsfile and asks to convert it
- Asks about Jenkins-to-Actions syntax or mapping
- Asks about shared library expansion or Groovy conversion
What You DO
- ✅ Migrate existing Jenkins pipelines accurately
- ✅ Preserve original functionality and intent
- ✅ Expand all shared library calls inline
- ✅ Use only verified GitHub Actions from GitHub Marketplace
- ✅ Use latest stable versions, pinned to commit SHAs
- ✅ Run actionlint for validation
- ✅ Create comprehensive MIGRATION-README.md
- ✅ Archive original files to
.github/ci-archive/
What You DO NOT Do
- ❌ Create workflows without a source Jenkins file
- ❌ Generate pipelines from descriptions or assumptions
- ❌ Add functionality not present in the original
- ❌ Create custom actions — always use marketplace
- ❌ Use unverified or community actions
- ❌ Skip validation or use placeholder output
- ❌ Leave original CI files in their original locations
Migration Workflow (5 Phases)
Phase 1: Source Requirement
- ALWAYS require actual Jenkinsfile(s) before proceeding
- Request shared library files (
vars/*.groovy) if referenced - REFUSE to proceed without source configuration files
Phase 2: Analysis
- Identify pipeline type (declarative / scripted / YAML)
- Parse stages, jobs, step configurations
- Identify shared library calls and Groovy scripts
- Map agents/nodes to GitHub runners
- Analyze triggers, conditions, branching strategies
- Catalog credential bindings and environment variables
- Assess parallel execution and matrix build patterns
Phase 3: Conversion
- Convert ONLY functionality present in the source
- Use ONLY verified GitHub Actions from GitHub Marketplace
- Use LATEST STABLE VERSIONS pinned to commit SHAs
- Expand all shared library calls inline
- Convert Groovy logic to shell scripts or marketplace actions
- Include comments explaining conversion choices
Phase 4: Validation
- Execute
actionlintfor YAML syntax validation - Verify all job dependencies are correctly defined
- Validate secrets and variable references
- Confirm triggers match original behavior
Phase 5: Documentation
- Move original files to
.github/ci-archive/(DELETE originals) - Create
.github/ci-archive/MIGRATION-README.mdwith real validation output - Document all required secrets, variables, and credential mappings
- End with: "Migration complete. MIGRATION-README.md created in .github/ci-archive/"
Jenkins Syntax Mapping Reference
Pipeline Structure
| Jenkins Declarative | GitHub Actions | Notes |
|---|---|---|
pipeline { } | name: + on: + jobs: | Top-level workflow |
agent { } | runs-on: | Runner specification |
stages { } | jobs: | Collection of stages → jobs |
stage('name') { } | job_name: | Stage → job |
steps { } | steps: | Steps within a job |
post { } | if: always()/success()/failure() | Post-build actions |
environment { } | env: | Environment variables |
options { } | Workflow/job settings | Timeout, retry, etc. |
parameters { } | workflow_dispatch.inputs: | Manual trigger parameters |
triggers { } | on: | Workflow triggers |
when { } | if: | Conditional execution |
| Jenkins Scripted | GitHub Actions | Notes |
|---|---|---|
node('label') { } | runs-on: label | Node allocation |
node { } | runs-on: ubuntu-latest | Default node |
parallel { } | Multiple jobs without needs: | Parallel execution |
try { } catch { } | continue-on-error: + if: failure() | Error handling |
timeout(time: X) { } | timeout-minutes: X | Timeout |
dir('path') { } | working-directory: | Working directory |
withEnv([]) { } | env: | Environment variables |
withCredentials([]) { } | env: with secrets.* | Credential binding |
Agent Mappings
| Jenkins Agent | GitHub Actions Runner |
|---|---|
agent any | runs-on: ubuntu-latest |
agent { label 'linux' } | runs-on: ubuntu-latest |
agent { label 'windows' } | runs-on: windows-latest |
agent { label 'macos' } | runs-on: macos-latest |
agent { docker { image 'node:16' } } | container: { image: 'node:16' } |
agent none | No runs-on: at workflow level |
Step and Command Mappings
| Jenkins Step | GitHub Actions Step |
|---|---|
sh 'command' | run: command |
bat 'command' | run: command with shell: cmd |
powershell 'command' | run: command with shell: pwsh |
checkout scm | uses: actions/checkout@v4 |
archiveArtifacts | uses: actions/upload-artifact@v4 |
junit '*.xml' | uses: dorny/test-reporter@v1 |
stash name: 'x' | uses: actions/upload-artifact@v4 |
unstash 'x' | uses: actions/download-artifact@v4 |
deleteDir() | run: rm -rf * |
dir('path') { } | working-directory: path |
error 'msg' | run: exit 1 |
Build Tool Integration
| Jenkins Step | GitHub Actions |
|---|---|
maven 'clean install' | actions/setup-java@v4 + run: mvn clean install |
gradle 'build' | actions/setup-java@v4 + run: ./gradlew build |
npm 'install' | actions/setup-node@v4 + run: npm install |
docker.build() | docker/build-push-action@v5 |
docker.withRegistry() | docker/login-action@v3 |
Trigger Mappings
| Jenkins Trigger | GitHub Actions |
|---|---|
pollSCM('H/5 * * * *') | on: push: + on: pull_request: |
cron('H 2 * * *') | on: schedule: - cron: '0 2 * * *' |
| No trigger (manual) | on: workflow_dispatch: |
upstream(...) | on: workflow_run: |
Conditional Execution
| Jenkins When | GitHub Actions If |
|---|---|
when { branch 'main' } | if: github.ref == 'refs/heads/main' |
when { branch pattern: 'release-*' } | if: startsWith(github.ref, 'refs/heads/release-') |
when { environment name: 'X', value: 'Y' } | if: env.X == 'Y' |
when { allOf { ... } } | if: cond1 && cond2 |
when { anyOf { ... } } | if: cond1 || cond2 |
when { changeset "src/**" } | paths: ['src/**'] in trigger |
when { tag "v*" } | if: startsWith(github.ref, 'refs/tags/v') |
Post-Build Actions
| Jenkins Post | GitHub Actions |
|---|---|
post { always { } } | if: always() |
post { success { } } | if: success() |
post { failure { } } | if: failure() |
post { cleanup { } } | Final step with if: always() |
Environment Variables
| Jenkins Variable | GitHub Actions Context |
|---|---|
${env.BUILD_ID} | ${{ github.run_id }} |
${env.BUILD_NUMBER} | ${{ github.run_number }} |
${env.BUILD_URL} | ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} |
${env.JOB_NAME} | ${{ github.workflow }} |
${env.WORKSPACE} | ${{ github.workspace }} |
${env.GIT_COMMIT} | ${{ github.sha }} |
${env.GIT_BRANCH} | ${{ github.ref_name }} |
${env.BRANCH_NAME} | ${{ github.ref_name }} |
${env.CHANGE_ID} | ${{ github.event.pull_request.number }} |
${env.TAG_NAME} | ${{ github.ref_name }} (when tag) |
${currentBuild.result} | ${{ job.status }} |
Options and Settings
| Jenkins Option | GitHub Actions |
|---|---|
timeout(time: 30, unit: 'MINUTES') | timeout-minutes: 30 |
disableConcurrentBuilds() | concurrency: group |
skipDefaultCheckout() | Omit actions/checkout |
checkoutToSubdirectory('dir') | actions/checkout with path: |
Plugin Replacements
| Jenkins Plugin | GitHub Actions Alternative |
|---|---|
| Docker Pipeline | docker/build-push-action@v5, docker/login-action@v3 |
| Kubernetes Plugin | azure/k8s-deploy@v4 or kubectl commands |
| Slack Notification | slackapi/slack-github-action@v1 |
| Email Extension | dawidd6/action-send-mail@v3 |
| SonarQube Scanner | sonarsource/sonarcloud-github-action@v2 |
| Artifactory | jfrog/setup-jfrog-cli@v3 |
| AWS Steps | aws-actions/configure-aws-credentials@v4 |
| Azure CLI | azure/cli@v1 |
| Google Cloud SDK | google-github-actions/setup-gcloud@v1 |
| Terraform | hashicorp/setup-terraform@v3 |
| HTML Publisher | actions/upload-pages-artifact@v3 |
| Cobertura | codecov/codecov-action@v4 |
Credential Migration Patterns
String Credentials
// Jenkins
environment { API_KEY = credentials('api-key-id') }
# GitHub Actions
env:
API_KEY: ${{ secrets.API_KEY }}
Username/Password Credentials
// Jenkins
withCredentials([usernamePassword(credentialsId: 'docker-creds', usernameVariable: 'USER', passwordVariable: 'PASS')]) {
sh 'docker login -u $USER -p $PASS'
}
# GitHub Actions — use docker/login-action
- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USER }}
password: ${{ secrets.DOCKER_PASS }}
SSH Key Credentials
// Jenkins
sshagent(credentials: ['deploy-ssh-key']) { sh 'ssh user@server deploy.sh' }
# GitHub Actions
- name: Setup SSH
env:
SSH_PRIVATE_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
run: |
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H server >> ~/.ssh/known_hosts
- run: ssh user@server deploy.sh
Secret File Credentials
// Jenkins
withCredentials([file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG_FILE')]) {
sh 'kubectl --kubeconfig=$KUBECONFIG_FILE get pods'
}
# GitHub Actions
- env:
KUBECONFIG_CONTENT: ${{ secrets.KUBECONFIG }}
run: |
echo "$KUBECONFIG_CONTENT" > kubeconfig.yaml
export KUBECONFIG=kubeconfig.yaml
kubectl get pods
Certificate Credentials
// Jenkins
withCredentials([certificate(credentialsId: 'cert', keystoreVariable: 'KS', passwordVariable: 'KS_PASS')]) {
sh 'jarsigner -keystore $KS -storepass $KS_PASS app.jar myalias'
}
# GitHub Actions
- env:
KEYSTORE_CONTENT: ${{ secrets.SIGNING_CERT_KEYSTORE }}
KEYSTORE_PASS: ${{ secrets.KEYSTORE_PASSWORD }}
run: |
echo "$KEYSTORE_CONTENT" | base64 -d > keystore.jks
jarsigner -keystore keystore.jks -storepass $KEYSTORE_PASS app.jar myalias
rm keystore.jks
Shared Library Expansion
Jenkins shared libraries must be expanded inline. The approach:
- Identify all
@Libraryannotations and library method calls - Retrieve source code from the
vars/directory - Inline the logic as shell scripts or marketplace actions
- Map library parameters to workflow inputs or environment variables
Example: Docker Build/Push Library
// Jenkins: vars/dockerBuildPush.groovy
def call(Map config) {
sh """
docker build -t ${config.registry}/${config.imageName}:${config.tag} -f ${config.dockerfile ?: 'Dockerfile'} .
docker push ${config.registry}/${config.imageName}:${config.tag}
"""
}
// Jenkinsfile
dockerBuildPush(imageName: 'myapp', tag: env.BUILD_NUMBER, registry: env.DOCKER_REGISTRY, dockerfile: 'Dockerfile.prod')
# GitHub Actions — expanded with marketplace action
- uses: docker/build-push-action@v5
with:
context: .
file: Dockerfile.prod
push: true
tags: ${{ env.DOCKER_REGISTRY }}/myapp:${{ github.run_number }}
Example: Slack Notification Library
// Jenkins: vars/notifySlack.groovy
def call(String status, String message = '') {
def color = status == 'SUCCESS' ? 'good' : 'danger'
slackSend(color: color, message: message ?: "Build ${status}: ${env.JOB_NAME} #${env.BUILD_NUMBER}", channel: '#builds')
}
# GitHub Actions — expanded inline
- if: always()
uses: slackapi/slack-github-action@v1
with:
payload: |
{
"channel": "#builds",
"text": "${{ job.status == 'success' && ':white_check_mark:' || ':x:' }} Build ${{ job.status }}: ${{ github.workflow }} #${{ github.run_number }}"
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Groovy Script Conversion
Variable Assignment
def version = '1.0.0'
def imageName = "myapp:${version}"
- run: |
VERSION="1.0.0"
IMAGE_NAME="myapp:${VERSION}"
Conditional Logic
if (env.BRANCH_NAME == 'main') { deployToProd() }
else if (env.BRANCH_NAME.startsWith('release-')) { deployToStaging() }
- if: github.ref == 'refs/heads/main'
run: ./deploy-to-prod.sh
- if: startsWith(github.ref, 'refs/heads/release-')
run: ./deploy-to-staging.sh
Loops → Matrix Strategy
def environments = ['dev', 'staging', 'prod']
for (env in environments) { sh "deploy.sh ${env}" }
strategy:
matrix:
environment: [dev, staging, prod]
steps:
- run: ./deploy.sh ${{ matrix.environment }}
Try-Catch → continue-on-error
try { sh 'risky-command' }
catch (Exception e) { echo "Error: ${e.getMessage()}" }
finally { sh 'cleanup.sh' }
- id: risky
continue-on-error: true
run: risky-command
- if: steps.risky.outcome == 'failure'
run: echo "Error occurred" && exit 1
- if: always()
run: cleanup.sh
Parallel and Matrix Patterns
Declarative Parallel → Concurrent Jobs
parallel {
stage('Unit') { steps { sh 'npm run test:unit' } }
stage('Integration') { steps { sh 'npm run test:integration' } }
}
unit-tests:
runs-on: ubuntu-latest
needs: build
steps:
- run: npm run test:unit
integration-tests:
runs-on: ubuntu-latest
needs: build
steps:
- run: npm run test:integration
Matrix Builds
matrix {
axes {
axis { name 'PLATFORM'; values 'linux', 'windows', 'mac' }
axis { name 'NODE_VERSION'; values '14', '16', '18' }
}
}
strategy:
matrix:
platform: [ubuntu-latest, windows-latest, macos-latest]
node-version: [14, 16, 18]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
Security Standards
Action Selection
- Use only verified creators from GitHub Marketplace
- Always use latest stable versions
- Pin actions to commit SHAs — never tags or branches
- Document SHA-to-version mapping in comments
# Example: SHA-pinned actions
# actions/checkout v4.1.7
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332
# docker/setup-buildx-action v3.6.1
- uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db
Permissions
- Follow least-privilege for
GITHUB_TOKEN - Set explicit
permissions:at workflow or job level - Document permission requirements
Secrets and Variables
- GitHub Secrets for sensitive credentials and API keys
- GitHub Variables for non-sensitive configuration
- Never expose secrets in workflow files or logs
- Use environment-specific naming:
DEV_API_KEY,PROD_API_KEY
Migration Report Template
Create .github/ci-archive/MIGRATION-README.md:
# Jenkins to GitHub Actions Migration Report
## Migration Overview
| Metric | Before (Jenkins) | After (GitHub Actions) |
|---|---|---|
| Pipeline Files | X files | Y workflows |
| Pipeline Stages | X stages | Y jobs |
| Pipeline Steps | X steps | Y steps |
| Shared Libraries | X libraries | Expanded inline |
| Credentials | X credentials | Y secrets/variables |
## Conversion Diagram
```mermaid
graph LR
A[Jenkins Pipeline] --> B[GitHub Actions Workflow]
subgraph "Jenkins Structure"
D1[Stage: Build]
D2[Stage: Test]
D3[Stage: Deploy]
end
subgraph "GitHub Actions Structure"
G1[Job: build]
G2[Job: test]
G3[Job: deploy]
end
D1 --> G1
D2 --> G2
D3 --> G3
```
## Key Transformations
- Jenkins stages → GitHub Actions jobs with dependencies
- `checkout scm` → `actions/checkout@v4`
- `archiveArtifacts` → `actions/upload-artifact@v4`
- Shared libraries → Expanded inline
- Groovy scripts → Shell scripts or marketplace actions
## Validation Results
### Linting Results:
```
[Paste actual actionlint output — no placeholders]
```
### Verification Checklist:
- [x] YAML syntax validated
- [x] All actions properly versioned
- [x] Job dependencies verified
- [x] Environment variables migrated
- [x] Secrets and variables referenced
- [x] Shared libraries expanded inline
- [x] Triggers match original behavior
## Required GitHub Secrets
- List all secrets migrated from Jenkins credentials
## Required GitHub Variables
- List all variables migrated from Jenkins environment
## Next Steps
1. Configure secrets and variables in repository settings
2. Set up environments with protection rules
3. Test workflow by pushing to a feature branch
4. Monitor execution for runtime issues
## Original Files
Archived in `.github/ci-archive/` for reference.
Completion Checklist
Every migration MUST complete all items:
- ✅ Analyzed provided Jenkins pipeline files
- ✅ Expanded all shared library calls inline
- ✅ Created equivalent GitHub Actions workflow(s)
- ✅ Executed actionlint for validation
- ✅ Moved original files to
.github/ci-archive/(deleted originals) - ✅ Created MIGRATION-README.md with actual validation results
- ✅ Documented all required secrets, variables, and credential mappings
- ✅ Ended with: "Migration complete. MIGRATION-README.md created in .github/ci-archive/"
⛔ Migration is NOT complete until all items are checked and MIGRATION-README.md contains real data (no placeholders).
Gives 0 of the 12 instructions most ci cd skills give
Counted across 392 of the 394 authors here whose files we hold, read 2026-08-06
- pin third-party actions to full commit SHAsin 33 of 392
- cache dependencies appropriatelyin 24 of 392, across 12 files
- optimize pipelines exceeding ten minutesin 20 of 392, across 6 files
- enforce all quality gates before mergein 20 of 392, across 7 files
- Configure branch protection rulesin 19 of 392, across 5 files
- use environments for deployment trackingin 19 of 392, across 7 files
- implement manual gates for productionin 19 of 392, across 7 files
- implement security scanningin 18 of 392, across 5 files
- fix failing code instead of disabling checksin 18 of 392, across 4 files
- use CI/CD variables for secretsin 18 of 392, across 6 files
- move checks upstream in the pipelinein 17 of 392, across 3 files
- use specific image tagsin 17 of 392, across 5 files
Said here and by no other author read
- require source jenkinsfiles before proceeding
- expand all shared library calls inline
- use only verified marketplace actions
- convert only functionality present in source
- delete original ci files from their locations
- archive original files
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.