当前位置: 首页 > news >正文

手摸手实战前端项目CI CD

由于图片和格式解析问题,为了更好阅读体验可前往 阅读原文

CI/CD 是 持续集成(Continuous Integration) 和 持续交付/部署(Continuous Delivery/Continuous Deployment) 的缩写,是现代软件开发中的一种自动化方法论,用于加速代码交付和部署的流程,同时保证代码质量和稳定性

大家工作中应该也都接触到了它的方便,如:提交MR、自动打包、自动部署等等,让开发者大大省去了大量的部署时间,从而专注于需求的开发(纯牛马)

那么时间久了你是否对这种方法有过思考,如:这一系列是如何运作的、自己如何搭建尝试呢?对于每位开发者来说都有必要尝试去搭建完整的体系,这样自己对软件落地的整体体系会有更明确的认知。本篇文章将手把手带你完成前端项目从开发到部署的整个过程

小贴士:🎁 文章中涉及到的代码示例你都可以从 这里查看 ,若对你有用还望点赞支持;本篇不适合0️⃣基础小白,需要掌握docker、linux、gitlab、k8s、node等相关知识,如果你对这方面的内容还是空白,可以参考我的往期文章

项目准备

首先在代码管理仓库创建一个项目用来存放项目代码(这里以Gitlab为例),创建fe-cicd

接着创建工程项目,并简单写2个页面;这里本人用CLI助手直接用已有的项目模板来作为演示项目,读者也可以直接使用:执行以下命令很快就会创建好空壳项目模板

# 初始化项目
➜ hengshuai create fe-cicd
HengShuai CLI v0.0.13
? 请选择要创建的模板👇  create a vue project
? 请选择模板类型👀  vue3 admin skeleton with nestjs
? 是否需要自动安装依赖❓ No
🎉 Successfully created project fe-cicd.
👉 Get started with the following commands:➜ cd fe-cicd
➜ pnpm install

将本地项目推送到代码仓库

git add .
git cm -m '初始化'
git remote add gitlab http://192.168.10.10/learn/fe-cicd.git
git push origin dev

以上步骤比较简单,我们搞完后就可以在仓库里看到项目代码了:

打包测试

对于一个新项目在真正部署前一般我们都会在本地执行打包脚本先验证下是否可以跑的通,执行以下命令:

pnpm run build
pnpm run start

查看运行结果:项目正常运行了

CI准备

跑流水线最重要的还是ci的配置脚本,通过ci脚本我们可以精确控制流水线如何执行,因此配置好ci是关键

注册Runner

在写ci配置前要确保已经准备好了gitlab runner,它主要来执行ci的,如果你对runner还是很陌生话请先参考我的往期文章;这里在项目中已经启用了准备好的runner,使用标签是testing;runner的标签名在注册时就可以确定,建议使用有意义的命名规则

一个项目可以使用的多个runner,在ci中体现就是:每个阶段都可以使用不同的runner,或者同阶段的并行任务使用不同runner也可以加速流程,各位视机器配置自行决定

编写gitlab ci

本次项目使用Gitlab CI 进行来执行流水线工作,因此我们在项目根目录下创建新建.gitlab-ci.yml

::: warning 温馨提示
如果你对gitlab ci的配置文件不是很熟悉,可以参考我的往期文章并结合官方文档,本篇以主要流程为主不做很详细的配置介绍
:::

这里我们将流水线分4个阶段:

  • install:安装依赖
  • build:项目构建
  • deploy:项目部署
  • notice:消息通知,消息通知又分为成功和失败

根据以上划分可以简单写出下面这些内容:

image: node:18-alpinevariables:IMAGE_TAG: $CI_PROJECT_NAME:$CI_COMMIT_REF_NAMEstages:- install_deps- build- deploy- noticeinstall_dependencies:stage: install_depsonly:- devtags:- testingcache:key:files:- pnpm-lock.yamlpaths:- node_modulesartifacts:expire_in: "30" #30spaths:- node_modulesscript:- echo "Installing dependencies..."- sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories- apk update && apk add git && apk add openssh-client- npm config set registry https://registry.npmmirror.com/- npm install -g pnpm- pnpm install- echo "Dependencies installed successfully!"build_project:stage: buildonly:- devtags:- testingartifacts:expire_in: "30"paths:- distneeds:- install_dependenciesscript:- echo "Building project..."- pnpm builddeploy_project:stage: deployonly:- devtags:- testingneeds:- build_projectscript:- echo "Deploying project..."- echo "success"# 流水线成功消息
notice_success:stage: noticeonly:- devtags:- testingneeds:- deploy_projectwhen: on_successscript:- echo "success"# 流水线失败消息
notice_failure:stage: noticeonly:- devtags:- testingneeds:- deploy_projectwhen: on_failurescript:- echo "failure"

以上流水线管道在GitLab上的可视化效果如下:

按分支执行

通常项目开发会分为好几个环节如:beta、testing、prod等等,不同环境的可能会有不同的权限,不同环境的runner可能也不一样,因此在ci脚本中就可以真不同环境来区分哪些阶段的流程

假设以下的消息通知,让它只在dev、testing环境下执行,那么就可以通过only关键字来明确指出:

notice_success:stage: noticeonly:- dev- testingtags:- testingscript:- echo "success"

自动化测试

团队中一般对于基建项目会很严格,出一点错误可能就会影响到成百上千的项目。所以通常都会在发布前做相关的自动化测试保证最基本的测试用例不会受到影响,只有这样才能把握住代码的质量;而在ci中我们也可以把它集成进来,在流水线时通过跑自动化测试根据结果来决定是否可以继续执行下去了

本次通过Vitest来演示单元测试,你可以通过其他的工具(如:Jest、Cypress)附加测试功能;先创建一个简单的测试用例:

// __test__/unit/demo.spec.ts
import { describe, expect, it } from "vitest";describe("Test Demo", () => {it("should pass", () => {expect(true).toBe(true);});
});

新增测试npm脚本:

{"scripts": {"test:unit": "vitest run"}
}

读者先在本地运行看能否跑通,避免在ci中增加未知问题

增加测试脚本后,我们需要把它集成到ci中;在ci中增加一个testing阶段用来跑测试用例

stages:- testing # 新增测试阶段testing_project:stage: testingtags:- testingneeds:- install_dependenciesscript:- echo "Testing project..."- pnpm run test:unit

以上只是简单的将测试放入了ci管道,如果你对测试数据比较感兴趣,如:代码覆盖率、代码质量等等,可以参考Test coverage文档、Code quality文档

打包镜像

以上我们就对流水线的上半部分的工作就基本做完了,接下来就是打包应用并发布了,这也是很关键的一个步骤;本篇只做云原生应用的部署,如果你还没有涉及到容器相关的技术,这里不做相关的介绍

容器最关键的就是镜像,对于应用来说可以通过Dockerfile来创建镜像文件,下面是简单的一个例子:

FROM node:18.19.0-alpine3.19WORKDIR /app# 直接从ci打包阶段拿到产物
COPY dist dist
COPY node_modules node_modules
COPY ecosystem.config.js ecosystem.config.jsRUN npm install pm2 -g --registry=https://registry.npmmirror.com/ENTRYPOINT ["pm2-runtime", "start", "ecosystem.config.js", "--env", "production"]

你可以能对上面的docker镜像文件有疑问❓可能觉得他太少了,最基本的项目打包脚本都没有哪来的构建产物;这里我们可以理解为在流水线的流程中在打包阶段将产物保存,然后在构建镜像时直接用就行而不需要在docker中再次构建,这样就省去了大量的时间(更过可以参考gitlab官方文档)

当然docker最终跑的脚本是通过pm2来维护的,我们还需要编写个pm2的配置文件:

// https://pm2.keymetrics.io/docs/usage/quick-start/
module.exports = {apps: [{name: "fe-cicd",script: "dist/server/main.js",watch: false,instance: 2,autorestart: true,max_memory_restart: "1G",env: {NODE_ENV: "development",},env_production: {NODE_ENV: "production",},},],
}

这里使用kaniko来构建镜像:

build_image:stage: buildneeds:- build_projectimage:name: gcr.io/kaniko-project/executor:debugentrypoint: [""]only:- devtags:- testingscript:- echo "Deploying project..."- for var in ${PROJECT_ENV_VARIABLE// / }; do echo $var >> .env;done- mkdir -p /kaniko/.docker- echo "{\"auths\":{\"${DOCKER_REPO}\":{\"username\":\"${DOCKER_REGISTRY_USER}\",\"password\":\"${DOCKER_REGISTRY_PASSWORD}\"}}}" > /kaniko/.docker/config.json- /kaniko/executor--context "${CI_PROJECT_DIR}"--dockerfile "${CI_PROJECT_DIR}/Dockerfile"--destination "$DOCKER_REPO/$IMAGE_TAG"rules:- if: $CI_COMMIT_TAG

以上构建镜像后会把它推送到容器的仓库中心,细心的读者已经发现我们在,我们在build阶段新增了镜像的构建,因此以下为整体的流程呈现效果

部署应用

在流水线中docker镜像构建好后,就可以把镜像推到镜像仓库了(通常公司都会有自己的私有仓库),然后通过k8s拉取最新镜像自动部署了,这就是部署的基本流程

deploy_to_k8s:stage: deployimage: bitnami/kubectl:latestonly:- devtags:- testingneeds:- build_imagebefore_script:- echo "Setting up kubectl"- mkdir -p ~/.kube- echo "$KUBE_CONFIG" > ~/.kube/configscript:- echo "Updating Kubernetes deployment"- kubectl set image deployment/$K8S_DEPLOYMENT_NAME $K8S_CONTAINER_NAME=$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA --namespace=$K8S_NAMESPACE- kubectl rollout status deployment/$K8S_DEPLOYMENT_NAME --namespace=$K8S_NAMESPACE

消息通知

等k8s镜像部署阶段完成后代表整个流程就结束了,因此我们可以在流水线的尾部在增加一个通知阶段,通过发送具体的消息来来告知我们的开发人员,当然流水线的执行状态有成功失败2中状态,根据不同的状态来告知

你可以通过HTTP请求将信息发送到消息服务中心,消息中心可以集成到公司用到的应用,这样就会一触即达

消息通知阶段的流水线以上已经展示过了,这里就不再写了,稍微补充下用到的基础镜像:

notice_success:# 通过curl来发送消息image: curlimages/curl:7.80.0# 以下内容自行发挥

执行机制

通常流水线的执行时机都是通过固定的事件触发的,如:分支合并、分支push等等,而对于重要的环境往往需要手动来降低风险,或者说可以更好的决定执行时机;对于一个复杂应用的发布,可能会涉及到很多基础服务的发布,那么对于自动化发布来说会很麻烦,这里简单提一下如何修改执行时机

deploy-job:stage: deployscript:- echo "Deploying the application"when: manual   # 配置为手动触发

在往期的文章中都有关于执行时机的介绍,这里只是提醒下如何更好的实践

心跳检测

大多数的应用都会面对很多问题,如:负载、故障等等;而稳定的应用都会有很多监控措施,对于镜像如何检测它是否正常运行呢,最简单的就是通过写一个检测接口,通过一定的频率来调用,根据响应来判断是否正常,这样在镜像拉胯时,可以重新部署

下面我们用NodeJS简单写了一个接口/common/health-check

@Controller("/common")
export class CommonController {// 心跳检测@Get("/health-check")healthCheck() {return "ok";}
}

接着在k8s pod配置文件中添加心跳检测

apiVersion: v1
kind: Pod
metadata:labels:test: livenessname: liveness-http
spec:containers:- name: livenessimage: registry.k8s.io/e2e-test-images/agnhost:2.40args:- livenesslivenessProbe:httpGet:path: /common/health-checkport: 8080initialDelaySeconds: 3periodSeconds: 3

更多玩法请参考探针检测

其他

纯静态前端项目,大部分会配合nginx使用,这里不做演示

线上的应用运行效果如何(内存、负载、响应等等),通常都会在相关的监控后台查看,可以参考k8s可视化资源监控,也可以根据api自行设计监控后台

由于图片和格式解析问题,为了更好阅读体验可前往 阅读原文

相关文章:

手摸手实战前端项目CI CD

由于图片和格式解析问题,为了更好阅读体验可前往 阅读原文 CI/CD 是 持续集成(Continuous Integration) 和 持续交付/部署(Continuous Delivery/Continuous Deployment) 的缩写,是现代软件开发中的一种自动…...

【Elasticsearch】搜索类型介绍,以及使用SpringBoot实现,并展现给前端

Elasticsearch 提供了多种查询类型,每种查询类型适用于不同的搜索场景。以下是八种常见的 Elasticsearch 查询类型及其详细说明和示例。 1. Match Query 用途:用于全文搜索,会对输入的文本进行分词,并在索引中的字段中查找这些分…...

K8S中的Pod调度之亲和性调度

亲和性调度 亲和性调度是一种比硬性指定节点(使用 nodeName 或 nodeSelector)更灵活的调度策略,它允许定义一组规则,根据这些规则,调度器会尝试将 Pod 调度到最合适的节点上,但如果找不到完全匹配的节点&a…...

高等数学学习笔记 ☞ 不定积分的积分法

1. 第一换元积分法 1. 基础概念:形如的过程,称为第一换元积分法。 2. 核心思想:通过对被积函数的观察(把被积函数的形式与积分表的积分公式进行比较),把外部的部分项拿到的内部(求原函数), 然后进行拼凑,…...

【HTTP】详解

目录 HTTP 基本概念啥是HTTP,有什么用?一次HTTP请求的过程当你在浏览器中输入一个浏览器地址,它会发送什么 ?---(底层流程)HTTP的协议头请求头(对应客户端)一些请求头请求方法 响应头…...

cursor重构谷粒商城01——为何要重构谷粒商城

前言:这个系列将使用最前沿的cursor作为辅助编程工具,来快速开发一些基础的编程项目。目的是为了在真实项目中,帮助初级程序员快速进阶,以最快的速度,效率,快速进阶到中高阶程序员。 本项目将基于谷粒商城…...

如何在 ASP.NET Core 中实现速率限制?

在 ASP.NET Core 中实现速率限制(Rate Limiting)中间件可以帮助你控制客户端对 API 的请求频率,防止滥用和过载。速率限制通常用于保护服务器资源,确保服务的稳定性和可用性。 ASP.NET Core 本身并没有内置的速率限制中间件&…...

STM32-笔记43-低功耗

一、什么是低功耗? 低功耗‌是指通过优化设计和采用特定的技术手段,降低电子设备在运行过程中消耗的能量,从而延长电池寿命、提高性能和减少发热。低功耗设计主要从芯片设计和系统设计两个方面进行,旨在减少所有器件的功率损耗&am…...

Facebook 隐私风波:互联网时代数据安全警钟

在社交媒体飞速发展的今天,个人数据的隐私保护已成为全球关注的焦点。作为全球最大的社交平台之一,Facebook面临的隐私问题,尤其是数据泄露事件,频繁引发公众的广泛讨论。从用户信息被滥用到数据泄漏,Facebook的隐私挑…...

Java 中的 ZoneOffset

介绍 在我们的这个世界上因为地球是圆的,所以每个国家都会有自己特定的时区。 时区在我们对时间的使用上扮演了非常重要的角色。但又因为时区的存在,又给我们带来了很多的麻烦,比如北美地区使用的夏令时和中国统一使用东 8 区的时间等。 当…...

amis模板语法、数据映射与表达式

模板字符串 表达式中获取变量 可以支持在普通文本中&#xff0c;使用数据映射语法&#xff1a;${xxx} 获取数据域中变量的值 "Hello ${text}"渲染 html 使用数据映射语法&#xff1a;${xxx} 获取数据域中变量的值&#xff0c;并渲染 HTML "<h1>Hello<…...

频域增强通道注意力机制EFCAM模型详解及代码复现

背景与动机 在深度学习领域,如何有效处理时间序列数据一直是一个重要的研究方向。近年来, 频域分析技术 在时间序列处理中展现出了巨大潜力,特别是离散余弦变换(DCT)因其能够高效捕捉低频信息并避免高频噪声干扰而受到广泛关注。 FECAM模型的开发正是基于这一背景,旨在…...

GitLab 国际站中国大陆等地区停服,如何将数据快速迁移到云效

代码托管平台 GitLab 国际站&#xff08;GitLab.com&#xff09;近日发布公告&#xff0c;官宣即将停止对中国大陆、香港、澳门地区的用户账号提供服务&#xff0c;并提供 60 天过渡期自行迁移账户数据&#xff0c;超期未迁移的账号可能会被 GitLab 清除。这一重要决策引起了全…...

BPG图像库和实用程序(译)

1)快速介绍 编辑Makefile以更改编译选项&#xff08;默认编译选项对于Linux应该是OK的&#xff09;。输入make来编译&#xff0c;输入make install来安装编译后的二进制文件。bpgview&#xff1a;为了编译它&#xff0c;你需要安装SDL和SDL_image库。Emscripten的使用&#xff…...

简述1个业务过程:从客户端调用接口,再到调用中间件(nacos、redis、kafka、feign),数据库的过程

以下是一个常见的业务过程示例&#xff0c;展示了从客户端调用接口&#xff0c;再到调用中间件&#xff08;Nacos、Redis、Kafka、Feign&#xff09;和数据库的过程&#xff1a; 假设我们有一个电商系统&#xff0c;客户端要查询某个商品的详细信息&#xff0c;这个商品信息可…...

01.02、判定是否互为字符重排

01.02、[简单] 判定是否互为字符重排 1、题目描述 给定两个由小写字母组成的字符串 s1 和 s2&#xff0c;请编写一个程序&#xff0c;确定其中一个字符串的字符重新排列后&#xff0c;能否变成另一个字符串。 在这道题中&#xff0c;我们的任务是判断两个字符串 s1 和 s2 是…...

什么是.NET中的反射,它有哪些应用场景

反射是.NET框架提供的一种强大的机制&#xff0c;它允许程序在运行时查询和操作对象的类型信息。以下是对.NET中反射的详细解释及其应用场景&#xff1a; 一、反射的定义 在.NET中&#xff0c;所有类型的信息&#xff08;包括类、结构、委托、接口、枚举等以及它们的成员信息…...

Linux离线部署ELK

文章目录 前期准备开始安装安装elastic search安装logstash安装kibana 配置ELK配置ElasticSearch配置logstash配置kibana 启动ELK启动命令启动测试 设置ELK策略创建ILM策略将ILM策略与日志index关联查看索引是否被ILM策略管理 前期准备 ELK包含三部分软件 ElasticSearch用作搜…...

解决 chls.pro/ssl 无法进入问题

使用charles的xdm不知道有没有遇到这样的问题。手机上访问 chls.pro/ssl 就始终进不去了… 各种检查&#xff0c;ip地址、证书&#xff0c;ssl设置等等都正常&#xff0c;就是进不去。 在一位好心人的提醒下得到了一个解决办法。那就是换一个地址 最新地址是: charlesproxy…...

Rust 游戏开发框架指南

Rust 游戏开发框架指南 主流游戏引擎 1. Bevy 最受欢迎的 Rust 游戏引擎之一&#xff0c;基于 ECS&#xff08;实体组件系统&#xff09;架构。 特点&#xff1a; &#x1f680; 高性能 ECS 系统&#x1f4e6; 热重载支持&#x1f3a8; 现代渲染器&#x1f50a; 内置音频系…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

网站指纹识别

网站指纹识别 网站的最基本组成&#xff1a;服务器&#xff08;操作系统&#xff09;、中间件&#xff08;web容器&#xff09;、脚本语言、数据厍 为什么要了解这些&#xff1f;举个例子&#xff1a;发现了一个文件读取漏洞&#xff0c;我们需要读/etc/passwd&#xff0c;如…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

云原生周刊:k0s 成为 CNCF 沙箱项目

开源项目推荐 HAMi HAMi&#xff08;原名 k8s‑vGPU‑scheduler&#xff09;是一款 CNCF Sandbox 级别的开源 K8s 中间件&#xff0c;通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度&#xff0c;为容器提供统一接口&#xff0c;实现细粒度资源配额…...