• 【CI/CD1】jenkins,actions,daocloud


    文章目录


    1.jenkins:构建/测试/部署就是CICD工具即jenkins,但jenkins需要个人提供一台运行jenkins的机器

    在这里插入图片描述
    官网https://www.jenkins.io/下载jenkins,可选择适合你自己系统的版本,也可选择不依赖于系统的docker(前提本机安装了docker)或war包(本机安装了java),如下开启服务端。
    在这里插入图片描述
    执行如上命令出现如下密码,复制这串密码,浏览器打开http://localhost:8080,粘贴到管理员密码里。点击安装推荐插件,创建管理员用户yu,密码123,到这里jenkins已经安装完成了(装在win上),主要用来配合git服务器。
    在这里插入图片描述
    Manage Jenkins中选择Global Tool Configuration添加git路径如下。
    在这里插入图片描述
    Create a job,选择Freestyle project,命名为newjob,点击配置。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    如上如果选择execute shell会出现系统找不到指定文件报错。liunx 下使用execute shell,并加上#!/bin/bash,cat ./README.md。这里的脚本可以做的事很多,比如构建项目,做代码测试等。如下点击控制台输出,可查看fetch拉取github代码并执行cat ./README.md脚本。
    在这里插入图片描述
    jenkins轮询github,有更新就pull下来,然后执行输入的构建脚本。
    在这里插入图片描述
    在这里插入图片描述

    2.GitLab-Jenkins集成:Jenkins镜像像nginx一样

    2.1 Jenkins-docker配置(服务端):运行在8080端口上,机器只要安装docker就能装载image,运行容器

    在指定服务器上安装docker客户端,使用docker命令进行下载jenkins-docker版本如下:

    docker pull jenkins/jenkins:2.54
    
    • 1

    运行jenkins-docker images,进入对应container,并相应安装vim、docker、gcc/g++、make、cppcheck等调试、编译环境,运行jenkins-docker命令如下:-name指定image名字。-p内部container和外部对应关系。-v外部地址和container内部地址对应关系,在container内部修改jenkins的话,外部也会更新。/etc/localtime时间同步。

    docker run --privileged=true -d --name jenkins -p 8080:8080 -v /var/run/docker.sock:/var/run/docker.sock -v /home/ju/jenkins_home:/var/jenkins_home/ -v /etc/localtime:/etc/localtime jenkins/jenkins:v4
    
    • 1

    进入docker container内部命令如下:

    docker exec -u 0 -it jenkins bash
    
    • 1

    在这里插入图片描述
    在这里插入图片描述
    保存docker images为tar包命令如下,-o(output):

    docker save –o jenkins_v4.tar jenkins/jenkins:v4
    
    • 1

    加载tar包为docker images命令如下,和上面相反:

    docker load -input jenkins_v4.tar
    
    • 1

    2.2 Jenkins与GitLab配置(客户端):docker ps查看正在运行,浏览器访问http://10…:8080/

    GitLab与Jenkins Access Token配置

    GitLab配置Access Token,用于jenkins连接GitLab获取GitLab API接口,GitLab页面->用户->Settings->Access Tokens。

    生成GitLab个人准入秘钥,设置Name,Expires at默认不填永久有效,Scopes全部勾选后,点击Create personal access token,生成后,页面上会提示"Your new personal access token has been created"。

    Jenkins配置GitLab,在jenkins界面点击Manage Jenkins->Configure System:
    在这里插入图片描述
    Jenkins配置界面查找GitLab,添加connect name与Gitlab host URL:
    在这里插入图片描述
    添加Credentials,点击Add->jenkins,进行添加对应的秘钥,Kind选择GitLab API Token,API Token添加GitLab personal api token,ID添加为jenkins_gitlab后,点击Add。
    在这里插入图片描述
    选择Credentials为GitLab API token,点击Test Connection,验证jenkins与GitLab是否建立连接,显示为”Success”。
    在这里插入图片描述

    新建jenkins job和配置job

    在jenkins主界面点击New Item,可新建job或者复制已有job,此处直接复制已有job,拷贝后的job不要运行build,避免回填错误数据到GitLab。
    在这里插入图片描述
    项目名为example的Jenkins pipeline script同下面导入的,可自行修改。
    在这里插入图片描述
    选择对应job后点击Configure进行job配置,在job配置界面查到Build Triggers,进行配置job触发条件,勾选“Build when a change is pushed to GitLab. GitLab webhook URL: http://10.75.92.229:8080/project/sw61_bsp_build”,勾选状态如下图。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    Jenkins pipeline script配置

    1)	环境模块导入, groovy语言
    import hudson.*
    
    2)	清空工作空间
    node(""){
        stage("clear workspace"){
            cleanWs()
        }
    }
    
    3)	下载源码
    node(""){
        stage("download code"){
            echo "download code"
            if (env.gitlabSourceBranch == null){   //当gitlab过来触发的job的话,环境变量上就会有gitlabSourceBranch字串
                git branch: "sw61", credentialsId: '18f53bc3-dc50-4178-acde-d628264ee453', url: 'https://gitlab-dbd...com/bsp_diag/prj_bsp.git'   // null说明不是gitlab触发
            }else{  //gitlab做了push或merge操作时触发,credentialsId就是Access Tokens
                git branch: env.gitlabSourceBranch, credentialsId: '18f53bc3-dc50-4178-acde-d628264ee453', url: env.gitlabSourceRepoHttpUrl
            }
        }
    }
    
    4)	源码cppcheck扫描
    try{
        node(""){
            stage("cppcheck"){
                echo "cppcheck starting"
                pwd()
                sh "/home/cppcheck-1.75/cppcheck 4 --enable=all --inconclusive  --xml --xml-version=2 "+env.WORKSPACE+" 2> cppcheck.xml"
                publishCppcheck ignoreBlankFiles: true, pattern: 'cppcheck.xml'
                def cppcheck_file_obj = new File(env.WORKSPACE+"/cppcheck.xml")
                if (cppcheck_file_obj.isFile()){
                    echo "cppcheck.xml file exist"
                    result = sh returnStdout: true ,script: "cat "+env.WORKSPACE+"/cppcheck.xml"
                    if (result == ""){
                        echo "analyse cppcheck.xml failure,cppcheck.xml is empty"
                        currentBuild.result="FAILURE"
                    }else{
                        echo "analyse cppcheck.xml"
                        cppcheck_result = sh returnStdout: true ,script: "cat "+env.WORKSPACE+"/cppcheck.xml | grep 'cppcheck version'"
                        if(cppcheck_result == ""){
                            echo "analyse cppcheck.xml failure,cppcheck.xml format error"
                            currentBuild.result="FAILURE"
                        }else{
                            final_result = sh returnStdout: true ,script: '''cat '''+env.WORKSPACE+'''/cppcheck.xml | grep severity=\\"error\\"'''
                            if(final_result == ""){
                                echo "analyse cppcheck.xml pass"
                            }else{
                                echo "analyse cppcheck.xml failure,cppcheck.xml has error"
                                currentBuild.result="FAILURE"
                            }
                        }
                        
                    }
                }else{
                    echo "cppcheck.xml file not exist"
                    currentBuild.result="FAILURE"
                }
            }
        }
    }catch(e) {
        echo "cppcheck failure"
        currentBuild.result="FAILURE"
    }
    
    5)	源码编译
    try{
        node(""){
            stage("compile code"){
                echo "compile code"
                sh "make"   //在docker里编译
            }
        }
    }catch(e) {
        echo "compile code failure"
        currentBuild.result="FAILURE"
    }
    
    6)	验证扫描与编译结果,成功后归档相关文件
    node(""){
        stage("archive"){
            echo "archive"
            if(currentBuild.result == 'FAILURE') {
                echo "Something unexpected happened. Please inspect Jenkins logs. Skip archive."
            }else{
                sh '''
                mkdir build
                cp cppcheck.xml build/
                cp *.ko build/
                tar -zcf archive.tar.gz build/
                '''
                archiveArtifacts artifacts: '*.tar.gz', followSymlinks: false
            }
        }
    }
    
    7)	根据扫描和编译结果,回填数据到GitLab
    stage("commit gitlab"){
        echo "commit gitlab"
        if(currentBuild.result == 'FAILURE') {
            updateGitlabCommitStatus(name: 'sw61_bsp_build', state: 'failed')
        }else{
            updateGitlabCommitStatus(name: 'sw61_bsp_build', state: 'success')
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105

    Jenkins&GitLab集成环境验证

    GitLab推送修改至仓库新分支,验证push event可触发jenkins job,jenkins回填数据至GitLab。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    3.github的actions:替代了travis,完成github上的cicd的操作

    如下点击Actions按钮后选择自定义流程。
    在这里插入图片描述
    如上点击后产生如下main.yml文件。
    在这里插入图片描述
    如上点击提交代码后,Actions其实正在运行了。
    在这里插入图片描述
    如下是.yml文件怎么写?三类:name,on(触发时机),jobs(具体任务)。
    在这里插入图片描述
    name:流程命名为,会显示在图像化界面上。
    on:[push] push代码时会触发。如下是src下文件发生改动的主分支下提交的代码才会触发当前的流程。
    在这里插入图片描述
    如下是每15分钟执行一次当前流程,有schedule(固定时间触发)就不能写push事件了。
    在这里插入图片描述
    具体触发的任务在jobs下,job1是命名,job2执行前必须是要job1执行完成。
    在这里插入图片描述
    runs-on是枚举类型,必须写如下8种。
    在这里插入图片描述
    steps:- (数组):git clone xxx 这样麻烦,如下uses中actions是github上有一官方用户叫actions,有一个仓库叫checkout,这仓库里面流程就是把代码下载下来【uses参数后面写另一个代码仓库,run参数后面写shell指令】。actions/setup-node@v1配置ubuntu-latest会安装好nodejs,这样下面npm就可用了。
    在这里插入图片描述
    在这里插入图片描述

    3.1 uses:后面可接其他仓库,还可接docker: //alpine: 3.8,注意只是在ubuntu下docker run一镜像,并不是下面的run在容器里运行

    timeout-minutes默认30分钟超时时间,指定超时时间如1分钟,1分钟内没有执行完会强制结束。如下指定3个版本的nodejs分别去测试。
    在这里插入图片描述
    在这里插入图片描述
    如下是自己写的main.yml文件并执行。
    在这里插入图片描述

    3.2 container:指定node8这个容器container下,显示8.x,不是ubuntu的node10.x版本

    在这里插入图片描述

    3.3 services:可指定基于nginx镜像的服务,点击Actions查看流程

    在这里插入图片描述
    如下nginx容器在当前ubuntu-latest环境下启动起来了。
    在这里插入图片描述

    3.4 Secrets:执行流程中有涉及到一些密码或敏感信息时,可在github中Settings中添加Secrets

    在这里插入图片描述
    在这里插入图片描述
    开源项目的actions日志可以被看到,所以如下日志打印*,但变量已经写进去了,比如登录其他网站用到密码时候,在这个脚本中其实是可用的。
    在这里插入图片描述

    4.生成springboot项目并上传github:https://start.spring.io/

    在这里插入图片描述
    如上项目生成压缩包,剪切到桌面进行解压,并用idea打开,并点击idea中提示的Enable Auto-import。如下DaocloudApplication.java和DaocloudApplicationTests.java是默认有的,MyController.java和MySrc.java是自己添加的。
    在这里插入图片描述

    //MySvc.java
    package com.example.daocloud;
    import org.springframework.stereotype.Service;
    
    @Service
    public class MySvc {
        public int add(int a,int b){
            return a+b;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    //MyController.java
    package com.example.daocloud;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    @Controller
    @ResponseBody
    public class MyController {
        @Autowired
        MySvc mySvc;
        
        @GetMapping("/")
        public String index(){
            return "hello spring boot";   //首页
        }
        
        @GetMapping("/add")
        public String add(int a, int b ){
            return mySvc.add(a,b)+"";  //最后加双引号是将数字变为字符串
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述
    如上运行后,浏览器输入如下。
    在这里插入图片描述
    如下添加测试接口在test文件夹下,本机控制台mvn test。

    package com.example.daocloud;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class DaocloudApplicationTests {
    	@Autowired
    	MySvc mySvc;  // 对服务进行测试,只要测试mySvc
    	
    	@Test
    	public void addTest() {  // 测试用例,点击这行的开始播放按钮
    		int res = mySvc.add(772,119);
    		assert  res == 891;   // 892测试不通过,控制台报红
    	}
    	
    	@Test
    	public void addTest2() {
    		int res = mySvc.add(556,119);
    		assert  res == 675;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在GitHub上创建空的名为daocloud的仓库。如下push时出现Permission时将origin用的ssh换成https。
    在这里插入图片描述

    5.daocloud关联github:https://www.daocloud.io/,用关联github登录注册。创建项目,关联github上的项目,点击开始创建后就进入cicd的配置流程,点击前往流程定义

    在这里插入图片描述

    5.1 测试:cicd的配置流程即点击如下测试任务,里面写mvn test。这个测试阶段不通过,不会到构建阶段,构建阶段主要目的是想要将项目生成docker镜像以便于后面的部署

    在这里插入图片描述
    mvn test这个测试任务是在云端自动帮我们完成,云端并没有安装maven,云端是基于docker镜像的,改为如下。
    在这里插入图片描述

    5.2 构建:点击默认构建任务,在项目中直接创建Dockerfile文件即本地创建Dockerfile

    // Dockerfile
    FROM maven:3 AS bd
    WORKDIR /code
    COPY ./ /code
    RUN mvn package -Dmaven.test.skip=true   //会跳过测试,在target文件夹下生成jar包
    // 如上利用maven3环境对代码进行打包
    // 如下将这个jar包拷贝到java8镜像的根目录下并重命名为app.jar
    FROM java:8   
    COPY --from=bd /code/target/*.jar /app.jar
    CMD java -jar /app.jar   // CMD是启动指令
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在idea控制台中重新add,commit,push添加Dockerfile文件到github(上面3中项目)。再回到如下构建任务页面,点击保存,Dockerfile就是在项目根目录下。
    在这里插入图片描述
    如下返回流程定义页面,点击如下手动触发。
    在这里插入图片描述
    如下可以点进去查看日志。
    在这里插入图片描述
    如下先将github项目代码git clone拷贝到云端的一台机器上,加载了自己.yml默认配置文件,拉取了在测试时配置好的maven3镜像,真正运行配置了mvn test(下载了springboot依赖,时间长)。
    在这里插入图片描述
    如上测试阶段,如下构建阶段,docker build里就是上面Dockerfile内容,镜像构建完后,需要上传到daocloud的官方仓库上。
    在这里插入图片描述

    5.3 docker pull:设为公开,docker pull就不用进行登录

    在这里插入图片描述
    如下就可将镜像部署到自己机器上了。
    在这里插入图片描述
    如下解决上面的不自动化,点击导入主机,添加新主机。
    在这里插入图片描述
    如下用crt连接win上装的虚拟机(需安装docker),输入下面脚本。
    在这里插入图片描述
    如上点击查看主机出现如下。
    在这里插入图片描述

    5.4 发布:前面全是CI,这里CD

    如下在流程定义中添加发布阶段。
    在这里插入图片描述
    在这里插入图片描述

    创建应用:应用就是将镜像部署到自由主机上

    点击左侧的应用 - 创建应用 - 部署最新版本,如下ubuntu就是虚拟机。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    如下创建子网穿透,可让互联网访问到。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    回到项目添加发布:自由主机就是集群管理中的虚拟机

    在这里插入图片描述
    修改了idea中代码并重新add,commit,push,通过提交代码方式重新触发了流程。
    在这里插入图片描述
    在集群管理中点击管理主机,可看见有容器(刚才被发布的)正在运行。
    在这里插入图片描述
    如下还要在应用中删除32768旧隧道,并新建32769新隧道。
    在这里插入图片描述
    执行CI:添加依赖,代码测试,将代码打包入docker并重新构建镜像。执行CD:生产机监听DaoCloud变化,拉取镜像并构建容器。

  • 相关阅读:
    SLAM从入门到精通(安全避障)
    七,vi和vim
    Lambda 表达式
    Django和jQuery,实现Ajax表格数据分页展示
    SpringBoot_快速入门
    Java的多态
    【前端源码解析】数据响应式原理
    【754. 到达终点数字】
    通信算法之189: 信道检测- MRC
    Redis篇(5)——持久化
  • 原文地址:https://blog.csdn.net/weixin_43435675/article/details/88137709