最近在整毕设,发现上线后每一次的修改应用到线上环境的时候就非常的烦躁,因为它总是重复着机械性的操作:打包->压缩->上传->解压->更新缓存。这种事情往复的操作显得十分没有意义,本着探索的精神,又发现很久没有水博客了,特此记录一下,水一水。

Jenkins

最早我在使用Jenkins的时候还是学校里面的一个校内项目,因为带着几个学弟学妹一起协同操作,索性我就用Github Actions+Jenkins实现了一套CI/CD,用下来也还不错。

但是,当时并没有深入学习Jenkins(其实现在也没有),想着速战速决,直接使用了最简单的命令执行,即直接远程执行Shell实现自动化部署。因为项目没有多分支,所以也久不需要CI的过程。

远程执行Shell并没有那么的优雅,因为包括clone、build都在服务器端运行,这是作为一个处女座所不能忍受的。

所以在这一次使用了更为广泛应用的Pipeline,其可定制化程度也更高,采用Docker作为编译环境,灵活性也更好。

基于Node.js持续部署

在Pipeline中,使用Docker作为编译环境,直接使用NodeJS官方镜像:

  agent {
    docker {
      image 'node:16.13.2'
    }
  }

项目打包

在agent中定义好了打包环境后,在stages中定义对应的每一个步骤。

使用sh执行对应的Shell命令,由于有一定的版本冲突,本项目采用Yarn包管理进行依赖安装。令人惊喜的是NodeJS镜像内置了Yarn包管理。

由于官方源下载太慢,因此在每一次依赖安装前还需要修改到国内源,加快安装速度。

在打包完成后,使用zip命令将产物进行压缩,由于umiJS产物最终打包在dist目录下,故直接指定对应的dir即可。

    stage('yarn env') {
      steps {
        sh '''node -v
yarn -v'''
      }
    }

    stage('yarn install') {
      steps {
        sh 'yarn config set registry https://registry.npm.taobao.org'
        sh 'yarn install'
      }
    }

    stage('build') {
      steps {
        sh 'yarn run build'
      }
    }

    stage('package') {
      steps {
        script {
          zip archive: true, dir: 'dist/', glob: '', zipFile: 'deploy.zip'
        }
      }
    }

部署

在一切准备就绪后,来到了部署环节。

部署即使用SSH远程执行命令,并使用SCP进行文件上传。这里使用的是SSH Agent插件,直接定义好全局凭证ID即可自动登入SSH(使用的是私钥免密登入)。

对于本前端项目部署而言,并无复杂的环境配置,仅为一些静态文件,直接上传到Web服务器对应的文件目录即可。

但是,由于每次打包后的文件并不一定文件名相同,直接替换文件可能导致后续服务器存储空间浪费,因此,还需要在每次解压部署前删除掉旧的版本。

这里踩了很久的坑,因为Nginx的配置文件.user.ini在Web的根目录下无法删除,因此在删除的时候需要排除掉这个文件,否则会因为删除失败导致部署出错。但是,由于莫名其妙的字符问题,使用rm -rf !(.user.ini)时无法正确执行,因此,需要采用xargs进行删除。

对于服务器的相关IP、部署目录,已提前定义在environment中。

    stage('deploy') {
      steps {
        sshagent(credentials: ['credentials-id']) {
          // 这里是将密钥加入到known_hosts, 同时配置对应的权限
          sh '''
              [ -d ~/.ssh ] || mkdir ~/.ssh && chmod 0700 ~/.ssh
              ssh-keyscan -t rsa,dsa $SERVER >> ~/.ssh/known_hosts
          '''
          // send zip
          sh "scp deploy.zip root@$SERVER:$SERVER_DIR"
          // check dir is exist
          sh '''ssh root@$SERVER "[ -d "$SERVER_DIR$SERVER_DIR_NAME" ] || mkdir $SERVER_DIR$SERVER_DIR_NAME"'''
          // 开启通配符
          sh '''ssh root@$SERVER "shopt -s extglob"'''
          // remove old version
          sh '''
            ssh root@$SERVER \"cd $SERVER_DIR$SERVER_DIR_NAME && ls | grep -v .user.ini | xargs rm -rf\"
          '''
          // unzip
          sh '''
            ssh root@$SERVER "cd $SERVER_DIR && unzip deploy.zip -d $SERVER_DIR_NAME"
          '''
          sh '''
            ssh root@$SERVER "cd $SERVER_DIR$SERVER_DIR_NAME chown -R www"
          '''
          sh '''
            ssh root@$SERVER "cd $SERVER_DIR && rm deploy.zip"
          '''
        }
      }
    }

运行结果

微信图片_20220427023154.png

最后修改:2022 年 04 月 27 日
如果觉得我的文章对你有用,请随意赞赏