Jenkins 同步 Bitbucket 代码到 GitHub 中

2020-06-12 15:44:43 浏览数 (1)

最近我们团队需要将一些示例和例子从内部的 Bitbucket 同步到 GitHub。我了解 GitHub 可以创建公共的或是私人的仓库,但我们需要保持以下两点

  • 只分享我们想给客户分享的内容
  • 不改变当前的工作流程,即继续使用 Bitbucket

因此我们需要在 GitHub 上创建相应的仓库,然后将内部 Bitbucket 仓库中对应的 master 分支定期的通过 CI Job 同步到 GitHub 对应仓库中,下图供参考。

分支策略

首先,需要对 Bitbucket 进行分支权限设置

  • master 分支只允许通过 Pull Request 进行修改
  • Pull Request 默认的 reviewer 至少需要一人,并且只有同意状态才允许合并

其次,为了方便产品、售后等人员使用,简化分支策略如下

  1. 从 master 分支上创建 feature 或是 bugfix 分支(取决于你的修改目的)
  2. 然后将你的更改提交到自己的 feature 或 bugfix 分支
  3. 在你自己的分支通过测试后,提交 Pull Request 到 master 分支
  4. 当 reviewer 同意状态,才能进行合并进入到 master 分支

Jenkins Pipeline

基于这样的工作不是特别的频繁,也为了方便维护 Jenkins Pipeline 的简单和易于维护,我没有在需要同步的每个仓库里添加 Jenkinsfile 或在 Bitbucket 里添加 webhooks,有以下几点好处:

  • 只创建一个 Jenkins Job,用一个 Jenkinsfile 满足所有仓库的同步
  • 减少了冗余的 Jenkinsfile 的代码,修改时只需更维护一个文件
  • 不需要在每个仓库里添加一个 Jenkinsfile,更纯粹的展示示例,避免给非 IT 人员造成困扰

不足之处,不能通过 SCM 来触发构建,如果想通过 webhooks 来触发,有的公司需要申请权限来添加 webhooks 比较麻烦;另外可能无法区分从哪个仓库发来的请求,实现指定仓库的同步。

因此如果不是特别频繁的需要同步,提供手动或是定时同步即可(代码太长了请滚动浏览)。

代码语言:javascript复制
// 这个 Jenkinsfile 是用来将 Bitbucket 仓库的 master 分支同步到 GitHub 仓库的 master 分支
@Library('jenkins-shared-library@develop') _
def email = new org.cicd.email()
pipeline {
  agent {
    label "main-slave"
  }
  parameters {
    booleanParam(defaultValue: false, name: 'git-repo-win', description: 'Sync internal git-repo-win master branch with external git-repo-win on GitHub')
    booleanParam(defaultValue: true,  name: 'git-repo-lin', description: 'Sync internal git-repo-lin master branch with external git-repo-lin on GitHub')
    booleanParam(defaultValue: false, name: 'git-repo-aix', description: 'Sync internal git-repo-aix master branch with external git-repo-aix on GitHub')
    booleanParam(defaultValue: false, name: 'git-repo-sol', description: 'Sync internal git-repo-sol master branch with external git-repo-sol on GitHub')
  }
  options {
    timestamps()
    buildDiscarder(logRotator(numToKeepStr:'50'))
  }
  stages {
    stage("Synchronous master branch"){
      steps{
        script {
          try {
            params.each { key, value ->
              def repoName = "$key"
              if ( value == true) {
                echo "Start synchronizing $key Bitbucket repository."
                sh """
                rm -rf ${repoName}
                return_status=0
                git clone -b master ssh://git@git.your-company.com:7999/~xshen/${repoName}.git
                cd ${repoName}
                git config user.name "Sync Bot"
                git config user.email "bot@your-company.com"
                git remote add github git@github.com:shenxianpeng/${repoName}.git
                git push -u github master
                return_status="$?"
                if [ $return_status -eq 0 ] ; then
                  echo "Synchronize ${repoName} from Bitbucket to GitHub success."
                  cd ..
                  rm -rf ${repoName}
                  exit 0
                else
                  echo "Synchronize ${repoName} from Bitbucket to GitHub failed."
                  exit 1
                fi """
              } else {
                echo "${repoName} parameter value is $value, skip it."
              }
            }
            cleanWs()
          }
          catch (error) {
            echo "Some error occurs during synchronizing $key process."
          } finally {
            email.Send(currentBuild.currentResult, env.CHANGE_AUTHOR_EMAIL)
          }
        }
      }
    }
  }
}

以上的 Jenkinsfile 的主要关键点是这句 params.each{key,value->},可以通过对构建时选择参数的进行判断,如果构建时参数已勾选,则会执行同步脚本;否则跳过同步脚本,循环到下一个参数进行判断,这样就实现了可以对指定仓库进行同步。


不瞒你说,为了找一张不那么随意的、有关同步的封面花了我几个小时,比写这篇文章内容花的时间都长…如果你觉得还不错的话,求在看,求转发,你的支持就是我更新的最大动力。

0 人点赞