最近因为公司的产研调整,决定将代码仓库从本地的 Gitlab 迁移到云效的 Codeup,不是 Gitlab 不够好,而是 Codeup 在度量、安全等方面比原生的 Gitlab 要好,再则公司的产研管理也迁移到了云效,也为了统一化管理。
有同学可能会问,都用云效了,为什么不直接用它的 AppStack,还要用 Zadig?
AppStack 还处于发展阶段,还有以下问题不适合我们现阶段的需求:
- AppStack 不支持管理私有云 Kubernetes 集群(没有公网入口)。
- AppStack 不支持 Helm 类应用,改造工作比较大
再则,我也是 Zadig 开源产品的忠实粉丝~~!
但是,Zadig 对非标准的代码仓库的支持力度有限,比如:
- 非标准代码仓库不支持列出仓库列表,需要自己手动填写
- 非标准代码仓库创建的流水线原生不支持 Webhook 触发
经过综合考虑,手动填写代码仓库信息以及不支持 Webhook 并不影响整体的使用,只是会影响部分项目的工作效率。
但是,为了最小程度上影响原有的产研节奏,我还是准备自己实现三方仓库的 Webhook 触发 Zadig 流水线。因为本身也不复杂。
整体思路

实现不复杂,也就是接收到 webhook 触发动作,解析内容,根据需要触发相应的流水线接口。截至目前(v1.17.0)zadig 的触发流水线接口已经可以正常使用了。
开始搬砖
封装 Zadig API
首先封装一下 Zadig 的 API。为了方便使用,之前的弄了一个 go-zadig 项目(https://github.com/joker-bai/go-zadig),这两天将其做了更新,支持最新的 1.17.0 版本的 API。
主要增加了以下内容:
这部分是执行标准工作流的接口。自定义工作流之前已经实现了,并没有什么变化。
开发 Http Server
由于 Zadig 原生不支持三方仓库的 Webhook,要实现不外乎两种:
- 自己修改 Zadig 源码,实现这部分功能。
- 找一个中间商,由它来协调。
修改源码的好处是可以不需要再单独对数据这块做太多处理,直接用现成的。但我选择了后者,主要是因为菜,源码改起来费劲。
!! 我使用的是 Uber 的 fx 框架。其实用什么框架不重要,本身的逻辑就很简单,我只是选了一个用起来比较简单和顺手的。
(1)、定义数据结构
我定义的比较简单,命名也比较随意。主要的字段就是 Zadig API 需要的字段,其他不需要的就没写了。
(2)实现 Zadig 触发标准和非标准流水线
package zadig
import (
"github.com/joker-bai/go-zadig"
"joker-bai/go-webhook/config"
)
type Zadig struct {
client *zadig.Client
}
func NewZadig(cfg *config.Config) *Zadig {
client, err := zadig.NewClient(cfg.ZadigConfig.Token, zadig.WithBaseURL(cfg.ZadigConfig.URL))
if err != nil {
panic(err)
}
return &Zadig{client: client}
}
// ExecProductWorkflowTask 执行标准工作流
func (z *Zadig) ExecProductWorkflowTask(workflowName, projectName, targetEnv, serviceModule, serviceName, codehostName, repoNamespace, repoName, branch string) error {
_, _, err := z.client.Workflow.ExecWorkflowTask(&zadig.ExecWorkflowTaskOptions{
WorkflowName: workflowName,
ProjectName: projectName,
Input: zadig.WorkflowInput{
TargetEnv: targetEnv,
Build: zadig.ExecBuildArgs{
Enabled: true,
ServiceList: []zadig.BuildServiceInfo{
{
ServiceModule: serviceModule,
ServiceName: serviceName,
RepoInfo: []zadig.RepositoryInfo{
{
CodehostName: codehostName,
RepoNamespace: repoNamespace,
RepoName: repoName,
Branch: branch,
},
},
},
},
},
Deploy: zadig.ExecDeployArgs{
Enabled: true,
Source: "zadig",
},
},
})
return err
}
// ExecCustomWorkflowTask 执行自定义工作流
func (z *Zadig) ExecCustomWorkflowTask(projectName, workflowName, jobName, jobType, registry, serviceModule, serviceName, codehostName, repoNamespace, repoName, branch string) error {
_, _, err := z.client.CustomWorkflow.CreateCustomWorkflowTask(&zadig.CreateCustomWorkflowTask{
ProjectName: projectName,
WorkflowName: workflowName,
Inputs: []zadig.CreateCustomWorkflowTaskInput{
{
JobName: jobName,
JobType: jobType,
Parameters: zadig.CreateCustomWorkflowTaskParameters{
Register: registry,
ServiceList: []zadig.ServiceList{
{
ServiceModule: serviceModule,
ServiceName: serviceName,
RepoInfo: []zadig.RepoInfo{
{
CodehostName: codehostName,
RepoNamespace: repoNamespace,
RepoName: repoName,
Branch: branch,
},
},
},
},
},
},
},
})
return err
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
这里对工作流的 API 进行了取舍,根据实际情况选择需要的字段。
(3)实现 service 方法
这里从数据库获取需要的信息,然后根据不同的工作流类型执行不同的接口。
(4)实现 controller 方法
这部分就更简单了,从 Webhook 中获取数据,然后调 service 去执行即可。
最后就是增加路由了,这部分就不用展示了。
搬砖结束
搬砖完成过后就是对自己开发的 HTTP Server 进行验证了。
整个思路和开发的工作量都不大,上面的代码还有很多地方需要去调整的,如果有相同需求的可以自己去实现,我仅仅是做了一个 demo。
通过引入中间商的方式来实现自己的需求的优点是比较简单,不需要去看或者兼容其他的代码,只需要实现自己的逻辑,缺点就是数据这一块需要单独去处理,比较麻烦。
文章转载自公众号:运维开发故事