如何让 Jenkins 在从 bitbucket 轮询后自动构建,而不是手动构建具有特定参数的作业

Posted

技术标签:

【中文标题】如何让 Jenkins 在从 bitbucket 轮询后自动构建,而不是手动构建具有特定参数的作业【英文标题】:How to make Jenkins to build automatically after polling from bitbucket instead to manually build a job with specific parameters 【发布时间】:2019-05-13 01:00:15 【问题描述】:

我的 Jenkinsfile 已就位,我可以使用两个参数手动执行,这取决于我是为 dev、staging 还是 prod 构建。

我现在想做的是,每次 Jenkins 发现 bitbucket 存储库中是否有新内容时,它都会使用特定参数构建一个新作业(首先构建 dev 并更新数据库),然后如果成功,则制作另一个使用 staging 参数构建,也使用数据库构建参数。

我希望为生产部署(或者更确切地说,创建一个新作业)的过程是一项手动任务,直到我检查所有在暂存中看起来都不错。

顺便说一句,我的 jenkins 管道按预期工作,轮询也按预期工作,我只需要使这个过程自动化。

注意

即使我尝试这样做,我也没有使用来自 Bitbucket 的 webhook,因为我的 jenkins 服务器运行在不允许有外部连接的主机上,并且当 bitbucket 向我的 jenkins 服务器发送信号时它只是时间出去。

提前感谢您的建议。

我的Jenkinsfile如下:

// Deployment template for CMS-based websites (Drupal or Wordpress)
// 
//
pipeline 
agent any

parameters 
    choice(choices: "Dev\nStaging\nProduction", description: "Choose which environment to push changes to.", name: "DEPLOY_TO")
    choice choices: "No\nYes", description: "Choose whether to deploy the database as well.", name: "DEPLOY_DB"


environment 
    SITEID = "ge"
    NOFLAGS = "0"
    DBNAME = "wpress_website"
    DBSERVER = "dbserver"
    DBUSER = "geWordpress"
    DBPASS = "akjh23kas"
    EXCLUDE = "comp_commentmeta,comp_comments"  // separate multiple tables with commas
    DEPLOY_TO = "$params.DEPLOY_TO"
    DEPLOY_DB = "$params.DEPLOY_DB"


stages 
    stage("deploy-db-dev") 
        when 
            allOf  
                environment ignoreCase: true, name: "DEPLOY_TO", value: "dev"; 
                environment ignoreCase: true, name: "DEPLOY_DB", value: "yes"; 
            
        
        steps 
            // this stage only required until we make our dev the master DB
            // copy full dev database from appserv1
            // import latest database dump to dev server
            script 
                FILENM = sh(script: 'ls -t goewp-s-dump* | head -1', returnStdout: true)
            
            //Fixing the problem with the collation existing in the sql dump file, refer to: https://***.com/questions/42385099/1273-unknown-collation-utf8mb4-unicode-520-ci 
            //apparently, this is due to a version of mysql issue. Once the problem is fixed from the server side we can then remove the following lines. 

            sh "sed -i s/utf8mb4_unicode_520_ci/utf8mb4_unicode_ci/g $FILENM"
            //The following line was added because the site is pointing to a staging server which we don't have control over, again, once this is fixed we can delete the following line of code. 
            sh "sed -i s/edit.staging.websites.3pth.com/stage.goewpfoods.hcgweb.net/g $FILENM"

            sh "mysql -h appserver -u $env.DBUSER --password='$env.DBPASS' $env.DBNAME_dev < $WORKSPACE/$FILENM"
        
    
    stage("deploy-dev") 
        when 
            environment ignoreCase: true, name: "DEPLOY_TO", value: "dev"
        
        steps 
            // copy files to appserv2
            // NOTE: if we move the repo to SVN, we should change httpdocs/ to $env.SITEIDdocs/
            sh "sudo chown jenkins:jenkins *"

            //Replace the wp-config.php file with our comp file with our information. 
            sh "/bin/cp httpdocs/wp-config-comp.php httpdocs/wp-config.php"

            // prepare the dev server to receive files by changing the owner
            sh "ssh webadmin@appserv2 \"sudo chown -R webadmin:webadmin /var/opt/httpd/$env.SITEIDdocs/\""
            // copy files from control server to dev
            sh "rsync --exclude=Jenkinsfile -rav -e ssh --delete $WORKSPACE/httpdocs/ webadmin@appserv2:/var/opt/httpd/$env.SITEIDdocs/"
            // fix the owner/permissions on the dev server
            sh "ssh webadmin@appserv2 \"sudo chown -R apache:$env.SITEID-web /var/opt/httpd/$env.SITEIDdocs/\""
            sh "ssh webadmin@appserv2 \"sudo chmod -R g+w /var/opt/httpd/$env.SITEIDdocs/\""
            sh "ssh webadmin@appserv2 \"sudo find /var/opt/httpd/$env.SITEIDdocs/ -type d -exec chmod g+s  \\;\""
        
    
    stage("deploy-db-staging") 
        when 
            allOf  
                environment ignoreCase: true, name: "DEPLOY_TO", value: "staging"; 
                environment ignoreCase: true, name: "DEPLOY_DB", value: "yes"; 
            
        
        steps 
            script 
                def myexcludes = env.EXCLUDE.split(',').toList()
                MYFLAGS = "-Q -K -c -e --default-character-set=utf8 "
                if (env.NOFLAGS == "0") 
                    myexcludes.each 
                        MYFLAGS = "$MYFLAGS --ignore-table=$env.DBNAME_dev.$it"
                    
                
            
            sh "cd $WORKSPACE"
            // pull a backup of the current dev database (may exclude some tables)
            sh "mysqldump -h appserv2 -u $env.DBUSER --password='$env.DBPASS' $env.DBNAME_dev $MYFLAGS > $env.DBNAME_dev.sql"
            // create a backup copy of the current staging database (full backup)
            sh "mysqldump -h $env.DBSERVER -u $env.DBUSER --password='$env.DBPASS' $env.DBNAME_stage > $env.DBNAME_stage_bak.sql"
            // upload the dev database dump to the staging database
            sh "mysql -h $env.DBSERVER -u $env.DBUSER --password='$env.DBPASS' $env.DBNAME_stage < $WORKSPACE/$env.DBNAME_dev.sql"
        
    
    stage("deploy-staging") 
        when 
            environment ignoreCase: true, name: "DEPLOY_TO", value: "staging"
        
        steps 
            // copy files from dev to control server
            sh "rsync --exclude=.svn --exclude=.git -rav -e ssh webadmin@appserv2:/var/opt/httpd/$env.SITEIDdocs/ /tmp/$env.SITEIDdocs/"

            //Replace the wp-config.php file with our comp file with our information. 
            sh "/bin/cp httpdocs/wp-config-comp.php httpdocs/wp-config.php"

            // prepare the staging server to receive files by changing the owner
            sh "ssh webadmin@stageserv \"sudo chown -R webadmin:webadmin /var/opt/httpd/$env.SITEIDdocs/\""
            // copy files from control server to staging
            sh "rsync --exclude=.svn --exclude=.git -rav -e ssh --delete /tmp/$env.SITEIDdocs/ webadmin@stageserv:/var/opt/httpd/$env.SITEIDdocs/"
            // fix the owner/permissions on the staging server
            sh "ssh webadmin@stageserv \"sudo chown -R apache:$env.SITEID-web /var/opt/httpd/$env.SITEIDdocs/\""
            sh "ssh webadmin@stageserv \"sudo chmod -R g+w /var/opt/httpd/$env.SITEIDdocs/\""
            sh "ssh webadmin@stageserv \"sudo find /var/opt/httpd/$env.SITEIDdocs/ -type d -exec chmod g+s  \\;\""

            // delete the temporary files on the control server
            sh "rm -Rf /tmp/$env.SITEIDdocs/"
            // clear the caches
            sh "wget -O - \"http://www.web.net/incacache.php?api_key=yoiVbjgtL&site_id=088\""
        
    
    stage("deploy-db-production") 
        when 
            allOf  
                environment ignoreCase: true, name: "DEPLOY_TO", value: "production"; 
                environment ignoreCase: true, name: "DEPLOY_DB", value: "yes"; 
            
        
        steps 
            script 
                def myexcludes = env.EXCLUDE.split(',').toList()
                MYFLAGS = "-Q -K -c -e --default-character-set=utf8 "
                if (env.NOFLAGS == "0") 
                    myexcludes.each 
                        MYFLAGS = "$MYFLAGS --ignore-table=$env.DBNAME_stage.$it"
                    
                
            
            sh "cd $WORKSPACE"
            // pull a backup of the current staging database (may exclude some tables)
            sh "mysqldump -h $env.DBSERVER -u $env.DBUSER --password='$env.DBPASS' $env.DBNAME_stage $MYFLAGS > $env.DBNAME_stage.sql"
            // create a backup copy of the current production database (full backup)
            sh "mysqldump -h $env.DBSERVER -u $env.DBUSER --password='$env.DBPASS' $env.DBNAME_prod > $env.DBNAME_prod_bak.sql"
            // upload the staging database dump to the production database
            sh "mysql -h $env.DBSERVER -u $env.DBUSER --password='$env.DBPASS' $env.DBNAME_prod < $WORKSPACE/$env.DBNAME_stage.sql"
        
    
    stage("deploy-production") 
        when 
            environment ignoreCase: true, name: "DEPLOY_TO", value: "production"
        
        steps 
            // copy files from staging to control server
            sh "rsync --exclude=.svn --exclude=.git -rav -e ssh webadmin@stageserv:/var/opt/httpd/$env.SITEIDdocs/ /tmp/$env.SITEIDdocs/"

            // prepare the production server to receive files by changing the owner
            sh "ssh webadmin@appserv3 \"sudo chown -R webadmin:webadmin /var/opt/httpd/$env.SITEIDdocs/\""
            sh "ssh webadmin@appserv4 \"sudo chown -R webadmin:webadmin /var/opt/httpd/$env.SITEIDdocs/\""
            // copy files from control server to production
            sh "rsync --exclude=.svn --exclude=.git -rav -e ssh --delete /tmp/$env.SITEIDdocs/ webadmin@appserv3:/var/opt/httpd/$env.SITEIDdocs/"
            sh "rsync --exclude=.svn --exclude=.git -rav -e ssh --delete /tmp/$env.SITEIDdocs/ webadmin@appserv4:/var/opt/httpd/$env.SITEIDdocs/"
            // fix the owner/permissions on the production server
            sh "ssh webadmin@appserv3 \"sudo chown -R apache:$env.SITEID-web /var/opt/httpd/$env.SITEIDdocs/\""
            sh "ssh webadmin@appserv4 \"sudo chown -R apache:$env.SITEID-web /var/opt/httpd/$env.SITEIDdocs/\""
            sh "ssh webadmin@appserv3 \"sudo chmod -R g+w /var/opt/httpd/$env.SITEIDdocs/\""
            sh "ssh webadmin@appserv4 \"sudo chmod -R g+w /var/opt/httpd/$env.SITEIDdocs/\""
            sh "ssh webadmin@appserv3 \"sudo find /var/opt/httpd/$env.SITEIDdocs/ -type d -exec chmod g+s  \\;\""
            sh "ssh webadmin@appserv4 \"sudo find /var/opt/httpd/$env.SITEIDdocs/ -type d -exec chmod g+s  \\;\""

            // delete the temporary files on the control server
            sh "rm -Rf /tmp/$env.SITEIDdocs/"
             // clear the caches
            sh "wget -O - \"http://www.web.net/incacache.php?api_key=yoiVbjgtL&site_id=088\""
        
    

【问题讨论】:

【参考方案1】:

您可以创建可以被视为阶段的函数,然后使用某些参数按您想​​要的顺序调用它们。

例如:

def deployDBDev(param1, param2)
  //some steps


def deployDev(diffParam1, diffParam2)
  //some steps


//then call it in the sequence you want

deployDBDev(param1, param2)
deployDev(diffParam1, diffParam2)

【讨论】:

感谢您的回答,我的 Jenkinsfile 中不是已经有了您所说的序列吗? 在您的代码中,您正在使用条件阶段,通过将阶段包装到函数中,您可以在第一步结束时使用不同的参数调用下一步。 我明白了,但是当Jenkins轮询后开始自动构建时,Jenkins如何知道调用哪些函数呢?或者我怎样才能告诉 Jenkins 遵循哪个函数/序列? 另外,我是否需要为您推荐的功能调整我所拥有的阶段?【参考方案2】:

我建议在bitbucket中创建3个分支

    开发 舞台和 生产(或母版)。

在 jenkins 方面,您可以为每个环境创建 3 个作业,并在特定分支上添加轮询以自动触发。

您的开发人员将在 dev 中提交,这将在您发现一切正常后触发 dev 的构建,您可以在 stage 分支中合并代码,这将触发 stage 作业。

最后,当您确认暂存一切正常时,只需将暂存合并到生产分支,这将再次触发生产作业。

【讨论】:

【参考方案3】:

要在推送代码或创建拉取请求时触发构建,您可以按照以下文章进行操作。

https://support.cloudbees.com/hc/en-us/articles/115000051132-How-to-Trigger-Multibranch-Jobs-from-BitBucket-Cloud-

【讨论】:

感谢您的回复,但是我已经尝试过这种方法,但我无法使用这种方法,因为我的 jenkins 服务器位于不允许任何传入连接或请求的防火墙后面,所以我可以不要像文章建议的那样使用 webhook,这就是我每 30 分钟使用一次轮询的原因。但无论如何,我在这里的问题更多的是关于我需要添加的 Jenkinsfile 配置,以便我使用特定参数自动构建作业,以及如果仅 dev build 成功,如何确保它一直到 staging。

以上是关于如何让 Jenkins 在从 bitbucket 轮询后自动构建,而不是手动构建具有特定参数的作业的主要内容,如果未能解决你的问题,请参考以下文章

Bitbucket 触发内网 Jenkins Build

我们如何捕获在bitbucket云中创建的拉取请求

Jenkins-X与BitBucket云

Jenkins webbook 在 Bitbucket 中失败,但在 curl 中工作正常

BitBucket Webhook - 无法连接到 Jenkins URL

continous integration environment (Jenkins and bitbucket configuration)