Skip to content

Commit ce59cf2

Browse files
authored
feat: [minor] gitlab testrunner override (#121)
* feat: add testRunner extra config * feat: infer branch * fmt: lint * doc: swag * fix: gitlab mr data type * fix: override gitlab field by field * test: gitlab api * doc: swag * doc: gitlab MR * test: unit * fix: remove pointer * test: add in script * fix: ginkgo test suite
1 parent 76f9fee commit ce59cf2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2243
-508
lines changed

api/v1/api_v1_suite_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package v1_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/agoda-com/samsahai/internal/util/unittest"
7+
)
8+
9+
func TestAPIv1Suite(t *testing.T) {
10+
unittest.InitGinkgo(t, "Test API v1")
11+
}

api/v1/config_types.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ type ConfigDeploy struct {
123123

124124
// ConfigTestRunner represents configuration about how to test the environment
125125
type ConfigTestRunner struct {
126+
// TODO: make Timeout and PollingTime pointers to reduce duplicate code in ConfigTestRunnerOverrider
127+
126128
// +optional
127129
Timeout metav1.Duration `json:"timeout,omitempty"`
128130
// +optional
@@ -135,19 +137,138 @@ type ConfigTestRunner struct {
135137
TestMock *ConfigTestMock `json:"testMock,omitempty"`
136138
}
137139

140+
// ConfigTestRunnerOverrider is data that overrides ConfigTestRunner field by field
141+
type ConfigTestRunnerOverrider struct {
142+
// +optional
143+
Timeout *metav1.Duration `json:"timeout,omitempty"`
144+
// +optional
145+
PollingTime *metav1.Duration `json:"pollingTime,omitempty"`
146+
// +optional
147+
Gitlab *ConfigGitlabOverrider `json:"gitlab,omitempty"`
148+
// +optional
149+
Teamcity *ConfigTeamcityOverrider `json:"teamcity,omitempty"`
150+
// +optional
151+
TestMock *ConfigTestMock `json:"testMock,omitempty"`
152+
153+
ConfigTestRunnerOverriderExtraParameters `json:",inline"`
154+
}
155+
156+
type ConfigTestRunnerOverriderExtraParameters struct {
157+
// PullRequestInferGitlabMRBranch is for Pull Request's testRunner on gitlab.
158+
// If true, samsahai will try to infer the testRunner branch name
159+
// from the gitlab MR associated with the PR flow.
160+
// +optional
161+
PullRequestInferGitlabMRBranch *bool `json:"pullRequestInferGitlabMRBranch,omitempty"`
162+
}
163+
164+
// Override overrides ConfigTestRunner and return a reference to the overridden instance.
165+
// The operation will try to override an instance in-place if possible.
166+
func (c ConfigTestRunnerOverrider) Override(confTestRunner *ConfigTestRunner) *ConfigTestRunner {
167+
ensureConfTestRunner := func() {
168+
if confTestRunner == nil {
169+
confTestRunner = &ConfigTestRunner{}
170+
}
171+
}
172+
if c.Timeout != nil {
173+
ensureConfTestRunner()
174+
confTestRunner.Timeout = *c.Timeout.DeepCopy()
175+
}
176+
if c.PollingTime != nil {
177+
ensureConfTestRunner()
178+
confTestRunner.PollingTime = *c.PollingTime.DeepCopy()
179+
}
180+
if c.Gitlab != nil {
181+
ensureConfTestRunner()
182+
confTestRunner.Gitlab = c.Gitlab.Override(confTestRunner.Gitlab)
183+
}
184+
if c.Teamcity != nil {
185+
ensureConfTestRunner()
186+
confTestRunner.Teamcity = c.Teamcity.Override(confTestRunner.Teamcity)
187+
}
188+
if c.TestMock != nil {
189+
ensureConfTestRunner()
190+
confTestRunner.TestMock = c.TestMock.DeepCopy()
191+
}
192+
return confTestRunner
193+
}
194+
138195
// ConfigTeamcity defines a http rest configuration of teamcity
139196
type ConfigTeamcity struct {
197+
// TODO: make every fields optional to reduce duplicate code in ConfigTeamcityOverrider
198+
140199
BuildTypeID string `json:"buildTypeID" yaml:"buildTypeID"`
141200
Branch string `json:"branch" yaml:"branch"`
142201
}
143202

203+
// ConfigTeamcityOverrider is data that overrides ConfigTeamcity field by field
204+
type ConfigTeamcityOverrider struct {
205+
// +optional
206+
BuildTypeID *string `json:"buildTypeID,omitempty"`
207+
// +optional
208+
Branch *string `json:"branch,omitempty"`
209+
}
210+
211+
// Override overrides ConfigTeamcity and return a reference to the overridden instance.
212+
// The operation will try to override an instance in-place if possible.
213+
func (c ConfigTeamcityOverrider) Override(confTeamcity *ConfigTeamcity) *ConfigTeamcity {
214+
ensureConfTeamcity := func() {
215+
if confTeamcity == nil {
216+
confTeamcity = &ConfigTeamcity{}
217+
}
218+
}
219+
if c.BuildTypeID != nil {
220+
ensureConfTeamcity()
221+
confTeamcity.BuildTypeID = *c.BuildTypeID
222+
}
223+
if c.Branch != nil {
224+
ensureConfTeamcity()
225+
confTeamcity.Branch = *c.Branch
226+
}
227+
return confTeamcity
228+
}
229+
144230
// ConfigGitlab defines a http rest configuration of gitlab
145231
type ConfigGitlab struct {
232+
// TODO: make every fields optional to reduce duplicate code in ConfigGitlabOverrider
233+
146234
ProjectID string `json:"projectID" yaml:"projectID"`
147235
Branch string `json:"branch" yaml:"branch"`
148236
PipelineTriggerToken string `json:"pipelineTriggerToken" yaml:"pipelineTriggerToken"`
149237
}
150238

239+
// ConfigGitlabOverrider is data that overrides ConfigGitlab field by field
240+
type ConfigGitlabOverrider struct {
241+
// +optional
242+
ProjectID *string `json:"projectID,omitempty"`
243+
// +optional
244+
Branch *string `json:"branch,omitempty"`
245+
// +optional
246+
PipelineTriggerToken *string `json:"pipelineTriggerToken,omitempty"`
247+
}
248+
249+
// Override overrides ConfigGitlab and return a reference to the overridden instance.
250+
// The operation will try to override an instance in-place if possible.
251+
func (c ConfigGitlabOverrider) Override(confGitlab *ConfigGitlab) *ConfigGitlab {
252+
ensureConfGitlab := func() {
253+
if confGitlab == nil {
254+
confGitlab = &ConfigGitlab{}
255+
}
256+
}
257+
if c.ProjectID != nil {
258+
ensureConfGitlab()
259+
confGitlab.ProjectID = *c.ProjectID
260+
}
261+
if c.Branch != nil {
262+
ensureConfGitlab()
263+
confGitlab.Branch = *c.Branch
264+
}
265+
if c.PipelineTriggerToken != nil {
266+
ensureConfGitlab()
267+
confGitlab.PipelineTriggerToken = *c.PipelineTriggerToken
268+
}
269+
return confGitlab
270+
}
271+
151272
// ConfigTestMock defines a result of testmock
152273
type ConfigTestMock struct {
153274
Result bool `json:"result" yaml:"result"`

api/v1/config_types_test.go

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
package v1_test
2+
3+
import (
4+
v1 "github.com/agoda-com/samsahai/api/v1"
5+
. "github.com/onsi/ginkgo"
6+
. "github.com/onsi/gomega"
7+
)
8+
9+
var _ = Describe("Config Overrider", func() {
10+
g := NewWithT(GinkgoT())
11+
12+
Describe("ConfigTeamcityOverrider", func() {
13+
var overrider v1.ConfigTeamcityOverrider
14+
var confTeamcity *v1.ConfigTeamcity
15+
var beforeOverride *v1.ConfigTeamcity
16+
var res *v1.ConfigTeamcity
17+
18+
BeforeEach(func() {
19+
overrider = v1.ConfigTeamcityOverrider{}
20+
confTeamcity = nil
21+
beforeOverride = nil
22+
res = nil
23+
})
24+
25+
It("should return new pointer if the old is nil", func() {
26+
buildTypeID := "123"
27+
branch := "branch"
28+
overrider = v1.ConfigTeamcityOverrider{
29+
BuildTypeID: &buildTypeID,
30+
Branch: &branch,
31+
}
32+
res = overrider.Override(nil)
33+
g.Expect(res).To(Equal(&v1.ConfigTeamcity{
34+
BuildTypeID: buildTypeID,
35+
Branch: branch,
36+
}))
37+
})
38+
39+
Context("nothing to override", func() {
40+
Specify("overridden is nil", func() {
41+
res = overrider.Override(nil)
42+
g.Expect(res).To(BeNil())
43+
})
44+
45+
Specify("overridden is not nil", func() {
46+
confTeamcity = &v1.ConfigTeamcity{
47+
BuildTypeID: "123",
48+
Branch: "branch",
49+
}
50+
beforeOverride = confTeamcity.DeepCopy()
51+
res = overrider.Override(confTeamcity)
52+
53+
// expect to not change anything
54+
g.Expect(confTeamcity).To(Equal(beforeOverride))
55+
// expect to yield the input
56+
g.Expect(res).To(BeIdenticalTo(confTeamcity))
57+
})
58+
})
59+
60+
Context("there is something to override", func() {
61+
Specify("override one field", func() {
62+
branch := "456"
63+
overrider = v1.ConfigTeamcityOverrider{
64+
Branch: &branch,
65+
}
66+
confTeamcity = &v1.ConfigTeamcity{
67+
BuildTypeID: "123",
68+
Branch: "branch",
69+
}
70+
beforeOverride = confTeamcity.DeepCopy()
71+
res = overrider.Override(confTeamcity)
72+
// expect to override 1 field
73+
g.Expect(res).To(Equal(&v1.ConfigTeamcity{
74+
BuildTypeID: beforeOverride.BuildTypeID,
75+
Branch: branch,
76+
}))
77+
// expect to yield the input pointer
78+
g.Expect(res).To(BeIdenticalTo(confTeamcity))
79+
})
80+
81+
Specify("override more than one field", func() {
82+
buildTypeID := "id"
83+
branch := "456"
84+
overrider = v1.ConfigTeamcityOverrider{
85+
BuildTypeID: &buildTypeID,
86+
Branch: &branch,
87+
}
88+
confTeamcity = &v1.ConfigTeamcity{
89+
BuildTypeID: "123",
90+
Branch: "branch",
91+
}
92+
beforeOverride = confTeamcity.DeepCopy()
93+
res = overrider.Override(confTeamcity)
94+
// expect to override fields
95+
g.Expect(res).To(Equal(&v1.ConfigTeamcity{
96+
BuildTypeID: buildTypeID,
97+
Branch: branch,
98+
}))
99+
// expect to yield the input pointer
100+
g.Expect(res).To(BeIdenticalTo(confTeamcity))
101+
})
102+
})
103+
})
104+
105+
Describe("ConfigGitlabOverrider", func() {
106+
g := NewWithT(GinkgoT())
107+
var overrider v1.ConfigGitlabOverrider
108+
var confGitlab *v1.ConfigGitlab
109+
var beforeOverride *v1.ConfigGitlab
110+
var res *v1.ConfigGitlab
111+
112+
BeforeEach(func() {
113+
overrider = v1.ConfigGitlabOverrider{}
114+
confGitlab = nil
115+
beforeOverride = nil
116+
res = nil
117+
})
118+
119+
It("should return new pointer if the old is nil", func() {
120+
projectID := "123"
121+
branch := "branch"
122+
overrider = v1.ConfigGitlabOverrider{
123+
ProjectID: &projectID,
124+
Branch: &branch,
125+
}
126+
res = overrider.Override(nil)
127+
g.Expect(res).To(Equal(&v1.ConfigGitlab{
128+
ProjectID: projectID,
129+
Branch: branch,
130+
}))
131+
})
132+
133+
Context("nothing to override", func() {
134+
Specify("overridden is nil", func() {
135+
res = overrider.Override(nil)
136+
g.Expect(res).To(BeNil())
137+
})
138+
139+
Specify("overridden is not nil", func() {
140+
confGitlab = &v1.ConfigGitlab{
141+
ProjectID: "123",
142+
Branch: "branch",
143+
PipelineTriggerToken: "token",
144+
}
145+
beforeOverride = confGitlab.DeepCopy()
146+
res = overrider.Override(confGitlab)
147+
148+
// expect to not change anything
149+
g.Expect(confGitlab).To(Equal(beforeOverride))
150+
// expect to yield the input
151+
g.Expect(res).To(BeIdenticalTo(confGitlab))
152+
})
153+
})
154+
155+
Context("there is something to override", func() {
156+
Specify("override one field", func() {
157+
branch := "456"
158+
overrider = v1.ConfigGitlabOverrider{
159+
Branch: &branch,
160+
}
161+
confGitlab = &v1.ConfigGitlab{
162+
ProjectID: "123",
163+
Branch: "branch",
164+
PipelineTriggerToken: "token",
165+
}
166+
beforeOverride = confGitlab.DeepCopy()
167+
res = overrider.Override(confGitlab)
168+
// expect to override 1 field
169+
g.Expect(res).To(Equal(&v1.ConfigGitlab{
170+
ProjectID: beforeOverride.ProjectID,
171+
Branch: branch,
172+
PipelineTriggerToken: beforeOverride.PipelineTriggerToken,
173+
}))
174+
// expect to yield the input pointer
175+
g.Expect(res).To(BeIdenticalTo(confGitlab))
176+
})
177+
178+
Specify("override more than one field", func() {
179+
projectID := "id"
180+
branch := "456"
181+
pipelineTriggerToken := "pipelinetriggertoken"
182+
overrider = v1.ConfigGitlabOverrider{
183+
ProjectID: &projectID,
184+
Branch: &branch,
185+
PipelineTriggerToken: &pipelineTriggerToken,
186+
}
187+
confGitlab = &v1.ConfigGitlab{
188+
ProjectID: "123",
189+
Branch: "branch",
190+
PipelineTriggerToken: "token",
191+
}
192+
beforeOverride = confGitlab.DeepCopy()
193+
res = overrider.Override(confGitlab)
194+
// expect to override fields
195+
g.Expect(res).To(Equal(&v1.ConfigGitlab{
196+
ProjectID: projectID,
197+
Branch: branch,
198+
PipelineTriggerToken: pipelineTriggerToken,
199+
}))
200+
// expect to yield the input pointer
201+
g.Expect(res).To(BeIdenticalTo(confGitlab))
202+
})
203+
})
204+
})
205+
})

api/v1/pullrequestqueue_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ type PullRequestQueueSpec struct {
8080
// TearDownDuration defines duration before teardown the pull request components
8181
// +optional
8282
TearDownDuration PullRequestTearDownDuration `json:"tearDownDuration,omitempty"`
83+
84+
// TestRunner represents configuration about how to test the environment. If defined, this will override
85+
// testRunner from config
86+
// +optional
87+
TestRunner *ConfigTestRunnerOverrider `json:"testRunner,omitempty"`
8388
}
8489

8590
// PullRequestQueueConditionType represents a condition type of pull request queue

api/v1/pullrequesttrigger_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ type PullRequestTriggerSpec struct {
5252
// tearDownDuration from pull request extra config
5353
// +optional
5454
TearDownDuration *PullRequestTearDownDuration `json:"tearDownDuration,omitempty"`
55+
// TestRunner represents configuration about how to test the environment. If defined, this will override
56+
// testRunner from config
57+
// +optional
58+
TestRunner *ConfigTestRunnerOverrider `json:"testRunner,omitempty"`
5559
}
5660

5761
// PullRequestTriggerResult represents the result status of a pull request trigger

0 commit comments

Comments
 (0)