版本控制的重要性应该是毋庸置疑了,git 作为现在最流行的版本控制工具,各种规模的公司都在用。通常开源项目都会放在 github 上,基础功能是免费的,私有项目收费。对于一个小团队来说,gitlab 就是另外一个替代品,可以用来搭建自己私有的git服务器。

为什么需要版本控制和持续继承?

经常听到很多程序员说自己没有时间写测试用例,但其实很多人的时间都花在了手动测试,修复bug,调试程序上。如果写好测试用例,每次提交代码后都自动进行编译,然后将测试用例全部跑一遍,如果测试失败能够获取到足够的反馈信息,这样避免了重复构建测试环境,手动运行测试用例等低效率的工作,而这就是持续集成的好处。

准备工作

docker 环境

安装 docker 环境,centos 的话可以使用 sudo yum install -y docker 直接安装

之后启动 dockersudo service docker start

docker 镜像加速

由于国内的网络环境过于恶劣,多次尝试从 gitlab 官网下载源码安装包未果,之后发现 gitlab 还提供 docker 镜像,这样不仅部署方便,利用国内一些云服务商提供的镜像加速功能,可以加速 docker 镜像的下载。

推荐 daocloud 的镜像加速服务,https://dashboard.daocloud.io/mirror,安装之后,使用 dao pull 替代 docker pull 即可。

下载相关docker镜像

  • gitlab/gitlab-ce:latest (gitlab 的 docker镜像)
  • gitlab/gitlab-runner:latest (用于持续集成,构建测试环境)
  • golang:1.5 (golang基础环境,用于编译代码,运行测试用例)

启动 gitlab

具体的官方说明文档:http://doc.gitlab.com/omnibus/docker/README.html

启动 gitlab 就是启动相应的 docker 镜像,设置好相关配置参数,命令如下:

sudo docker run --detach \
    --hostname x.x.x.x \
    --publish 7000:443 --publish 80:80 --publish 7002:22 \
    --name gitlab \
    --restart always \
    --volume /srv/gitlab/config:/etc/gitlab \
    --volume /srv/gitlab/logs:/var/log/gitlab \
    --volume /srv/gitlab/data:/var/opt/gitlab \
    gitlab/gitlab-ce:latest

如果你的机器开启了 SELINUX,需要使用如下的命令

sudo docker run --detach \
    --hostname x.x.x.x \
    --publish 7000:443 --publish 80:80 --publish 7002:22 \
    --name gitlab \
    --restart always \
    --volume /srv/gitlab/config:/etc/gitlab:Z \
    --volume /srv/gitlab/logs:/var/log/gitlab:Z \
    --volume /srv/gitlab/data:/var/opt/gitlab:Z \
    gitlab/gitlab-ce:latest

hostname 可以是gitlab服务器的ip,也可以是绑定的域名,80端口需要映射到宿主机的80端口,因为之后 github-ci-runner 会从这个端口下载测试源码。

/srv/gitlab 是用于持久化 docker 容器中产生的数据,例如 redispostgresql 等等,gitlab 的docker 镜像中已经内置了这些服务。

启动成功后,可以通过浏览器访问80端口来使用 gitlab 了,可能是由于我的测试服务器配置较低,等待约2分钟后才能访问。

初始帐号和密码为 root  5iveL!fe,第一次登录成功后需要修改密码。

gitlab 的具体使用文档比较多,这里就不详细介绍了。

创建测试项目

简单创建一个 test 项目,先不要提交到 gitlab 仓库。

包含一个 a.go 文件,文件内容如下

package main

import fmt 

func main() {
    fmt.Printf("aaa\n")
}

可以看到 import 包名没有加双引号,显然编译时就会出错。

添加 .gitlab-ci.yml 文件

配置文件详细内容请参考 http://doc.gitlab.com/ce/ci/yaml/README.html

这里简单写一下,仅仅用于测试:

image: golang:1.5

job1:
    script:
        - go build a.go
        - ./a

image 表示使用 golang:1.5 的 docker 镜像来部署编译和测试代码,我们之前已经下好了。

测试命令有两条,go build a.go 编译源码, ./a 执行编译后的程序。

获取 Runner registration token

registration-token

gitlab 的管理员配置界面,左边有一个 Runners,点进去之后可以看到有一个 Registration token,这个是用于之后创建的 runner 服务与 gitlab 通信的时候认证使用。

例如图中的 Registration tokenXKZmVj9t8j4xj1e5k34N

启动 Runner

Runner 官方详细说明文档: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/install/docker.md

Runner其实就是用于编译和管理测试环境的服务,当 gitlab 上的项目有 commitmerge 的时候,Runner 可以 hook 到相关信息,然后从 gitlab 上拉取代码,利用 docker 创建一个新的测试环境,之后执行 .gitlab-ci.yml 文件中预先配置好的命令。

docker run -d --name gitlab-runner --restart always \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v /srv/gitlab-runner/config:/etc/gitlab-runner \
      gitlab/gitlab-runner:latest

如果你的机器开启了 SELINUX,需要使用如下的命令:

docker run -d --name gitlab-runner --restart always \
      -v /var/run/docker.sock:/var/run/docker.sock \
      -v /srv/gitlab-runner/config:/etc/gitlab-runner:Z \
      gitlab/gitlab-runner:latest

关联 gitlab

启动成功后的 Runner 需要在 gitlab 上注册,通过在 Runner 上执行注册命令,会调用 gitlab 的相关接口注册。

docker exec -it gitlab-runner gitlab-runner register

Please enter the gitlab-ci coordinator URL (e.g. [https://gitlab.com/ci](https://gitlab.com/ci) )
[https://gitlab.com/ci](https://gitlab.com/ci)(这里的gitlab.com替换成之前启动gitlab时填写的 hostname)

Please enter the gitlab-ci token for this runner
xxx(填写获取到的 runner registration token)

Please enter the gitlab-ci description for this runner
my
INFO[0034] fcf5c619 Registering runner... succeeded

Please enter the executor: shell, docker, docker-ssh, ssh?
docker

Please enter the Docker image (eg. ruby:2.1):
golang:1.5
INFO[0037] Runner registered successfully. Feel free to start it, but if it's
running already the config should be automatically reloaded!

测试

利用 docker 来搭建这套环境还是非常简单的。

接着提交我们之前创建的两个文件,a.go.gitlab-ci.yml

访问 gitlab 查看 build 的结果。

test-commit

可以看到提交记录右边有一个红叉,表示测试未通过,点击红叉,可以看到测试的摘要信息。

test-info

继续点 红色的 failed 按钮就可以看到详细的测试信息。

test-deatil

Runner 测试过程的输出信息可以看出来,Runnerpull 我们指定的 docker 镜像,这里是 golang:1.5,之后 git clone 代码到测试环境,然后开始执行测试命令,在执行 go build a.go 的时候出现了错误,并且显示了错误信息。

将错误的代码修改后再次提交

package main

import (
    "fmt"
)

func main() {
    fmt.Printf("aaa\n")
}

可以看到能够通过测试了,执行程序后的输出 aaa 也能够看到。

test-commit-all

test-succ-detail