在介绍.gitlab-ci.yml以前,咱们先看几个概念:node
通常来讲,构建任务都会占用不少的系统资源 (譬如编译代码),而 GitLab CI
又是 GitLab
的一部分,若是由 GitLab CI
来运行构建任务的话,在执行构建任务的时候,GitLab
的性能会大幅降低。git
GitLab CI
最大的做用是管理各个项目的构建状态,所以,运行构建任务这种浪费资源的事情就交给 GitLab Runner
来作啦。由于 GitLab Runner
能够安装到不一样的机器上,因此在构建任务运行期间并不会影响到 GitLab
的性能。web
GitLab Runner
的安装特别简单,官网有各平台的安装方法或安装包,此处再也不赘述。正则表达式
GitLab
中的项目页面,在项目设置中找到 runners
runner
运行的机器上,用命令行注册,好比:gitlab-runner register --name="XX" --url="https://git.xx.com/" --token="XXX" --executor="shell"redis
按照提示一步一步安装就能够了。其中,executor
能够是多种类型,简单的话能够选shell
。有熟悉docker
的可使用docker
。docker
配置文件在/etc/gitlab-runner/config.toml
shell
配置项相似下面,可能须要手动添加builds_dir
和cache_dir
这两个变量,再重启服务npm
[[runners]] name = "216XX" url = "https://git.XX.com/" token = "XX" executor = "shell" builds_dir = "/home/gitlab-runner/builds" cache_dir = "/home/gitlab-runner/cache" [runners.cache]
sudo gitlab-runner list 查看各个 Runner 的状态 sudo gitlab-runner stop 中止服务 sudo gitlab-runner start 启动服务 sudo gitlab-runner restart 重启服务
Stages
表示构建阶段,说白了就是上面提到的流程。默认有3个stages
:build
, test
, deploy
。咱们能够在一次 Pipeline
中定义多个 Stages
,这些 Stages
会有如下特色:windows
Stages
会按照顺序运行,即当一个 Stage
完成后,下一个 Stage
才会开始Stages
完成后,该构建任务 (Pipeline) 才会成功Stage
失败,那么后面的 Stages
不会执行,该构建任务 (Pipeline) 失败Jobs
表示构建工做,表示某个 Stage
里面执行的工做。咱们能够在 Stages
里面定义多个 Jobs
,这些 Jobs 会有如下特色:缓存
一、相同 Stage
中的 Jobs
会并行执行
二、相同 Stage
中的 Jobs
都执行成功时,该 Stage
才会成功
三、若是任何一个 Job
失败,那么该 Stage
失败,即该构建任务 (Pipeline) 失败
.gitlab-ci.yml
用来配置 CI
用你的项目中作哪些操做,这个文件位于仓库的根目录。
当有新内容push
到仓库,或者有代码合并后,GitLab
会查找是否有.gitlab-ci.yml
文件,若是文件存在,Runners
将会根据该文件的内容开始build
本次commit
。
.gitlab-ci.yml
使用YAML
语法, 你须要格外注意缩进格式,要用空格来缩进,不能用tabs
来缩进。
任务中必须得有script
部分。
# 定义 stages(阶段)。任务将按此顺序执行。 stages: - build - test - deploy # 定义 job(任务) job1: stage: test tags: - XX #只有标签为XX的runner才会执行这个任务 only: - dev #只有dev分支提交代码才会执行这个任务。也能够是分支名称或触发器名称 - /^future-.*$/ #正则表达式,只有future-开头的分支才会执行 script: - echo "I am job1" - echo "I am in test stage" # 定义 job job2: stage: test #若是此处没有定义stage,其默认也是test only: - master #只有master分支提交代码才会执行这个任务 script: - echo "I am job2" - echo "I am in test stage" allow_failure: true #容许失败,即不影响下步构建 # 定义 job job3: stage: build except: - dev #除了dev分支,其它分支提交代码都会执行这个任务 script: - echo "I am job3" - echo "I am in build stage" when: always #无论前面几步成功与否,永远会执行这一步。它有几个值:on_success (默认值)\on_failure\always\manual(手动执行) # 定义 job .job4: #对于临时不想执行的job,能够选择在前面加个".",这样就会跳过此步任务,不然你除了要注释掉这个jobj外,还须要注释上面为deploy的stage stage: deploy script: - echo "I am job4" # 模板,至关于公用函数,有重复任务时颇有用 .job_template: &job_definition # 建立一个锚,'job_definition' image: ruby:2.1 services: - postgres - redis test1: <<: *job_definition # 利用锚'job_definition'来合并 script: - test1 project test2: <<: *job_definition # 利用锚'job_definition'来合并 script: - test2 project #下面几个都至关于全局变量,均可以添加到具体job中,这时会被子job的覆盖 before_script: - echo "每一个job以前都会执行" after_script: - echo "每一个job以后都会执行" variables: #变量 DATABASE_URL: "postgres://postgres@postgres/my_database" #在job中能够用${DATABASE_URL}来使用这个变量。经常使用的预约义变量有CI_COMMIT_REF_NAME(项目所在的分支或标签名称),CI_JOB_NAME(任务名称),CI_JOB_STAGE(任务阶段) GIT_STRATEGY: "none" #GIT策略,定义拉取代码的方式,有3种:clone/fetch/none,默认为clone,速度最慢,每步job都会从新clone一次代码。咱们通常将它设置为none,在具体任务里设置为fetch就能够知足需求,毕竟不是每步都须要新代码,那也不符合咱们测试的流程 cache: #缓存 #由于缓存为不一样管道和任务间共享,可能会覆盖,因此有时须要设置key key: ${CI_COMMIT_REF_NAME} # 启用每分支缓存。 #key: "$CI_JOB_NAME/$CI_COMMIT_REF_NAME" # 启用每一个任务和每一个分支缓存。须要注意的是,若是是在windows中运行这个脚本,须要把$换成% untracked: true #缓存全部Git未跟踪的文件 paths: #如下2个文件夹会被缓存起来,下次构建会解压出来 - node_modules/ - dist/
https://git.xx.com/ci/lint
若是你的commit
信息包涵[ci skip]
或者[skip ci]
,不论大小写,这个commit
将会被建立,可是job
会被跳过
使用shell
脚本时,每步job
一开始总有不短的等待时间,对于咱们而言是没必要要的,除去后台jenkins_build
这步外,仍要最快20
分钟。
以前,我曾在release
分支时,暂时将各步整合到一个job
里,时间缩短为5
分钟。固然,这是不符合语义的。
最近,发现docker
没有这个问题。因此,建议使用docker
。
如下是咱们项目中使用的.gitlab-ci.yml
文件:
image: xx:1.0 stages: - jenkins_build - install - test - build - e2e - zip - copy - end cache: policy: pull key: "$CI_COMMIT_REF_NAME" paths: - node_modules/ - .eslintcache variables: DOCKER_DRIVER: overlay2 GIT_STRATEGY: "fetch" .template: &templateDef # 建立一个锚,'template' only: - master - release - dev install: stage: install <<: *templateDef # 利用锚'templateDef'来合并 cache: key: "$CI_COMMIT_REF_NAME" paths: - node_modules script: - cnpm i eslint: stage: test <<: *templateDef script: - npm run eslint unit: stage: test <<: *templateDef script: - npm run unit build: stage: build <<: *templateDef only: - release script: - npm run clear_dist - npm run build .e2e_ci: stage: e2e <<: *templateDef script: - npm run e2e_ci zip: stage: zip <<: *templateDef only: - release script: - npm run zip ## Jenkins 复制 jenkins_copyweb: stage: copy <<: *templateDef only: - release script: - ssh $JENKINS_SERVER_IP /jenkins/XX_copyweb.sh ## Jenkins 提交 jenkins_commit: stage: end <<: *templateDef only: - release script: - ssh $JENKINS_SERVER_IP /jenkins/XX_svn_commit.sh ## Jenkins 构建 jenkins_build: stage: jenkins_build <<: *templateDef only: - master script: - ssh $JENKINS_SERVER_IP /jenkins/build.sh
其中,XX:1.0
是咱们本身建立的docker
镜像,它主要安装了nodejs
、cnpm
、jdk
、sshpass
,其中sshpass
不是必须的,它是使用密码登录宿主机时的一种方案。
如今,咱们使用ssh
来与宿主机交互,须要将容器内生成的ssh
的key
(ssh-keygen -t rsa
),即/root/.ssh/id_rsa.pub
中内容,复制到宿主机的/root/.ssh/authorized_keys
文件中。
配置文件/etc/gitlab-runner/config.toml
修改成
[[runners]] name = "216xx" url = "https://git.xx.com/" token = "xx" executor = "docker" [runners.docker] tls_verify = false image = "xx:1.0" privileged = false disable_cache = false pull_policy = "if-not-present" volumes = ["/cache","/tmp:/tmp:rw"] shm_size = 0 [runners.cache]
其中,pull_policy
是下载docker
镜像image
的策略,默认会先从网上找,没有就报错,咱们改成先从本地找;volumes
是将docker
中的数据卷挂载到宿主机上。