先来说一下配置CI/CD的目的,我们在提交代码后即提交push请求后gitLab会自动生成一个pipeLine任务,如果我们想要在每次提交代码之后都跑一次单元测试就需要对其进行编辑,此外我们还可以在此运行我们自定义的脚本来实现更多需求,例如向钉钉发出推送。
下面这就是对应的配置文件——.gitlab-ci.yml
我们在此文件中主要用到的一共就只有下面几个关键词:
stages:设置运行步骤
variables:定义变量
tags:设置运行环境
script:设置要执行的命令
关于stages:
stages:
-step1 //步骤一
-step2 //步骤二
step_one:
stage: step1 //声明是属于步骤一
. . .
step_two:
stage: step1 //声明是属于步骤一
. . .
step_three
stage: step2 //声明是属于步骤二
. . .
其中step_one和step_two是并行执行的。step_two在其后执行。
关于variables需要提醒的是gitLab有自己内置的变量,我们可以直接进行使用,只需要在scrpts: 执行-env,就可以查看总共有那些变量。
关于scrpts:其作用就相当我们本地的在项目根目录下的终端,输入相应指令就可以在运行相应步骤时执行。
关于tags:声明运行时所用的环境
第一个问题—在远端执行时出现格式报错
我们自定义的脚本在本地运行没有问题后就提交到了gitlab中通过gitlab CI/CD调用时却发生了格式错误,例如:存在预期之外的“(”等报错。
在网上查找后所得到的问题出处都是出现在脚本解释器的说明上即脚本开头的 #!/bin/bash
但是经过测试——新建test.sh在远端运行通过bash解释器运行发现并没有问题,不会发生报错;
于是我又仔细地看了一边shell教程,发现这上面对于函数的说明是这样的:
没有用到function关键字,于是我尝试着去掉它之后发现确实不报错了,但之后在远端执行时还遇到等等其他的格式问题就不在此一一赘述了。
一步一步跟着远端运行的报错解决完格式问题后确实可以在远端完整运行我们自定义的.sh文件,但是为什么在本地就没有这些格式问题在远端就出现问题了当时还是没有解决,当时只是把它归结于可能是版本不一样。
所以这样的解决方法就带来了下面第二个问题:
问题二—获取pipeLine运行时间时遇到的问题
在gitlab给出的pipeLine自带的变量中只有pipeLine的创建时间:CI_PIPELINE_CREATED_AT
一开始是想可不可以直接在gitLab CI 运行时获得当前时间,直接在gitLab配置文件中计算出其时间差,但是找了很久都没有找到可以直接在gitLab CI中获取当前时间的方法,所以只能转变思路——把CI_PIPELINE_CREATED_AT
传给我们的shell脚本,在脚本中完成这些操作。
currentTime=`date "+%Y-%m-%d %H:%M:%S"` //获取时间
while [ -n "$1" ]; do //shell脚本是以字符串为单位接受的变量
case "$1" in
. . .
-M)
PIPE="$2" //把$2即传过来的时间赋给PIPE
CURRENT_STAMP=$(date -d "$currentTime" +%s) //转化为时间戳
PIPE_STAMP=$(date -d "$PIPE" +%s) //转化为时间戳
TIME_STRING=$((CURRENT_STAMP-PIPE_STAMP)) //计算时间戳差值
CONTENT=$CONTENT$TIME_STRING"秒"
shift 2 //将数据前移2项,即$1=$3,$2=$4...
;;
done
在本地执行之后可以正常运行,在远端运行时发现最后计算出来的差值始终为零,起初认为是pipe_line的开始时间有误,但是查看后与预期一致,于是就尝试着在脚本中输出转化后的起始时间戳和当前时间戳但是发现其打印结果都为空。
起初还是认为是由于版本不同,于是又在网上找了很多在shell中对时间戳的操作,但是基本上都是大同小异,都不适用。
到了最后才注意到tags字段,即给其设置运行环境,当我在其步骤中声明运行环境再运行就可以正常使用了。
tags:
- ubuntu
问题三—获取pipeLine对应的mergeRequest的链接时遇到的问题
我们推送到钉钉上的PipeLine的运行信息最好要附带上其对应的mergeRequest链接,但是在gitLab给出的环境变量中并没有直接给出mergeRequest链接,而是给出了CI_OPEN_MERGE_REQUESTS变量。
CI_OPEN_MERGE_REQUESTS=yunzhiclub/smart-community!9
这说明了其对应的mergeRequest编号是9,而我们还发现mergeRequest链接是这样的
https://gitlab.xxx.com:xxxx/xxxclub/smart-community/-/merge_requests/9
这也就是说我们可以人为把这个链接构造出来,其中/-/merge_requests/
部分是固定的,我们可以直接在脚本中声明,而https://gitlab.xxx.com:xxxx/xxxclub/smart-community
部分可以通过gitLab所给出的环境变量$CI_PROJECT_URL$mergeRequestUrl
获得。
然后我们要做的就是如何从CI_OPEN_MERGE_REQUESTS
中只获得其最后的编号,我们在shell中可以通过一下方法来从string1中获得截去string2部分的字符串string3。
string3 = ${string1#${string2}}
起初我也想过能不能直接在配置文件运行中直接修改我们要传给脚本的contetnt即内容主体,但是经过测试,在scrpts中运行命令只能获取配置文件中内容,但是在其中定义的变量无法被配置文件获取,所以我们还是在脚本中进行修改。
而我们所要去掉的部分即yunzhiclub/smart-community
可由CI_PROJECT_PATH
获得,所以我们要做的就是把这些传给脚本,即
//配置文件中
- sh send-ding.sh-U $CI_PROJECT_URL$mergeRequestUrl${CI_OPEN_MERGE_REQUESTS#${CI_PROJECT_PATH}"!" . . .
-U)
MERGE_URL="$2"
MARKDOWN_URL="### [pullRequest]($MERGE_URL)"
CONTENT=$MARKDOWN_URL"\n"$CONTENT
shift 2
;;
但是使用CI_OPEN_MERGE_REQUESTS
获得mergeRequest编号会有一个bug,比如我们进行完一次push后开启mergeRequest这时是没有问题的,但是当我们关闭这个mergeRequest,再进行push然后再开启mergeRequest就会发现CI_OPEN_MERGE_REQUESTS
中所对应的mergeRequest还是第一次提出的mergeRequest,目前在搜集相关资料后也没能找到很好的解决方法。