-
Notifications
You must be signed in to change notification settings - Fork 96
/
testpipeline.go
192 lines (157 loc) · 4.82 KB
/
testpipeline.go
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
package db
import (
"database/sql/driver"
"encoding/json"
"fmt"
"github.com/jinzhu/gorm"
)
type (
TestPipeline struct {
gorm.Model
Name string
AppName string
Env string `gorm:"type:varchar(32)"`
ZoneCode string
Branch string
CodeCheck bool
UnitTest bool
HttpTestCollection *int
GrpcTestAddr string
GrpcTestCases PipelineGrpcTestCases `gorm:"type:json"` // GRPC 测试用例列表
CreatedBy uint
UpdatedBy uint
App AppInfo `gorm:"foreignKey:AppName;association_foreignkey:AppName" json:"-"`
}
//TestPipelineTask 任务下发执行的单位
TestPipelineTask struct {
gorm.Model
PipelineID uint
Name string
AppName string
Branch string
Env string `gorm:"type:varchar(32)"`
ZoneCode string `gorm:"type:varchar(32)"`
Desc TestPipelineDesc `gorm:"type:json"`
Status TestTaskStatus // pending, running, failed, success
Logs string `gorm:"type:longtext"`
CreatedBy uint
StepStatus []TestPipelineStepStatus `gorm:"foreignKey:TaskID" json:"-"`
}
//TestPipelineStepStatus 任务阶段状态
TestPipelineStepStatus struct {
gorm.Model
TaskID uint
StepName string
Status TestStepStatus // waiting, running, failed, success
Logs string `gorm:"type:longtext"`
}
StepType int
TestPipelineDesc struct {
Parallel bool `json:"parallel"`
Steps []TestPipelineStep `json:"steps"`
}
TestPipelineStep struct {
Type StepType `json:"type"` // Step Type
Name string `json:"name"` // MUST be unique under one TestPipelineDesc
SubPipeline *TestPipelineDesc `json:"sub_pipeline"` // MUST be set when Type equals StepTypeSubPipeline
JobPayload *TestJobPayload `json:"job_payload"` // MUST be set when Type equals StepTypeJob
}
TestJobPayload struct {
Type TestJobType `json:"type"`
Payload json.RawMessage `json:"payload"`
}
PipelineGrpcTestCases []struct {
Service uint `json:"service"`
Method uint `json:"method"`
TestCase uint `json:"testcase"`
}
TestJobType string
TestTaskStatus string
TestStepStatus string
)
const (
StepTypeSubPipeline StepType = 1 // 子Pipeline类型,当前Step拥有多个子Step
StepTypeJob = 2 // 任务类型,当前Step执行某个任务
JobGitPull TestJobType = "git_pull"
JobUnitTest TestJobType = "unit_test"
JobCodeCheck TestJobType = "code_check"
JobHttpTest TestJobType = "http_test"
JobGrpcTest TestJobType = "grpc_test"
TestTaskStatusPending TestTaskStatus = "pending"
TestTaskStatusRunning = "running"
TestTaskStatusFailed = "failed"
TestTaskStatusSuccess = "success"
TestStepStatusWaiting TestStepStatus = "waiting"
TestStepStatusRunning = "running"
TestStepStatusFailed = "failed"
TestStepStatusSuccess = "success"
)
func (*TestPipeline) TableName() string {
return "test_pipeline"
}
func (*TestPipelineTask) TableName() string {
return "test_pipeline_task"
}
func (*TestPipelineStepStatus) TableName() string {
return "test_pipeline_step_status"
}
func (d TestPipelineDesc) Value() (driver.Value, error) {
return json.Marshal(d)
}
func (d *TestPipelineDesc) Scan(input interface{}) error {
return json.Unmarshal(input.([]byte), d)
}
func (d PipelineGrpcTestCases) Value() (driver.Value, error) {
return json.Marshal(d)
}
func (d *PipelineGrpcTestCases) Scan(input interface{}) error {
return json.Unmarshal(input.([]byte), d)
}
//ValidatePipelineDesc 检查 TestPipelineDesc 是否有效
func (d TestPipelineDesc) ValidatePipelineDesc() error {
names := make(map[string]bool)
var functor func(desc TestPipelineDesc) error
functor = func(desc TestPipelineDesc) error {
for _, step := range desc.Steps {
if names[step.Name] {
return fmt.Errorf("step name conflicts: %s", step.Name)
}
names[step.Name] = true
switch step.Type {
case StepTypeSubPipeline:
if step.SubPipeline == nil {
return fmt.Errorf("step.SubPipeline MUST not be nil when type = StepTypeSubPipeline")
}
err := functor(*step.SubPipeline)
if err != nil {
return err
}
case StepTypeJob:
if step.JobPayload == nil {
return fmt.Errorf("step.JobPayload MUST not be nil when type = StepTypeJob")
}
}
}
return nil
}
return functor(d)
}
func (d TestPipelineDesc) JobCount() int {
count := 0
var functor func(desc TestPipelineDesc)
functor = func(desc TestPipelineDesc) {
for _, step := range desc.Steps {
switch step.Type {
case StepTypeSubPipeline:
if step.SubPipeline == nil {
continue
}
functor(*step.SubPipeline)
case StepTypeJob:
count += 1
}
}
}
functor(d)
return count
}