Gitlab 的 CI 还是比较有好的,只要配置好一些 Shared Runner,所有的项目都可以共享这些 Runner 来跑 CI 了,这样比较节省资源,这些 Runner 勤勤恳恳地跑完了一个就去跑下一个。

但是 CD 自动部署稍稍有些麻烦,Gitlab 这边能做到的就是跑完所有的测试之后发送一个 Curl 通知,告诉 Build 所有的测试通过了,可以开始部署了。.gitlab-ci.yml 文件类似下面:

ZSH

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

image: reg.docker.com/laixintao/test:latest

stages:

  - test

  - deploy

unit_test:

  stage: test

  script:

    - pytest

  tags:

    - swarm

style_check:

  stage: test

  script:

    - flake8 --show-source --statistics

  tags:

    - swarm

deploy_staging:

  stage: deploy

  only:

    - master

  script:

    - curl -v your-domain.com:9999

这样 Runner 在所有的 test stage 执行完了之后,就会执行 deploy 这个 stage。

最后 deploy 这个地方只写了一个 curl ,那么接收 Gitlab 的通知,然后执行部署这个步骤就有些麻烦了。可能需要一个 HTTP 服务监听端口,在网上找了一些方案,有用 PHP 写的脚本,也有用 Python 写的,但是这样就有了更多的依赖要维护了。

找了一圈,发现 netcat 这个小巧的工具就能实现监听端口->响应请求->执行脚本部署的需求。

下面的命令可以一直监听 9999 端口,有请求的话就响应 echo 的内容。然后结束命令。

ZSH

1

echo -e "hello" | nc -l 0.0.0.0 9999

配合 && 连接起来,就可以做到通过 Curl 触发部署操作了。

ZSH

1

echo -e "HTTP/1.1 200 ok,glass\r\nConnection: close\r\n\r" |  nc -l 0.0.0.0 9999 ; sh /home/admin/update.sh >> /home/admin/logs/webhook.log 2>&1

通过 systemd,可以将这个脚本管理起来,让它永远重启,这样一次部署之后,马上就可以重新监听,等待下一次部署命令。注意要添加 StartLimitInterval ,限制一下执行的频率。最终的 systemd service 如下:

ZSH

1

2

3

4

5

6

7

8

9

10

11

12

13

14

[Unit]

Description=Autopull through webhook

After=network.target

[Service]

User=admin

Type=simple

ExecStart=/bin/bash -xc 'echo -e "HTTP/1.1 200 ok,glass\r\nConnection: close\r\n\r" |  nc -l 0.0.0.0 9999 ; sh /home/admin/deploy/update.sh >> /home/admin/logs/webhook.log 2>&1'

Restart=always

StartLimitInterval=1min

StartLimitBurst=60

[Install]

WantedBy=multi-user.target

这样就可以实现每次向 master push 代码,自动测试成功并且马上推送到测试环境中。 update.sh 脚本的最后可以加一个 Curl 命令向钉钉或者 slack 发送提醒。