用Flow.CI搭建CI/CD

一、前言

在上一篇文章里,我使用Travis来做自动部署,链接在此:Travis构建Google App Engine的CI/CD)。Travis使用起来挺方便,只不过它仅支持github。

不希望某些关键代码被人看到,而且,大部分代码托管在bitbucket上,挪移代码仓库不方便,考虑下来,只能找一个支持自定义代码仓库的CI平台了。
调研下来,有CodeShip/JenKins/Flow.Ci等几个工具。

CodeShip支持Bitbucket,只不过每个月只能构建100次。
JenKins是开源的,可以自己部署到服务器上,公司内部用的就是它,不过我不太喜欢JenKins,因为它的icon不甚好看…
Flow.Ci是国产开源的工具,现在(2018-02-13)还是Beta测试版本,类似Jenkins,自己部署,我选的就是它。

二、安装Flow.Ci

Flow支持Docker形式的安装过程,装好Docker之后步骤就简单多了。

a. 拉取Flow的配置代码:

1
2
git clone https://github.com/flowci/docker.git
cd docker

b.启动Flow的docker容器(把”yourhost.com”替换成服务器的域名):

1
FLOW_API_DOMAIN=yourhost.com FLOW_WEB_DOMAIN=yourhost.com ./start-services.sh

c.注册一个Flow的agent
打开url yourhost.com:3000,登录进去,在『系统管理』中增添一个Agent,记下Agent的token。

d.启动agent的docker容器(把”yourhost.com”替换成服务器的域名,把your-agent-token替换成上一步骤中得到的token):

1
docker run --network=host -v ~/.ssh:/root/.ssh -e FLOW_BASE_URL=http://yourhost.com:8080/flow-api -e FLOW_TOKEN=your-agent-token -d flowci/flow-agent:latest

到这里,Flow就算是安装并启动完成了。

三、配置自动部署脚本

(此文中用的demo项目还是上一篇Github里的项目appengine-try-java,如果你也想部署一遍到自己的服务器上的话,可以照上一篇文章的介绍进行改动。)

在Flow中创建一个项目,进入它的『工作流设置』,复制Webhook,注册到代码仓库中去(GitHub或是BitBucket)。

接着,配置YML工作流。

第一个step用于拉取git最新代码,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
echo "################################# clone code start..."
rm -rf qiuyongchen/appengine-try-java

git clone --branch=master https://github.com/qiuyongchen/appengine-try-java.git qiuyongchen/appengine-try-java
cd qiuyongchen/appengine-try-java
ls -lah

echo "################################# try to decrypt..."
openssl aes-256-cbc -K $encrypted_c9b056f6a4fd_key -iv $encrypted_c9b056f6a4fd_iv -in service-account.json.enc -out service-account.json -d
echo "################################# try to decrypt done..."

echo "################################# clone code done..."

cd ~
ls -lah
df -h

第二个step用于安装更新google cloud sdk,如下:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
java -version
pwd
ls -lah

export GOOGLE_APPLICATION_CREDENTIALS="$(pwd)/qiuyongchen/appengine-try-java/service-account.json"
export GOOGLE_CLOUD_PROJECT=red-cloud-177511
echo "################################# the gcloud_project is:" $GOOGLE_CLOUD_PROJECT

PYTHON=python
if which "$PYTHON" >/dev/null 2>&1; then
echo "################################# already has python..."
else
echo "################################# install python..."
apt-get install python
fi

set -e

echo "################################# check credential..."
if [[ -z "${GOOGLE_APPLICATION_CREDENTIALS}" ]]; then
echo "GOOGLE_APPLICATION_CREDENTIALS must be set" 1>&2
exit 1
fi

echo "################################# check project name..."
if [[ -z "${GOOGLE_CLOUD_PROJECT}" ]]; then
echo "GOOGLE_CLOUD_PROJECT must be set" 1>&2
exit 1
fi

GCLOUD_FILE="google-cloud-sdk.tar.gz"
if [[ -d google-cloud-sdk ]]; then
echo "################################# already has google cloud sdk..."
else
echo "################################# download google cloud sdk..."
wget https://dl.google.com/dl/cloudsdk/release/google-cloud-sdk.tar.gz
tar xzf google-cloud-sdk.tar.gz
rm -rf google-cloud-sdk.tar*

echo "################################# install google cloud sdk..."
./google-cloud-sdk/install.sh --usage-reporting false --path-update false --command-completion false
fi

source ./google-cloud-sdk/completion.bash.inc
source ./google-cloud-sdk/path.bash.inc

echo "################################# update google cloud sdk..."
gcloud -q components update app-engine-java

echo "################################# auth google cloud sdk..."
gcloud -q auth activate-service-account --key-file "${GOOGLE_APPLICATION_CREDENTIALS}"
gcloud -q config set project "${GOOGLE_CLOUD_PROJECT}"

echo "################################# show google cloud sdk..."
gcloud info

第三个step用于编译并部署代码到服务器上,如下:

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
set -e
set -x
# Set pipefail so that `egrep` does not eat the exit code.
set -o pipefail

source ./google-cloud-sdk/completion.bash.inc
source ./google-cloud-sdk/path.bash.inc
GOOGLE_CLOUD_SDK_ROOT="$(gcloud --format='value(installation.sdk_root)' info)"
export GOOGLE_APPLICATION_CREDENTIALS="$(pwd)/qiuyongchen/appengine-try-java/service-account.json"
export GOOGLE_CLOUD_PROJECT=red-cloud-177511

apt-get install expect

cd qiuyongchen/appengine-try-java

# Run tests using App Engine local devserver.
test_localhost() {
if [[ ! -d java-repo-tools ]]; then
git clone https://github.com/qiuyongchen/java-repo-tools.git
fi
# skip local run
# ./java-repo-tools/scripts/test-localhost.sh appengine:run . -- -DcloudSdkPath="$GOOGLE_CLOUD_SDK_ROOT"
# curl --silent --output /dev/stderr http://localhost:8080/demo
}

test_localhost

# deploy to google app engine
mvn appengine:deploy