很多情况下,在工作流结束之后,可能你需要通过邮件向相关用户发送通知,下面是一个例子
首先我们通过golang创建一个可以用来发送邮件的镜像
下面的golang代码接收几个参数分别是
标题、工作流的结束状态、失败的异常信息 和 提交的注释内容
另外还通过环境变量,配置了其他信息
stmp服务器地址、端口、用户名和密码、cc list、发件人等
package main
import (
"bytes"
"crypto/tls"
"fmt"
"log"
"os"
"os/exec"
"strconv"
"strings"
"gopkg.in/gomail.v2"
)
func main() {
projectname := os.Getenv("projectname")
smtpHost := os.Getenv("smtphost")
smtpPort, _ := strconv.Atoi(os.Getenv("smtpport")) // 端口
smtpPass := os.Getenv("smtppass") // 密码
smtpUser := os.Getenv("smtpuser") // 用户
smtpCc := os.Getenv("smtpCc")
sender := os.Getenv("sender") // 发送者
subject := os.Getenv("subject")
buildstatus := os.Getenv("message")
commitidtxt := "commitid.txt"
failures := "None"
log.Println(len(os.Args))
if len(os.Args) == 5 {
subject = os.Args[1]
buildstatus = os.Args[2]
failures = os.Args[3]
commitidtxt = os.Args[4]
log.Println(subject + " " + os.Args[1])
log.Println(buildstatus + " " + os.Args[2])
log.Println(failures + " " + os.Args[3])
log.Println(commitidtxt + " " + os.Args[4])
}
commitid, _ := exec_shell("cat " + commitidtxt)
log.Println("commitid:" + commitid)
git_receiver_str, _ := exec_shell("git log --no-merges --pretty=format:\"%ae\" -1 " + commitid)
log.Println("git_receiver:" + git_receiver_str)
comments, _ := exec_shell("git log --pretty=format:\"%s\" -1 " + commitid)
log.Println("comments:" + comments)
committer, _ := exec_shell("git log --pretty=format:\"%cn\" -1 " + commitid)
log.Println("committer:" + committer)
time, _ := exec_shell("git log --pretty=format:\"%ad\" -1 " + commitid)
log.Println("time:" + time)
os_receivers_str := os.Getenv("receivers")
log.Println("os_receivers_str:" + os_receivers_str)
receivers_str := ""
if os_receivers_str == "" {
receivers_str = git_receiver_str
} else {
receivers_str = os_receivers_str
}
receivers := strings.Split(receivers_str, ",")
m := gomail.NewMessage()
m.SetHeader("From", sender)
m.SetHeader("To", receivers...)
if smtpCc != "" {
log.Println("ccs:" + smtpCc)
ccs := strings.Split(smtpCc, ",")
m.SetHeader("Cc", ccs...)
}
m.SetHeader("Subject", subject)
m.SetBody("text/html",
"<br/><br/>Project Name: "+projectname+
"<br/>Build status: "+buildstatus+
"<br/>Committer: "+committer+
"<br/>Comments: "+comments+
"<br/>Commitid: "+commitid+
"<br/>Time: "+time+
"<br/>Failures: "+failures)
d := gomail.NewDialer(smtpHost, smtpPort, smtpUser, smtpPass)
d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
if err := d.DialAndSend(m); err != nil {
fmt.Println(err)
}
}
//阻塞式的执行外部shell命令的函数,等待执行完毕并返回标准输出
func exec_shell(s string) (string, error) {
//函数返回一个*Cmd,用于使用给出的参数执行name指定的程序
cmd := exec.Command("/bin/bash", "-c", s)
//读取io.Writer类型的cmd.Stdout,再通过bytes.Buffer(缓冲byte类型的缓冲器)将byte类型转化为string类型(out.String():这是bytes类型提供的接口)
var out bytes.Buffer
cmd.Stdout = &out
//Run执行c包含的命令,并阻塞直到完成。 这里stdout被取出,cmd.Wait()无法正确获取stdin,stdout,stderr,则阻塞在那了
err := cmd.Run()
return out.String(), err
}
打包好镜像之后,可以使用下面的工作流
apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
name: lizhegithub
namespace: argo
spec:
template:
serviceAccountName: operate-workflow-sa
dependencies:
- name: fe-dep
eventSourceName: lizhegithub
eventName: lizhegitwebhook
triggers:
- template:
name: lizhe-workflow-trigger
argoWorkflow:
group: argoproj.io
version: v1alpha1
resource: workflows
operation: submit
source:
resource:
apiVersion: argoproj.io/v1alpha1
kind: WorkflowTemplate
metadata:
generateName: lizhebuildkit-
namespace: argo
spec:
templates:
- name: main
dag:
tasks:
- name: clean
template: clean
arguments: {}
- name: clone
template: clone
arguments:
parameters:
- name: repo
value: '{{workflow.parameters.repo}}'
- name: branch
value: '{{workflow.parameters.branch}}'
depends: clean
- name: getcommitid
template: getcommitid
arguments: {}
depends: clone
- name: mountcommitid
template: mountcommitid
arguments: {}
depends: getcommitid
- name: build
template: build
arguments: {}
depends: mountcommitid
- name: image
template: image
arguments:
parameters:
- name: image
value: '{{workflow.parameters.image}}'
- name: commitid
value: '{{tasks.mountcommitid.outputs.parameters.commitid}}'
depends: build
- name: deploy
template: deploy
arguments: {}
depends: image
onExit: deploy-exit-handler
- name: clean
container:
name: ''
image: k8s.gcr.io/busybox
command:
- /bin/sh
args:
- '-c'
- 'rm -rf /work/*'
workingDir: /work
volumeMounts:
- name: work
mountPath: /work
- name: clone
inputs:
artifacts:
- name: argo-source
path: /src
git:
repo: '{{workflow.parameters.repo}}'
revision: '{{workflow.parameters.branch}}'
usernameSecret:
name: github-creds
key: username
passwordSecret:
name: github-creds
key: password
container:
image: k8s.gcr.io/busybox
command:
- /bin/sh
args:
- '-c'
- cp -rf /src/. /work/ && ls /work
workingDir: /src
volumeMounts:
- name: work
mountPath: /work
- name: getcommitid
inputs: {}
outputs: {}
metadata: {}
container:
name: ''
image: libaibai/getcommitid
command:
- /bin/bash
args:
- '-c'
- /getcommitid.sh
workingDir: /work
volumeMounts:
- name: work
mountPath: /work
- name: mountcommitid
outputs:
parameters:
- name: commitid
valueFrom:
path: /work/commitid.txt
default: mockup_commitid
metadata: {}
container:
name: ''
image: k8s.gcr.io/busybox
command:
- /bin/sh
args:
- '-c'
- ls /work
workingDir: /work
resources: {}
volumeMounts:
- name: work
mountPath: /work
- name: build
container:
name: ''
image: 'node-alpine-3.13'
command:
- sh
args:
- -c
- 'yarn install && yarn build-storybook'
workingDir: /work/packages/components
env:
- name: ENVTEST
value: helloworld
volumeMounts:
- name: work
mountPath: /work
- name: image
inputs:
parameters:
- name: image
- name: commitid
container:
name: ''
image: gcr.io/kaniko-project/executor@sha256:f652f28537fa76e8f4f9393de13a064f0206003c451ce2ad6e4359fd5a21acbc
args:
- '-f'
- /work/packages/components/Dockerfile
- '-c'
- /work/packages/components
- --destination={{inputs.parameters.image}}:{{inputs.parameters.commitid}}
workingDir: /work
env:
- name: envkey
value: envvalue
resources: {}
volumeMounts:
- name: docker-config
mountPath: /kaniko/.docker/
- name: aws-secret
mountPath: /root/.aws/
- name: work
mountPath: /work
volumes:
- name: docker-config
configMap:
name: docker-config
- name: aws-secret
secret:
secretName: aws-secret
- name: deploy
container:
name: ''
image: 'libaibai/sedcommitid:latest'
command:
- /main.sh
args:
- weblizheponents/weblizheponents_dep.yaml
workingDir: /
env:
- name: GIT_URL
valueFrom:
secretKeyRef:
key: lizhe
name: giturl
- name: REPO
value: devops
- name: BRANCH
value: main
- name: USER_NAME
value: lizhe
- name: USER_EMAIL
value: xxxxx@email.com
volumeMounts:
- name: work
mountPath: /work
- name: deploy-exit-handler
container:
image: docker/whalesay
command: [cowsay]
args: ["task cleanup"]
- name: exit-handler
container:
image: xxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/mailsender
command:
- /bin/bash
args:
- -c
- "/main {{workflow.name}} {{workflow.status}} {{workflow.failures}} /work/commitid.txt"
workingDir: /work
env:
- name: projectname
value: YOURPROJECTNAME
- name: smtppass
valueFrom:
secretKeyRef:
key: password
name: smtpaccount
- name: smtpuser
valueFrom:
secretKeyRef:
key: username
name: smtpaccount
- name: smtphost
value: smtp.gmail.com
- name: smtpport
value: "587"
- name: sender
value: sender@email.com
- name: smtpCc
value: xxx@email.com,xxxx@email.com
- name: subject
value: mockup_subject
- name: body
value: mockup_body
volumeMounts:
- name: work
mountPath: /work
entrypoint: main
onExit: exit-handler
imagePullSecrets:
- name: regcred
arguments:
parameters:
- name: repo
value: https://github.com/xxxxx/xxxxxx.git
- name: branch
value: develop
- name: image
value: xxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/weblizheponents
volumeClaimTemplates:
- metadata:
name: work
creationTimestamp: null
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: gp2
status: {}
ttlStrategy:
secondsAfterCompletion: 1800
secondsAfterSuccess: 1800
secondsAfterFailure: 1800