美文网首页
Jenkins-打包应用程序

Jenkins-打包应用程序

作者: 野生DBNull | 来源:发表于2021-08-20 14:28 被阅读0次

    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就能用的脚本
    拿来吧你~

    相关文章

      网友评论

          本文标题:Jenkins-打包应用程序

          本文链接:https://www.haomeiwen.com/subject/xbebpltx.html