Please enable Javascript to view the contents

常用的一些 CI 脚本

 ·  ☕ 3 分钟

由于负责小组的 CI 公共事项,经常需要配置 CI 流程,或者帮助其他人解决一些问题,整理了一下常用的 CI 脚本,以方便查阅。

1. .gitlab-ci.yml 结构

下面是, GitLab CI 的配置文件结构。

.gitlab-ci.yml 文件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 一些前置脚本,完成激活环境等操作
before_script:
  - source /data/runner/node/bin/activate
  - which node && node --version
  - which npm && npm --version
  - LANG="zh_CN.utf8"
  - export LC_ALL=zh_CN.UTF-8

# 编排需要执行的 stage
stages:
  - build
  - deploy

# 定义 job。job 属于某一个 stage,比如这里的 build 、deploy。GitLab CI 会按照 stages 配置的先后,顺序执行每一个 stage。

2. 编译 Webpack 工程并提交到 GitLab 仓库

这里约定:

  • 前端工程在根目录的 webpack 目录下
  • 前端工程编译之后的输出文件在根目录的 static/dist 目录下
  • 前端的编译命令是 npm run build

GitLab CI 内置变量可以去 这里 查看。也可以,使用关键字 variables 定义自己的变量。比如,上面的目录路径,就可以配置为变量。但是每个项目有其独特性,这里就没有写成通用的形式,避免误导。

通常,我会将一些账户信息配置在 settings/ci_cd 页面,并将这些变量勾选保护。勾选保护之后,只有受保护的分支才能够获取到这些变量,也就是下面的 GIT_USERNAMEGIT_PASSWORD 这部分。

这里强烈建议,不要直接在当前代码目录直接提交 Git,应该将代码重新拉一份到本地,以保证环境不被污染。

.gitlab-ci.yml 文件,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
stages:
  - build
build-webpack:
  stage: build
  variables:
  CI_REPOSITORY_URL:
    http://$GIT_USERNAME:$GIT_PASSWORD@gitlab.yourdomain.com/$CI_PROJECT_PATH.git
  cache:
    untracked: true
    paths:
      - webpack/node_modules
  script:
    - echo "start build and commit"
    - cd webpack
    # 可通过关键字优化
    - npm install
    # 可通过关键字优化
    - npm run build
    - cd ..
    - rm -rf git-dir
    - git clone -b $CI_COMMIT_REF_NAME http://$GIT_USERNAME:$GIT_PASSWORD@gitlab.yourdomain.com/$CI_PROJECT_PATH.git git-dir
    - cd git-dir && rm -rf ./static/dist
    - mv ../static/dist static/
    - git config --global user.name $GITLAB_USER_NAME
    - git config --global user.email $GITLAB_USER_EMAIL
    - git add static/dist
    # 避免循环构建
    - git commit -m "auto commit [ci skip]`git log -1 --pretty=%B`" || exit 0
    - git push $CI_REPOSITORY_URL $CI_COMMIT_REF_NAME >/dev/null 2>&1 || exit 0
    - echo "end build and commit"
  tags:
    # 指定 runner
    - linux
    - shell
  only:
    # 指定分支
    - master

3. 从 GitLab 推送代码到 SVN 仓库

由于发布系统采用的是 SVN 仓库,但是 Git 更适合多人开发协助,在开发的过程中使用的是 GitLab 仓库。

为了将 GitLab 仓库自动推送到 SVN 仓库,可以使用下面这个 job:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
push-to-svn:
  stage: deploy
  variables:
    CI_REPOSITORY_URL:
      http://$GIT_USERNAME:$GIT_PASSWORD@gitlab.yourdomain.com/$CI_PROJECT_PATH.git
  script:
    - echo "start push to svn"
    - echo "step 1/3: git clone"
    - git clone -b $CI_COMMIT_REF_NAME $CI_REPOSITORY_URL git-dir
    - echo "finished"
    - echo "setp 2/3: svn checkout"
    - echo 't' | svn checkout $SVN_PATH svn-dir --username $SVN_USERNAME --password $SVN_PASSWORD --no-auth-cache
    - echo "finshed"
    - echo "step 3/3: push git master to svn trunk"
    # 确保删除文件操作有效,可优化
    - cd svn-dir && svn delete *
    - rsync -avq git-dir/ svn-dir/
    - cd ./svn-dir
    - svn add * --force
    - echo 't' | svn commit -m "`git log -1 --pretty=%B`" --username $SVN_USERNAME --password $SVN_PASSWORD --no-auth-cache
    - echo "end push to svn"

4. 通过关键字控制执行的脚本

GitLab CI 提供了一些内置关键字用于控制 CI 的行为。比如,在提交信息中增加 [ci skip][skip ci] 就会跳过当次提交触发的 CI 构建。

受到这种想法的启发,我们也可以在脚本中,从提交信息中匹配一些关键字,用于控制脚本执行逻辑。

  • 通过是否有关键字 [install] ,判断是否执行依赖包的安装
1
if [[ $(git log -1 --pretty=%B) = *"["*"install"*"]"* ]]; then npm install; else echo "not npm install"; fi;
  • 通过是否有关键字 [build] ,判断是否进行前端的打包
1
if [[ $(git log -1 --pretty=%B) = *"["*"build"*"]"* ]]; then npm run build; else echo "not npm install"; fi;
  • 通过是否有关键字 [delete] ,判断在执行 SVN 推送时,是否需要删除文件。这里主要是由于 svn add * 命令不能将删除的文件提交,删除文件必须使用 svn delete 处理。如果不使用 svn delete 命令,会导致 GitLab 中被删除的文件,在 SVN 中实际上没有被删除。
1
if [[ $(git log -1 --pretty=%B) = *"["*"delete"*"]"*]]; then cd svn-dir && svn delete * && cd ..; else echo "not svn delete"; fi;

5. 从 yml 获取变量

yml 文件格式:

1
2
3
4
code: test
name: 测试
author: admin
version: 1.2.3

以上面的 yml 格式为例,需要获取相关字段信息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
parse_yaml() {
   local prefix=$2
   local s='[[:space:]]*' w='[a-zA-Z0-9_]*' fs=$(echo @|tr @ '\034')
   sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
        -e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p"  $1 |
   awk -F$fs '{
      indent = length($1)/2;
      vname[indent] = $2;
      for (i in vname) {if (i > indent) {delete vname[i]}}
      if (length($3) > 0) {
         vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
         printf("%s%s%s=\"%s\"\n", "'$prefix'",vn, $2, $3);
      }
   }'
}
eval $(parse_yaml test.yml "config_")

通过执行上面的脚本,可以获取到 test.yml 中的字段信息。

1
2
3
echo ${config_code}
echo ${config_name}
...

6. 将环境变量值,写到 yml 文件

yml 文件格式:

1
2
3
4
code: test
name: 测试
author: admin
version: 1.2.3

以上面的 yml 格式为例,获取环境变量中的 VER 值,并将其写到 version: 后面中。

1
sed -i "/version:/s/[0-9].*$/${VER}/g" test.yml

微信公众号
作者
微信公众号