React/Vue 等前端应用通过jenkins 自动打包升级全流程演示(一万多字有点长)

2022-05-06 17:15:34 浏览数 (1)

开发环境目前前端团队自己管理,发版项目越来越多且频繁,决定自己搞一套jinkens 自动打包部署,网上搜了搜,都过老或者不可用,研究了三天终于完成了,写下分享给各位。

文章目录

  • 前言
  • 一、Docker 安装 Jinkens
    • 1.系统要求
    • 2. 安装
      • 2.1 下载 镜像
      • 2.2 docker 容器运行镜像
    • 3. Jinkens 初始化
  • 二、构建前端插件安装
  • 三、使用pipeline 构建项目
    • 1、新建任务
    • 2、gitlab 触发器
      • 2.1 配置gitlab 插件
      • 2.2 选择触发器
        • 2.2.1 切换到构建触发器选择:
    • 3、构建项目pipeline 配置
    • 4、前端构建Jinkensfile 脚本
      • 4.1 node 环境
      • 4.2 依赖安装和构建
      • 4.3 部署
        • 4.3.1 ssh 连接服务器
        • 4.3.2 ngnix 发布shell 脚本
  • 四、通知
    • 1. 测试发送邮箱
    • 2. 配置 Extended E-mail Notification
    • 3. pipeline 发送邮箱脚本
  • 全部Jenkinsfile 配置

前言

本文涉及一下内容:

  • 在Linux 上使用Docker 部署Jenkins
  • Jenkins初始化以及常用插件安装
  • 使用pipeline 构建前端项目
  • 添加gitlab触发器,提交代码合并请求时自动触发构建
  • Jenkins 所在Docker容器Node 环境安装
  • 前端项目安装构建
  • 通过ssh 将前端项目发布到服务器
  • ngnix 部署
  • 发布完成邮件通知

安装系统:linux Docker版本:Docker version 19.03.5, build 633a0ea

一、Docker 安装 Jinkens

Docker 安装Jinkens 十分便利,注意的是对硬件要求较高。Docker就不赘述了,不明白的可以看看之前写过的一篇文章。

1.系统要求

最低推荐配置:

  • 256MB可用内存
  • 1GB可用磁盘空间(作为一个Docker容器运行jenkins的话推荐10GB)

为小团队推荐的硬件配置:

  • 1GB 可用内存
  • 50 GB 可用磁盘空间

注意:

最初在linux 上安装的分盘空间较小,安装插件的时候会遇到各种错误,重新安装位置比较麻烦

2. 安装

Docker镜像选择:

  • jenkinsci/blueocean :捆绑了所有Blue Ocean插件和功能
  • jenkins/jenkins

推荐jenkinsci/blueocean,这里下载 jenkinsci/blueocean镜像。

2.1 下载 镜像

执行docker -v,确保已安装docker

执行docker pull jenkinsci/blueocean 下载镜像,下载完之后执行docker image ls 确保镜像下载成功。

2.2 docker 容器运行镜像

代码语言:javascript复制
docker run 
  # 第一个主机端口(浏览器访问端口)随便填,第二个容器端口
  -p 9090:8080 
  # 将jenkinsci/blueocean 容器的端口50000 映射到主机上的端口50000。
  -p 50000:50000 
  # 将容器目录映射到本地目录。 :前端是你指定的服务器目录,后边固定
  -v /data/jenkins-data:/var/jenkins_home 
  # 守护进程是必需的
  -v /var/run/docker.sock:/var/run/docker.sock 
  jenkinsci/blueocean

3. Jinkens 初始化

执行docker ps 查看容器是否运行

运行之后即可浏览器访问 (http://服务器地址:9090/):

解锁 Jenkins 页面出现

按照其路径找到initialAdminbPassword文件,vim 访问。 容器jinkens目录已映射到主机,在主机目录找到即可,我映射到了/data/jenkins-data/ 文件夹。

复制密码继续下一步,然后按照推荐一步步安装即可,不多说。

二、构建前端插件安装

除了默认安装插件,我们还需要安装如下插件列表。

可以按照如下操作安装:

安装插件列表:

  • GitLab Plugin :使用gitlab 提交合并动作的触发器,自动构建项目。
  • SSH Pipeline Steps : 在pipeline 使用ssh 操作插件
  • Docker plugin
  • Docker Pipeline
  • NodeJS Plugin

三、使用pipeline 构建项目

1、新建任务

选择新建任务,然后输入名字,选择流水线构建。

2、gitlab 触发器

首先先了解目标,我们期望项目在dev 开发环境push 或者 merge requeset 的时候自动构建。

2.1 配置gitlab 插件

确保下载完gitlab plugin之后,去系统工具下配置gitlab

设置名称、gitlab 部署host 和添加Gitlab API Token。

获取GitLab API token 步骤:

点击头像 -> settings

产生记下即可。

2.2 选择触发器

回到job的配置界面,查看gitlab 连接,选择刚才配置的名称。

2.2.1 切换到构建触发器选择:

勾选gitlab 改变时候构建,选择时间 push 和 允许合并请求的时候构建。

点击高级,因为我只想在开发环境构建dev 分支,所以需要分支过滤。

然后点击生成token 密码,用于gitlab 通知。

回到gitlab ,定位到仓库,选择 Settings -> Integrations,将webhook 和 生成的token 填入配置。 构建器步骤生成的

然后 add 添加webhook , 当以下Trigger 触发webhooks 通知jenkins。

到这里触发器完成,一会在jenkins 配置好仓库可以测试。

3、构建项目pipeline 配置

切换到流水线tab, 选择 Pipeline script from scm 然后输入仓库地址 和 gitlab 账号、密码。

指定分支和脚本路径: 图中设置 Jenkinsfile 即 在项目根目录 Jenkinsfile文件读入执行脚本。

4、前端构建Jinkensfile 脚本

示例项目是一个基于umi的React 项目,目录如下:

重点是Jenkinsfile 位置放到根目录。下面一一介绍pipeline 脚本文件Jenkinsfile构建前端的配置。

4.1 node 环境

构建前端应用需要node 环境,因为在docker容器中不能直接拿到宿主机node 。

这里使用pipeline agent 来指定代理环境。代理环境是docker 运行的node 镜像容器。

代码语言:javascript复制
pipeline {
    agent {
        docker {
            image 'node:16-alpine3.14' 
            args '-p 3000:3000' 
        }
    }
    stages {
        stage('Node') { 
            steps {
               sh 'node -v' 
            }
        }
    }
}

4.2 依赖安装和构建

利用 stages 流程分别执行,依赖安装和打包命令。

代码语言:javascript复制
pipeline {
    agent {
        docker {
            image 'node:16-alpine3.14' 
            args '-p 3000:3000' 
        }
    }
    stages {
        stage('Install') { 
            steps {
               sh 'npm install --registry=https://registry.npm.taobao.org' 
            }
        }
        stage('Build') { 
            steps {
               sh 'npm run build:dev'
            }
        }
    }
}

4.3 部署

执行完打包命令之后,在workspaces 文件夹里项目已经产生了dist 目录,但是现在在docker 容器内部,所以不能直接部署到ngnix。

那么需要借助ssh 连接到ngnix 服务器,将文件夹赋值到ngnix 和 使用 ngnix命令。

4.3.1 ssh 连接服务器

首先确保 SSH Pipeline Steps 插件是否安装。

然后Jenkinsfile 里建立连接脚本:

代码语言:javascript复制
stage('Deploy'){
            steps{
                script{
                    def remote = [:]
                    remote.name = 'feService'
                    remote.host = '服务器ip'
                    remote.user = 'root'
                    remote.password = '服务器密码'
                    remote.allowAnyHosts = true
                    stage('Remote SSH') {
                        sshScript remote: remote, script: "deploy.sh"
                    }
                }
            }
        }
4.3.2 ngnix 发布shell 脚本

连接到服务器这时候只需要,将web app 和 ngnix 配置拷贝到服务器部署。

部署有两种情况需要分别考虑:

  • 第一次发布,配置启动
  • 更新应用

ngnix 配置:

代码语言:javascript复制
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    server {
        listen       端口号需要替换; 
        server_name  localhost;

        location / {
            root   html/项目名称;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;
        }
        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

发布脚本deploy.sh:

代码语言:javascript复制
PRO_NAME="项目名称"
if [! -f "/usr/local/nginx/conf/$PRO_NAME.conf"];then
   echo "第一次需要新建配置文件,nginx 发布"
   mv /data/jenkins-data/workspace/$PRO_NAME/$PRO_NAME.conf /usr/local/nginx/conf
   mv /data/jenkins-data/workspace/$PRO_NAME/dist /usr/local/nginx/html/$PRO_NAME
   /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/$PRO_NAME.conf
else
 echo "更新应用"
   mv /data/jenkins-data/workspace/$PRO_NAME/dist /data/jenkins-data/workspace/$PRO_NAME/$PRO_NAME
   cp -rf /data/jenkins-data/workspace/$PRO_NAME/$PRO_NAME /usr/local/nginx/html
   rm -rf /data/jenkins-data/workspace/$PRO_NAME/$PRO_NAME
fi

这时候全部流程基本完成,但是缺少点啥。

四、通知

构建成功和失败需要通知,这里选择邮件通知,如果公司使用钉钉推荐用钉钉机器人接收。

使用 Email Extension Plugin 插件发送

1. 测试发送邮箱

系统配置中使用jenkins 自带邮件配置功能测试。

我这里使用的是163邮箱,需要去开启smtp。

jenkins 邮箱测试配置

注意: 这里注意如果是新邮箱刚开启smtp 服务,密码不是邮箱密码,是开启smtp产生的token

测试发送:

输入邮箱,测试成功接收即可。

2. 配置 Extended E-mail Notification

将测试的邮箱配置相同的写进来即可,这里有一个 内容模板,如果想发送的漂亮选择html 模板

3. pipeline 发送邮箱脚本

不管成功还是失败都去发送,指定发送模板。

代码语言:javascript复制
 post {
        always {
        emailext (
            subject: ''构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} - ${BUILD_STATUS}'',
            body: '${FILE,path="jenkinsMail.html"}',
            to: 'xxxx@qq.com'        
            )
        }
    }

html 模板:

代码语言:javascript复制
<!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>
            <ht size="2" width="100%" byte="center" /></td>
    </tr>
    <tr>
        <td>

            <ul>
                <li>项目名称&nbsp;:&nbsp; ${PROJECT_NAME}</li>
                <li>构建编号&nbsp;:&nbsp; 第${BUILD_NUMBER}</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}workflow-stage">${PROJECT_URL}workflow-stage</a></li>
                <li>项目&nbsp;:&nbsp;Url&nbsp;:&nbsp;<a href="${PROJECT_URL}">${PROJECT_URL}</a></li>
            </ul>
        </td>
    </tr>
    <tr>

        <td><font color="#0B610B">Changes Since Last
            Successful Build:</font></b>
            <hr size="2" width="100%" byte="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="%p"}
        </td>
    </tr>   
    <tr>
        <td><b><font color="#0B610B">Failed Test Results</font></b>
            <hr size="2" width="100%" byte="center" /></td>
    </tr>
    <tr>
        <td><pre
                style="font-size: 11pt; font-family: Tahoma,Aarial,Helvetica,sans-serif">$FAILED_TESTS</pre>
                <br />
        </td>
    </tr>
    <tr>
        <td><font><font color="#0B610B">构建日志(最后100行):</font></b>
            <hr size="2" width="100%" byte="center" /></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>

到此全部完成,感谢阅读。

全部Jenkinsfile 配置

代码语言:javascript复制
pipeline {
    agent {
        docker {
            image 'node:16-alpine3.14' 
            args '-p 3000:3000' 
        }
    }
    stages {
        stage('Install') { 
            steps {
               sh 'npm install --registry=https://registry.npm.taobao.org' 
            }
        }
        stage('Build') { 
            steps {
               sh 'npm run build:dev'
            }
        }
        stage('Deploy'){
            steps{
                script{
                    def remote = [:]
                    remote.name = 'feService'
                    remote.host = '服务器'
                    remote.user = 'root'
                    remote.password = '密码'
                    remote.allowAnyHosts = true
                    stage('Remote SSH') {
                        sshScript remote: remote, script: "deploy.sh"
                    }
                }
            }
        }
    }
     post {
        always {
        emailext (
            subject: ''构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} - ${BUILD_STATUS}'',
            body: '${FILE,path="jenkinsMail.html"}',
            to: 'xxx@qq.com'        
            )
        }
    }
}

0 人点赞