使用Jenkins流水线pipeline自动构建和发布

277 阅读3分钟

jenkins安装

官网下载安装

jenkins官网

自行查看官方文档,选择对应系统,进行安装

Docker安装

jenkins官方docker镜像

sudo docker run \
  -u root \
  --name jenkins-blueocean \
  --restart=on-failure \
  --detach \
  --publish 8080:8080 \
  --volume /root/jenkins-data:/var/jenkins_home \
  jenkins/jenkins:latest

面板安装(宝塔/1Panel)

推荐1Panel

  • 安装1Panel
  • 应用商店搜索jenkins,进行安装
  • 安装完成后启动

需要插件

进入jenkins后,推荐插件直接安装,失败就多试几次

登录jenkins后,手动安装自己需要的插件

  • NodeJs
  • pipeline-utility-steps
  • SSH Pipeline Steps
  • WXWork Notification
  • Pipeline: Stage View
  • Pipeline Maven Integration
  • openJDK-native-plugin

全局凭据配置

系统管理-凭据管理-全局-添加凭据

可以添加服务器私钥、用户名密码、token等

方便后续脚本调用

推荐拉取代码使用部署公钥,相对使用账号密码来得安全

远程连接服务器,也使用私钥来连接

具体操作自行百度

踩过的坑:jenkins如果是docker部署的话,生成私钥需要进入docker内部,宿主机的好像不能用

NodeJs配置

系统管理-全局工具配置-NodejS

  1. 新增NodejS
  2. 别名(后续调用脚本时使用)
  3. 选择版本
  4. 全局安装必要的依赖,比如pnpm、yarn等等
  5. 勾选自动安装,保存就行

Maven配置

系统管理-全局工具配置-Maven安装

  1. 新增Maven
  2. 别名(后续调用脚本时使用)
  3. 勾选自动安装,选择新增安装,从Apache安装
  4. 选择版本

系统管理-Managed files

  1. 新增JDK
  2. 别名(后续调用脚本时使用)
  3. 勾选自动安装,选择新增安装,OpenJDK installer
  4. 选择版本

默认全局 settings 提供

  1. 新增配置文件
  2. 选择Global Maven settings.xml,next
  3. 将项目的Maven settings.xml文件内容粘贴进去
  4. 不需要,jenkins会自动读默认的
  5. 提交

回到 系统管理-全局工具配置-Maven 配置

  • 默认全局 settings 提供
  • 选择 privided global settings.xml
  • 选择刚刚新增的settings.xml的别名

JDK配置

系统管理-全局工具配置-JDK安装

  1. 新增JDK
  2. 别名(后续调用脚本时使用)
  3. 勾选自动安装,选择新增安装,OpenJDK installer
  4. 选择版本

企业微信机器人配置

系统管理-系统配置-企业微信机器人

新增机器人,ID和名称随便填,后续脚本调用时使用

将企业微信机器人的webhook地址填入,保存即可

前期准备工作完毕,下面开始创建流水线

前端项目构建发布

创建一个流水线任务

  • 前面的配置无所谓,贴上我的配置

jenkins-pipeline-config.png

  • 流水线脚本
def lastCommitMessage
def gitUrl = 'git@xxxxxxxx.git'
def branch = 'develop'
def buildScript = 'pnpm build'
def privateKey = 'xxxxxxxxxxxxxx'
def remote = [:]
remote.name = 'xxxxxxxxx'
remote.host = '192.168.1.1'
remote.user = 'root'
remote.allowAnyHosts = true
def distPath = './dist/'
def remotePath = '/usr/share/nginx/html/xxx/'

pipeline {
    agent any

    stages {
        stage('拉取代码') {
            steps {
                git branch: branch, credentialsId: privateKey, url: gitUrl
            }
        }
        stage('获取最后一次提交的消息') {
            steps {            
                script {
                    lastCommitMessage = sh(returnStdout: true, script: 'git log -1 --pretty=%B').trim()
                    echo "Last Commit Message: ${lastCommitMessage}"
                }
            }
        }
        stage('安装依赖') {
            steps {
                nodejs('node18') {
                    sh 'pnpm i -r --no-frozen-lockfile'
                }
            }
        }
        stage('构建') {
            steps {
                nodejs('node18') {
                    sh buildScript
                }
                dir(distPath) {
                    echo pwd()
                    zip defaultExcludes: false, dir: '', exclude: '', glob: '', zipFile: 'dist.zip'
                }
            }
        }
        stage('上传到服务器') {
            steps {
                withCredentials([sshUserPrivateKey(credentialsId: privateKey, keyFileVariable: 'identity')]) {
                    script {
                        remote.identityFile = identity
                        sshCommand remote: remote, command: "rm -rf ${remotePath}*"
                        dir(distPath) {
                            sshPut remote: remote, from: 'dist.zip', into: remotePath
                        }
                        sshCommand remote: remote, command: "cd ${remotePath} && unzip dist.zip && rm dist.zip"
                    }
                }
                
            }
        }
        
    }
    post {
        success {
            wxwork(
                robot: 'CODING',
                type: 'markdown',
                text: [
                    "# [**${JOB_NAME}**](${JOB_URL})",
                    "> 发布结果:<font color='info'>**成功**</font>",
                    "> 构建时长:<font color='comment'>**${currentBuild.durationString}**</font>",
                    "> 本地更新:${lastCommitMessage}",
                    "> 构建ID:[${BUILD_DISPLAY_NAME}](${BUILD_URL})"
                ]
            )
        }
        failure {
            wxwork(
                robot: 'CODING',
                type: 'markdown',
                text: [
                    "# [**${JOB_NAME}**](${JOB_URL})",
                    "> 发布结果:<font color='warning'>**失败**</font>",
                    "> 构建时长:<font color='comment'>**${currentBuild.durationString}**</font>",
                    "> 本地更新:${lastCommitMessage}",
                    "> 构建ID:[${BUILD_DISPLAY_NAME}](${BUILD_URL})"
                ]
            )
        }
    }
}

JAVA服务构建发布

  • 流水线脚本
def lastCommitMessage
def gitUrl = 'git@xxxxx.git'
def branch = 'develop'
def privateKey = 'xxxxxxxxxxxxxx'
def remote = [:]
remote.name = 'xxxxxxxxxxxxxx'
remote.host = '192.168.1.1'
remote.user = 'root'
remote.allowAnyHosts = true
def packageName = 'platform-2.0'
def localPackagePath = './xxxxxx/target/'
def remotePackagePath = "/xxxxxx/"

pipeline {
    agent any

    stages {
        stage('拉取代码') {
            steps {
                git branch: branch, credentialsId: privateKey, url: gitUrl
            }
        }
        stage('获取最后一次提交的消息') {
            steps {            
                script {
                    lastCommitMessage = sh(returnStdout: true, script: 'git log -1 --pretty=%B').trim()
                    echo "Last Commit Message: ${lastCommitMessage}"
                }
            }
        }
        stage('构建') {
            steps {
                withMaven(globalMavenSettingsConfig: '', jdk: 'JDK11', maven: 'mvn3.8.6') {
                    sh 'mvn clean install -Dmaven.test.skip=true'
                }
            }
        }
        stage('上传到服务器') {
            steps {
                withCredentials([sshUserPrivateKey(credentialsId: privateKey, keyFileVariable: 'identity')]) {
                    script {
                        remote.identityFile = identity
                        sshCommand remote: remote, command: "rm -rf ${remotePackagePath}${packageName}.jar"
                        dir(localPackagePath) {
                            sshPut remote: remote, from: "${packageName}.jar", into: "${remotePackagePath}"
                        }
                        sshCommand remote: remote, command: "${remotePackagePath}app.sh restart"
                    }
                }
                
            }
        }
        
    }
    post {
        success {
            wxwork(
                robot: 'CODING',
                type: 'markdown',
                text: [
                    "# [**${JOB_NAME}**](${JOB_URL})",
                    "> 发布结果:<font color='info'>**成功**</font>",
                    "> 构建时长:<font color='comment'>**${currentBuild.durationString}**</font>",
                    "> 本地更新:${lastCommitMessage}",
                    "> 构建ID:[${BUILD_DISPLAY_NAME}](${BUILD_URL})"
                ]
            )
        }
        failure {
            wxwork(
                robot: 'CODING',
                type: 'markdown',
                text: [
                    "# [**${JOB_NAME}**](${JOB_URL})",
                    "> 发布结果:<font color='warning'>**失败**</font>",
                    "> 构建时长:<font color='comment'>**${currentBuild.durationString}**</font>",
                    "> 本地更新:${lastCommitMessage}",
                    "> 构建ID:[${BUILD_DISPLAY_NAME}](${BUILD_URL})"
                ]
            )
        }
    }
}

编译过程中,出现了open too many files问题,需要修改ulimit,设置最大打开文件数量

* soft nofile 65536
* hard nofile 65536

docker

ulimits:
  nofile:
      soft: 65536
      hard: 65536

结束