Introduction
For some software development projects, there may be a need to backup or mirror the repository to a different location.
Jenkins or other continuous integration (CI) can automate this. This log is a brief summary of how in case I need to reproduce.
Workflow
The requirement is to have a single jenkins job that synchronizes various other projects and repositories.
To do this, the job calls another job to mirror any source repository to any set of destination repositories.
Git Mirroring
Git has mirroring capability built into cloning and pushing.
To make the Jenkins script easier you can also pass the remote URL to push, instead of adding a remote configuration.
git push [email protected]:user/repo
Jenkins
You should have a list of the possible repositories you would use.
To allow for multiple destination repositories, add the Extended Choice Parameter.
To keep things simple, all repositories should have the same user/project
path.
Job: Git Mirror
A new pipeline job configured with the parameters:
- the source repository as a single selection from a list of repositories
- the destination repository as a multi selection from the list of repositories.
- the project path in the repositories
The pipeline script looks like this:
node {
stage ("Prepare") {
deleteDir()
dest = sh(returnStdout: true, script: 'echo "${destination}"').trim().tokenize(',')
// skip adding new host key to jenkins
sh 'git config --global core.sshCommand "ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"'
}
stage ("Build") {
// create ssh key credentials for jenkins
sshagent(credentials: ['jenkins']) {
sh 'git clone --mirror ${source}/${project_path} .'
for (int i = 0; i < dest.size(); i++) {
sh "git push --mirror ${dest[i]}/${project_path}"
}
}
}
Job: Mirror Repositories
Another pipeline job, this one configured to run on a schedule (example: every day at 12:00AM).
The pipeline script defines the repositories and a few functions to simplify:
def dest(String... repos) {
return string(name: "destination", value: repos.join(','))
}
def src(repo) {
return string(name: "source", value: repo)
}
def path(val) {
return string(name: "project_path", value: val)
}
node {
def github = 'ssh://[email protected]'
def bitbucket = 'ssh://[email protected]'
def micrantha = 'ssh://[email protected]:2222'
build job: 'git_mirror', parameters: [
src(github),
dest(bitbucket, micrantha),
path("ryjen/blog")
]
build job: 'git_mirror', parameters: [
src(github), dest(bitbucket, micrantha),
path("ryjen/dotfiles")
]
// etc...
}
Conclusion
Not bad for a few jenkins jobs. I will enjoy the
- data loss redundancy
- organization (housekeeping)
- scheduling
Maybe you will too. 😎