Skip to content

Commit 6686a89

Browse files
committed
refactor(testrunner): improve lint execution and error handling for multiple work directories
Refactor lint execution to support multiple work directories via StartingPaths, enabling proper linter config discovery relative to each directory rather than the git root. Changes: - Add lintWorkDirs() helper to resolve StartingPaths into absolute WorkDir values - Update lint execution to iterate over resolved directories and aggregate results - Add lint dry-run support during test execution when Lint option is enabled - Change detectAndRun() to log info messages instead of returning errors when no frameworks or test packages are found, allowing graceful handling of empty test scenarios - Add null check for diagnostics in UI snapshot application to prevent overwriting with undefined - Simplify diagnostics availability check in useEffect hook This enables more flexible test and lint execution patterns while improving error messaging and UI stability.
1 parent 85c803a commit 6686a89

3 files changed

Lines changed: 49 additions & 12 deletions

File tree

cmd/gavel/test.go

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"os"
1010
"os/exec"
1111
"os/signal"
12+
"path/filepath"
1213
"runtime"
1314
"strconv"
1415
"strings"
@@ -80,6 +81,13 @@ func runTests(opts testrunner.RunOptions) (any, error) {
8081
if _, err := testrunner.Run(opts); err != nil {
8182
return nil, err
8283
}
84+
if opts.Lint {
85+
for _, workDir := range lintWorkDirs(opts.WorkDir, opts.StartingPaths) {
86+
if err := displayLintDryRun(LintOptions{WorkDir: workDir, Timeout: "5m"}); err != nil {
87+
return nil, err
88+
}
89+
}
90+
}
8391
if !opts.SkipHooks {
8492
printDryRunHooks(opts.WorkDir, gavelCfg.Post, "post-hook")
8593
}
@@ -160,10 +168,14 @@ func runTests(opts testrunner.RunOptions) (any, error) {
160168
if workDir == "" {
161169
workDir, _ = os.Getwd()
162170
}
163-
lintResults, lintErr = executeLinters(LintOptions{
164-
WorkDir: workDir,
165-
Timeout: "5m",
166-
})
171+
for _, dir := range lintWorkDirs(workDir, opts.StartingPaths) {
172+
results, err := executeLinters(LintOptions{WorkDir: dir, Timeout: "5m"})
173+
if err != nil {
174+
lintErr = err
175+
break
176+
}
177+
lintResults = append(lintResults, results...)
178+
}
167179
if lintErr == nil {
168180
linters.FilterIgnoredViolations(lintResults, gavelCfg.Lint.Ignore)
169181
}
@@ -262,6 +274,31 @@ func printDryRunHooks(workDir string, hooks []verify.HookStep, label string) {
262274
}
263275
}
264276

277+
// lintWorkDirs resolves StartingPaths into WorkDir values for the lint
278+
// codepath. Each directory path becomes its own WorkDir so linter config
279+
// discovery happens relative to that directory (not the git root).
280+
// When no paths are given, the fallback WorkDir is returned.
281+
func lintWorkDirs(fallback string, startingPaths []string) []string {
282+
if len(startingPaths) == 0 {
283+
return []string{fallback}
284+
}
285+
var dirs []string
286+
for _, p := range startingPaths {
287+
abs := p
288+
if !filepath.IsAbs(p) {
289+
abs = filepath.Join(fallback, p)
290+
}
291+
abs, _ = filepath.Abs(abs)
292+
if info, err := os.Stat(abs); err == nil && info.IsDir() {
293+
dirs = append(dirs, abs)
294+
}
295+
}
296+
if len(dirs) == 0 {
297+
return []string{fallback}
298+
}
299+
return dirs
300+
}
301+
265302
// runPushHooksReportingUI runs verify's hook list while also publishing
266303
// each step to the testui (when active) as a pseudo-test: pending while
267304
// running, passed or failed on completion. When the UI is not active,

testrunner/runner.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,8 @@ func escapeRegexNames(names []string) []string {
619619

620620
func (o *TestOrchestrator) detectAndRun(frameworks []Framework, startingPaths []string, extraArgs []string) (parsers.TestSuiteResults, error) {
621621
if len(frameworks) == 0 {
622-
return nil, fmt.Errorf("no frameworks provided for test execution")
622+
logger.Infof("No test frameworks detected")
623+
return nil, nil
623624
}
624625
// Validate that starting paths exist
625626
if len(startingPaths) > 0 {
@@ -676,9 +677,11 @@ func (o *TestOrchestrator) detectAndRun(frameworks []Framework, startingPaths []
676677

677678
if len(allPackages) == 0 {
678679
if len(startingPaths) > 0 {
679-
return nil, fmt.Errorf("no test packages found in starting paths %v", startingPaths)
680+
logger.Infof("No test packages found in starting paths %v", startingPaths)
681+
} else {
682+
logger.Infof("No test packages found")
680683
}
681-
return nil, fmt.Errorf("no test packages found")
684+
return nil, nil
682685
}
683686

684687
// Narrow via change graph and/or run cache. Both selectors share a

testrunner/ui/src/App.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ function applySnapshot(
6161
setLintRun(!!status.lint_run);
6262
setBench(snap.bench);
6363
setDiagnosticsAvailable(!!status.diagnostics_available);
64-
setDiagnostics(snap.diagnostics);
64+
if (snap.diagnostics) setDiagnostics(snap.diagnostics);
6565
setRunMeta(meta);
6666
if (!status.running) {
6767
doneRef.current = true;
@@ -222,10 +222,7 @@ export function App() {
222222
}, []);
223223

224224
useEffect(() => {
225-
if (!diagnosticsAvailable) {
226-
setDiagnostics(undefined);
227-
return;
228-
}
225+
if (!diagnosticsAvailable) return;
229226

230227
fetchDiagnostics().catch(() => {});
231228
const timer = window.setInterval(() => {

0 commit comments

Comments
 (0)