• 物联网架构成长之路(29)-Jenkins环境搭建


    0. 说明

      哈哈,前面中间插入了一篇Eclipse增加Git插件,在此之前真的没有用过GIT。

    1. 运行Jenkins

      这里为了方便,还是用Docker方式安装,由于这个是标准的war报,不对Docker Image进行过多的干预,直接使用官方的Jenkins即可

    docker pull jenkins/jenkins:lts

      写一份docker-compose.yml

    1 version: '3'
    2 services:
    3     jenkins:
    4         image: registry.cn-shenzhen.aliyuncs.com/wunaozai/jenkins
    5         ports:
    6             - 8080:8080
    7             - 50000:50000
    8         volumes:
    9             - /root/workspace/docker/jenkins/data:/var/jenkins_home

    2. 运行jenkins

      docker-compose启动容器

      然后访问宿主机,开始Jenkins安装和配置,安装就不多说了,就是下一步下一步。还有之前的博客也简单的讲解的Jenkins的搭建及使用。安装插件就使用官方默认的就可以了,以后有需要还可以在管理界面上增加。 遇到网速不好的,等一下重试一下就可以了。

      Ps: 安装后,如果刷新页面,没有出现登录界面的,重启一下jenkins
      进入欢迎界面

    3. 本地eclipse关联GitLab仓库、利用Spring Cloud的Eureka测试自动构建

      物联网服务注册中心 global-service-eureka

      GlobalServiceEurekaApplication.java

    1 @EnableEurekaServer
    2 @SpringBootApplication
    3 public class GlobalServiceEurekaApplication {
    4     public static void main(String[] args) {
    5         SpringApplication.run(GlobalServiceEurekaApplication.class, args);
    6     }
    7 }

      application.yml

    1 server:
    2   port: 8761
    3 eureka:
    4   client:
    5     register-with-eureka: false
    6     fetch-registry: false
    7     service-url:
    8       defaultZone: http://localhost:8761/eureka/

      在GitLab上创建项目

      Eclipse关联项目到GitLab这一步就不做过多说明

    4. Jenkins 系统配置

      创建前,先标准插件安装,然后我们还需要安装几个插件,在系统管理-插件管理

      由于我们使用Maven构建Spring Cloud项目,所以需要增加对应的Maven Plugin。我们还使用了GitLab作为代码版本管理,因此需要安装Gitlab Hook Plugin用来使用提交代码,触发自动构建行为。最后还需要把自动构建的结果通过邮件返回给相关人员,这里又需要Email Extension Plugin。

      这一步需要配置Maven,默认的Jenkins Docker Image是有包含了JDK和GIT,所以我们只需要配置Maven。在系统管理-全局工具配置 这个界面,只需要配置Maven工具,使用自动安装。

      配置一下GIT帐号密码,在Jenkins-凭证-系统-全局凭证-新增


      配置邮件 在Jenkins-系统管理-系统设置
      配置Jenkins Locaion

      配置E-mail Notification,填入SMTP服务器、邮件后缀,用户名、密码。有些服务器要求SSL、SSL端口有587、465两种,好像可以不填,JavaMail包会自动选择。然后就可以测试发送了。

      由于默认的E-mail Notificaion功能比较弱,因此,需要Email Extension Plugin,对应的配置如下

    5. Jenkins 任务

      创建一个任务、构建一个Maven项目

      配置源码管理Git方式,输入对应Repo URL、选择对应的认证凭证,这个在签名一步已经配置了,这里选择就可以。分支就选默认主分支的。

      构建触发器,采用Git上有人提交时触发构建

      这里将 GitLab Webhook URL,复制到GitLab对应的项目上。注意这里的URL,必须GitLab所在的服务器要能访问到。

      下面这个,根据实际构建Goals及Options进行配置,以后可能会通过Maven 直接构建成 Docker Image

      下面这个是配置构建成功后,对应执行的操作,以后可能会通过这个脚本,构建成docker Image然后上传到Aliyun Repo

      下面这个是配置自定义构建后,把结果发邮件到指定人,最前面的 Project From 要填前面配置的管理,下面的Recipient List可以写邮件接收人

      下面的高级,注意下面这个配置才是实际要发送的邮件内容。我们先默认的发送一份邮件测试一下。

      一切完成后,点击保存

    6. 触发构建

      可以在GitLab的Web Hooks 点击 Test Hook 按钮,测试一下是否触发自动构建。

      看这里,自动触发构建、等构建完成,对应的邮箱就会收到构建结果。

      可以看到这个邮件已经收到了。结果也是显示在邮件里面

    7. 自定义邮件格式

      初看邮件内容,感觉有点Low,通过下面方式实现自定义邮件内容。在 $JENKINS_HOME 目录下创建 email-templates 文件,创建 wunaozai.html 文件,并写上以下内容,可以通过以下方式预览效果。

      wunaozai.html 内容

    <STYLE>
    BODY, TABLE, TD, TH, P {
        font-family:Verdana,Helvetica,sans serif;
        font-size:11px;
        color:black;
    }
    h1 { color:black; }
    h2 { color:black; }
    h3 { color:black; }
    TD.bg1 { color:white; background-color:#0000C0; font-size:120% }
    TD.bg2 { color:white; background-color:#4040FF; font-size:110% }
    TD.bg3 { color:white; background-color:#8080FF; }
    TD.test_passed { color:blue; }
    TD.test_failed { color:red; }
    TD.console { font-family:Courier New; }
    </STYLE>
    <BODY>
    
        <TABLE>
        <TR><TD align="right"><IMG SRC="${rooturl}static/e59dfe28/images/32x32/<%= (build.result == null || build.result.toString() == 'SUCCESS') ? "blue.gif" : build.result.toString() == 'FAILURE' ? 'red.gif' : 'yellow.gif' %>" />
        </TD><TD valign="center"><B style="font-size: 200%;">BUILD ${build.result ?: 'SUCCESSFUL'}</B></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 width="100%">
                    <TR><TD class="bg1" colspan="2"><B>CHANGES</B></TD></TR>
                    <%  changeSets.each() { cs_list ->
                    cs_list.each() { cs ->
                    hadChanges = true %>
                    <TR>
                    <TD colspan="2" class="bg2">&nbsp;&nbsp;Revision <B><%= cs.metaClass.hasProperty('commitId') ? cs.commitId : cs.metaClass.hasProperty('revision') ? cs.revision :
                cs.metaClass.hasProperty('changeNumber') ? cs.changeNumber : "" %></B> by
            <B><%= cs.author %>: </B>
            <B>(${cs.msgAnnotated})</B>
                    </TD>
                    </TR>
                    <%      cs.affectedFiles.each() { p -> %>
                    <TR>
                    <TD width="10%">&nbsp;&nbsp;${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 width="100%">
             <TR><TD class="bg1"><B>BUILD ARTIFACTS</B></TD></TR>
             <TR>
             <TD>
                 <%      artifacts.each() { f -> %>
                 <li>
                 <a href="${rooturl}${build.url}artifact/${f}">${f}</a>
                 </li>
                 <%      } %>
             </TD>
             </TR>
         </TABLE>
         <BR/>
         <% } %>
    
         <!-- MAVEN ARTIFACTS -->
         <%
           try {
           def mbuilds = build.moduleBuilds
           if(mbuilds != null) { %>
           <TABLE width="100%">
           <TR><TD class="bg1"><B>BUILD ARTIFACTS</B></TD></TR>
           <%
            try {
            mbuilds.each() { m -> %>
            <TR><TD class="bg2"><B>${m.key.displayName}</B></TD></TR>
            <%      m.value.each() { mvnbld ->
            def artifactz = mvnbld.artifacts
            if(artifactz != null && artifactz.size() > 0) { %>
            <TR>
            <TD>
                <%              artifactz.each() { f -> %>
                <li>
                <a href="${rooturl}${mvnbld.url}artifact/${f}">${f}</a>
                </li>
                <%              } %>
            </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 width="100%">
          <TR><TD class="bg1" colspan="2"><B>${junitResultList.first().displayName}</B></TD></TR>
          <% junitResultList.each{
                   junitResult -> %>
                   <% junitResult.getChildren().each { packageResult -> %>
                   <TR><TD class="bg2" colspan="2"> Name: ${packageResult.getName()} Failed: ${packageResult.getFailCount()} test(s), Passed: ${packageResult.getPassCount()} test(s), Skipped: ${packageResult.getSkipCount()} test(s), Total: ${packageResult.getPassCount()+packageResult.getFailCount()+packageResult.getSkipCount()} test(s)</TD></TR>
                   <% packageResult.getFailedTests().each{ failed_test -> %>
                   <TR bgcolor="white"><TD class="test_failed" colspan="2"><B><li>Failed: ${failed_test.getFullName()} </li></B></TD></TR>
                   <% }
                                 }
                                 } %>
          </TABLE>
          <BR/>
          <%
                                 } %>
    
                                 <!-- CONSOLE OUTPUT -->
                                 <% if(build.result==hudson.model.Result.FAILURE) { %>
                                 <TABLE width="100%" cellpadding="0" cellspacing="0">
                                 <TR><TD class="bg1"><B>CONSOLE OUTPUT</B></TD></TR>
                                 <%  build.getLog(100).each() { line -> %>
                                 <TR><TD class="console">${org.apache.commons.lang.StringEscapeUtils.escapeHtml(line)}</TD></TR>
                                 <%  } %>
                                 </TABLE>
                                 <BR/>
                                 <% } %>
    
    </BODY>

      进入到项目任务的配置界面,配置一下自定义邮件格式,如下图所属,配置Content部分,最后的Attach build log 也加上

      下图就是经过自定义后的邮件格式

      哈哈,收到邮件,格式还行,还带构建日志。就这样吧。

    8. 小结

      终于完了,发现这种截图式博客真的特别麻烦,应该是录视频好些。哈哈!!这一篇博客就讲到这里的。还有更多的功能,暂时没有讲到。Jenkins可以做的事情还是很多的。通过写脚本,做任意想要做的事情。不过这个就是根据实际项目来实现了。以后有机会用到我再讲。

    参考资料:

      https://blog.csdn.net/u013066244/article/details/78665075
      https://blog.csdn.net/galen2016/article/details/77975965
      https://www.cnblogs.com/gcgc/p/5631385.html
      https://www.cnblogs.com/bigben0123/p/7886092.html
      https://www.cnblogs.com/xiewenming/p/7490828.html

    本文地址: https://www.cnblogs.com/wunaozai/p/9997566.html

  • 相关阅读:
    谈谈django里的Contex和RequestContext---向模板里添加全局变量
    Django如何重设Admin密码
    javascript的闭包
    javascript的this用法
    阮一峰---javascript系列
    Javascript继承机制总结 [转]
    chrome浏览器开发者工具使用教程[转]
    WAMP设置默认访问目录
    js 去掉空格.回车.换行
    网站服务器上载目录
  • 原文地址:https://www.cnblogs.com/wunaozai/p/9997566.html
Copyright © 2020-2023  润新知