Jenkins自动构建部署项目

1. 楔子

在实际开发中,经常需要编译、静态代码检查、自动化测试、打包、部署、启动等一连串重复机械的动作,浪费时间、而且容易出错,而Jenkins就是专门Continuous integration(CI)/ Continuous Deploy(CD)开源工具,本文简单介绍Jenkins的使用。

在线无安装免费试用Jenkins:http://www.jenkins.org.cn/test

2.jenkins介绍

Jenkins只是一个平台,真正运作的都是插件。这就是jenkins流行的原因,因为jenkins什么插件都有
Hudson是Jenkins的前身,是基于Java开发的一种持续集成工具,用于监控程序重复的工作,Hudson后来被收购,成为商业版。后来创始人又写了一个jenkins,jenkins在功能上远远超过hudson

官网:https://jenkins.io/
插件库:https://plugins.jenkins.io/

3.创建流水线

首先创建一个新的自由风格的流水线,是功能比较强大和自由的流水线方式。
在这里插入图片描述
填写流水线信息和构建结果保留策略:
在这里插入图片描述
配置代码管理,主要是拉取哪个目录的代码、放入哪个目录。
在这里插入图片描述
代码仓库结构为:
在这里插入图片描述
拉取到的效果为:(当前目录为workspace/Travel-dev-deploy Travel-dev-deploy为流水线项目名字)
在这里插入图片描述
可以配置流水线触发策略,比如定时,间隔或者cron表达式等:
在这里插入图片描述
执行gradle脚本完成构建、部署等。主要功能有gradle脚本完成。
在这里插入图片描述
一定要配置gradle脚本的目录,不然gradle的命令task找不到。
在这里插入图片描述
一个可用的部署脚本为:

    task deploy(dependsOn: distTar) {
        println("configDir------->" + System.getProperty("configDir"))
        def role = ""
        if (System.getProperty("configDir") == null || System.getProperty("configDir").isEmpty()) {
            role = "debug"
        }
        println "buildDir------>$buildDir"
        doLast {
            ssh.run {
                session(remotes.travle) {
                    println "role" + role
//                    if (role.equals("debug")) {
                    executeScript '''#!/bin/sh
                          cd /u01/SINO/SSP-Travel-Dev
                          bin/SSP-Travel stop
                          pwd
                          mv -f /u01/SINO/SSP-Travel-Dev/log /u01/SINO/log-dev
                          rm -rf /u01/SINO/SSP-Travel-Dev
                        '''

                    put from: "$buildDir/distributions/SSP-Travel-${version}.tar", into: '/u01/SINO/'
                    execute "tar -xvf /u01/SINO/SSP-Travel-${version}.tar -C /u01/SINO/"
                    execute "mv /u01/SINO/SSP-Travel-${version} /u01/SINO/SSP-Travel-Dev"
                    execute "mv -f /u01/SINO/log-dev /u01/SINO/SSP-Travel-Dev/log"
                    execute "rm -rf /u01/SINO/SSP-Travel-${version}.tar"

                    executeScript '''#!/bin/sh
                          cd /u01/SINO/SSP-Travel-Dev
                          bin/SSP-Travel stop
                          bin/SSP-Travel debug 5006
                        '''
                }
            }
        }
    }

    ssh.settings {
        knownHosts = allowAnyHosts
    }

    remotes {
        travle {
            role('debug')
            host = '1.1.1.1'
            user = 'root'
            password = 'xxxxxxx'
        }
    }

归档打包部署完成的包:
在这里插入图片描述
构建成果文件在Jenkins上的位置如下,需要把这个文件拷贝归档。
在这里插入图片描述
采用匹配的方式,把所有符合规则的构建成果文件进行归档,效果如下:
在这里插入图片描述
配置邮件发送,构建成功或者失败给 特定的人 和 更改过代码的人发送邮件:

Default Content:默认邮件内容;这里是关键;我这里使用的是模板${SCRIPT, template="groovy-html-dev.template"};后面会讲;当然不想使用模板的话,可以通过使用jenkins自身提供的变量来自己定义;
在这里插入图片描述
下面一定要注意:
在这里插入图片描述
邮件模板采用groovy模板,官方给出了很多的模板(matrix模板、groovy模板):
在这里插入图片描述
本文采用的是Gradle的变成语言groovy模板,官方实例为:
https://github.com/jenkinsci/email-ext-plugin/blob/master/src/main/resources/hudson/plugins/emailext/templates/groovy-html.template

<STYLE>
  BODY, TABLE, TD, TH, P {
    font-family: Calibri, Verdana, Helvetica, sans serif;
    font-size: 12px;
    color: black;
  }
  .console {
    font-family: Courier New;
  }
  .filesChanged {
    width: 10%;
    padding-left: 10px;
  }
  .section {
    width: 100%;
    border: thin black dotted;
  }
  .td-title-main {
    color: white;
    font-size: 200%;
    padding-left: 5px;
    font-weight: bold;
  }
  .td-title {
    color: white;
    font-size: 120%;
    font-weight: bold;
    padding-left: 5px;
    text-transform: uppercase;
  }
  .td-title-tests {
    font-weight: bold;
    font-size: 120%;
  }
  .td-header-maven-module {
    font-weight: bold;
    font-size: 120%;    
  }
  .td-maven-artifact {
    padding-left: 5px;
  }
  .tr-title {
    background-color: <%= (build.result == null || build.result.toString() == 'SUCCESS') ? '#27AE60' : build.result.toString() == 'FAILURE' ? '#E74C3C' : '#f4e242' %>;
  }
  .test {
    padding-left: 20px;
  }
  .test-fixed {
    color: #27AE60;
  }
  .test-failed {
    color: #E74C3C;
  }
</STYLE>
<BODY>
  <!-- BUILD RESULT -->
  <table class="section">
    <tr class="tr-title">
      <td class="td-title-main" colspan=2>
        BUILD ${build.result ?: 'COMPLETED'}
      </td>
    </tr>
    <tr>
      <td>URL:</td>
      <td><A href="${rooturl}${build.url}">${rooturl}${build.url}</A></td>
    </tr>
    <tr>
      <td>Project:</td>
      <td>${project.name}</td>
    </tr>
    <tr>
      <td>Date:</td>
      <td>${it.timestampString}</td>
    </tr>
    <tr>
      <td>Duration:</td>
      <td>${build.durationString}</td>
    </tr>
    <tr>
      <td>Cause:</td>
      <td><% build.causes.each() { cause -> %> ${cause.shortDescription} <%  } %></td>
    </tr>
  </table>
  <br/>

  <!-- CHANGE SET -->
  <%
  def changeSets = build.changeSets
  if(changeSets != null) {
    def hadChanges = false %>
  <table class="section">
    <tr class="tr-title">
      <td class="td-title" colspan="2">CHANGES</td>
    </tr>
    <% changeSets.each() { 
      cs_list -> cs_list.each() { 
        cs -> hadChanges = true %>
    <tr>
      <td>
        Revision
        <%= cs.metaClass.hasProperty('commitId') ? cs.commitId : cs.metaClass.hasProperty('revision') ? cs.revision : cs.metaClass.hasProperty('changeNumber') ? cs.changeNumber : "" %>
        by <B><%= cs.author %></B>
      </td>
      <td>${cs.msgAnnotated}</td>
    </tr>
        <% cs.affectedFiles.each() {
          p -> %>
    <tr>
      <td class="filesChanged">${p.editType.name}</td>
      <td>${p.path}</td>
    </tr>
        <% }
      }
    }
    if ( !hadChanges ) { %>
    <tr>
      <td colspan="2">No Changes</td>
    </tr>
    <% } %>
  </table>
  <br/>
  <% } %>

<!-- ARTIFACTS -->
  <% 
  def artifacts = build.artifacts
  if ( artifacts != null && artifacts.size() > 0 ) { %>
  <table class="section">
    <tr class="tr-title">
      <td class="td-title">BUILD ARTIFACTS</td>
    </tr>
    <% artifacts.each() {
      f -> %>
      <tr>
        <td>
          <a href="${rooturl}${build.url}artifact/${f}">${f}</a>
      </td>
    </tr>
    <% } %>
  </table>
  <br/>
  <% } %>

<!-- MAVEN ARTIFACTS -->
  <%
  try {
    def mbuilds = build.moduleBuilds
    if ( mbuilds != null ) { %>
  <table class="section">
    <tr class="tr-title">
      <td class="td-title">BUILD ARTIFACTS</td>
    </tr>
      <%
      try {
        mbuilds.each() {
          m -> %>
    <tr>
      <td class="td-header-maven-module">${m.key.displayName}</td>
    </tr>
          <%
          m.value.each() { 
            mvnbld -> def artifactz = mvnbld.artifacts
            if ( artifactz != null && artifactz.size() > 0) { %>
    <tr>
      <td class="td-maven-artifact">
              <% artifactz.each() {
                f -> %>
        <a href="${rooturl}${mvnbld.url}artifact/${f}">${f}</a><br/>
              <% } %>
      </td>
    </tr>
            <% }
          }
        }
      } catch(e) {
        // we don't do anything
      } %>
  </table>
  <br/>
    <% }
  } catch(e) {
    // we don't do anything
  } %>

<!-- JUnit TEMPLATE -->

  <%
  def junitResultList = it.JUnitTestResult
  try {
    def cucumberTestResultAction = it.getAction("org.jenkinsci.plugins.cucumber.jsontestsupport.CucumberTestResultAction")
    junitResultList.add( cucumberTestResultAction.getResult() )
  } catch(e) {
    //cucumberTestResultAction not exist in this build
  }
  if ( junitResultList.size() > 0 ) { %>
  <table class="section">
    <tr class="tr-title">
      <td class="td-title" colspan="5">${junitResultList.first().displayName}</td>
    </tr>
    <tr>
        <td class="td-title-tests">Name</td>
        <td class="td-title-tests">Failed</td>
        <td class="td-title-tests">Passed</td>
        <td class="td-title-tests">Skipped</td>
        <td class="td-title-tests">Total</td>
      </tr>
    <% junitResultList.each {
      junitResult -> junitResult.getChildren().each {
        packageResult -> %>
    <tr>
      <td>${packageResult.getName()}</td>
      <td>${packageResult.getFailCount()}</td>
      <td>${packageResult.getPassCount()}</td>
      <td>${packageResult.getSkipCount()}</td>
      <td>${packageResult.getPassCount() + packageResult.getFailCount() + packageResult.getSkipCount()}</td>
    </tr>
    <% packageResult.getPassedTests().findAll({it.getStatus().toString() == "FIXED";}).each{
        test -> %>
            <tr>
              <td class="test test-fixed" colspan="5">
                ${test.getFullName()} ${test.getStatus()}
              </td>
            </tr>
        <% } %>
        <% packageResult.getFailedTests().sort({a,b -> a.getAge() <=> b.getAge()}).each{
          failed_test -> %>
    <tr>
      <td class="test test-failed" colspan="5">
        ${failed_test.getFullName()} (Age: ${failed_test.getAge()})
      </td>
    </tr>
        <% }
      }
    } %>
  </table>
  <br/>
  <% } %>

<!-- CONSOLE OUTPUT -->
  <%
  if ( build.result == hudson.model.Result.FAILURE ) { %>
  <table class="section" cellpadding="0" cellspacing="0">
    <tr class="tr-title">
      <td class="td-title">CONSOLE OUTPUT</td>
    </tr>
    <% 	build.getLog(100).each() {
      line -> %>
	  <tr>
      <td class="console">${org.apache.commons.lang.StringEscapeUtils.escapeHtml(line)}</td>
    </tr>
    <% } %>
  </table>
  <br/>
  <% } %>
</BODY>

模板需要在Jenkins的主目录下建立email-templates目录,把模板放入其中,如下所示:
在这里插入图片描述
可以测试下邮件效果:
在这里插入图片描述
邮件的最终效果如下:
在这里插入图片描述

4.邮件添加附件和附件正文

进行如下配置即可添加附件:
在这里插入图片描述
效果如下:
在这里插入图片描述
实现把附件的内容添加到邮件正文,需要使用groovy的邮件模板,采用groovy编程语言的优势进行文件的读取和显示:
在这里插入图片描述
在这里插入图片描述
结果如下:
在这里插入图片描述

5.认证,使用域账户登录

在这里插入图片描述

6.参考文献

发布了418 篇原创文章 · 获赞 745 · 访问量 126万+

猜你喜欢

转载自blog.csdn.net/u013467442/article/details/89971122