├── .drone.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── docker-compose.yml ├── go.mod ├── main.go ├── renovate.json └── util ├── util.go └── util_test.go /.drone.yml: -------------------------------------------------------------------------------- 1 | kind: pipeline 2 | name: demo 3 | 4 | steps: 5 | - name: build 6 | image: golang:1.18.2 7 | commands: 8 | - pwd 9 | - go version 10 | - go build . 11 | - go test demo/util 12 | 13 | # - name: frontend 14 | # image: node:6 15 | # commands: 16 | # - npm install 17 | # - npm test 18 | 19 | - name: publish 20 | image: plugins/docker:latest 21 | settings: 22 | username: 23 | from_secret: docker_username 24 | password: 25 | from_secret: docker_password 26 | repo: example/demo 27 | tags: latest 28 | 29 | - name: deploy 30 | image: appleboy/drone-ssh 31 | pull: true 32 | settings: 33 | host: kanda.me 34 | user: cpp 35 | key: 36 | from_secret: deploy_key 37 | script: 38 | - cd /data/ 39 | - mkdir app/ 40 | - cd /data/app 41 | - docker rmi -f example/demo 42 | - echo "login docker" 43 | # - docker login --username ${DOCKER_USER} --password ${DOCKER_SEC} 44 | - echo "login success, pulling..." 45 | - docker pull example/demo:latest 46 | - echo "image running" 47 | - docker run -p 8088:8088 -d example/demo 48 | - echo "run success" 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, build with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | vendor 14 | .idea 15 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.18.2 2 | WORKDIR ${GOPATH}/src/demo 3 | COPY . ${GOPATH}/src/demo 4 | 5 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o demo . 6 | 7 | EXPOSE 8088 8 | CMD ["./demo"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 壳壳 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](http://192.168.1.108:8080/api/badges/cpp/demo/status.svg)](http://192.168.1.108:8080/cpp/demo) 2 | 3 | drone是一个基于容器的本地持续交付平台,和Jenkins是差不多的,然后配合轻量级的gogs来作为git管理,都是基于golang开发的很符合我的需求,我们来把它们结合作为一个完整的CI、CD平台。 4 | 5 | 首先我们要先安装docker,上次的篇幅我们已经说过了我就不赘述了。 6 | 7 | 需要的东西有:linux,docker,docker-compose,drone,gogs。 8 | 9 | ## 安装gogs和drone 10 | 11 | 配合[荣锋亮大哥](https://www.cnblogs.com/rongfengliang/p/9963311.html)的yml文件和docker-compose我们可以很容易安装他们: 12 | 13 | ```yaml 14 | version: '3' 15 | services: 16 | drone-server: 17 | image: drone/drone:latest 18 | ports: 19 | - "8080:80" 20 | - 8843:443 21 | - 9000 22 | volumes: 23 | - ./drone:/var/lib/drone/ 24 | - /var/run/docker.sock:/var/run/docker.sock 25 | environment: 26 | - DRONE_OPEN=true 27 | - DRONE_SERVER_HOST=drone-server 28 | - DRONE_DEBUG=true 29 | - DRONE_GIT_ALWAYS_AUTH=false 30 | - DRONE_GOGS=true 31 | - DRONE_GOGS_SKIP_VERIFY=false 32 | - DRONE_GOGS_SERVER=http://gogs:3000 33 | - DRONE_PROVIDER=gogs 34 | - DRONE_DATABASE_DATASOURCE=/var/lib/drone/drone.sqlite 35 | - DRONE_DATABASE_DRIVER=sqlite3 36 | - DRONE_SERVER_PROTO=http 37 | - DRONE_RPC_SECRET=ALQU2M0KdptXUdTPKcEw 38 | - DRONE_SECRET=ALQU2M0KdptXUdTPKcEw 39 | gogs: 40 | image: gogs/gogs:latest 41 | ports: 42 | - "10022:22" 43 | - "3000:3000" 44 | volumes: 45 | - ./data/gogs:/data 46 | depends_on: 47 | - mysql 48 | mysql: 49 | image: mysql:5.7.16 50 | volumes: 51 | - ./gogs/mysql:/var/lib/mysql 52 | - /var/run/docker.sock:/var/run/docker.sock 53 | ports: 54 | - 3308:3306 55 | command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci 56 | environment: 57 | MYSQL_ROOT_PASSWORD: pass 58 | MYSQL_DATABASE: gogs 59 | MYSQL_USER: gogs 60 | MYSQL_PASSWORD: pass 61 | TZ: Asia/Shanghai 62 | drone-agent: 63 | image: drone/agent:latest 64 | depends_on: 65 | - drone-server 66 | environment: 67 | - DRONE_RPC_SERVER=http://drone-server 68 | - DRONE_RPC_SECRET=ALQU2M0KdptXUdTPKcEw 69 | - DRONE_DEBUG=true 70 | - DOCKER_HOST=tcp://docker-bind:2375 71 | - DRONE_SERVER=drone-server:9000 72 | - DRONE_SECRET=ALQU2M0KdptXUdTPKcEw 73 | - DRONE_MAX_PROCS=5 74 | docker-bind: 75 | image: docker:dind 76 | privileged: true 77 | # command: --storage-driver=overlay 78 | ``` 79 | 80 | 我们创建一个存放docker-compose.yml文件的目录比如就叫gogs,然后我们把这些yml保存成docker-compose.yml,然后执行docker-compose来安装: 81 | 82 | ```bash 83 | $ docker-compose up -d 84 | ``` 85 | 86 | 配合yml文件,我们就安装好了drone-server和drone-agent还有gogs,然后我们用浏览器打开`http://localhost:3000/`来进入gogs并初始化它。 87 | 88 | ![gogs初始化1](https://i.loli.net/2019/03/02/5c7a4622758c4.png) 89 | 90 | 域名和应用URL记得一样接着我们创建一个管理员用户,然后其他的都默认,点击立即安装完成。 91 | 92 | ![gogs初始化2](https://i.loli.net/2019/03/02/5c7a46de1ddff.png) 93 | 94 | 初始化成功之后我们可以在gogs里边创建一个仓库,然后登陆drone。 95 | 96 | # drone 97 | 98 | 打开浏览器输入`http://localhost/`直接进入drone,密码是gogs的你的刚刚的账户和密码。 99 | 100 | ![drone](https://i.loli.net/2019/03/02/5c7a495a6c7a1.png) 101 | 102 | 我们会看到一个刚刚创建的仓库,激活它! 103 | 104 | 激活之后,我们回到gogs那边,仓库的设置里边的webhook应该已经配置好了 105 | 106 | ![web hook](https://i.loli.net/2019/03/06/5c7f4e9198fb6.png) 107 | 108 | 我们可以测试web hook,如果没有问题的话,应该会提示成功。 109 | 110 | ## 上传源码 111 | 112 | 测试没有问题之后,我们初始化我们的代码文件夹为git仓库,然后push到gogos上边 113 | 114 | ![test仓库](https://i.loli.net/2019/03/06/5c7f4f152f320.png) 115 | 116 | 然后为你的仓库加上`.drone.yml`配置文件,drone-server会自动读取这个文件进行CI、CD操作等。以下这个是我们的示例文件 117 | 118 | ```yaml 119 | kind: pipeline 120 | name: demo 121 | 122 | steps: 123 | - name: build 124 | image: golang:1.11.4 125 | commands: 126 | - pwd 127 | - go version 128 | - go build . 129 | - go test demo/util 130 | 131 | # - name: frontend 132 | # image: node:6 133 | # commands: 134 | # - npm install 135 | # - npm test 136 | 137 | - name: publish 138 | image: plugins/docker:latest 139 | settings: 140 | username: 141 | from_secret: docker_username 142 | password: 143 | from_secret: docker_password 144 | repo: example/demo 145 | tags: latest 146 | 147 | - name: deploy 148 | image: appleboy/drone-ssh 149 | pull: true 150 | settings: 151 | host: example.me 152 | user: root 153 | key: 154 | from_secret: deploy_key 155 | script: 156 | - cd /data 157 | - mkdir app/ 158 | - cd /data/app 159 | - docker rmi -f example/demo 160 | - echo "login docker" 161 | - echo "login success, pulling..." 162 | - docker pull example/demo:latest 163 | - echo "image running" 164 | - docker run -p 8088:8088 -d example/demo 165 | - echo "run success" 166 | 167 | ``` 168 | 169 | 我们首先进行简单的golang build和test操作然后根据Dockerfile文件把我们的程序构建成docker镜像,接着上传到docker hub中,然后通过drone-ssh插件部署这个镜像。 170 | 171 | 172 | 173 | ## 开始构建 174 | 175 | 有了配置文件之后,推送代码我们就可以去drone查看构建进度: 176 | 177 | ![drone](https://i.loli.net/2019/03/06/5c7f655ba2519.png) 178 | 179 | # drone的设置 180 | 181 | 在进入drone的时候,选择一个项目我们可以进行一些必要的设置,比如配置secrets,定时任务和徽章等等。 182 | 183 | 比如配置文件需要的密钥,用户名和密码,一些环境变量都可以在secrets设置,构建状态徽章可以在你的项目README.md文件加上去。 184 | 185 | ![设置](https://i.loli.net/2019/03/06/5c7f66a50f9b1.png) 186 | 187 | 项目加上徽章: 188 | 189 | ![徽章](https://i.loli.net/2019/03/06/5c7f66ed1d946.png) 190 | 191 | [示例代码](https://github.com/nagaame/drone-golang-example),本文完。 192 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | demo-server: 4 | image: example/demo:latest 5 | ports: 6 | - "8088:8088" 7 | volumes: 8 | # - ./data:/var/lib/drone/ 9 | - /var/run/docker.sock:/var/run/docker.sock 10 | environment: -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module demo 2 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "demo/util" 5 | "net/http" 6 | ) 7 | 8 | func main() { 9 | http.HandleFunc("/", util.SayHello) 10 | 11 | if err := http.ListenAndServe(":8088", nil); err != nil { 12 | panic(err) 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /util/util.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "strings" 7 | ) 8 | 9 | func SayHello(response http.ResponseWriter, r *http.Request) { 10 | message := r.URL.Path 11 | 12 | message = strings.TrimPrefix(message, "/") 13 | 14 | message = "Hello " + message + " : " + fmt.Sprintf("%d", GetNameLen(message)) 15 | 16 | response.Write([]byte(message)) 17 | } 18 | 19 | func GetNameLen(s string) int { 20 | return len(s) 21 | } -------------------------------------------------------------------------------- /util/util_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | 4 | import ( 5 | "testing" 6 | ) 7 | 8 | func Test_GetNameLen_1(t *testing.T) { 9 | if l := GetNameLen("nick"); l != 4 { 10 | t.Error("test failed, the length of nick is not correct.") 11 | } else { 12 | t.Log("test passed.") 13 | } 14 | } 15 | 16 | func Test_GetNameLen_2(t *testing.T) { 17 | if l := GetNameLen(""); l != 0 { 18 | t.Error("test failed, the length of empty string is not correct.") 19 | } else { 20 | t.Log("test passed.") 21 | } 22 | } --------------------------------------------------------------------------------