background

Recently, my friend had a code cloud for code hosting for a project. There was only one test server (ECS of Ali Cloud), and three or four people developed it. Therefore, I wanted to quickly build a set of automatic CICD process based on The CodePipeline of Ali Cloud, and use Docker to deploy multiple sets of environments.

CodePipeline introduction

Ali cloud CodePipeline is compatible with Jenkins standards and provides fast and reliable continuous integration and continuous delivery services. Based on container technology and Ali Cloud basic service architecture, it provides stable and secure Code /Docker compilation and construction, testing, scanning and deployment tool services, and provides Pipeline As Code code-level configuration mode to meet the rapid and reliable delivery and update of applications and infrastructure.

New Build Project

Build the project basic configuration

Basic Information Configuration

Source management configuration

Build configuration

I use here is ali cloud private mirror warehouse based on Dockerfile to build the image, pay attention to configuration credentials. ! [Insert picture description here]

Project directory
Gin_demo ├ ─ ─ app │ └ ─ ─ app. Go ├ ─ ─ the conf │ └ ─ ─ app. Ini ├ ─ ─ Dockerfile ├ ─ ─ docs │ └ ─ ─ SQL │ └ ─ ─ MJS. SQL ├ ─ ─. Mod ├ ─ ─ Go. Sum ├ ─ ─ main. Go ├ ─ ─ middleware │ ├ ─ ─ JWT │ │ └ ─ ─ JWT. Go │ └ ─ ─ logging │ └ ─ ─ logger. Go ├ ─ ─ MJS. Exe ├ ─ ─ models │ ├ ─ ─ Mongo │ │ └ ─ ─ the db. Go │ └ ─ ─ mysql │ ├ ─ ─ the go │ ├ ─ ─ the teacher. Go │ └ ─ ─ user. Go ├ ─ ─ PKG │ ├ ─ ─ app │ │ ├ ─ ─ form. Go │ │ ├ ─ ─ Request. Go │ │ └ ─ ─ response. Go │ ├ ─ ─ def │ │ └ ─ ─ def. Go │ ├ ─ ─ e │ │ ├ ─ ─ code. Go │ │ ├ ─ ─ def. Go │ │ └ ─ ─ MSG. Go │ ├ ─ ─ the file │ │ └ ─ ─ file. Go │ ├ ─ ─ gredis │ │ └ ─ ─ redis. Go │ ├ ─ ─ logging │ │ ├ ─ ─ file. Go │ │ └ ─ ─ the go │ ├ ─ ─ setting │ │ └ ─ ─ Setting. Go │ ├ ─ ─ the upload │ │ └ ─ ─ image. Go │ └ ─ ─ util │ ├ ─ ─ JWT. Go │ ├ ─ ─ the md5. Go │ ├ ─ ─ pagination. Go │ └ ─ ─ util. Go ├ ─ ─ As soon as you go to school, you should go to school. As soon as you go to school, you should go to school. As soon as you go to school, you should go to school │ ├─ ├─ all, all, all, all, all, all, all, all, allCopy the code
Dockerfile
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"]
Copy the code

Note: If you select domestic node construction, you must configure ENV GOPROXY goproxy. IO

Configuring triggers

Configure the deployment

package main

import (
	"fmt"
	"log"
	"net/http"
	"os/exec"
	"path"
)

/* * @author :hanyajun * @date :2019/5/28 16:44 * @name :ci_tools * @function :ci tool */

//
func HandleCi(w http.ResponseWriter, req *http.Request) {
	user := path.Base(req.URL.Path)
	// Different pushes for different developers pull different mirrors and map different ports
	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"."* * * * * * * * *")// Note that using 465 SSL to send, port 25 is disabled by Aliyun ECS.
	s:=&SendObject{
		ToMails:[]string{"******@qq.com"."******@qq.com"."******@qq.com"},
		CcMails:[]string{"******@qq.com"},
		Object:"Cicd Process Result Notification",
		ContentType:"text/html",
		Content:user+" has push something to the branch: "+user+"\n"+"result: "+string(result),
	}
	err:=client.SendMail(s)
	iferr! =nil{
		println("send mail fail",err)
	}
	_, _ = w.Write(result)
}
func main(a) {
	http.HandleFunc("/ci/", HandleCi)
	err := http.ListenAndServe(": 8080".nil)
	iferr ! =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() // Wait for execution to complete
	if nil! = err { fmt.Println(err)return []byte(err.Error())
	}
	fmt.Println("ProcessState PID:", command.ProcessState.Pid())
	return []byte("success")}Copy the code

mail.go

package main

import (
	"fmt"
	"gopkg.in/gomail.v2"
)

/* * @author :15815 * @date: 2019/5/817:47 * @name :mail * @function: send email */

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)
	iferr := d.DialAndSend(mgs); err ! =nil {
		fmt.Printf("send mail err:%v", err)
		return err
	}
	return nil
}

Copy the code

ci.sh

#! /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
Copy the code

The first parameter is the name of the corresponding developer startup container and the tag for the build image that matches the configuration built above. The second parameter is the mapped port. The computer used to build CI_web_server was Windows, and there was no GO environment on my friend’s Aliyun ECS. I wanted to build binary programs based on Linux, so I directly used Docker Image to build the image, and solved the problem with one instruction. build.sh

Docker run --rm -i -v 'PWD' :/go/ SRC/ci-w /go/ SRC /ci golang:1.11.5 go build -o ci ciCopy the code

Use Nohup to place CI Server directly in the background.

nohup ./ci  >output 2>&1 &
Copy the code

Effect of the test

Doesn’t it feel good to just change something and submit the code and then wait for an email?