0
点赞
收藏
分享

微信扫一扫

基于Docker的Jenkins安装部署与流水线脚本

奋斗De奶爸 2021-09-30 阅读 69
Jenkins

一. Docker

1.1 docker安装

1.2 docker常用命令


二. Jenkins

2.1 jenkins安装

生产项目中还需要将配置文件(-v /root/jenkins/conf/config.xml:/var/jenkins_home/config.xml),项目文件等挂载到宿主机上。

2.2 参数介绍

2.3 配置

2.4 存在的问题

jenkins需要安装大量的第三方插件,但是所有的数据源都是指向国外仓库,导致国内下载插件缓慢甚至大量失败,因此需要配置国内的镜像源。



三. Nginx

3.1 nginx安装

3.2 配置文件


四. Pipeline脚本

4.1 自动化部署脚本

方式一:通过账号密码远程登录

pipeline {
  agent any
  //系统参数配置
  options{
    buildDiscarder(logRotator(numToKeepStr:'2'))  //持久化工件和控制台输出,规定pipeline运行的最大个数
    disableConcurrentBuilds() //设置pipeline不能并行运行,放置同时访问共享资源。
    skipDefaultCheckout() //跳过默认设置的代码check out
    skipStagesAfterUnstable() //一旦构建状态变成unstable不稳定状态,跳过该阶段
    timeout(time:1,unit:'HOURS')  //设置该pipeline运行的超时时间,超时的pipeline会自动被终止
    timestamps()  //为控制台输出增加时间戳
  }
  //变量定义
  environment {   
    CREDENTIALSID = 'smartcook'
    GIT_URL = 'http://gitlab.iotmars.com/backend/smartcook/smartcook.git'
    BRANCH = 'dev'
    ALIYUN_NAMESPACE = 'wecook'
    ALIYUN_REPOSITORY = 'menu-center-dev'
    IMAGE_VERSION = '0.0.1-SNAPSHOT'
    DOCKER_CONTAINER_NAME = 'smartcook'
    REMOTE_SERVER_IP = '192.168.32.128'
    REMOTE_SERVER_NAME = 'localhost.localdomain'
    REMOTE_SERVER_CREDENTIALSID = 'server_128'
    REMOTE_REPOSITORY_CREDENTIALSID = 'hxr_aliyun'
    SERVER_PORT = '8002'
    EMAIL = '792965772@qq.com'
  }
  //定义工具
  triggers {
    GenericTrigger (
      genericVariables: [
        [key: 'ref',value: '$.ref']
      ],
      causeString: 'Triggered on $ref',
      token: 'Smartcook_Menu-Center',
            
      printContributedVariables: true,
      printPostContent: true,
            
      silentResponse: false,
            
      regexpFilterText: '$ref',
      regexpFilterExpression: "refs/heads/dev"
    )
  }

  stages {
    //1.拉取源码
    stage('Git Checkout'){
      steps {
        retry(3){
          git (
            branch:"${BRANCH}" ,
            credentialsId:"${CREDENTIALSID}" ,
            url: "${GIT_URL}" ,
            changelog: true 
          )
        }
      }
    }
    //2.编译成jar包
    stage('Maven Build') {
      steps { 
        retry(3){
          sh "mvn -Dmaven.test.failure.ignore=true clean package"
        }
      }
    }
    //3.构建镜像并上传到阿里云镜像仓库
    stage('Build and Push Image'){
      steps{
        withCredentials([usernamePassword(credentialsId: 'hxr_aliyun', passwordVariable: 'password', usernameVariable: 'username')]) {
          script{
            out=sh(script:"ls ./Dockerfile",returnStatus:true)
            println out
            if( out == 2 ){
              println "创建默认Dockerfile"
              sh '''
                cat  <<  EOF  >  Dockerfile
                FROM openjdk:8-jdk-alpine
                VOLUME /tmp
                ADD ./target/*.jar app.jar
                EXPOSE ${SERVER_PORT}
                ENTRYPOINT ["java","-Xmx200m","-Xms200m","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
EOF
              '''
            }
          retry(3){
            sh """
              docker build -t ${DOCKER_CONTAINER_NAME} .
              sudo docker login --username=${username} --password=${password} registry.cn-hangzhou.aliyuncs.com
              sudo docker tag ${DOCKER_CONTAINER_NAME} registry.cn-hangzhou.aliyuncs.com/${ALIYUN_NAMESPACE}/${ALIYUN_REPOSITORY}:${IMAGE_VERSION}
              sudo docker push registry.cn-hangzhou.aliyuncs.com/${ALIYUN_NAMESPACE}/${ALIYUN_REPOSITORY}:${IMAGE_VERSION}
            """
            }
          }
        }
      }
    }
    //4.拉取镜像并启动
    stage('Pull Image and Run'){
      steps{
        retry(3){
          script{
            withCredentials([usernamePassword(credentialsId: REMOTE_SERVER_CREDENTIALSID, passwordVariable: 'password', usernameVariable: 'username')]) {
              def remote = [:]
              remote.name = REMOTE_SERVER_NAME
              remote.host = REMOTE_SERVER_IP
              remote.user = username
              remote.password = password
              remote.allowAnyHosts = true
              withCredentials([usernamePassword(credentialsId: REMOTE_REPOSITORY_CREDENTIALSID, passwordVariable: 'password', usernameVariable: 'username')]) {
                //从阿里云镜像仓库中拉取镜像并启动
                sshCommand remote: remote, command: "sudo docker login --username=\"${username}\" --password=\"${password}\" registry.cn-hangzhou.aliyuncs.com"
                sshCommand remote: remote, command: "sudo docker pull registry.cn-hangzhou.aliyuncs.com/\"${ALIYUN_NAMESPACE}\"/\"${ALIYUN_REPOSITORY}\":\"${IMAGE_VERSION}\""
                sshCommand remote: remote, command: "docker stop \"${DOCKER_CONTAINER_NAME}\" || true"
                sshCommand remote: remote, command: "docker rm  \"${DOCKER_CONTAINER_NAME}\" || true"
                sshCommand remote: remote, command: "docker run -it -d -p \"${SERVER_PORT}\":\"${SERVER_PORT}\" --name \"${DOCKER_CONTAINER_NAME}\" registry.cn-hangzhou.aliyuncs.com/\"${ALIYUN_NAMESPACE}\"/\"${ALIYUN_REPOSITORY}\":\"${IMAGE_VERSION}\""
              }
            }
          }
        }
      }
    }
  }
  post {
    always {
      echo 'This will always run'
      script{
        currentBuild.description = "\n always"
      }
      deleteDir() /* clean up our workspace */
      //archiveArtifacts artifacts: 'build/libs/**/*.jar', fingerprint: true
      //junit 'build/reports/**/*.xml'
      //TODO 添加邮箱服务
    }
    success {
      println("success!!!!!!!")
      script{
        currentBuild.description = "\n success"
      }
      //mail  to: "${EMAIL}", 
      //      subject: "Success Pipeline: ${currentBuild.fullDisplayName}",
      //      body: "Success with ${env.BUILD_URL}" /*该构建的url地址*/
    }
    failure {
      echo 'This will run only if failed'
      script{
        currentBuild.description = "\n failure"
      }
      //mail  to: "${EMAIL}", 
      //      subject: "Failed Pipeline: ${currentBuild.fullDisplayName}",
      //      body: "Something is wrong with ${env.BUILD_URL}" /*该构建的url地址*/
    }
  }
}


方式二:通过设置私钥凭证的方式远程登录

如果不会写流水线语法,有两种解决方式:

pipeline {
  agent any
  options{
    buildDiscarder(logRotator(numToKeepStr:'2'))  //持久化工件和控制台输出,规定pipeline运行的最大个数
    disableConcurrentBuilds() //设置pipeline不能并行运行,放置同时访问共享资源。
    skipDefaultCheckout() //跳过默认设置的代码check out
    skipStagesAfterUnstable() //一旦构建状态变成unstable不稳定状态,跳过该阶段
    timeout(time:1,unit:'HOURS')  //设置该pipeline运行的超时时间,超时的pipeline会自动被终止
    timestamps()  //为控制台输出增加时间戳
  }
  environment {
    CREDENTIALSID = 'CJsGitlab'
    GIT_URL = 'http://gitlab.iotmars.com/backend/duerosbots.git'
    BRANCH = 'master'
    ALIYUN_NAMESPACE = 'wecook'
    ALIYUN_REPOSITORY = 'menu-center-dev'
    IMAGE_VERSION = '0.0.1-SNAPSHOT'
    DOCKER_CONTAINER_NAME = 'duerosbots'
    REMOTE_SERVER_IP = '121.41.68.248'
    REMOTE_SERVER_NAME = 'iotmars.ecs.area.h03'
    REMOTE_SERVER_CREDENTIALSID = 'server_aliyun_248'
    REMOTE_REPOSITORY_CREDENTIALSID = 'hxr_aliyun'
    SERVER_PORT = '8090'
    EMAIL = '792965772@qq.com'
  }
  //定义工具
  tools {
    maven "mvn3.5.0"
  }
  //定义远程触发器
  triggers {
    GenericTrigger (
      genericVariables: [
        [key: 'ref',value: '$.ref']
      ],
      causeString: 'Triggered on $ref',
      token: 'Smartcook_Menu-Center',
            
      printContributedVariables: true,
      printPostContent: true,
            
      silentResponse: false,
            
      regexpFilterText: '$ref',
      regexpFilterExpression: "refs/heads/dev"
    )
  }

  stages {
    stage('Git Checkout'){
      steps {
        retry(3){
        //1.拉取源码
          git (
            branch:"${BRANCH}" ,
            credentialsId:"${CREDENTIALSID}" ,
            url: "${GIT_URL}" ,
            changelog: true 
          )
        }
      }
    }
    stage('Maven Build') {
      steps { 
        //2.编译成jar包
        retry(3){
          sh "mvn -Dmaven.test.failure.ignore=true clean package"
        }
      }
    }
    stage('Build and Push Image'){
      steps{
        //3.构建镜像
        withCredentials([usernamePassword(credentialsId: REMOTE_REPOSITORY_CREDENTIALSID, passwordVariable: 'password', usernameVariable: 'username')]) {
          script{
            //判断路径下是否有dockerfile文件,没有则创建默认的dockerfile
            out=sh(script:"ls ./Dockerfile",returnStatus:true)
            println out
            if( out == 2 ){
              println "创建默认Dockerfile"
              sh '''
                cat  <<  EOF  >  Dockerfile
                FROM openjdk:8-jdk-alpine
                VOLUME /tmp
                ADD ./target/*.jar app.jar
                EXPOSE ${SERVER_PORT}
                ENTRYPOINT ["java","-Xmx200m","-Xms200m","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
EOF
              '''
            }
          retry(3){
            sh """
              docker build -t ${DOCKER_CONTAINER_NAME} .
              sudo docker login --username=${username} --password=${password} registry.cn-hangzhou.aliyuncs.com
              sudo docker tag ${DOCKER_CONTAINER_NAME} registry.cn-hangzhou.aliyuncs.com/${ALIYUN_NAMESPACE}/${ALIYUN_REPOSITORY}:${IMAGE_VERSION}
              sudo docker push registry.cn-hangzhou.aliyuncs.com/${ALIYUN_NAMESPACE}/${ALIYUN_REPOSITORY}:${IMAGE_VERSION}
            """
            }
          }
        }
      }
    }
    
    stage('Pull Image and Run'){
      steps{
        retry(3){
          script{
            //通过私钥登录到远程服务器
            withCredentials([sshUserPrivateKey(credentialsId: REMOTE_SERVER_CREDENTIALSID, keyFileVariable: 'keyFile', passphraseVariable: 'passphrase', usernameVariable: 'username')]) {
              def remote = [:]
              remote.name = REMOTE_SERVER_NAME
              remote.host = REMOTE_SERVER_IP
              remote.user = username
              remote.identityFile = keyFile
              remote.port = 22
              remote.allowAnyHosts = true
              withCredentials([usernamePassword(credentialsId: REMOTE_REPOSITORY_CREDENTIALSID, passwordVariable: 'password', usernameVariable: 'username')]) {
                //4.拉取镜像并启动
                sshCommand remote: remote, command: "sudo docker login --username=\"${username}\" --password=\"${password}\" registry.cn-hangzhou.aliyuncs.com"
                sshCommand remote: remote, command: "sudo docker pull registry.cn-hangzhou.aliyuncs.com/\"${ALIYUN_NAMESPACE}\"/\"${ALIYUN_REPOSITORY}\":\"${IMAGE_VERSION}\""
                sshCommand remote: remote, command: "docker stop \"${DOCKER_CONTAINER_NAME}\" || true"
                sshCommand remote: remote, command: "docker rm  \"${DOCKER_CONTAINER_NAME}\" || true"
                sshCommand remote: remote, command: "docker run -it -d -p \"${SERVER_PORT}\":\"${SERVER_PORT}\" --name \"${DOCKER_CONTAINER_NAME}\" registry.cn-hangzhou.aliyuncs.com/\"${ALIYUN_NAMESPACE}\"/\"${ALIYUN_REPOSITORY}\":\"${IMAGE_VERSION}\""
              }
            }
          }
        }
      }
    }
  }
  post {
    always {
      echo 'This will always run'
      script{
        currentBuild.description = "\n always"
      }
      deleteDir() /* clean up our workspace */
      //archiveArtifacts artifacts: 'build/libs/**/*.jar', fingerprint: true
      //junit 'build/reports/**/*.xml'
      //TODO 添加邮箱服务
    }
    success {
      println("success!!!!!!!")
      script{
        currentBuild.description = "\n success"
      }
      //mail  to: "${EMAIL}", 
      //      subject: "Success Pipeline: ${currentBuild.fullDisplayName}",
      //      body: "Success with ${env.BUILD_URL}" /*该构建的url地址*/
    }
    failure {
      echo 'This will run only if failed'
      script{
        currentBuild.description = "\n failure"
      }
      //mail  to: "${EMAIL}", 
      //      subject: "Failed Pipeline: ${currentBuild.fullDisplayName}",
      //      body: "Something is wrong with ${env.BUILD_URL}" /*该构建的url地址*/
    }
  }
}   


方式三:通过私钥文件远程登录(将pem文件放到jenkins容器中)

pipeline {
  agent any
  options{
    buildDiscarder(logRotator(numToKeepStr:'2'))  //持久化工件和控制台输出,规定pipeline运行的最大个数
    disableConcurrentBuilds() //设置pipeline不能并行运行,放置同时访问共享资源。
    skipDefaultCheckout() //跳过默认设置的代码check out
    skipStagesAfterUnstable() //一旦构建状态变成unstable不稳定状态,跳过该阶段
    timeout(time:1,unit:'HOURS')  //设置该pipeline运行的超时时间,超时的pipeline会自动被终止
    timestamps()  //为控制台输出增加时间戳
  }
  environment {
    CREDENTIALSID = 'CJsGitlab'
    GIT_URL = 'http://gitlab.iotmars.com/backend/duerosbots.git'
    BRANCH = 'master'
    ALIYUN_NAMESPACE = 'wecook'
    ALIYUN_REPOSITORY = 'menu-center-dev'
    IMAGE_VERSION = '0.0.1-SNAPSHOT'
    DOCKER_CONTAINER_NAME = 'duerosbots'
    REMOTE_SERVER_IP = '121.41.68.248'
    REMOTE_SERVER_NAME = 'iotmars.ecs.area.h03'
    REMOTE_SERVER_CREDENTIALSID = 'server_128'
    REMOTE_SERVER_USERNAME = 'root'
    REMOTE_SERVER_IDENTITYFILE = '/home/jenkins/.ssh/M20200509_162337marssenger.pem'
    REMOTE_REPOSITORY_CREDENTIALSID = 'hxr_aliyun'
    SERVER_PORT = '8090'
    EMAIL = '792965772@qq.com'
  }
  //定义工具
  tools {
    maven "mvn3.5.0"
  }
  //定义远程触发器
  triggers {
    GenericTrigger (
      genericVariables: [
        [key: 'ref',value: '$.ref']
      ],
      causeString: 'Triggered on $ref',
      token: 'Smartcook_Menu-Center',
            
      printContributedVariables: true,
      printPostContent: true,
            
      silentResponse: false,
            
      regexpFilterText: '$ref',
      regexpFilterExpression: "refs/heads/dev"
    )
  }

  stages {
    stage('Git Checkout'){
      steps {
        retry(3){
        //1.拉取源码
          git (
            branch:"${BRANCH}" ,
            credentialsId:"${CREDENTIALSID}" ,
            url: "${GIT_URL}" ,
            changelog: true 
          )
        }
      }
    }
    stage('Maven Build') {
      steps { 
        //2.编译成jar包
        retry(3){
          sh "mvn -Dmaven.test.failure.ignore=true clean package"
        }
      }
    }
    stage('Build and Push Image'){
      steps{
        //3.构建镜像
        withCredentials([usernamePassword(credentialsId: 'hxr_aliyun', passwordVariable: 'password', usernameVariable: 'username')]) {
          script{
            out=sh(script:"ls ./Dockerfile",returnStatus:true)
            println out
            if( out == 2 ){
              println "创建默认Dockerfile"
              sh '''
                cat  <<  EOF  >  Dockerfile
                FROM openjdk:8-jdk-alpine
                VOLUME /tmp
                ADD ./target/*.jar app.jar
                EXPOSE ${SERVER_PORT}
                ENTRYPOINT ["java","-Xmx200m","-Xms200m","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
EOF
              '''
            }
          retry(3){
            sh """
              docker build -t ${DOCKER_CONTAINER_NAME} .
              sudo docker login --username=${username} --password=${password} registry.cn-hangzhou.aliyuncs.com
              sudo docker tag ${DOCKER_CONTAINER_NAME} registry.cn-hangzhou.aliyuncs.com/${ALIYUN_NAMESPACE}/${ALIYUN_REPOSITORY}:${IMAGE_VERSION}
              sudo docker push registry.cn-hangzhou.aliyuncs.com/${ALIYUN_NAMESPACE}/${ALIYUN_REPOSITORY}:${IMAGE_VERSION}
            """
            }
          }
        }
      }
    }
    
    stage('Pull Image and Run'){
      steps{
        retry(3){
          script{
            def remote = [:]
            remote.name = REMOTE_SERVER_NAME
            remote.host = REMOTE_SERVER_IP
            remote.user = REMOTE_SERVER_USERNAME
            remote.port = 22
            remote.identityFile = '/home/jenkins/.ssh/M20200509_162337marssenger.pem'
            remote.allowAnyHosts = true
            withCredentials([usernamePassword(credentialsId: REMOTE_REPOSITORY_CREDENTIALSID, passwordVariable: 'password', usernameVariable: 'username')]) {
              //4.拉取镜像并启动
              sshCommand remote: remote, command: "sudo docker login --username=\"${username}\" --password=\"${password}\" registry.cn-hangzhou.aliyuncs.com"
              sshCommand remote: remote, command: "sudo docker pull registry.cn-hangzhou.aliyuncs.com/\"${ALIYUN_NAMESPACE}\"/\"${ALIYUN_REPOSITORY}\":\"${IMAGE_VERSION}\""
              sshCommand remote: remote, command: "docker stop \"${DOCKER_CONTAINER_NAME}\" || true"
              sshCommand remote: remote, command: "docker rm  \"${DOCKER_CONTAINER_NAME}\" || true"
              sshCommand remote: remote, command: "docker run -it -d -p \"${SERVER_PORT}\":\"${SERVER_PORT}\" --name \"${DOCKER_CONTAINER_NAME}\" registry.cn-hangzhou.aliyuncs.com/\"${ALIYUN_NAMESPACE}\"/\"${ALIYUN_REPOSITORY}\":\"${IMAGE_VERSION}\""
            }
          }
        }
      }
    }
  }
  post {
    always {
      echo 'This will always run'
      script{
        currentBuild.description = "\n always"
      }
      deleteDir() /* clean up our workspace */
      //archiveArtifacts artifacts: 'build/libs/**/*.jar', fingerprint: true
      //junit 'build/reports/**/*.xml'
      //TODO 添加邮箱服务
    }
    success {
      println("success!!!!!!!")
      script{
        currentBuild.description = "\n success"
      }
      //mail  to: "${EMAIL}", 
      //      subject: "Success Pipeline: ${currentBuild.fullDisplayName}",
      //      body: "Success with ${env.BUILD_URL}" /*该构建的url地址*/
    }
    failure {
      echo 'This will run only if failed'
      script{
        currentBuild.description = "\n failure"
      }
      //mail  to: "${EMAIL}", 
      //      subject: "Failed Pipeline: ${currentBuild.fullDisplayName}",
      //      body: "Something is wrong with ${env.BUILD_URL}" /*该构建的url地址*/
    }
  }
}


4.2 pipeline脚本设置

4.2.1 脚本路径为配置文件在仓库中的路径

4.2.2 配置钩子程序

需要安装插件Generic Webhook Trigger

在gitlab的项目settings=>Integrations中设置jenkins项目的url:
http://192.168.32.128:8080/generic-webhook-trigger/invoke?token=Smartcook_Menu-Center

token需要和脚本中的TRIGGER_TOKEN对应

 triggers {
    GenericTrigger (
      genericVariables: [
        [key: 'ref',value: '$.ref']
      ],
      causeString: 'Triggered on $ref',
      token: 'Smartcook_Menu-Center',
            
      printContributedVariables: true,
      printPostContent: true,
            
      silentResponse: false,
            
      regexpFilterText: '$ref',
      regexpFilterExpression: "refs/heads/dev"
    )
  }

可以指定前置任务完成后触发
triggers { upstream(upstreamProjects: 'Smartcook_Register-Center', threshold: hudson.model.Result.SUCCESS) }


4.3 邮箱服务设置

4.3.1 系统配置

①下载插件Email Extension Plugin
②在系统配置中设置系统管理员邮箱


③在系统配置Extended E-mail Notification中进行设置
User Name必须与系统管理员邮箱一致,Password是获取的邮箱第三方登录授权码。

4.3.2 邮件脚本(一般添加在pipeline脚本的always{}中)

emailext body: '''<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title>
</head>

<body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4"
    offset="0">
    <table width="95%" cellpadding="0" cellspacing="0"
        style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">
        <tr>
            <td>(本邮件是程序自动下发的,请勿回复!)</td>
        </tr>
        <tr>
            <td><h2>
                    <font color="#0000FF">构建结果 - ${BUILD_STATUS}</font>
                </h2></td>
        </tr>
        <tr>
            <td><br />
            <b><font color="#0B610B">构建信息</font></b>
            <hr size="2" width="100%" align="center" /></td>
        </tr>
        <tr>
            <td>
                <ul>
                    <li>项目名称&nbsp;:&nbsp;${PROJECT_NAME}</li>
                    <li>构建编号&nbsp;:&nbsp;第${BUILD_NUMBER}次构建</li>
                    <li>SVN&nbsp;版本:&nbsp;${SVN_REVISION}</li>
                    <li>触发原因:&nbsp;${CAUSE}</li>
                    <li>构建日志:&nbsp;<a href="${BUILD_URL}console">${BUILD_URL}console</a></li>
                    <li>构建&nbsp;&nbsp;Url&nbsp;:&nbsp;<a href="${BUILD_URL}">${BUILD_URL}</a></li>
                    <li>工作目录&nbsp;:&nbsp;<a href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li>
                    <li>项目&nbsp;&nbsp;Url&nbsp;:&nbsp;<a href="${PROJECT_URL}">${PROJECT_URL}</a></li>
                </ul>
            </td>
        </tr>
        <tr>
            <td><b><font color="#0B610B">Changes Since Last
                        Successful Build:</font></b>
            <hr size="2" width="100%" align="center" /></td>
        </tr>
        <tr>
            <td>
                <ul>
                    <li>历史变更记录 : <a href="${PROJECT_URL}changes">${PROJECT_URL}changes</a></li>
                </ul> ${CHANGES_SINCE_LAST_SUCCESS,reverse=true, format="Changes for Build #%n:<br />%c<br />",showPaths=true,changesFormat="<pre>[%a]<br />%m</pre>",pathFormat="&nbsp;&nbsp;&nbsp;&nbsp;%p"}
            </td>
        </tr>
        <tr>
            <td><b>Failed Test Results</b>
            <hr size="2" width="100%" align="center" /></td>
        </tr>
        <tr>
            <td><pre
                    style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans-serif">$FAILED_TESTS</pre>
                <br /></td>
        </tr>
        <tr>
            <td><b><font color="#0B610B">构建日志 (最后 100行):</font></b>
            <hr size="2" width="100%" align="center" /></td>
        </tr>
        <!-- <tr>
            <td>Test Logs (if test has ran): <a
                href="${PROJECT_URL}ws/TestResult/archive_logs/Log-Build-${BUILD_NUMBER}.zip">${PROJECT_URL}/ws/TestResult/archive_logs/Log-Build-${BUILD_NUMBER}.zip</a>
                <br />
            <br />
            </td>
        </tr> -->
        <tr>
            <td><textarea cols="80" rows="30" readonly="readonly"
                    style="font-family: Courier New">${BUILD_LOG, maxLines=100}</textarea>
            </td>
        </tr>
    </table>
</body>
</html>''', subject: '${BUILD_STATUS} - ${PROJECT_NAME} - Build # ${BUILD_NUMBER} !', to: "${EMAIL}"


五、使用LDAP进行登陆认证

进入Manage Jenkins -> Configure Global Security ,在访问控制中选择LDAP,配置如下。用户的权限控制可以通过Manage and Assign Roles来实现。

以上都完成后,可以使用Test LDAP Settings按钮进行用户登陆测试,user为uid,password为对应的用户密码。

举报

相关推荐

0 条评论