背景

是这样的,公司内有一个需求是在 CI 阶段完成文档的构建和输出到另一个工程,那就需要在 gitlab 提供的工具(框架)内完成这件事,于是就开始和 .gitlab-ci.yml 纠缠的这件事

准备

首先要熟悉一下这个 yml 文件,文件的基本语法百度都有就不赘述,这里只记录一下我的问题

其实我本想在 Merge 之后再做这件事,本以为会有个这种事件,但是其实不是的,这个文件内的所有 stage 都是在合并前执行的

换句话说,只有 push 了,就会触发 pipeline , 执行的流程也就是 stage 的顺序

解决环境依赖

这就很狗了, gitlab 的 runner 只提供一个最基础的运行环境,那我们需要 apidoc / git 这些工具就很难办,不过还好公司使用的是 k8s ,还好 gitlab 支持 docker

所以增加了一个 image: xxx:xx 的配置项,我分了两个阶段,第一个阶段是生成文档的 json ,第二个阶段是把生成出来的 json 同步到另外一个仓库,阶段二很简单,有现成的 git 镜像可以直接使用,但是阶段一就很难看了, apidoc 并没有提供镜像,何况我还需要几个插件,所以只好自己封装一个镜像,问题至此也解决了

解决文件的跨任务传递

那么既然是两个阶段来完成,而且生成的 json 是需要在第二个阶段去上传的,那就必须将生成的 json 文件传递到阶段二,也就是第二个任务,我忘记怎么搜索的了,但是最后的解决方法是在第一阶段的任务中增加以下配置

artifacts:

paths:

- file

同其他 git 仓库交互

最终生成的 json 文件还是要上传到指定的仓库的,对此我找到了一篇文档

https://cloud.tencent.com/developer/article/2186300

我做简要概述

首先生成自己的 access_token ,然后将此 token 和自己的用户名字注入进 CI 中,分别命名为 GITLAB_TOKEN / GITLAB_USERNAME

那么拉取的模版就是

git clone “https://${GITLAB_USERNAME}:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${GITLAB_USERNAME}/test_json.git”

推送的模版就是

git push https://gitlab-ci-token:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${GITLAB_USERNAME}/test_json.git master

那其实还有个问题,不是每次 push 都修改了文档的,也就是没有必要每次都触发 pipeline, 对此我并没有更好的办法,只能做局部的优化

每次生成完 json 文件后,检查有没有变更,如果没有就放弃提交

最后放上我的完整 yaml 文件

# 定义两个步骤, 生成文档和同步生成的文档去另一个仓库
stages:
  - genDocs
  - syncJsonRepo

genDocJob:
  stage: genDocs
  script: 
    - echo "I'm doing gen doc..."
    - apidoc -h
    - node -v && apidoc --version
    - apidoc -i apps --write-json -o apidoc/
    - cp ./apidoc/assets/api-data.json ./
    - rm -rf apidoc/
  only:
    refs:
      - dev # 仅在 dev 分支生效
  image: wzhihui/uhome_api_doc:0.3 # 使用包含 apidoc 的镜像
  artifacts:
    paths:
      - api-data.json # 这个是生成的 json


syncJsonRepoJob:
  stage: syncJsonRepo
  script:
    - echo "I'm doing sync json repo job.."
    - git config --global user.email "ci@example.com"
    - git config --global user.name "ci"
    - git clone "https://${GITLAB_USERNAME}:${GITLAB_TOKEN}@${CI_SERVER_HOST}/json.git" # 使用 access_token 来拉取
    - cp ./api-data.json ./json/
    - cd json
    - |
      if [[ $(git status --porcelain) ]]; then
        git add . && git commit -m "from ci"
        git push https://gitlab-ci-token:${GITLAB_TOKEN}@${CI_SERVER_HOST}/json.git master
      else
      echo "nothing to change"
      fi
  only:
    refs:
      - dev
  image: bitnami/git:2.42.0