Программа go основана на практике разработки Alibaba Cloud CodePipeline.

Go

задний план

Недавно у знакомого появилось облако кода для хостинга кода проекта, тестовый сервер всего один (Alibaba Cloud ECS), а разрабатывают его три-четыре человека.CodePipelineБыстро создайте автоматизированный процесс cicd и используйте Docker для развертывания нескольких сред.

Введение в CodePipeline

Alibaba Cloud CodePipeline совместим со стандартом Jenkins и обеспечивает быструю и надежную непрерывную интеграцию и услуги непрерывной доставки. Основанный на контейнерной технологии и базовой сервисной архитектуре Alibaba Cloud, он обеспечивает стабильную и безопасную компиляцию кода/Docker, создание, тестирование, сканирование и услуги инструментов развертывания, а также обеспечивает режим конфигурации на уровне кодирования Pipeline As Code для удовлетворения быстрых и надежных требований. приложений и инфраструктуры.Поставлено и обновлено.

Выше официальное введение Alibaba Cloud, которое совместимо со стандартом jekins.Появляется непреднамеренный щелчок по значку на картинке ниже.Ощущение, что на базе Jenkins сделана вторичная разработка.

Новые строительные проекты

Собираем базовую конфигурацию проекта

Конфигурация базовой информации

Так как в проекте используются какие-то иностранные либы, конечно, можно выбрать отечественные ноды, но не забудьте добавить прокси при написании Dockerfile.

Конфигурация управления исходным кодом

Выберите подходящий репозиторий кода или частный репозиторий, но вам нужно добавить свою собственную учетную запись и информацию, связанную с ключом ssh.

конфигурация сборки

Я использую это здесь, что склад Частный зеркальный зеркал Alibaba Cloud основан на DockerFile для создания зеркала, обратите внимание на настройку учетных данных. ! [Вставьте описание изображения здесь]

каталог проекта
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

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"]

Примечание. Если вы решите построить внутренний узел, он должен быть оснащен агентом ENV GOPROXY.goproxy.io

Настроить триггеры

Здесь выберите созданную ветку кода, а затем нажмите «Создать».Сгенерированный URL-адрес можно настроить с помощью веб-перехватчика и других конфигураций в соответствующем репозитории кода. Выберите подходящий метод триггера.

Настройка развертывания

На этапе сборки Alibaba Cloud развертывание в ECS (неудобно) и развертывание в k8s (платно) не может удовлетворить потребности сценария проекта, но поддерживает сценарии оболочки, поэтому я хочу запустить ci web на ECS Alibaba Cloud моего друга. сервер, после завершения построения перейдите к уведомлению интерфейса, а затем выполните некоторые командные сценарии docker, вытащите образ после построения и перезапустите и уведомите по электронной почте после запуска. Итак, я написал такой очень простой веб-сервер. главный

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.go

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.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

Первый параметр - это имя контейнера соответствующего разработчика и начнет создавать согласующуюся конфигурацию сборки тегов и верхнего зеркала, второй параметр - это отображение порта.построить ci_web_server
Мой компьютер - Windows, а Alibaba Cloud ecs моего друга не имеет среды go. Я хочу создать бинарную программу на основе Linux, поэтому я напрямую использую образ docker для создания образа и решения проблемы с помощью одной инструкции. build.sh

docker run --rm -i -v `pwd`:/go/src/ci -w /go/src/ci  golang:1.11.5   go build -o ci  ci

Используйте nohup для прямого запуска сервера ci в фоновом режиме.

nohup ./ci  >output 2>&1 &

тест на эффект

Круто ли напрямую что-то изменить, отправить код и ждать уведомления по электронной почте?

После отправки кода сборка будет запущена.
Наконец, сервер CI запускается после завершения завершения, и почтовое уведомление завершено.
После входа в Alibaba Cloud Ecs мы обнаружили, что наш контейнер успешно запущен.