概念
Gitlab内置了CI/CD的工具,在项目中添加.gitlab-ci.yml
文件,并且配置gitlab-runner
(运行器)后,代码更新时会自动构建、部署。
.gitlab-ci.yml
一般放在项目根目录,该文件是用来指定构建、测试和部署流程、以及CI触发条件的脚本。当Gitlab检测到代码提交符合.gitlab-ci.yml
文件指定的触发条件时,则会使用配置的gitlab-runner
执行.gitlab-ci.yml
脚本。
gitlab-runner
相当于Gitlab中任务的执行器,Gitlab会在需要执行任务时调用它。
配置gitlab CICD流程
配置gitlab CICD流程需要两步:
- 第一步:在服务器安装 gitlab-runner 并关联仓库。
- 第二步:编写gitlab-ci.yml。
在服务器安装 gitlab-runner,编写gitlab-ci.yml:juejin.cn/post/740058…
最终YML文件:
sonar检测 - build - 上传sentry源码映射 - 删除MAP文件 - 丢到nginx
今天专门解决丢到nginx,而且是丢到宿主机的Nginx.
知识点:
- gitLab为了安全,不支持在.gitlab-ci.yml中直接使用volumes(卷挂载),但可以在gitLabrunner配置文件中配置加载卷,与宿主机进行文件交互。位置在/etc/gitlab-runner/config.toml,
修改完了要记得重启。
[[runners]]
...
[runners.custom_build_dir]
[runners.docker]
tls_verify = false
# 在这里进行目录挂载
volumes = ["/cache", "宿主机目录:容器内目录"]
privileged = true(PS: 这个设置允许容器以特权模式运行。特权模式给予容器几乎与主机相同的权限,包括访问所有设备。这对于运行需要更高权限的任务(如 Docker-in-Docker)是必要的。警告:特权模式可能带来安全风险,应谨慎使用。)
pull_policy = ["if-not-present", "always"](PS: 现在普通环境不允许访问docker了,所以要加上缓存,如果有镜像就不拉取了)
- GitLab artifacts: 整个构建脚本分N个阶段,artifacts是当前阶段可以传递到其他阶段的产物。每个阶段执行前先下载
之前所有阶段
传递的产物(所以产物尽量不要过大)
artifacts:
name: "dist-${CI_COMMIT_REF_NAME}"
paths:
- dist/
expire_in: 1 hour
3.DinD: DIND(Docker-in-Docker)是让你可以在 Docker 容器里面运行 Docker 的一种方式.
工作原理:
- 在主机上运行一个 Docker 容器(父容器)
- 这个父容器内部运行另一个 Docker 守护进程
- 允许在父容器内创建和管理子容器
services:
- docker:dind
环境说明
nginx是部署在服务器本地的(宿主机),没有使用docker。所以需要将构建产物丢到/usr/local/nginx/html。目录,但是整个stage都是docker运行的,卡在了不知如何同宿主机进行交互,apk-get和yum等等常用工具都没办法使用,容器内也不能下载一些常用包。GPT了一下,方案大概有四种:
- 使用 SSH 部署:
在这种方法中,我们使用 SSH 将构建好的文件复制到目标服务器。
deploy_to_server:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache openssh-client
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- scp -r hcsp-frontend/dist/* $SERVER_USER@$SERVER_IP:/usr/local/nginx/html/hcsp-frontend/
only:
- sunshu_cicd_build
您需要在 GitLab CI/CD 变量中设置 SSH_PRIVATE_KEY、SSH_KNOWN_HOSTS、SERVER_USER 和 SERVER_IP。
卡在了没有apk包。
- 使用 rsync:
如果您的服务器支持 rsync,这可能是一个更好的选择:
deploy_to_server:
stage: deploy
image: alpine:latest
before_script:
- apk add --no-cache openssh-client rsync
- eval $(ssh-agent -s)
- echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
script:
- rsync -avz --delete hcsp-frontend/dist/ $SERVER_USER@$SERVER_IP:/usr/local/nginx/html/hcsp-frontend/
only:
- sunshu_cicd_build
卡在了不支持rsync。
- 使用 GitLab Runner 的 shell 执行器:
如果可能的话,您可以在目标服务器上设置一个 GitLab Runner,并使用 shell 执行器。这样,Runner 就可以直接访问服务器的文件系统。
deploy_to_server:
stage: deploy
tags:
- shell # 确保这个 tag 匹配您在服务器上设置的 Runner
script:
- cp -R hcsp-frontend/dist/* /usr/local/nginx/html/hcsp-frontend/
only:
- sunshu_cicd_build
这个也失败了。
- 使用 Docker 卷挂载:
如果您的 GitLab Runner 在目标服务器上运行,并且使用 Docker 执行器,您可以尝试挂载目标目录:
deploy_to_server:
stage: deploy
image: alpine:latest
volumes:
- /usr/local/nginx/html/hcsp-frontend:/deploy
script:
- cp -R hcsp-frontend/dist/* /deploy/
only:
- sunshu_cicd_build
如知识点1,这个参数根本就不支持。
这些在文档中都有讲。所以要仔细看文档啊喂!
最终YML文件:
sonar检测 - build - 上传sentry源码映射 - 删除MAP文件 - 丢到nginx
stages:
- build
- release
- deploy
sonarqube-check:
stage: .pre
image:
name: sonarsource/sonar-scanner-cli:latest
entrypoint: [ "" ]
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # 缓存SonarQube插件
cache:
key: "${CI_JOB_NAME}"
paths:
- .sonar/cache
script:
- sonar-scanner
-Dsonar.projectKey=projectKey
-Dsonar.sources=.
-Dsonar.host.url=host.url
-Dsonar.login=${SONAR_TOKEN}
-Dsonar.scanner.timeoutSeconds=300
allow_failure: true
only:
- merge_requests
- sunshu_cicd_build
cache:
key:
files:
- hcsp-frontend/package.json
- hcsp-frontend/package-lock.json
paths:
- hcsp-frontend/node_modules/
build:
stage: build
image: node:16.19.1 # 使用适合您项目的 Node.js 版本
script:
- cd hcsp-frontend || echo "Failed to change directory"
- pwd # 再次显示当前工作目录
- ls -la # 再次列出当前目录下的所有文件和文件夹
- npm install # 或者 yarn install,取决于您使用的包管理器
- npm run build # 假设这是您的构建命令
- mkdir -p $CI_PROJECT_DIR/dist
- rm -rf $CI_PROJECT_DIR/dist/*
- cp -r dist/* $CI_PROJECT_DIR/dist/ # 将 dist 目
artifacts:
name: "dist-${CI_COMMIT_REF_NAME}"
paths:
- dist/
expire_in: 1 hour
sentry_release:
stage: release
image: getsentry/sentry-cli:latest
script:
- pwd # 显示当前工作目录
- ls -la # 列出当前目录下的所有文件和文件夹
- pwd # 再次显示当前工作目录
- ls -la # 再次列出当前目录下的所有文件和文件夹
- export SENTRY_AUTH_TOKEN="$SENTRY_AUTH_TOKEN"
- export SENTRY_ORG="$SENTRY_ORG"
- export SENTRY_PROJECT="$SENTRY_PROJECT"
# 如果您使用的是自托管的Sentry,请取消下面这行的注释并设置正确的URL
- export SENTRY_URL="https://tisi.sentry.io/"
# 创建新的Sentry版本
- sentry-cli releases new -p $SENTRY_PROJECT $CI_COMMIT_SHA
# 设置提交数据
- sentry-cli releases set-commits --auto $CI_COMMIT_SHA
# 上传 /hcsp/ 目录下的文件
- sentry-cli releases files $CI_COMMIT_SHA upload-sourcemaps dist/js --url-prefix ~/js/
# 完成发布
- sentry-cli releases finalize $CI_COMMIT_SHA
# 部署到生产环境(如果适用)
- sentry-cli releases deploys $CI_COMMIT_SHA new -e production
- pwd # 显示当前工作目录
- ls -la # 列出当前目录下的所有文件和文件夹
only:
- sunshu_cicd_build # 或者您希望触发此作业的分支名称
variables:
SENTRY_AUTH_TOKEN: - SENTRY_AUTH_TOKEN -
SENTRY_ORG: tisi
SENTRY_PROJECT: admin-vue
deploy:
stage: deploy
script:
- rm -rf dist/js/*.map
- mkdir -p /cache/hcsp-frontend
- ls -al
- cp -r dist/* /cache/hcsp-frontend
only:
- sunshu_cicd_build # 只在特定分支上运行
飞书通知
找到了一个库 github.com/goodideal/g…
由于7001端口暂时没开,平替:
notify_feishu:
stage: deploy
image:
name: curlimages/curl:latest
pull_policy: if-not-present
script:
- |
curl -k -X POST -H "Content-Type:application/json" \
-d '{
"msg_type": "post",
"content": {
"post": {
"zh_cn": {
"title": "XXX项目/分支:'"${CI_COMMIT_BRANCH/tool/}"'已发布",
"content": [
[
{
"tag": "text",
"text": "提交人: '"${CI_COMMIT_AUTHOR}"'\n"
},
{
"tag": "text",
"text": "本次更新内容:'"${CI_COMMIT_MESSAGE}"'\n"
},
{
"tag": "a",
"text": "查看流水线",
"href": "'"${CI_PROJECT_URL}/-/pipelines/${CI_PIPELINE_ID}"'"
}
]
]
}
}
}
}' \
https://open.feishu.cn/open-apis/bot/BOT地址
only:
- cicd_build # 或者您想触发通知的分支
when: on_success