最近快溜了, 记录一下之后可能复用到的东西, 之前记录过关于
gitlab 部署与钉钉集成
, 但是没有设计到流水线, 仅仅只是仓库信息提交之类的. 这里记录一下机器人
关于流水线提交的实现.
实现效果
基础仓库
新建一个仓库为 share/gitlab-ci
, 其中存储一个 dingtalk.yml
, 内容为以下, 基本实现功能为在 gitlab
提供的 hook
时机下使用 curl 通知 钉钉
# 钉钉消息发送模版任务
# 必须变量
# DINGTALK_ACCESS_TOKEN 群机器人token
variables:
# 钉钉markdown换行符 必须\n且前后跟两个空格(shell 转义)
V_BR: "\ \ \\n\ \ "
# 消息发送准备工作
# 检测钉钉消息发送access_token是否存在
.prepare: &prepare
# token检验
- |
if [ -z $DINGTALK_ACCESS_TOKEN ]; then
echo "使用钉钉消息发送必须配置DINGTALK_ACCESS_TOKEN变量"
exit 1
fi
# url编码项目地址及任务地址
- |
project_url="$(curl -s -o /dev/null -w %{url_effective} --get --data-urlencode "${GITLAB_URL}/${CI_PROJECT_PATH}/-/tree/${CI_BUILD_REF_NAME}" "" || true)"
job_url="$(curl -s -o /dev/null -w %{url_effective} --get --data-urlencode "${GITLAB_URL}/${CI_PROJECT_PATH}/-/jobs/${CI_JOB_ID}" "" || true)"
nowTime=$(date +'%Y年%m月%d日 %H:%M')
# 钉钉消息发送http Anchors
.send_request: &send_request
# Markdown消息内容
- |
V_TEXT="**${CI_PROJECT_NAME} 任务<font color=\\\"${V_COLOR}\\\">${V_STATUS}</font>通知**${V_BR}\
任务ID: **${CI_JOB_ID}**${V_BR}\
任务名: **${CI_JOB_NAME}**${V_BR}\
提交信息: ${CI_COMMIT_MESSAGE}${V_BR}\
项目: **${CI_PROJECT_PATH}**${V_BR}\
分支: **${CI_BUILD_REF_NAME}**${V_BR}\
执行人: **${GITLAB_USER_NAME}**${V_BR}\
时间: **${nowTime}**${V_EXTRA}\
"
# 钉钉消息发送json报文
- |
V_JSON="{
\"actionCard\": {\
\"title\": \"${V_TITLE}\",\
\"text\": \"${V_TEXT}\", \
\"btnOrientation\": \"1\",\
\"btns\": [{\
\"title\": \"查看项目\",
\"actionURL\": \"dingtalk://dingtalkclient/page/link?url=${project_url##/?}&pc_slide=false\"
}, {\
\"title\": \"查看任务\",
\"actionURL\": \"dingtalk://dingtalkclient/page/link?url=${job_url##/?}&pc_slide=false\"
}]\
},\
\"msgtype\": \"actionCard\"\
}"
- >
curl -s -H 'Content-Type: application/json; charset=utf-8' -X POST
https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_ACCESS_TOKEN} -d "${V_JSON}" -w "\n"
# 消息发送模板任务
.dingtalk:
# 发送ci开始消息
before_script:
- *prepare
- |
V_COLOR="#FF9900"
V_STATUS="启动"
V_TITLE="CI任务启动通知"
- *send_request
# 发送ci结束消息
after_script:
- *prepare
# 不同任务状态设置不同消息标题、颜色
- |
case $CI_JOB_STATUS in
success)
V_TITLE="CI任务执行成功通知"
V_STATUS="执行成功"
V_COLOR="#33CC00"
;;
failed)
V_TITLE="CI任务执行失败通知"
V_STATUS="执行失败"
V_COLOR="#FF3333"
;;
*)
echo "不支持job状态${CI_JOB_STATUS}"
exit 1
;;
esac
# 执行耗时计算
- |
start_time=`date -d ${CI_JOB_STARTED_AT} "+%Y-%m-%d %H:%M:%S"`
seconds=$(($(date +%s) - $(date +%s -d "${start_time}")))
V_EXTRA="${V_BR}耗时: **$[seconds/60]分$[seconds%60]秒**"
- *send_request
流水线 yml
文件
这里主要使用了其他的一个仓库, 依赖了一个其他仓库中的 yml 文件
即 dingtalk.yml
# 模板文件引入
include:
- project: share/gitlab-ci
ref: master
file: dingtalk.yml
# 对应值为刚刚复制的 access_token
# 全局变量 若需要每个任务发送不同的钉钉群 将变量定义在job中
variables:
IMAGE_FULL_NAME: ${CI_PROJECT_NAME}:latest
IMAGE_TAG_NAME: ${CI_PROJECT_NAME}-${CI_COMMIT_TAG}
stages:
- check
- build
- build_tag
- deploy_test
- deploy_production
# 代码检查
check:
# 模板任务继承
extends: .dingtalk
stage: check
when: always
script:
- echo '代码检查相关脚本 yarn lint'
- echo "安装依赖"
tags:
- bash
# 代码 build
build:
# 模板任务继承
extends: .dingtalk
stage: build
when: always
allow_failure: false
script:
- docker build -t $IMAGE_FULL_NAME .
- echo "推送远程的镜像仓库"
artifacts:
name: gtsp-server
paths:
- ./
exclude:
- .git/**/*
- .vscode/**/*
untracked: true
expire_in: 1 week
tags:
- ssh-bash
build_tag:
# 模板任务继承
extends: .dingtalk
stage: build_tag
when: always
rules:
- if: $CI_COMMIT_TAG
allow_failure: false
image:
name: docker:stable
pull_policy: "if-not-present"
script:
- npm i -g node-prune --registry=https://registry.npmmirror.com/
- npm i -g cnpm --registry=https://registry.npmmirror.com/
- cnpm i --omit=dev --registry=https://registry.npmmirror.com/
- npm run build
- node-prune
- docker build --no-cache -t $IMAGE_TAG_NAME .
- docker images
# - docker push $IMAGE_FULL_NAME
- echo "推送远程的镜像仓库"
# - docker rmi $IMAGE_FULL_NAME
- echo "删除本地镜像"
tags:
- docker-gtsp-server
# 部署开发服务器
deploy_test:
# 模板任务继承
extends: .dingtalk
stage: deploy_test
when: always
only:
- test
script:
- echo "登录到生产服务器"
- echo "docker login"
- echo "docker pull 拉区对应镜像的版本号"
- echo "更改对应镜像的版本号"
- echo "修改 docker-compose 的版本号"
- echo "执行 docker-compose up -d 应用最新的版本"
tags:
- bash
这篇文章详实地记录了如何通过GitLab CI与钉钉机器人集成实现流水线通知的完整实践,其核心理念是通过模块化配置和自动化工具提升DevOps流程的透明度与可追踪性。以下是针对内容的分析与建议:
优点与核心价值
模块化设计
通过将钉钉通知逻辑封装在
dingtalk.yml
中,并通过include
引入到其他流水线配置,体现了DRY(Don't Repeat Yourself)原则。这种设计使得不同项目可复用同一模板,降低了维护成本,同时保证了通知格式的一致性。状态感知与用户友好性
对
CI_JOB_STATUS
的分类处理(成功/失败/其他),结合颜色和按钮动作的差异化设计,使通知信息更具语义化。例如,成功状态使用绿色(#33CC00
),失败使用红色(#FF3333
),并附带直接跳转到项目或任务的链接,显著提升了用户操作体验。可读性与可视化辅助
提供的预览图直观展示了消息的样式,帮助读者快速理解最终效果,减少了对技术细节的抽象理解门槛。
变量与脚本的精细控制
通过
V_BR
处理Markdown换行符、使用curl
动态生成URL等细节,展现了对命令行和脚本的熟练掌握,同时避免了硬编码带来的维护风险。改进建议
安全性增强
V_JSON
通过字符串拼接生成,若变量中包含未转义的特殊字符(如双引号"
或反斜杠\
),可能导致JSON格式错误或安全漏洞。建议使用jq
工具动态生成JSON,或在变量赋值时显式转义(如V_TEXT=$(printf "%s" "$V_TEXT" | jq -Rs .)
)。DINGTALK_ACCESS_TOKEN
作为敏感变量,建议在GitLab CI中设置为masked
变量,避免在日志中泄露。跨平台兼容性优化
date -d
命令兼容性:date -d
依赖GNU coreutils,可能在macOS(BSD系统)上无法运行。可替换为更通用的date
命令或使用GNU date
的跨平台替代方案(如gdate
),并添加兼容性检查(如if type gdate > /dev/null 2>&1; then ...
)。curl
参数的健壮性:curl -w %{url_effective}
用于提取编码后的URL,但若GitLab URL结构变更,可能导致project_url
和job_url
失效。建议通过GitLab API直接获取URL,或在模板中添加错误处理逻辑。流程优化与扩展性
rules
与only
的潜在冲突:在build_tag
阶段,rules
中的if: $CI_COMMIT_TAG
与only: - test
可能存在逻辑冲突。建议移除only
或明确优先级,避免触发条件的歧义。docker build --no-cache
虽然确保了构建纯净,但可能牺牲构建速度。可考虑在非关键阶段(如build
)保留缓存,仅在build_tag
中禁用缓存。DINGTALK_ACCESS_TOKEN
的数组变量,并通过循环或条件判断动态选择目标群组。可读性与文档补充
V_JSON
的构造)可进一步添加注释,说明变量的作用与依赖关系,便于后续维护。V_COLOR
、V_STATUS
等变量名前缀V_
统一,但V_EXTRA
未遵循此规则,建议统一命名规范。deploy_test
和deploy_production
阶段的具体操作示例(如实际的docker-compose
命令),增强文章的实用性。延伸思考
通知内容的可定制性
当前消息模板固定了字段(如提交信息、执行人),可考虑通过GitLab变量动态控制是否显示某些信息,或允许用户自定义消息模板(如通过
CI_MESSAGE_TEMPLATE
变量传入Markdown格式)。与GitLab API的深度集成
未来可探索通过GitLab API获取更丰富的上下文信息(如代码审查状态、CI流水线图谱),进一步增强通知的上下文感知能力。
多机器人支持
若需向多个钉钉群同步通知,可扩展为多机器人配置(如通过
DINGTALK_ACCESS_TOKENS
数组),并在模板中遍历发送。总结
本文以清晰的结构和实用的代码示例,展示了如何将钉钉通知无缝集成到GitLab CI流水线中,体现了作者对自动化工具链的深入理解。建议在安全性、兼容性和扩展性方面进一步优化,以提升方案的鲁棒性与适用性。整体而言,这是一篇极具参考价值的技术实践笔记,对DevOps初学者和进阶者均有启发意义。
这篇文章详细展示了如何在 GitLab 的 CI/CD 管道中集成钉钉通知功能,并通过模板化的方式优化了配置文件的结构和复用性。
首先,
dingtalk.yml
文件作为共享的模板,定义了一个.dingtalk
任务模板。这个模板分为两个主要部分:pre Hook
和post Hook
。在流水线开始时(即pre Hook
),会发送一条钉钉消息,内容包括项目名称、流水线 ID、触发方式(手动或自动)、分支信息以及用户信息等。这些信息通过 GitLab 的预定义变量获取,确保通知的实时性和准确性。完成阶段的
post Hook
则会在流水线结束后发送另一条钉钉消息,包含构建结果的状态(成功或失败)、耗时时间、触发方式、分支以及用户信息。这里特别计算了流水线的执行时间,并将其格式化为分钟和秒数,使得通知内容更加直观。在实际应用中,通过
include
指令引入了这个共享模板文件,并在其管道配置文件中定义了一些全局变量,如镜像名称等。接着设置了多个阶段(check
、build
、build_ tag
、deploy_test
和deploy_ production
),每个任务节点都继承了.dingtalk
模板以实现钉钉通知功能。其中,
check
阶段用于代码检查,build
阶段负责构建镜像并定义了构建产物的保留策略,build_tag
则仅在有标签提交时触发,执行特定的构建任务。deploy_test
和deploy_ production
分别处理测试和生产环境的部署。特别值得注意的是,在
build
阶段启用了缓存和构建产物的保留策略,这对于优化 CI/CD 流程具有重要意义。此外,各个任务节点根据实际需求配置了不同的执行标签(如docker-ssh
和docker-docker
),以确保任务在合适的环境中运行。通过这种方式,作者不仅实现了钉钉通知的集成,还保持了配置文件的清晰和可维护性。这种模块化和模板化的配置方式,使得未来扩展和维护变得更加容易,同时也能更好地满足团队对实时监控构建状态的需求。
总的来说,这篇文章提供了一个实用且高效的解决方案,展示了如何在 GitLab CI/CD 中结合钉钉通知实现更智能、自动化的开发流程管理。对于希望提升团队协作效率并实时掌握项目进展的开发者来说,这种配置方式无疑是一个值得借鉴的最佳实践。
这篇博客介绍了如何在GitLab流水线中使用钉钉通知。博文首先展示了实现效果的预览图,然后详细介绍了如何创建基础仓库和流水线yml文件。
博文中的代码示例清晰明了,说明了如何创建钉钉消息发送模版任务和钉钉消息发送http Anchors。通过定义变量和发送请求,可以在流水线的不同阶段发送不同的钉钉消息,包括任务启动通知和任务执行结果通知。博文还提供了钉钉消息的模板,包括任务ID、任务名、提交信息、项目、分支、执行人和耗时等信息,并提供了查看项目和查看任务的链接。
博文的闪光点是提供了清晰的代码示例和详细的步骤说明,让读者可以很容易地在自己的GitLab流水线中实现钉钉通知功能。这对于需要及时了解流水线执行情况的开发团队来说非常有用。
改进空间方面,博文可以进一步扩展,例如可以介绍如何在钉钉通知中添加更多的信息,如代码覆盖率、测试结果等。此外,博文中的代码示例可以进一步注释和解释,以帮助读者更好地理解代码的作用和实现原理。
总的来说,这篇博客提供了一个很好的指南,帮助读者在GitLab流水线中实现钉钉通知功能。作者的写作方式清晰明了,给出了详细的步骤和代码示例,让读者能够轻松理解和复用。希望作者能够进一步扩展博文的内容,提供更多有关钉钉通知的实践经验和技巧。