最近朋友有個項目代碼託管用的碼雲,測試服務器(阿里雲ECS)只有一臺,三四我的開發,因而想基於阿里雲的CodePipeline快速打造一套自動化cicd的流程,使用docker來進行多套環境部署。html
阿里雲CodePipeline是兼容Jenkins標準的、提供快速可靠的持續集成與持續交付服務。基於容器技術和阿里雲基礎服務架構,提供穩定和安全的代碼/Docker編譯構建,測試,掃描和部署的工具服務,並提供Pipeline As Code的編碼級配置模式,知足應用程序和基礎設施快速可靠的交付和更新。mysql
我這裏使用的是阿里雲的私有的鏡像倉庫基於Dockerfile來構建鏡像,注意配置憑證。 ![在這裏插入圖片描述]linux
gin_demo
├── app
│ └── app.go
├── conf
│ └── app.ini
├── Dockerfile
├── docs
│ └── sql
│ └── mjs.sql
├── go.mod
├── go.sum
├── main.go
├── middleware
│ ├── jwt
│ │ └── jwt.go
│ └── logging
│ └── logger.go
├── mjs.exe
├── models
│ ├── mongo
│ │ └── db.go
│ └── mysql
│ ├── db.go
│ ├── teacher.go
│ └── user.go
├── pkg
│ ├── app
│ │ ├── form.go
│ │ ├── request.go
│ │ └── response.go
│ ├── def
│ │ └── def.go
│ ├── e
│ │ ├── code.go
│ │ ├── def.go
│ │ └── msg.go
│ ├── file
│ │ └── file.go
│ ├── gredis
│ │ └── redis.go
│ ├── logging
│ │ ├── file.go
│ │ └── log.go
│ ├── setting
│ │ └── setting.go
│ ├── upload
│ │ └── image.go
│ └── util
│ ├── jwt.go
│ ├── md5.go
│ ├── pagination.go
│ └── util.go
├── README.en.md
├── README.md
├── routers
│ ├── api
│ │ └── v1
│ └── router.go
├── runtime
│ └── logs
│ ├── log20190528.log
│ └── log20190529.log
└── service
├── teacher_service
│ └── teacher.go
└── user_service
└── user.go
複製代碼
FROM golang:1.12.4 as build
#ENV GOPROXY https://goproxy.io
WORKDIR /go/cache
ADD go.mod . ADD go.sum . RUN go mod download
WORKDIR /go/release
ADD . .
RUN GOOS=linux CGO_ENABLED=0 go build -ldflags="-s -w" -installsuffix cgo -o gin_demo main.go
FROM scratch as prod
COPY --from=build /usr/share/zoneinfo/Asia/Shanghai /etc/localtime COPY --from=build /go/release/gin_demo / COPY --from=build /go/release/conf ./conf CMD ["/gin_demo"] 複製代碼
注:若是選擇國內節點構建必須配上代理 ENV GOPROXY goproxy.iogolang
package main
import (
"fmt"
"log"
"net/http"
"os/exec"
"path"
)
/* * @Author:hanyajun * @Date:2019/5/28 16:44 * @Name:ci_tools * @Function: ci 工具 */
//
func HandleCi(w http.ResponseWriter, req *http.Request) {
user := path.Base(req.URL.Path)
//針對不一樣開發人員的push拉取不一樣的鏡像和映射不一樣的端口
var port string
switch user {
case "zhangsan":
port = "8088"
case "lisi":
port = "8087"
case "wangmazi":
port = "8086"
case "dev":
port = "8085"
case "master":
port = "8084"
}
println(user)
result := Run(user,port)
client:=NewMailClient("smtp.qq.com",465,"******@qq.com","*********")//注意使用465 ssl發送,25端口阿里雲ecs禁止了。
s:=&SendObject{
ToMails:[]string{"******@qq.com","******@qq.com","******@qq.com"},
CcMails:[]string{"******@qq.com"},
Object:"cicd流程結果通知",
ContentType:"text/html",
Content:user+" has push something to the branch: "+user+"\n"+"result: "+string(result),
}
err:=client.SendMail(s)
if err!=nil{
println("send mail fail",err)
}
_, _ = w.Write(result)
}
func main() {
http.HandleFunc("/ci/", HandleCi)
err := http.ListenAndServe(":8080", nil)
if err != nil {
log.Fatal("ListenAndServe: ", err)
}
}
func Run(user string,port string) []byte {
shellPath := "/root/ci/ci.sh"
command := exec.Command(shellPath, user,port)
err := command.Start()
if nil != err {
fmt.Println(err)
return []byte(err.Error())
}
fmt.Println("Process PID:", command.Process.Pid)
err = command.Wait() //等待執行完成
if nil != err {
fmt.Println(err)
return []byte(err.Error())
}
fmt.Println("ProcessState PID:", command.ProcessState.Pid())
return []byte("success")
}
複製代碼
mail.goweb
package main
import (
"fmt"
"gopkg.in/gomail.v2"
)
/* * @Author:15815 * @Date:2019/5/8 17:47 * @Name:mail * @Function:郵件發送 */
type Client struct {
Host string
Port int
Mail string
Password string
}
type SendObject struct {
ToMails []string
CcMails []string
Object string
ContentType string
Content string
}
func NewMailClient(host string, port int, sendMail, password string) *Client {
return &Client{
Host: host,
Port: port,
Mail: sendMail,
Password: password,
}
}
func (m *Client) SendMail(s *SendObject) error {
mgs := gomail.NewMessage()
mgs.SetHeader("From", m.Mail)
mgs.SetHeader("To", s.ToMails...)
mgs.SetHeader("Cc", s.CcMails...)
mgs.SetHeader("Subject", s.Object)
mgs.SetBody(s.ContentType, s.Content)
d := gomail.NewDialer(m.Host, m.Port, m.Mail, m.Password)
if err := d.DialAndSend(mgs); err != nil {
fmt.Printf("send mail err:%v", err)
return err
}
return nil
}
複製代碼
ci.shredis
#!/bin/bash
funCiTools()
{
docker pull registry.cn-shanghai.aliyuncs.com/***/***:$1
docker rm -f $1
docker run -d -p $2:8000 --name $1 registry.cn-shanghai.aliyuncs.com/***/***:$1
}
funCiTools $1 $2
複製代碼
第一個參數是對應開發人員啓動容器的名字以及構建鏡像的tag和上面構建的配置一致,第二個參數是映射的端口。 構建ci_web_server
本身的電腦是windows的,朋友的阿里雲ecs上又沒有go環境,想構建基於linux的二進制程序,因而直接利用docker image 來構建了鏡像,一個指令解決問題。 build.shsql
docker run --rm -i -v `pwd`:/go/src/ci -w /go/src/ci golang:1.11.5 go build -o ci ci
複製代碼
使用nohup直接將ci server放置後臺運行。docker
nohup ./ci >output 2>&1 &
複製代碼
直接修改點東西提交代碼後就等郵件通知了,是否是感受很爽。 shell