Skip to content

Commit 0381f1b

Browse files
authored
[rayci] add option noTagMeansAlways (#266)
and set as false by default. when it is set to false, this will shake off unnecessary steps that have no tags when tag based conditional testing is enabled. this is a change on the default behavior.
1 parent ab70fb3 commit 0381f1b

File tree

6 files changed

+84
-5
lines changed

6 files changed

+84
-5
lines changed

raycicmd/config.go

+5
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ type config struct {
146146
//
147147
// Optional.
148148
DockerPlugin *dockerPluginConfig `yaml:"docker_plugin"`
149+
150+
// NoTagMeansAlways sets if a step without any tags should be treated as
151+
// a step with a magic "always" tag, that will always be picked during the
152+
// conditional testing tag picking phase.
153+
NoTagMeansAlways bool `yaml:"no_tag_means_always"`
149154
}
150155

151156
func builderAgent(config *config, instanceType string) string {

raycicmd/converter_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,8 @@ func TestConvertPipelineGroup(t *testing.T) {
751751
filter := &stepFilter{
752752
skipTags: stringSet("disabled"),
753753
tags: stringSet("foo"),
754+
755+
noTagMeansAlways: true,
754756
}
755757
bk, err := convertSingleGroup(c, g, filter)
756758
if err != nil {

raycicmd/make.go

+2
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ func makePipeline(repoDir string, config *config, info *buildInfo) (
9999
return nil, fmt.Errorf("run tag filter command: %w", err)
100100
}
101101

102+
filter.noTagMeansAlways = config.NoTagMeansAlways
103+
102104
// Build steps for CI.
103105
bkDirs := config.BuildkiteDirs
104106
if len(bkDirs) == 0 {

raycicmd/make_test.go

+35-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,6 @@ func TestMakePipeline(t *testing.T) {
225225
SkipTags: []string{"disabled"},
226226
BuildkiteDirs: []string{".buildkite", "private/buildkite"},
227227
}
228-
229228
t.Run("filter", func(t *testing.T) {
230229
config := *commonConfig
231230
config.TagFilterCommand = []string{"echo", "enabled"}
@@ -240,6 +239,41 @@ func TestMakePipeline(t *testing.T) {
240239
t.Fatalf("makePipeline: %v", err)
241240
}
242241

242+
// Should only select the enabled steps and its dependencies.
243+
// which are 2 steps in 2 different groups.
244+
if want := 2; len(got.Steps) != want {
245+
t.Errorf("got %d groups, want %d", len(got.Steps), want)
246+
}
247+
248+
// sub funtions are already tested in their unit tests.
249+
// so we only check the total number of groups here.
250+
// we also have an e2e test at the repo level.
251+
252+
totalSteps := 0
253+
for _, g := range got.Steps {
254+
totalSteps += len(g.Steps)
255+
}
256+
257+
if want := 2; totalSteps != want {
258+
t.Fatalf("got %d steps, want %d", totalSteps, want)
259+
}
260+
})
261+
262+
t.Run("filter_noTagMeansAlways", func(t *testing.T) {
263+
config := *commonConfig
264+
config.TagFilterCommand = []string{"echo", "enabled"}
265+
config.NoTagMeansAlways = true
266+
267+
buildID := "fakebuild"
268+
info := &buildInfo{
269+
buildID: buildID,
270+
}
271+
272+
got, err := makePipeline(tmp, &config, info)
273+
if err != nil {
274+
t.Fatalf("makePipeline: %v", err)
275+
}
276+
243277
if want := 3; len(got.Steps) != want { // all steps are groups.
244278
t.Errorf("got %d groups, want %d", len(got.Steps), want)
245279
}

raycicmd/step_filter.go

+7-3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ type stepFilter struct {
1818
// third pass: selecting steps
1919
selects map[string]bool // based on ID or key
2020
tagSelects map[string]bool // or based on tags
21+
22+
noTagMeansAlways bool
2123
}
2224

2325
func (f *stepFilter) reject(step *stepNode) bool {
@@ -42,9 +44,11 @@ func (f *stepFilter) acceptTagHit(step *stepNode) bool {
4244
return true
4345
}
4446

45-
// if not in run-all mode, hit when the step has any of the tags.
46-
if !step.hasTags() {
47-
return true // step does not have any tags: a step that always runs
47+
if f.noTagMeansAlways {
48+
// if noTagMeansAlways is set, hit when the step has any of the tags.
49+
if !step.hasTags() {
50+
return true // step does not have any tags: a step that always runs
51+
}
4852
}
4953
return step.hasTagInMap(f.tags)
5054
}

raycicmd/step_filter_test.go

+33-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ func TestStepFilter_tags(t *testing.T) {
6464
filter := &stepFilter{
6565
skipTags: stringSet("disabled"),
6666
tags: stringSet("tune"),
67+
68+
noTagMeansAlways: true,
6769
}
6870

6971
for _, tags := range [][]string{
@@ -217,12 +219,13 @@ func TestStepFilter_tagSelects(t *testing.T) {
217219
}
218220
}
219221

220-
func TestStepFilter_selectsAndTags(t *testing.T) {
222+
func TestStepFilter_selectsAndTags_noTagMeansAlways(t *testing.T) {
221223
filter, _ := newStepFilter(
222224
[]string{"disabled"},
223225
[]string{"foo", "bar", "tag:pick"},
224226
[]string{"echo", "tune"},
225227
)
228+
filter.noTagMeansAlways = true
226229

227230
for _, node := range []*stepNode{
228231
{key: "foo"},
@@ -246,6 +249,35 @@ func TestStepFilter_selectsAndTags(t *testing.T) {
246249
}
247250
}
248251

252+
func TestStepFilter_selectsAndTags(t *testing.T) {
253+
filter, _ := newStepFilter(
254+
[]string{"disabled"},
255+
[]string{"foo", "bar", "tag:pick"},
256+
[]string{"echo", "tune"},
257+
)
258+
259+
for _, node := range []*stepNode{
260+
{id: "foo", tags: []string{"tune"}},
261+
{id: "other", tags: []string{"pick", "tune"}},
262+
} {
263+
if !filter.accept(node) {
264+
t.Errorf("miss %+v", node)
265+
}
266+
}
267+
268+
for _, node := range []*stepNode{
269+
{key: "foo"}, // need to have tags
270+
{id: "bar"}, // need to have tags
271+
{id: "foo", tags: []string{"not_tune"}},
272+
{id: "bar", tags: []string{"tune_not"}},
273+
{key: "w00t"},
274+
} {
275+
if filter.accept(node) {
276+
t.Errorf("hit %+v", node)
277+
}
278+
}
279+
}
280+
249281
func TestRunFilterCmd(t *testing.T) {
250282
for _, test := range []struct {
251283
cmd []string

0 commit comments

Comments
 (0)