@@ -3,16 +3,21 @@ package service
33import (
44 "context"
55 "fmt"
6+ "sort"
67
78 "github.com/gobwas/glob"
9+ "github.com/pkg/errors"
810 batcheslib "github.com/sourcegraph/sourcegraph/lib/batches"
11+ "github.com/sourcegraph/sourcegraph/lib/batches/template"
912 "github.com/sourcegraph/src-cli/internal/batches"
1013 "github.com/sourcegraph/src-cli/internal/batches/graphql"
14+ "github.com/sourcegraph/src-cli/internal/batches/util"
1115)
1216
1317type RepoWorkspace struct {
1418 RepoID string
1519 Path string
20+ Steps []batcheslib.Step
1621 OnlyFetchWorkspace bool
1722}
1823
@@ -31,6 +36,11 @@ func findWorkspaces(
3136 finder directoryFinder ,
3237 repos []* graphql.Repository ,
3338) ([]RepoWorkspace , error ) {
39+ repoByID := make (map [string ]* graphql.Repository )
40+ for _ , repo := range repos {
41+ repoByID [repo .ID ] = repo
42+ }
43+
3444 // Pre-compile all globs.
3545 workspaceMatchers := make (map [batcheslib.WorkspaceConfiguration ]glob.Glob )
3646 for _ , conf := range spec .Workspaces {
@@ -117,12 +127,71 @@ func findWorkspaces(
117127 fetchWorkspace = false
118128 }
119129
130+ repo , ok := repoByID [workspace .RepoID ]
131+ if ! ok {
132+ return nil , errors .New ("invalid state, repo not found" )
133+ }
134+
135+ steps , err := stepsForRepo (spec , repo )
136+ if err != nil {
137+ return nil , err
138+ }
139+
140+ // If the workspace doesn't have any steps we don't need to include it.
141+ if len (steps ) == 0 {
142+ continue
143+ }
144+
120145 workspaces = append (workspaces , RepoWorkspace {
121146 RepoID : workspace .RepoID ,
122147 Path : path ,
148+ Steps : steps ,
123149 OnlyFetchWorkspace : fetchWorkspace ,
124150 })
125151 }
126152 }
153+
154+ // Stable sorting.
155+ sort .Slice (workspaces , func (i , j int ) bool {
156+ if workspaces [i ].RepoID == workspaces [j ].RepoID {
157+ return workspaces [i ].Path < workspaces [j ].Path
158+ }
159+ return workspaces [i ].RepoID < workspaces [j ].RepoID
160+ })
161+
127162 return workspaces , nil
128163}
164+
165+ // stepsForRepo calculates the steps required to run on the given repo.
166+ func stepsForRepo (spec * batcheslib.BatchSpec , r * graphql.Repository ) ([]batcheslib.Step , error ) {
167+ taskSteps := []batcheslib.Step {}
168+ for _ , step := range spec .Steps {
169+ // If no if condition is given, just go ahead and add the step to the list.
170+ if step .IfCondition () == "" {
171+ taskSteps = append (taskSteps , step )
172+ continue
173+ }
174+
175+ batchChange := template.BatchChangeAttributes {
176+ Name : spec .Name ,
177+ Description : spec .Description ,
178+ }
179+ stepCtx := & template.StepContext {
180+ Repository : util .GraphQLRepoToTemplatingRepo (r ),
181+ BatchChange : batchChange ,
182+ }
183+ static , boolVal , err := template .IsStaticBool (step .IfCondition (), stepCtx )
184+ if err != nil {
185+ return nil , err
186+ }
187+
188+ // If we could evaluate the condition statically and the resulting
189+ // boolean is false, we don't add that step.
190+ if ! static {
191+ taskSteps = append (taskSteps , step )
192+ } else if boolVal {
193+ taskSteps = append (taskSteps , step )
194+ }
195+ }
196+ return taskSteps , nil
197+ }
0 commit comments