关于ci:设计并实现一个简单自动化部署工具

7次阅读

共计 3668 个字符,预计需要花费 10 分钟才能阅读完成。

说之前先放地址 https://cycle.bucai.cc/,开发环境运行的,有点慢请急躁期待加载。

GitHub: https://github.com/notbucai/c…

这是我尝试用流程化的思路进行我的项目开发实现的记录。

至于为什么不实用市面上现有且欠缺的框架,是因为我好久没写残缺且有意义的货色了,当然仍然会“借鉴”一些成熟的我的项目。

设计

需要起源

近期间歇性踌躇满志的对博客性能点进行降级、优化,该我的项目分为后盾 nestjs 我的项目、前台 nuxtjs、管理系统 vue.js,目前部署形式采纳 Docker 进行本地的镜像编译后 push 到公有仓库后再进入服务器 pull 之后重启。还有是多人合作开发每个人都须要在本地装置服务器环境(Docker 等)来确保环境一致性。

通过上述形容不难发现:

  1. 因为我的项目应用的模版、语言以及部署后的状态(动态、服务)都有区别导致编译形式无奈对立。
  2. 目前的手动部署流程的重复性问题。
  3. 须要匹配服务器环境,本地开发电脑配置要求高。

指标冀望

  1. 我的项目部署模版化,针对不同类型可抉择不同模板进行打包。
  2. 将手动部署过渡成自动化部署。
  3. 依赖分支监控,push 主动触发部署,解决本地配置要求高。

调研

因为大多数人平时工作中都接触是有须要这套工具的,所以调研简略阐明。

调研指标:Netlify(国外)、腾讯云 Webify(国内)。

它们解决了什么问题

  1. 将资源进行部署。
  2. CI/CD 工作流。

它们的毛病(强行进步当初所做的我的项目高度

  1. Netlify 国外,dddd。
  2. Webify 云厂商进行运维,保不齐什么时候就开始割韭菜。

需要剖析

通过上述内容很直观的失去我的项目须要性能点。

外围剖析

外围性能是以“工作”为单元进行操作,创立工作和治理工作。

所谓“工作”即须要对状态进行流转的,目前工作分为 进行中、失败、已进行。

每次触发都应该生成一个子工作,如果触发时有进行中的子工作该当进行后启用新工作。

进行中的工作蕴含子状态:编译中、编译胜利、编译失败。

用户交互以及外围环节请看下方流程图。

功能设计

  1. 创立工作

    次要对某个仓库的分支进行 webhook 的注册,并将工作信息写入数据库。

  2. 治理工作

    次要对创立后的工作信息进行治理,删除、暂停、开始。

    1. 开始

      对暂停的工作持续进行。

    2. 暂停

      对正在进行中的工作进行。

    3. 删除

      删除此条数据,并删除 webhook。

  3. 工作执行

    通过 webhook 触发执行,找到以后数据进行执行。

工作执行设计

如何不同配置进行不同的编译 / 运行形式?

所有编译都采纳 docker 进行隔离编译,运行依据不同类型进行抉择不同的形式。

目前辨别两种类型,一种是动态、一种是动静:

  • 动态:采纳采纳 docker 编译后上传 cdn 形式,当然只是模仿暂只放 nginx 动态目录中。
  • 动静:应用 docker 编译后 docker 运行。
web service
无需端口 端口
nginx 转发资源 nginx 转发端口
可能须要编译 可能须要编译
不须要容器运行 须要容器运行
动作 spa 我的项目 一般网页 Ts node 我的项目 一般 node 我的项目
构建
编译
运行

上方从资源类型和我的项目类型进行比照,直观的表白了工作的执行动作。

动态资源(web)容器构建后,通过 docker cp 将镜像中 dist 数据 copy 到主机中,而后转移到 nginx 中。

服务资源(service)容器构建编译后,再运行起来,而后增加 nginx 将容器映射到机器端口上。

端口后续进行保护,容器内端口不做治理,靠 nginx 容器进行映射保护。

用户本人的工作容器之间能够互相通信,通过工作 id 即可拜访,如果是动态资源须要拜访后续通过配置将接口进行转发,同时用户能够绑定本人的域名到以后机器上。

页面设计

前端采纳 naive-ui 作为前端布局款式组件。

其在交互上次要分为三步:

  1. 抉择托管平台

    github、gitee 等平台,抉择的托管平台必须是受权登录过的。

  2. 输出信息

    输出工作所必须的数据字段

  3. 确认信息

    确认输出的是否符合要求

因为设计比较简单,间接以图片模式展现。

工作列表字段:工作名称 /ID、托管平台、模版、状态、创建人、创立工夫、更新工夫、操作工夫。

详情页

数据库设计

只展现外围表的设计

用户表

托管平台表

模版表

工作表

子工作表

接口设计

蕴含 crud,间接查看接口文档:

https://www.apifox.cn/apidoc/…

技术选型

抉择的计划的规范是 我会 简略

目前抉择 egg + mysql + redis + vue 架构,编码尽量 ts 化。其余框架也思考过比方 nestjs、koa,相对而言 nest 太大了,koa 又太小了,选 vue 其实只是想试一下 3.x 的版本。

eggjs: 为企业级框架和利用而生。

vue: 懂得都懂。

我的项目架构

架构很简略,就是存储配合依赖进行触发。

服务器运维架构

独立以后利用,用户可共享本人的服务并独立运行(隔离),原则上每个用户都能够申请一些存储与其余资源(待定),不过依然倡议应用近程 / 第三方资源。

编译 / 部署 触发 流程

是否编译:有些 node 我的项目是不须要编译的步骤

是否运行:动态资源不须要运行,间接打到 nginx 中即可

实现

外围性能实现(临时只做实现 github 相干业务,其余平台预留接口)。

我的项目进度查看

绑定托管平台

援用阮一峰一图,一文,绑定流程基本上就是浏览器重定向,后返回 code,拿到 code 换 token,而后将 token 保留。

获取相干信息

通过以下 api 进行操作

用户储存库列表

获取分支列表

获取指定文件内容

创立工作

创立工作写入 webhook。

创立 webhook

工作执行

期待 webhook 回调

https://docs.github.com/cn/developers/webhooks-and-events/webhooks/testing-webhooks

工作执行相干模版每次触发都执行,应用 ejs 进行配置渲染生成。

// 注入内容
{
  user, // 数据库 user model
  task, // 数据库 task model
  taskChild, // 数据库 task_child model
  template, // 数据库 template
  path: {
    ...path, // 相干门路
    code: relativeCodePath // 代码与配置的绝对地位
  }
}
# dock er file
FROM node:12.18.2

LABEL maintainer="<%= user.id %><<%= user.email %>>"

ADD <%= path.code %> /app/

WORKDIR /app

RUN rm -rf node_modules

RUN rm -rf <%= path.build %>

RUN npm config set sharp_binary_host https://npm.taobao.org/mirrors/sharp

RUN npm config set sharp_libvips_binary_host https://npm.taobao.org/mirrors/sharp-libvips

RUN npm config set sass_binary_site https://npm.taobao.org/mirrors/node-sass

RUN npm install --registry https://registry.npm.taobao.org --max-old-space-size=4096

ENV NODE_ENV production

<% if (template.is_build) { %>
RUN npm run <%= task.build_script %>
<% } %>

<% if (template.is_run) { %>
EXPOSE <%= task.server_port %>

CMD  nohup sh -c 'npm run <%= task.run_script %>'
<% } %>
# docker compose config
version: "3.7"

services:
  "<%= task.id %>":
    build: .
    image: <%= task.id %>:<%= taskChild.version || '0.0.1' %>
    container_name: <%= task.id %>
    restart: always
<% if (template.is_run) { %>
    networks:
      <%= user.id %>-network:
        ipv4_address: <%= task.ip %>

networks:
  <%= user.id %>-network:
    external: true
<% } %>

构建 / 编译 / 运行 相干

node child_process exec 进行命令执行:

应用 exec('docker-compose build')进行镜像的构建。

应用 exec(docker cp $(docker create --rm ${imageName}):/app/${buildPath} ./dist)将容器内数据 copy 到主机中。

应用 docker-compose down 将已有镜像镜像进行。

应用 'docker-compose restart 镜像容器的重启。

应用 docker-compose up 启动编译好的镜像。

正文完
 0