Skip to content

Commit 38d65f5

Browse files
add -f to smart-test run (#166)
* rename {get,list,cancel}x subcommands * bugfix * rename "test" to "smart-test" * execution subcommand * add x alias * add -f to smart-test run * Bug fix in label processing --------- Co-authored-by: Daniel De Vera <[email protected]>
1 parent 786a5a6 commit 38d65f5

File tree

5 files changed

+108
-30
lines changed

5 files changed

+108
-30
lines changed

internal/command/smarttest/run.go

Lines changed: 73 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"io"
88
"os"
9+
"strconv"
910
"time"
1011

1112
"github.com/signadot/cli/internal/config"
@@ -42,27 +43,14 @@ func run(ctx context.Context, cfg *config.SmartTestRun, wOut, wErr io.Writer,
4243
return err
4344
}
4445

45-
// create a test finder
46-
tf, err := repoconfig.NewTestFinder(cfg.Directory)
46+
testFiles, gitRepo, err := testFilesAndRepo(cfg)
4747
if err != nil {
4848
return err
4949
}
5050

51-
// find tests
52-
testFiles, err := tf.FindTestFiles()
53-
if err != nil {
54-
return err
55-
}
56-
if len(testFiles) == 0 {
57-
return errors.New("could not find any test")
58-
}
59-
6051
// create a run ID
6152
runID := repoconfig.GenerateRunID()
6253

63-
// get the git repo (if any)
64-
gitRepo := tf.GetGitRepo()
65-
6654
// trigger test executions
6755
err = triggerTests(cfg, runID, gitRepo, testFiles)
6856
if err != nil {
@@ -106,6 +94,38 @@ func run(ctx context.Context, cfg *config.SmartTestRun, wOut, wErr io.Writer,
10694
return structuredOutput(cfg, wOut, runID, txs)
10795
}
10896

97+
func testFilesAndRepo(cfg *config.SmartTestRun) ([]repoconfig.TestFile, *repoconfig.GitRepo, error) {
98+
if cfg.File == "-" {
99+
host, err := os.Hostname()
100+
if err != nil {
101+
host = "unknown"
102+
}
103+
pid := strconv.Itoa(os.Getpid())
104+
return []repoconfig.TestFile{
105+
{
106+
Name: host + "-" + "stdin-" + pid,
107+
Reader: os.Stdin,
108+
},
109+
}, nil, nil
110+
}
111+
// create a test finder
112+
// NOTE: at most one of cfg.{Dir,File} is non-empty
113+
tf, err := repoconfig.NewTestFinder(cfg.Directory + cfg.File)
114+
if err != nil {
115+
return nil, nil, err
116+
}
117+
118+
// find tests
119+
testFiles, err := tf.FindTestFiles()
120+
if err != nil {
121+
return nil, nil, fmt.Errorf("error finding test files: %w", err)
122+
}
123+
if len(testFiles) == 0 {
124+
return nil, nil, errors.New("could not find any test")
125+
}
126+
return testFiles, tf.GetGitRepo(), nil
127+
}
128+
109129
func validateRun(cfg *config.SmartTestRun) error {
110130
count := 0
111131
if cfg.Cluster != "" {
@@ -153,6 +173,28 @@ func validateRun(cfg *config.SmartTestRun) error {
153173
}
154174
}
155175

176+
if cfg.Directory != "" && cfg.File != "" {
177+
return fmt.Errorf("cannot specify both directory and file")
178+
}
179+
if cfg.Directory != "" {
180+
st, err := os.Stat(cfg.Directory)
181+
if err != nil {
182+
return fmt.Errorf("unable to stat input directory: %w", err)
183+
}
184+
if !st.IsDir() {
185+
return fmt.Errorf("%q is not a directory", cfg.Directory)
186+
}
187+
}
188+
if cfg.File != "" && cfg.File != "-" {
189+
st, err := os.Stat(cfg.File)
190+
if err != nil {
191+
return fmt.Errorf("unable to stat input file: %w", err)
192+
}
193+
if st.IsDir() {
194+
return fmt.Errorf("%q is not a file", cfg.File)
195+
}
196+
}
197+
156198
return nil
157199
}
158200

@@ -186,11 +228,15 @@ func triggerTests(cfg *config.SmartTestRun, runID string,
186228
for _, tf := range testFiles {
187229
if gitRepo != nil {
188230
// define the repo path
189-
repoPath, err := repoconfig.GetRelativePathFromGitRoot(gitRepo.Path, tf.Path)
190-
if err != nil {
191-
return err
231+
if tf.Reader == nil {
232+
repoPath, err := repoconfig.GetRelativePathFromGitRoot(gitRepo.Path, tf.Path)
233+
if err != nil {
234+
return err
235+
}
236+
spec.Path = repoPath
237+
} else {
238+
spec.Path = tf.Path
192239
}
193-
spec.Path = repoPath
194240
}
195241
// define the test name
196242
spec.TestName = tf.Name
@@ -200,7 +246,15 @@ func triggerTests(cfg *config.SmartTestRun, runID string,
200246
spec.Labels[k] = v
201247
}
202248
// define the script
203-
scriptContent, err := os.ReadFile(tf.Path)
249+
var (
250+
scriptContent []byte
251+
err error
252+
)
253+
if tf.Reader != nil {
254+
scriptContent, err = io.ReadAll(tf.Reader)
255+
} else {
256+
scriptContent, err = os.ReadFile(tf.Path)
257+
}
204258
if err != nil {
205259
return fmt.Errorf("failed to read test file %q: %w", tf.Path, err)
206260
}

internal/config/smarttest.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type SmartTest struct {
1919
type SmartTestRun struct {
2020
*SmartTest
2121
Directory string
22+
File string
2223
Labels RunLabels
2324
Cluster string
2425
Sandbox string
@@ -62,6 +63,7 @@ func (tl RunLabels) Type() string {
6263
// AddFlags adds the flags for the test run command
6364
func (c *SmartTestRun) AddFlags(cmd *cobra.Command) {
6465
cmd.Flags().StringVarP(&c.Directory, "directory", "d", "", "Base directory for finding tests")
66+
cmd.Flags().StringVarP(&c.File, "file", "f", "", "Smart Test file to run")
6567
cmd.Flags().StringVar(&c.Cluster, "cluster", "", "Cluster where to run tests")
6668
cmd.Flags().StringVar(&c.Sandbox, "sandbox", "", "Sandbox where to run tests")
6769
cmd.Flags().StringVar(&c.RouteGroup, "route-group", "", "Route group where to run tests")

internal/repoconfig/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package repoconfig
22

33
import (
44
"fmt"
5+
"io"
56
"math/rand"
67
"os"
78
"path/filepath"
@@ -18,6 +19,7 @@ type Config struct {
1819
type TestFile struct {
1920
Name string // Test name
2021
Path string // Full path relative to base directory
22+
Reader io.Reader // if Path is empty, may be a Reader
2123
Labels map[string]string // Labels from all parent directories
2224
}
2325

internal/repoconfig/finder.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@ type TestFinder struct {
1212
repo *GitRepo
1313
basePath string
1414

15-
dirLabelsCache map[string]map[string]string
15+
dirLabelsCache LabelsCache
1616
}
1717

18-
func NewTestFinder(inputDir string) (*TestFinder, error) {
18+
func NewTestFinder(inputPath string) (*TestFinder, error) {
1919
var tf *TestFinder
2020

21-
if inputDir != "" {
21+
if inputPath != "" {
2222
// use the provided dir as the base for finding tests
2323

2424
// make the input dir absolute
25-
basePath, err := filepath.Abs(inputDir)
25+
basePath, err := filepath.Abs(inputPath)
2626
if err != nil {
2727
return nil, fmt.Errorf("failed to convert input dir into an absolute dir: %w", err)
2828
}
@@ -78,7 +78,7 @@ func NewTestFinder(inputDir string) (*TestFinder, error) {
7878
}
7979

8080
// build the label cache
81-
dirLabelsCache, err := buildLabelsCache(tf.basePath)
81+
dirLabelsCache, err := NewLabelsCache(tf.basePath)
8282
if err != nil {
8383
return nil, err
8484
}
@@ -140,12 +140,9 @@ func (tf *TestFinder) processTestFile(path string, testFileMap map[string]TestFi
140140
return nil
141141
}
142142

143-
dirPath := filepath.Dir(relPath)
144-
var labels map[string]string
145-
if dirLabels, exists := tf.dirLabelsCache[dirPath]; exists {
146-
labels = dirLabels
147-
} else {
148-
labels = make(map[string]string)
143+
labels, err := tf.dirLabelsCache.ForFile(relPath)
144+
if err != nil {
145+
return fmt.Errorf("unable to get labels for path %q: %w", relPath, err)
149146
}
150147

151148
testFileMap[relPath] = TestFile{

internal/repoconfig/labels.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,29 @@ import (
99
"strings"
1010
)
1111

12+
type LabelsCache interface {
13+
ForFile(p string) (map[string]string, error)
14+
}
15+
16+
type labelsCache struct {
17+
root string
18+
labelsMap map[string]map[string]string
19+
}
20+
21+
// ForFile: finds the labels for a given path relative to the labels cache root.
22+
func (l *labelsCache) ForFile(relFile string) (map[string]string, error) {
23+
relDir := filepath.Dir(relFile)
24+
return l.labelsMap[relDir], nil
25+
}
26+
27+
func NewLabelsCache(rootPath string) (LabelsCache, error) {
28+
cache, err := buildLabelsCache(rootPath)
29+
if err != nil {
30+
return nil, err
31+
}
32+
return &labelsCache{root: rootPath, labelsMap: cache}, nil
33+
}
34+
1235
// readLabels reads labels from a .labels file
1336
func readLabels(filePath string) (map[string]string, error) {
1437
file, err := os.Open(filePath)

0 commit comments

Comments
 (0)