基于 Lark 机器人的 CI/CD 构建通知

495 阅读5分钟

背景

  1. 随着时间的推移,我们维护的代码仓库越来越多,基本上每个组都有快10个仓库,甚至远超这个数。基于目前的架构而言,我们每个代码仓库有一个 .gitlab-ci.yml, 此文件维护的是 CI 配置文件。 每个仓库 对应的在 argocd 项目里面有 2个 [*.yaml] 文件,这两个文件维护的是 CD 配置文件。
  2. 基于上述背景,我们一个代码仓库需要维护 有 3个 [*.yaml] 配置文件,分别是1个 CI 配置文件,2个 CD 配置文件。 且 2个CD 配置文件维护在 argocd 两个仓库,对应的一个是 state 环境 argocd 仓库,一个 prod 环境 argocd 仓库。
  3. 前端组每个项目有一个 lark 文档,此文档上 维护 CI /CD 发布流程 & 该前端项目在 两个 argocd 仓库需要编辑的 [*.yaml] 文件 地址。(因为 CD 的时候需要变更 tag, 所以需要维护 stage 环境的 [*.yaml]发布文件 & prod 环境的 [*.yaml]发布文件)

痛点

  1. 我们每次 CI 都是通过 Merge request 触发,因为每个 项目 配置的 CI job 不太一样,有的需要配置 CDN, 有的需要启动 SSR 服务,造成的问题就是 CI 构建时间不确定。 我们没办法确定 CI 具体多久才能跑完,可能几分钟也可能十几分钟跑完。因为 我们需要拿着 CI 产生的 tag 去 进行 CD。所以我们需要打开浏览器的页面 一直等待 pipeline, 查看 pipeline 状态。 有时候我们比较忙的时候,一边编写代码,过几分钟来看一下 CI 状态, 看有没有构建完成
  2. 因为维护的仓库较多,我们可能 也记不清每次 CI 完成的时候, 对应的业务代码仓库 在 argocd上面 需要 CD 的[*.yaml] 文件具体的文件名。我们可能要去查看一下 该项目的文档,确认一下需要编辑的 具体是 argocd 仓库 哪个 [*.yaml]发布文件
  3. 新人加入团队,在 CI 完成的时候,不知道去哪里进行后续的 CD,因为不确定 具体要编辑 argocd仓库 哪个 [*.yaml] 配置文件

前端组作出的调整

  1. 我们通过在 CI 完成阶段,通过 curl 发送一个 jsonlark 机器人,明确告知 CI 已经完成。 这样,大家不需要一直刷新 gitlab 页面,只需要看群消息即可 查看 pipeline 构建状态

  2. 发送给 lark 的消息卡片里面,包含了 此次构建产生的 tag,这个 tag 就是我们去 argocd 仓库 编辑 [*.yaml] 的 重要变更。 且包含变更的仓库名字,方便我们确定哪个仓库在构建

  3. 发送给 lark 的消息卡片里面,还包含本次 CD 需要编辑 的 argocd 仓库 具体的某一个文件绝对路径

  1. 上图中, 在 CI 完成阶段,会发出一个消息到 lark 群,且明确告知 tag 版本号 和 仓库名称。 图中 点击我跳转到CD仓库链接 这个超链接文字,当用户点击 会 跳转到对应的 环境的 argocd 需要编辑的 CD 文件,基于不同的环境构建 可以跳转到不同的 argocd 仓库文件, 可以明确跳转到 stage 环境编辑的 文件 还是 Prod 环境编辑的文件 (图例: 区分了 stage 环境 和 prod 环境 需要编辑的 文件)

  2. 我们直接点击 点击我跳转到CD仓库链接 这个超链接文字,会在浏览器自动定位到需要改动的文件,我们直接复制 tag号 ,选择 Edit single file 即可在浏览器直接编辑此文件,且自动创建一个分支

image.png

  1. 基于上述,我们在 业务代码 提完 Merge Request, 可以不关心 pipeline 状态,等着群里的消息。等群里有消息之后,点击 lark 消息卡片,复制对应的 tag 号,直接粘贴进 CD 文件,点击 argocd merge 按钮 即可

  2. 且 开发同学也不需要记住 具体 某个仓库 在 CD 时,需要编辑 argocd 仓库具体 哪个 [*.yaml] 文件

  3. 新人入职之后也不需要问来问去,直接点击群消息编辑文件即可完成CD 工作

如何接入

  1. 在对应的 lark 群, 添加机器人,添加机器人文档在这里 open.larksuite.com
  2. CI 仓库接入, LARK_WEBHOOK_URLlark 群的 webhook地址。 ARGOCD_STAGE_URL 是需要编辑的 argocd 仓库 CD 文件,这里默认是 stage 环境文件
variables:
  LARK_WEBHOOK_URL: 'xxx' 
  ARGOCD_STAGE_URL: 'test-url'

publish-job:
  ...
  variables:
      REQUEST_STAGE_JSON: |
          {
            "msg_type":"post",
            "content":{
              "post":{
                "zh_CN":{
                  "title":"platform-web-ui 仓库 stage 环境 CI 执行成功",
                  "content":[
                    [
                      {"tag":"text","text":"请去 执行 CD 工作, CD tag 版本号是: $CI_COMMIT_SHORT_SHA"},
                      {"tag":"a","text":"点击我跳转到 测试环境 CD仓库链接, ","href":"$ARGOCD_STAGE_URL"},
                      {"tag":"text","text":"触发者: $GITLAB_USER_NAME"}      
                    ]
                  ]
                }
              }
            }
          }
  script:
    - docker build -t $APP_REPO_NAME:$CI_COMMIT_SHORT_SHA .
    - docker push --all-tags $APP_REPO_NAME
  after_script:
    - 'curl -X POST -H "Content-Type: application/json" -d "$REQUEST_JSON" $LARK_WEBHOOK_URL'


publish-job-prod:
  variables:
    ARGOCD_PROD_URL: 'prod--url'
    REQUEST_PROD_JSON: |
      {
        "msg_type":"post",
        "content":{
          "post":{
            "zh_CN":{
              "title":"platform-web-ui 仓库 prod 环境 CI 执行成功",
              "content":[
                [
                  {"tag":"text","text":"请去 执行 CD 工作, CD tag 版本号是: $CI_COMMIT_TAG"},
                  {"tag":"a","text":"点击我跳转到 生产环境 CD仓库链接, ","href":"$ARGOCD_PROD_URL"},
                  {"tag":"text","text":"触发者: $GITLAB_USER_NAME"}      
                ]
              ]
            }
          }
        }
      }
  script:
    - echo Docker-Image-Tag=${CI_COMMIT_TAG}
    - docker build -t $APP_REPO_NAME:${CI_COMMIT_TAG} -f Dockerfile .
    - docker push $APP_REPO_NAME:${CI_COMMIT_TAG}
  after_script:
    - 'curl -X POST -H "Content-Type: application/json" -d "$REQUEST_JSON" $LARK_WEBHOOK_URL'

3. 上面的 yamlCI 期间明确区分了 不同的 job,分别对应的 stage 环境 jobprod 环境 job。默认给了一个 stage 环境需要编辑的 [*.yaml]发布文件,执行 prod job 在变更 [*.yaml]发布文件地址 4. REQUEST_JSON 就是发送给 lark 的消息体, CI_COMMIT_TAG gitlab 自带的

  1. 因为前端需要执行 build,俗称的 打包操作,所以这个发送 消息到 lark ,目前前端放在 打包完成之后发送,这样确保打包完成,在发送消息到 lark, 所以放在 after_script
  2. 各个组的业务不一样,但是最终 CI 构建完成都有一个 docker 镜像,可以在 构建 docker 镜像完成之后,触发 CI 通知到 lark 的机器人
  3. 至于 CD 完成之后,需要不要同步到 lark 群,我觉得暂时没必要,因为 CD 很快,点击完 merge 按钮就 立马开始 CD