2023-03-02
< view all posts最近写了一个小工具,让它在每次commit之后,自动统计仓库里面的一些内容,并且在仓库内生成一份新的统计文件。查询资料之后,了解到在GitLab的CI/CD Runner中,是可以使用git命令的,能够实现这样的功能。下面记录一些容易遇到问题的细节。
首先,需要为项目生成一个 Project Access Token ,在项目左侧的Settings-Access Tokens里面操作。注意这个token是必须设定一个过期日期的。
在拿到这个token之后,在项目的 .gitlab-ci.yml 文件中,push时使用这样的配置:
git push http://[任意一个用户名]:[生成的token]@[gitlab地址]/具体仓库路径.git HEAD:master
注意点有几个。一是看一下本地的GitLab有没有启用 https ,如果用的是 http 的话,使用 https 连接就会遇到443报错: git failed to connect to port 443。另一个点是用户名可以是任意的,不一定是自己的账户名称/仓库名称。例如:
git push http://anything:tokenxxxxxxxxx@127.0.0.1/user/repo.git HEAD:master
在提交的时候还有一个注意点。因为我们不希望这次CI当中的自动commit再次触发CI(那样就会无限循环),因此需要指定跳过CI的配置。虽然GitLab提供了 git push -o ci.skip 的选项,但这个选项有两个缺点。其一是 -o ci.skip 在进行Merge Request是时候是不触发的,其二是旧版本的GitLab并不支持这个选项。更方便的方法是在commit message中标明 [skip ci] 。方法非常简单,直接写在message里面就行:
git commit -m "xxxxxx [skip ci]"
在实践中还遇到了一个问题,CI/CD流水线前几次都能正常运行,但一定次数之后就开始报错:
fatal: git fetch-pack: expected shallow list fatal: The remote end hung up unexpectedly
查阅资料之后发现这是因为GitLab的CI/CD runner中的git版本太旧,不支持 fetch-pack 命令。最简单的修复方法是在yml文件中增加如下配置:
variables: GIT_STRATEGY: clone
最后,我们希望这个CI只在某个文件被改动时触发,其它文件改动时不触发,可以使用如下的配置:
rules: - changes: - filename
总结上面这些点之后,以下是一份运行成功的 .gitlab-ci.yml 模板:
image: python:latest variables: GIT_STRATEGY: clone before_script: - python --version - git --version run: script: - python do_something.py - git config user.email "xxx@mail.com" - git config user.name "bot" - git add . - git commit -m "auto push back [skip ci]" - git push http://anything:tokenxxxxxxxxx@127.0.0.1/user/repo.git HEAD:master rules: - changes: - filename