Jenkins-打包应用程序

2021-08-20  本文已影响0人  野生DBNull

0.Jenkins构建产物的几种方式

1.使用Pipeline脚本去构建
这种方式的好处就是可以使用Groovy脚本去写,自由度很高,使用多少节点,使用什么容器,使用什么规则,只要是Groovy支持的基本都能写,这也是Jenkins2.0的主要构建方式。这种方式适用于插件用的多,构建Node多,构建环境复杂,构建流程复杂的团队。推荐使用~

2.使用FreeStyle方式去构建
这种方式的好处的自由,想怎么写怎么写,想用什么打包就用什么打包,想写什么脚本就写什么脚本。这种方式的对于Shell和NodeJs写的好的人来说简直就是神器,但是使用插件就没得Pipeline那么舒心了。适合插件用的少的,Shell写的牛逼的团队、初学者、项目构建不复杂的团队。但是项目不复杂用Pipeline会更加的顺滑。

接下来我全部使用Pipeline作为例子来进行讲解,其中会将构建产物上传至Jforg,有兴趣的小伙伴可以移步
安装并配置Jfrog-Artifactory

1.使用Jenkins构建Dotnet包

stage('Init Environment'){
    script {
        env.p_ns = 'namespace' // 命名空间 
        env.p_fullname = 'Data' // 项目名称
        env.p_name = 'data' // 项目名称
        env.c_type = '7z' // 压缩方式
        env.artifactory = 'http://jfrog.xxx.top/artifactory' // 产物仓库地址
        env.git_branch = 'devlop'  // 所用分支
        env.git_addr = 'http://git.xxx.com/project.git'  // Git地址
        
        if (!env.app_version) {
            env.app_version = "auto_version_${env.BUILD_NUMBER}" 
        }
            
        echo "${env.p_name}"
        echo "${env.p_ns}"
    }
}

node('k8s-agent-dotnet'){
    stage('Clone'){
        checkout([$class: 'GitSCM', branches: [[name: "origin/${env.git_branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'git-user-id', url: "${env.git_addr}"]]])
    }
    
    dir("01.src/services/${env.p_name}/Eimp.${env.p_fullname}.HttpApi.Host"){
        stage('Build Project Test'){
            container('dotnet5'){
                sh 'dotnet --info'
                // jnlp镜像的用户是Jenkins,dotnet镜像的用户是root,所以有下面的这一句
                // 没有777的权限,jenkins用户就没办法操作这个root用户新建的文件夹
                sh 'rm -rf ./publish && mkdir publish && chmod -R 777 publish'
                // sh "dotnet restore ./Eimp.${env.p_fullname}.HttpApi.Host.csproj --configfile ./Scripts/Nuget/nuget.config"
                sh "dotnet publish ./Eimp.${env.p_fullname}.HttpApi.Host.csproj -c Release -o  ./publish --configfile ./Scripts/Nuget/nuget.config"
                sh 'cp -r ./Scripts/Docker/Dockerfile ./publish/'
            }
            
            dir('publish'){
                sh "7z a -t${env.c_type} ${env.p_name}.${env.c_type} ./"
            }   
        }
    
        stage('Upload PKG'){
            withCredentials([usernamePassword(credentialsId: 'jfrog_robot', passwordVariable: 'password', usernameVariable: 'username')]) {
                sh "curl -u ${username}:${password} -T ./publish/${env.p_name}.${env.c_type} ${env.artifactory}/${env.p_ns}/${env.app_version}/${env.p_name}_${env.app_version}.${env.c_type}"
            }
        }   
        
    }
}

node('docker-agent'){
    stage('Clear Workspace'){
        sh 'rm -rf ./*'
    }

   // 将产物下载到Docker构建专用Node上
    stage('Download PKG'){
        withCredentials([usernamePassword(credentialsId: 'jfrog_robot', passwordVariable: 'password', usernameVariable: 'username')]) {
            sh "curl -u ${username}:${password} ${env.artifactory}/${env.p_ns}/${env.app_version}/${env.p_name}_${env.app_version}.${env.c_type} -o ./${env.p_name}.${env.c_type}"
        }

        sh "7za x ./${env.p_name}.${env.c_type} -r -o./"
        sh "rm -rf ./${env.p_name}.${env.c_type}"
    }
    // 构建镜像
    stage('Build And Push Docker Image'){
        docker.withRegistry('https://docker-factory.xxx.top', 'harbor_push_robot') {
            def docker_img = docker.build("${env.p_ns}/${env.p_name}:${env.app_version}");
            docker_img.push()
        }
    }
    
    // 执行一段NodeJs通知Rancher平台更新最新的Images
    stage('Update Project In Rancher'){
        script{
            if(env.need_startup){
                nodejs('NodeJs 15.5.0') {
                   
                    withCredentials([usernamePassword(credentialsId: 'rancher', passwordVariable: 'password', usernameVariable: 'username')]) {
                        sh "node /home/jenkins/tools/rancher/publish.js /project/c-gwjgg:p-h485k/workloads/deployment:xxxx:${env.p_name} ${env.app_version} ${password} ${username}"
                    }
                }
            }
            else{
                echo "No startup required"
            }
        }
    }
    // 利用sshPublisher插件发布到服务器,这里不能拿来就用啊,这里是我从别的项目复制过来的
    // 需要修改一下才能正常使用的
    stage('Publish To Server') {
            script {
                def servers = env.pub_servers.tokenize(',')
                if(servers.size() > 0){
                    def server_params = []
                    for(server in servers) {
                        server_params.add(
                            sshPublisherDesc(
                                configName: server,
                                transfers: [
                                    sshTransfer(
                                        cleanRemote: false,
                                        excludes: '',
                                        execCommand: "sh ./scripts/update_service_v2.sh ${env.p_name} ${env.c_type}",
                                        execTimeout: 120000,
                                        flatten: false,
                                        makeEmptyDirs: true,
                                        noDefaultExcludes: false,
                                        patternSeparator: '[, ]+',
                                        remoteDirectory: 'pkgs',
                                        remoteDirectorySDF: false,
                                        removePrefix: 'publish',
                                        sourceFiles: "publish/${env.p_name}.${env.c_type}"
                                    )
                                ], 
                                usePromotionTimestamp: false,
                                useWorkspaceInPromotion: false,
                                verbose: true
                            )
                        )
                    }
                    sshPublisher(publishers: server_params)
                }
                else{
                    echo 'Not Choose Server'
                }
            }
        }
}


2.使用Jenkins构建Node/Web包

stage('Init Environment'){
    script {
        env.p_ns = 'namespace' // 命名空间 
        env.p_name = 'web-client' // 项目名称
        env.c_type = '7z' // 压缩方式
        env.artifactory = 'http://jfrog.xxxx.top/artifactory'
        env.git_branch = 'devlop'  // 所用分支
        env.git_addr = 'http://git.xxx.com/project.git'  // Git地址
        
        if (!env.app_version) {
            env.app_version = "auto_version_${env.BUILD_NUMBER}" 
        }
            
        echo "${env.p_name}"
        echo "${env.p_ns}"
    }
}
// 为了复用节点,这里随意选择带有jnlp的节点就行了,因为大部分操作都只基于NodeJs这个插件
node('k8s-agent || k8s-agent-dotnet'){
    
    stage('Clone'){
        checkout([$class: 'GitSCM', branches: [[name: "origin/${env.git_branch}"]], extensions: [], userRemoteConfigs: [[credentialsId: 'dbadff90-a2c7-4d03-8e48-808118abcaf5', url: "${env.git_addr}"]]])
    }
    
    stage('Build Project'){
        sh 'rm -rf ./build'
                        
        nodejs('NodeJs 15.5.0') {
            sh 'yarn'
            sh "yarn build"
        }
                    
            
        sh 'cp -r ./nginx ./build/'        
        sh 'cp -r ./Dockerfile ./build/'
            
        dir('build'){
            sh "7z a -t${env.c_type} ${env.p_name}.${env.c_type} ./"
        }
    }
    
    stage('Upload PKG'){
        
        withCredentials([usernamePassword(credentialsId: 'jfrog_robot', passwordVariable: 'password', usernameVariable: 'username')]) {
            sh "curl -u ${username}:${password} -T ./build/${env.p_name}.${env.c_type} ${env.artifactory}/${env.p_ns}/${env.app_version}/${env.p_name}_${env.app_version}.${env.c_type}"
        }
    }
    
}

node('docker-agent'){

    stage('Clear Workspace'){
        sh 'rm -rf ./*'
    }

    stage('Download PKG'){
        withCredentials([usernamePassword(credentialsId: 'jfrog_robot', passwordVariable: 'password', usernameVariable: 'username')]) {
            sh "curl -u ${username}:${password} ${env.artifactory}/${env.p_ns}/${env.app_version}/${env.p_name}_${env.app_version}.${env.c_type} -o ./${env.p_name}.${env.c_type}"
        }


        sh "7za x ./${env.p_name}.${env.c_type} -r -o./build"
        sh 'mv ./build/nginx ./'
        sh 'mv ./build/Dockerfile ./'
    }

    stage('Build And Push Docker Image'){
        docker.withRegistry('https://docker-factory.xxx.top', 'harbor_push_robot') {
            def docker_img = docker.build("${env.p_ns}/${env.p_name}:${env.app_version}");
            docker_img.push()
        }
    }
    
    stage('Update Project In Rancher'){
        script{
            if(env.need_startup){
                nodejs('NodeJs 15.5.0') {
                    
                    withCredentials([usernamePassword(credentialsId: 'rancher', passwordVariable: 'password', usernameVariable: 'username')]) {
                        sh "node /home/jenkins/tools/rancher/publish.js /project/c-gwjgg:p-h485k/workloads/deployment:xxxx:${env.p_name} ${env.app_version} ${password} ${username}"
                    }
                }
            }
            else{
                echo "No startup required"
            }
        }
    }

    // 利用sshPublisher插件发布到服务器,这里不能拿来就用啊,这里是我从别的项目复制过来的
    // 需要修改一下才能正常使用的
    stage('Publish To Server') {
            script {
                def servers = env.pub_servers.tokenize(',')
                if(servers.size() > 0){
                    def server_params = []
                    for(server in servers) {
                        server_params.add(
                            sshPublisherDesc(
                                configName: server,
                                transfers: [
                                    sshTransfer(
                                        cleanRemote: false,
                                        excludes: '',
                                        execCommand: "sh ./scripts/update_service_v2.sh ${env.p_name} ${env.c_type}",
                                        execTimeout: 120000,
                                        flatten: false,
                                        makeEmptyDirs: true,
                                        noDefaultExcludes: false,
                                        patternSeparator: '[, ]+',
                                        remoteDirectory: 'pkgs',
                                        remoteDirectorySDF: false,
                                        removePrefix: 'publish',
                                        sourceFiles: "publish/${env.p_name}.${env.c_type}"
                                    )
                                ], 
                                usePromotionTimestamp: false,
                                useWorkspaceInPromotion: false,
                                verbose: true
                            )
                        )
                    }
                    sshPublisher(publishers: server_params)
                }
                else{
                    echo 'Not Choose Server'
                }
            }
        }
}


3. 注意

所有需要用到环境变量的地方都要用双引号"",不然就会被当做字符串使用
sshPublisher插件的execCommand参数值只能执行服务器~/这个路径下面的脚本

4. 贴一下update_service_v2.sh 的脚本

#!/bin/bash

m_p="/apps" # 主路径
service=$1       # 服务名称
pkg_type=$2   # 压缩包类型

if [ ! -n "$pkg_type" ]; then
  pkg_type='zip';
fi

update_services() {
    # 进入执行主目录
    cd "${m_p}"

    if [ ! -f "./pkgs/${service}.${pkg_type}" ]; then
        echo "压缩包不存在,请确认压缩包存在后再试"
        exit 1
    fi

    # 检测运行目录是否存在
    if [ ! -d "./apps/${service}" ]; then
        mkdir "./apps/${service}"
    else
        if [ ${service} != "web_client" ] && [ ${service} != "app_client" ]; then # 前端比较特殊无需用supervisor守护
            # supervisorctl status "$service" | awk '{print $2}'
            # echo $?
            if [ $(supervisorctl status "$service" | awk '{print $2}') = "RUNNING" ]; then # 当处于运行状态下的情况下才进行停止操作
                supervisorctl stop "$service"; #--rt2
            fi
        fi

        rm -rf "./apps/${service}/*"
    fi

    if [ ${pkg_type} == "zip" ]; then
        unzip -oq "./pkgs/${service}.${pkg_type}" -d "./apps/${service}"
    else
        7za x -y t${pkg_type} "./pkgs/${service}.${pkg_type}" -r -o./apps/${service}
    fi
    

    if [ -d "./configs/${service}" ]; then
        for c_name in $(ls ./configs/${service}/); do
            rm -rf "./apps/${service}/$c_name"
            cp -r "./configs/${service}/$c_name" "./apps/${service}"
        done
    fi

    if [ ${service} != "web_client" ] && [ ${service} != "app_client" ]; then # 前端比较特殊无需用supervisor守护
        # 检测日志存储目录是否存在
        if [ ! -d "./app_logs/${service}" ]; then
            mkdir "./app_logs/${service}"
        fi

        supervisorctl start "$service"
    fi

}

update_services

我要的是实现思路吗?我要的是Ctrl+C,Ctrl+V就能用的脚本
拿来吧你~

上一篇 下一篇

猜你喜欢

热点阅读