7

DevOps | 基于 Drone CI 部署 Go 语言项目 — Web Server

 2 years ago
source link: https://ijayer.github.io/post/tech/devops/cicd/20181029-cicd-03-drone-03-practices2/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

DevOps | 基于 Drone CI 部署 Go 语言项目 — Web Server

2018-10-29 5401 words 11 mins read 886 times read

前面完成了基础设施搭建和测试,接下来就该将 Drone CI/CD 应用到项目中了。 这里涉及到的前几篇内容有:

这里以一个 Golang 项目(Go-Web-App)为例,基于 Drone CI 服务完成其自动化部署工作流的配置和演示:主要步骤包含:

clone => test => build => image => deploy => notify

包含开发的完成流程说明:

  • 开发项目代码, 包括源码文件,.drone.yml 文件、Dockerfile 文件等配置文件和一系列执行脚本(*.sh)
  • 提交代码:pushpull requesttag 到代码仓库(Bitbucket Server), 通过 Webhook 触发 Drone 的 Pipeline
  • Drone 开始 Pipeline 的执行

    • Clone 代码至容器(Drone 默认执行)
    • 执行单元测试
    • 编译代码,构建生成可执行程序
    • 构建 Docker 镜像,并发布到 Docker Registry
    • 打包资源文件、执行脚本、配置文件等到远程测试服务器
    • 部署应用容器到测试环境

Note: Drone 引入了 pipeline 的概念,上述整个构建过程由多个 stage 组成,每一个 stage 都是在一个 Docker 容器内执行:

  • 各 stage 间可以通过共享宿主机的磁盘目录, 实现 build 阶段的数据共享和缓存基础数据, 实现加速下次 build 的目标
  • 各 stage 也可以共享宿主机的 docker 环境,实现共享宿主机的 docker image, 不用每次 build 都重新拉取 base image,减少 build 时间
  • 可以并发运行。多个 build 可以并发运行,单机并发数量由服务器 cpu 数决定

准备 Go-Web-App 演示项目

Go-Web-App Demo Project 简介:

  • 由 Golang 实现一组 RESTFul API
  • 由 Gorilla Mux 提供路由
  • 由 MongoDB 提供数据存储服务

准备 Go-Web-App 项目:

  • 创建源码根目录

    $ cd /home/workspace/code/bitbucket/
    $ mkdir goweb-app && cd goweb-app
    • 初始化工程
    $ git init
    $ touch .gitignore README.md
    $ echo .idea >> .gitignore
    $ git add --all
    $ git commit -m "Initial Commit"
    $ git remote add origin http://admin@<_bitbucket_server_>.com:7990/scm/sof/goweb-app.git
    $ git push -u origin master
  • 添加源码文件

    $ mkdir api cicd www 
    #   - cicd:存放 Drone CI 服务的相关配置文件和脚本
    #   - www: 存放网站资源
    $ touch api/app.go api/model.go main.go main_test.go
    • 源码内容可以 Click Here 进行拷贝。

    • 初始化 go module 并运行项目

    $ go mod init go-web
    $ go run .
    go: finding github.com/gedex/inflector latest
    go: finding gopkg.in/mgo.v2 latest
    2018/10/31 16:03:14 mgo listen and serve on [mgo, localhost:27017]
    2018/10/31 16:03:14 api listen and serve on [:8090]
  • 项目创建完成后先提交代码到源码库

    $ git add -A && git commit -m "initial project" && git push

    此时的项目结构为:

    goweb-app/
    |-- README.md
    |-- api
    |   |-- app.go
    |   `-- model.go
    |-- go.mod
    |-- go.sum
    |-- main.go
    `-- main_test.go
    
    1 directory, 7 files

配置 Drone CI/CD 服务

需要提前阅读的相关文档:

在项目 根目录 创建 Drone CI/CD 的配置文件:.drone.yml;然后跳转到 Drone Web UI:http://your_company_domain.com:8000,完成登陆后 Drone Server 会自动同步你的账号下面的项目列表(或者手动同步)。然后选择需要启用 Drone CI 的项目,点击右侧开关选项即可启用。如下图:

最后,需要在 Drone Web UI 管理界面,找到 goweb-app 的设置选项,开启 Repo Hooks,如下图:

Drone Pipeline: 单元测试(test)

Go-Web-App 的接口单元测试依赖于 MongoDB 数据库服务,因此在配置 pipeline: test 前需要先配置好 services

  • 需要提前阅读的相关文档:

  • 此时 .drone.yml 配置如下:

    workspace:
    base: /go
    path: src/repo/goweb-app
    
    clone:    # Clone code from bitbucket
      git:
        image: plugins/git
        depth: 50
        tags: true
    
    pipeline:
    
      ping:   # Mgo-server for testing restful api
        image: mongo:latest
        commands:
          - sleep 3
          - mongo --host mgo --eval "{ping:1}"
    
      test:   # Golang unit testing
        image: golang:latest
        group: build
        environment:
          - BRC=${DRONE_COMMIT_BRANCH}
          - SHA=${DRONE_COMMIT_SHA:0:8}
          - EVN=${DRONE_BUILD_EVENT}
          - MSG=${DRONE_COMMIT_MESSAGE}
          - TAG=${DRONE_TAG}
          - MGO=mgo:27017
        commands:
          - cd cicd
          - /bin/sh test_api.sh $MGO $BRC $SHA $EVN $MSG $TAG
    
    services:  # Dependent service
      mgo:
        image: mongo:latest
    
    branches:  # Enable Drone CICD on: master & release/* branches
      include: [ master, release/* ]

    Note:

    • workspace 定义了所有工作流步骤共享的容器空间和目录
    • clone 部分是默认配置, 也可以自定义
    • Pipeline:ping stage 放在第一步是用来验证 mgo services 已经可以正常提供服务了
    • 命令 mongo --host mgo --eval "{ping:1} 的选项 --host 的值填写 services 部分配置的名称,即:mgo
    • 官网的 --eval "{ ping: 1 }" 会导致错误,需改成 --eval "{ping:1}"
    • ${DRONE_COMMIT_BRANCH} 等一系列预设变量可用来动态配置 pipelines
    • commands 部分如果内容过多或想让 .drone.yml 配置变得简洁时,可用脚本实现
    • services 部分用来定义服务应用容器,例如:database、cache、redis等
    • branches 部分可以用来限定 Drone CI 作用在那些分支上(这里只作用在:master 和 release/* 开头的所有分支上)
    • 添加脚本 test_api.sh
    # 进入项目根目录,创建 cicd 目录用来存放 Drone 执行时的一些脚本和配置文件
    $ cd goweb-app && mkdir cicd
    
    # 创建 test_api.sh
    $ touch test_api.sh 
    
    # 脚本内容如下:
    
    #!/bin/sh
    #
    # Program: API 单元测试脚本
    # Authors: zhangzhe
    # History:
    #   2018-10-24:编写脚本实现
    #
    
    # Pre Set
    set -x
    
    # Set ENV
    export GO111MODULE=on                               # Go1.11.x 版本需要开启
    export http_proxy=http://10.0.0.121:1080
    export https_proxy=${http_proxy}
    
    # Set Var
    Src=../                                             # 程序源码
    DB=$1                                               # Database Server Address
    if [ -z $1 ]; then
        DB=mgo:27017
    fi
    
    # Golang Test
    echo Test Info: $@                                  # 打印构建信息, 脚本执行参数
                                                        # ${DRONE_COMMIT_BRANCH}
                                                        # ${DRONE_COMMIT_SHA:0:8}
                                                        # ${DRONE_BUILD_EVENT}
                                                        # ${DRONE_COMMIT_MESSAGE}
                                                        # ${DRONE_TAG}
    echo $PWD
    
    go mod tidy                                         # 解决依赖包
    go test -v --cover ${Src} --db_addr=${DB}           # 'mgo:27017' Drone 提供的数据库服务
                                                        # 'localhost:27017' 宿主机提供的数据库服务
  • Now, 提交代码进行测试(备注:Drone CI/CD 设定只在 master 和 以 release/ 开头的分支起作用)

    $ git add -A && git commit -m "test drone cicd pipeline -> test stage" && git push
    • 构建结果如下图:

    Drone Pipeline: 构建 Go-Web-App(build)

    单元测试执行完成后,就可以进入 build 阶段来构建可执行程序了。

    • 此时的 .drone.yml 配置如下:
    workspace:
      base: /go
      path: src/repo/goweb-app
        
    clone:    # Clone code from bitbucket
      git:
        image: plugins/git
        depth: 50
        tags: true
        
    pipeline:
      ping:   # Mgo-server for testing restful api
        image: mongo:latest
        commands:
          - sleep 3
          - mongo --host mgo --eval "{ping:1}"
          
      test:   # Golang unit testing
        image: golang:latest
        group: build
        environment:
          - BRC=${DRONE_COMMIT_BRANCH}
          - SHA=${DRONE_COMMIT_SHA:0:8}
          - EVN=${DRONE_BUILD_EVENT}
          - MSG=${DRONE_COMMIT_MESSAGE}
          - TAG=${DRONE_TAG}
          - MGO=mgo:27017
        commands:
          - cd cicd
          - /bin/sh test_api.sh $MGO $BRC $SHA $EVN $MSG $TAG
        
        + build:  # Build go app and package source files
        +   image: golang:latest
        +   commands:
        +     - cd cicd
        +     - /bin/sh build_app.sh
        
    services:  # Dependent service
      mgo:
        image: mongo:latest
        
    branches:  # Enable Drone CICD on: master & release/* branches
      include: [ master, release/* ]
  • 构建可执行程序的具体步骤由脚本:build_app.sh 定义,内容如下:

    # 进入项目根目录,创建 cicd 目录用来存放 Drone 执行时的一些脚本和配置文件
    $ cd cicd
    
    # 创建 build_app.sh
    $ touch build_app.sh 
    
    # 脚本内容如下:
    
    #!/bin/sh
    #
    # Program: 构建 Go-App & 打包资源文件
    # Authors: zhangzhe
    # History:
    #   2018-10-24:编写脚本实现
    #
    
    # Pre Set
    set -x
    
    # Set ENV
    export GO111MODULE=on                               # Go1.11.x 版本需要开启
    export http_proxy=http://10.0.0.121:1080
    export https_proxy=${http_proxy}
    
    # Set Var
    Src=../                                             # 程序源码
    Out="app"
    Options="-a -installsuffix cgo -o"
    # PreSet='GOOS=linux GOARCH=amd64'                  # 构建变量设置
    
    # Build
    go version
    go env
    
    CGO_ENABLED=0 go build -o ${Out} ${Src}             # build
    
    # Package
    tar -zcvf release.tar.gz ../www ./*

    Note:

    • build_app.sh 脚本的最后一行用来打包资源文件(网站资源、配置文件和脚本等),该资源文件最终需要上传到远程服务器
    • 最后,在创建 www 目录用来测试静态页面:
    # 进入项目根目录,创建 www 目录
    $ cd goweb-app && mkdir www
    
    # 创建 index.html 静态页面
    $ touch www/index.html
    
    # 填入如下内容:
    <!DOCTYPE html>
    <html>
    <body>
    
    <h1>I'm zher.</h1>
    
    </body>
    </html>
  • Now, 提交代码进行测试(备注:Drone CI/CD 设定只在 master 和 以 release/ 开头的分支起作用)

    $ git add -A && git commit -m "test drone cicd pipeline -> build stage" && git push
    • 构建结果如下图:

    Drone Pipeline: 发布 Docker 镜像(image)

    这里 Docker 镜像是发布到自建的 Docker Registry Server 的,其部署文档参考:Docker | Deploy Docker Registry and Web UI

    • 生成 Go-Web-App 的可执行文件后,就可以将其打包为 Docker Image 发布了,此时的 .drone.yml 配置如下:
    workspace:
      base: /go
      path: src/repo/goweb-app
    
    clone:    # Clone code from bitbucket
      git:
        image: plugins/git
        depth: 50
        tags: true
    
    pipeline:
    
      ping:   # Mgo-server for testing restful api
        image: mongo:latest
        commands:
          - sleep 3
          - mongo --host mgo --eval "{ping:1}"
    
      test:   # Golang unit testing
        image: golang:latest
        group: build
        environment:
          - BRC=${DRONE_COMMIT_BRANCH}
          - SHA=${DRONE_COMMIT_SHA:0:8}
          - EVN=${DRONE_BUILD_EVENT}
          - MSG=${DRONE_COMMIT_MESSAGE}
          - TAG=${DRONE_TAG}
          - MGO=mgo:27017
        commands:
          - cd cicd
          - /bin/sh test_api.sh $MGO $BRC $SHA $EVN $MSG $TAG
    
      build:  # Build go app and package source files
        image: golang:latest
        commands:
          - cd cicd
          - /bin/sh build_app.sh
    
        +  image:  # Build image and publish to private registry
        +    image: plugins/docker
        +    repo: repo.company.com:5000/go-app
        +    registry: repo.company.com:5000
        +    secrets: [ docker_username, docker_password ]
        +    context: ./cicd/
        +    dockerfile: ./cicd/Dockerfile
        +    default_tags: true
        +    when:
        +      event: tag
    
    services:  # Dependent service
      mgo:
        image: mongo:latest
    
    branches:  # Enable Drone CICD on: master & release/* branches
      include: [ master, release/* ]

    Note:

    • image 阶段使用了插件:plugins/docker 来构建 Docker Image 且将其发布到指定的远程 Docker Registry, 详细说明可以查阅其文档

    • image 阶段限制只在 tag 事件被触发式才执行 Docker Image 构建和发布

    • secrets 选项中的 docker_username & docker_password 是 Drone 注入的,我们需要在提前在 Drone Web 端先设置好这些 secrets,如下图:

  • 构建镜像的 Dockerfile 内容如下:

    # 进入项目根目录,创建 cicd 目录用来存放 Drone 执行时的一些脚本和配置文件
    $ cd cicd
    
    # 创建 Dockerfile
    $ touch Dockerfile
    
    # 填入以下内容:
    # Program: Dockerfile for API Service
    # Build:
    #   docker build -t <image_name> .
    
    # 基础镜像
    # Usage: FROM image:tag
    FROM repo.company.com:5000/alpine:3.8
        
    # 设置环境变量
    # Usage: ENV <key=value> <key=value>
    ENV WorkDir=/home/api
    
    # 指定维护者信息
    # Usage: MAINTAINER name
    MAINTAINER <[email protected]>
    
    # 给镜像添加工作目录
    # Usage: RUN [命令]
    # RUN mkdir -p ${WorkDir}}
    # Set Time Zone
    RUN echo 'http://mirrors.ustc.edu.cn/alpine/v3.5/main' > /etc/apk/repositories \
        && echo 'http://mirrors.ustc.edu.cn/alpine/v3.5/community' >> /etc/apk/repositories \
        && apk update && apk add tzdata \
        && ln -sf /usr/share/zoneinfo/Asia/Shanghai/etc/localtime \
        && echo "Asia/Shanghai" > /etc/timezone
    
    # 设定默认工作路径
    # Usage: WORKDIR [path]
    WORKDIR ${WorkDir}
    
    # 复制本地应用程序文件[src]到Container的工作目录[dst]
    # Usage: COPY [src] [dst]
    COPY app ${WorkDir}/
    
    RUN chmod +x ${WorkDir}/app
            
    # 容器暴漏给外侧的端口号
    # Usage: EXPOSE port [port...]
    EXPOSE 80
    
    # 指定容器启动时执行的命令
    # Usage: CMD ["executable", "param1", "param2"]
    CMD ["./app"]

    Note:

    • Dockerfile 中的基础镜像使用的是 alpine, 这里将 alpine:3.8 上传到我们自建的 Docker Registry 以节省构建时间。如果使用 Docker Hub 中的镜像每次都要拉取一次,会很慢。
  • 上传构建 Go-Web-App 的基础镜像到我们自建的 Docker Private Registry:

    • 上传镜像到 Docker Registry 参考文章

      $ docker pull alpine:3.8
      $ docker tag alpine:3.8 repo.company.com:5000/alpine:3.8
      $ docker push repo.company.com:5000/alpine:3.8
      
      # push 失败时,尝试重新登陆后继续 push 即可

      Push repo.company.com:5000/alpine:3.8 成功后,可以打开 Docker Registry UI (http://your_domain.com:5001) 即可看到刚刚提交的镜像信息。

  • Now, 提交代码进行测试(备注:Drone CI/CD 设定只在 master 和 以 release/ 开头的分支起作用)

    $ git add -A && git commit -m "test drone cicd pipeline -> publish image stage" && git push
    
    # 打 tag, 触发 when: [event: tag] 事件,即触发 publish_image 阶段执行
    $ git tag 0.0.1 -m "release 0.0.1" && git push origin 0.0.1
    • 构建结果如下图:

    Drone Pipeline: 上传静态资源和部署脚本(scp)

    要实现自动部署容器服务,光有镜像是不够的,因此,还需要将网站资源,配置文件等一些脚本打包发到远端服务器上.

    • 此时的 .drone.yml 配置如下:
    workspace:
      base: /go
      path: src/repo/goweb-app
    
    clone:    # Clone code from bitbucket
      git:
        image: plugins/git
        depth: 50
        tags: true
    
    pipeline:
    
      ping:   # Mgo-server for testing restful api
        image: mongo:latest
        commands:
          - sleep 3
          - mongo --host mgo --eval "{ping:1}"
    
      test:   # Golang unit testing
        image: golang:latest
        group: build
        environment:
          - BRC=${DRONE_COMMIT_BRANCH}
          - SHA=${DRONE_COMMIT_SHA:0:8}
          - EVN=${DRONE_BUILD_EVENT}
          - MSG=${DRONE_COMMIT_MESSAGE}
          - TAG=${DRONE_TAG}
          - MGO=mgo:27017
        commands:
          - cd cicd
          - /bin/sh test_api.sh $MGO $BRC $SHA $EVN $MSG $TAG
    
      build:  # Build go app and package source files
        image: golang:latest
        commands:
          - cd cicd
          - /bin/sh build_app.sh
    
      image:  # Build image and publish to private registry
        image: plugins/docker
        repo: repo.company.com:5000/go-app
        registry: repo.company.com:5000
        secrets: [ docker_username, docker_password ]
        context: ./cicd/
        dockerfile: ./cicd/Dockerfile
        default_tags: true
        when:
          event: tag
    
        +  scp:    # Upload resource and config files to remote server
        +    image: appleboy/drone-scp
        +    group: build
        +    host:
        +      - your_server_address
        +    username: root
        +    port: 22
        +    secrets: [ ssh_password ]
        +    target: /home/workspace/service/api-server # 远程服务器目录
        +    source: ./cicd/release.tar.gz              # 打包好的文件
        +    when:
        +      event: tag
    
    services:  # Dependent service
      mgo:
        image: mongo:latest
    
    branches:  # Enable Drone CICD on: master & release/* branches
      include: [ master, release/* ]

    Note:

    • 预设变量 ssh_password 也需要提前在 Drone Web 端设置好
  • 部署脚本 deploy_services.sh 内容如下:

    # 进入项目根目录,创建 cicd 目录用来存放 Drone 执行时的一些脚本和配置文件
    $ cd cicd
    
    # 创建部署脚本:deploy_services.sh
    $ touch deploy_services.sh
    
    # 填入如下内容:
    
    #!/bin/sh
    #
    # Program: 部署 Docker 容器服务
    # Authors: zhangzhe
    # History:
    #   2018-10-24:编写脚本实现
    #
    
    # Pre Set
    set -x
    
    # Set Var
    Tag=$1                                    # 读取 git tag (版本号:x.y.z)
    Commit=$2                                 # 读取 git commit 号(8位)
    
    if [ -z ${Tag} ]; then
        echo -e "Empty git tag given"
        exit 1
    fi
    
    ImageName=go-app:${Tag}                   # 镜像名
    Registry=develop.robot-qixing.com:5000    # 私有仓库地址
    BaseImage=${Registry}/${ImageName}        # 远程 Image 地址:docker pull ${BaseImage}
    ContainerName=api${Tag}
    
    # Reconfigure docker-compose.yml & Caddyfile
    sed -i "s/api(@tag)/${ContainerName}/g" docker-compose.yml  # 启动对应版本(Tag)的 API 容器
    sed -i "s/(@tag)/${Tag}/g" dockere-compose.yml              # 拉去对应版本(Tag)的 API 镜像
    sed -i "s/api(@tag)/${ContainerName}/g" Caddyfile           # Caddy 代理到对应版本的 API 容器服务
    
    # Pull image and run docker container
    docker pull ${BaseImage}
    docker-compose up -d
    docker ps
    docker-compose logs caddy
    docker-compose logs mgo
    docker logs api${Tag}

    配置 docker-compose.yml

    $ cd cicd && touch docker-compose.yml
    
    # 填入如下内容
    version: '3'
    services:
      caddy: # caddy proxy server
        container_name: caddy
        image: abiosoft/caddy:latest
        restart: always
        ports:
          - 80:80
          - 443:443
        volumes:
          - /etc/ssl/server-certs:/root/.caddy
          - ./Caddyfile:/etc/Caddyfile
          - ./www:/srv
        depends_on:
          - api
    
      api:  # api server
        container_name: api(@tag)
        image: repo.company.com:5000/go-app:(@tag)
        restart: always
        command: './app --port=80 --db_addr=mgo:27017'
        depends_on:
          - mgo
    
      mgo:  # mgo server
        container_name: mgo
        image: mongo:latest
        restart: always
        environment:
          MONGO_INITDB_ROOT_USERNAME: <__input_username__>
          MONGO_INITDB_ROOT_PASSWORD: <__input_password__>
        volumes:
          - ./mgo-data/db:/data/db
    • Caddyfile 配置内容如下:
    $ cd cicd && touch Caddyfile.yml
    
    # 填入如下内容
    https://company-domain.com {
        gzip
        root /srv
        tls /root/.caddy/cert.crt /root/.caddy/cert.key
        timeouts none
    
        proxy /v0 api(@tag):80 {
            transparent
            websocket
            except static
        }
    
        cors /v0 {
            origin            *
            methods           POST,GET,PATCH,DELETE,OPTIONS
            allow_credentials false
            max_age           3600
            allowed_headers   content-type,Authorization
            exposed_headers   X-Something-Special,SomethingElse,Authorization
        }
    }

    Note:

    • Now, 提交代码进行测试(备注:Drone CI/CD 设定只在 master 和 以 release/ 开头的分支起作用)
    $ git add -A && git commit -m "test drone cicd pipeline -> scp stage" && git push
    
    # 打 tag, 触发 when: [event: tag] 事件,即触发 publish_image 阶段执行
    $ git tag 0.0.2 -m "release 0.0.2" && git push origin 0.0.2
  • 构建结果如下图:

Drone Pipeline: 服务部署(deploy)

一切准备好后,就可以执行容器服务部署了,主要包括:Caddy Server Container、Go Web Server Container、MongoDB Server Container,这一组应用容器服务通过 docker-compose 进行管理和组织。

  • 此时的 .drone.yml 配置如下:

    workspace:
      base: /go
      path: src/repo/goweb-app
        
    clone:    # Clone code from bitbucket
      git:
        image: plugins/git
        depth: 50
        tags: true
        
    pipeline:
        
      ping:   # Mgo-server for testing restful api
        image: mongo:latest
        commands:
          - sleep 3
          - mongo --host mgo --eval "{ping:1}"
        
      test:   # Golang unit testing
        image: golang:latest
        group: build
        environment:
          - BRC=${DRONE_COMMIT_BRANCH}
          - SHA=${DRONE_COMMIT_SHA:0:8}
          - EVN=${DRONE_BUILD_EVENT}
          - MSG=${DRONE_COMMIT_MESSAGE}
          - TAG=${DRONE_TAG}
          - MGO=mgo:27017
        commands:
          - cd cicd
          - /bin/sh test_api.sh $MGO $BRC $SHA $EVN $MSG $TAG
        
      build:  # Build go app and package source files
        image: golang:latest
        commands:
          - cd cicd
          - /bin/sh build_app.sh
        
      image:  # Build image and publish to private registry
        image: plugins/docker
        repo: repo.company.com:5000/go-app
        registry: repo.company.com:5000
        secrets: [ docker_username, docker_password ]
        context: ./cicd/
        dockerfile: ./cicd/Dockerfile
        default_tags: true
        when:
          event: tag
        
      scp:    # Upload resource and config files to remote server
        image: appleboy/drone-scp
        group: build
        host:
          - your_server_address
        username: root
        port: 22
        secrets: [ ssh_password ]
        target: /home/workspace/service/api-server # 远程服务器目录
        source: ./cicd/release.tar.gz              # 随镜像一起发布的文件
        when:
          event: tag
        
        +  deploy: # Deploy api-server, caddy-server, mgo-server
        +    image: appleboy/drone-ssh
        +    host:
        +      - your_server_address
        +    username: root
        +    port: 22
        +    secrets: [ ssh_password ]
        +    command_timeout: 60
        +    script:
        +      - cd /home/workspace/service/api-server/cicd
        +      - tar -zxvf release.tar.gz
        +      - ls -l
        +      - /bin/sh deploy_services.sh ${DRONE_TAG} ${DRONE_COMMIT_SHA:0:8}
        +    when:
        +      event: tag
        
    services:  # Dependent service
      mgo:
        image: mongo:latest
        
    branches:  # Enable Drone CICD on: master & release/* branches
      include: [ master, release/* ]

    Note:

    • Drone Plugins: appleboy/drone-ssh 用来连接到远程服务器
    • deploy_services.sh 是执行服务部署的脚本,需要接收 ${DRONE_TAG} 用来动态构建容器名称等
    • Now, 提交代码进行测试(备注:Drone CI/CD 设定只在 master 和 以 release/ 开头的分支起作用)
    $ git add -A && git commit -m "test drone cicd pipeline -> deploy stage" && git push
    
    # 打 tag, 触发 when: [event: tag] 事件,即触发 publish_image 阶段执行
    $ git tag 0.0.3 -m "release 0.0.3" && git push origin 0.0.3
  • 构建结果如下图:

Drone Pipeline: 结果通知(notify:hipchat)

为了确保能够及时获取 Drone CI 构建结果,需要选取一种合适的方式来接收通知,这里集成了我们在用的 hipchat.

  • 此时的 .drone.yml 配置如下:

    workspace:
      base: /go
      path: src/repo/goweb-app
        
    clone:    # Clone code from bitbucket
      git:
        image: plugins/git
        depth: 50
        tags: true
        
    pipeline:
        
      ping:   # Mgo-server for testing restful api
        image: mongo:latest
        commands:
          - sleep 3
          - mongo --host mgo --eval "{ping:1}"
        
      test:   # Golang unit testing
        image: golang:latest
        group: build
        environment:
          - BRC=${DRONE_COMMIT_BRANCH}
          - SHA=${DRONE_COMMIT_SHA:0:8}
          - EVN=${DRONE_BUILD_EVENT}
          - MSG=${DRONE_COMMIT_MESSAGE}
          - TAG=${DRONE_TAG}
          - MGO=mgo:27017
        commands:
          - cd cicd
          - /bin/sh test_api.sh $MGO $BRC $SHA $EVN $MSG $TAG
        
      build:  # Build go app and package source files
        image: golang:latest
        commands:
          - cd cicd
          - /bin/sh build_app.sh
        when:
          event: tag
        
      image:  # Build image and publish to private registry
        image: plugins/docker
        repo: repo.company.com:5000/go-app
        registry: repo.company.com:5000
        secrets: [ docker_username, docker_password ]
        context: ./cicd/
        dockerfile: ./cicd/Dockerfile
        default_tags: true
        when:
          event: tag
        
      scp:    # Upload resource and config files to remote server
        image: appleboy/drone-scp
        group: build
        host:
          - your_server_address
        username: root
        port: 22
        secrets: [ ssh_password ]
        target: /home/workspace/service/api-server # 远程服务器目录
        source: ./cicd/release.tar.gz              # 随镜像一起发布的文件
        when:
          event: tag
        
      deploy: # Deploy api-server, caddy-server, mgo-server
        image: appleboy/drone-ssh
        host:
          - your_server_address
        username: root
        port: 22
        secrets: [ ssh_password ]
        command_timeout: 60
        script:
          - cd /home/workspace/service/api-server/cicd
          - tar -zxvf release.tar.gz
          - ls -l
          - /bin/sh deploy_services.sh ${DRONE_TAG} ${DRONE_COMMIT_SHA:0:8}
        when:
          event: tag
        
        +  hipchat: # Notify
        +    image: jmccann/drone-hipchat
        +    url: https://hipchat.your_company_domain.com
        +    room: 19
        +    auth_token: tWVtsTFzsbkwSJO79JHcyb11TR8dLyEYAlicHviB
        +    from: Drone
        +    when:
        +      status: [ success, failure ]
        +    template: >
            <strong>{{ uppercasefirst build.status }}</strong> <a href=\"{{ system.link_url }}/{{     repo.owner }}/{{ repo.name }}/{{ build.number }}\">{{ repo.owner }}/{{ repo.name }}#{{     truncate build.commit 8 }}</a> ({{ build.branch }}) by {{ build.author }} in {{ duration     build.started_at build.finished_at }} </br> - {{ build.message }}
        
    services:  # Dependent service
      mgo:
        image: mongo:latest
        
    branches:  # Enable Drone CICD on: master & release/* branches
      include: [ master, release/* ]

    Note:

    • Now, 提交代码进行测试(备注:Drone CI/CD 设定只在 master 和 以 release/ 开头的分支起作用)
    $ git add -A && git commit -m "test drone cicd pipeline -> notify stage" && git push
  • 构建结果如下图:

至此,一套完整的 Drone CI/CD Pipeline 流已配置完成。

最终完整的项目结构如下:

goweb-app/
|-- README.md
|-- api
|   |-- app.go
|   `-- model.go
|-- cicd
|   |-- Caddyfile
|   |-- Dockerfile
|   |-- build_app.sh
|   |-- deploy_services.sh
|   |-- docker-compose.yml
|   `-- test_api.sh
|-- go.mod
|-- go.sum
|-- main.go
|-- main_test.go
`-- www
    `-- index.html

3 directories, 14 files

See Also

Thanks to the authors 🙂

Q: go: golang.org/x/[email protected]: unrecognized import path “golang.org/x/crypto” (https fetch: Get https://golang.org/x/crypto?go-get=1: dial tcp 216.239.37.1:443: i/o timeout) go: golang.org/x/[email protected]: unrecognized import path “golang.org/x/sys” (https fetch: Get https://golang.org/x/sys?go-get=1: dial tcp 216.239.37.1:443: i/o timeout) go: error loading module requirements

A: https://gocn.vip/question/567


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK