Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions cmd/bagel/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var (
strict bool
noCache bool
noProgress bool
baseDirs []string
)

// scanCmd represents the scan command
Expand All @@ -42,6 +43,9 @@ func init() {
scanCmd.Flags().BoolVar(&strict, "strict", false, "exit with code 2 if any findings are detected")
scanCmd.Flags().BoolVar(&noCache, "no-cache", false, "bypass file index cache and force rebuild")
scanCmd.Flags().BoolVar(&noProgress, "no-progress", false, "disable progress bars")
scanCmd.Flags().StringSliceVar(&baseDirs, "base-dirs", nil,
"comma-separated directories to scan; overrides file_index.base_dirs. "+
"e.g. --base-dirs /home,/Users,/root")
}

func runScan(cmd *cobra.Command, args []string) error {
Expand All @@ -55,6 +59,12 @@ func runScan(cmd *cobra.Command, args []string) error {
return fmt.Errorf("failed to load config: %w", err)
}

// --base-dir takes precedence over config/defaults
if len(baseDirs) > 0 {
cfg.FileIndex.BaseDirs = baseDirs
log.Debug().Strs("base_dirs", baseDirs).Msg("Overriding base dirs from --base-dirs")
}
Comment thread
SUSTAPLE117 marked this conversation as resolved.

log.Debug().Msg("Starting scan")

// Initialize probes
Expand Down
14 changes: 10 additions & 4 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,19 @@ func Load(configPath string) (*models.Config, error) {
v.SetEnvPrefix("BAGEL")
v.AutomaticEnv()

// Read config file if it exists
// Read config file if it exists.
// A missing or unreadable config must never block a scan
Comment thread
SUSTAPLE117 marked this conversation as resolved.
if err := v.ReadInConfig(); err != nil {
var configFileNotFoundError viper.ConfigFileNotFoundError
if !errors.As(err, &configFileNotFoundError) {
return nil, fmt.Errorf("failed to read config file: %w", err)
switch {
case errors.As(err, &configFileNotFoundError):
log.Debug().Msg("config: no config file found; using built-in defaults")
case configPath != "":
return nil, fmt.Errorf("failed to read config file %q: %w", configPath, err)
default:
log.Warn().Err(err).Msg(
"config: could not read a discovered config file; using built-in defaults")
}
// Config file not found is OK, we'll use defaults
}

// Unmarshal config
Expand Down
41 changes: 41 additions & 0 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,44 @@ func TestLoad_DefaultsEnableBothAIProbes(t *testing.T) {
assert.True(t, cfg.Probes.AICredentials.Enabled)
assert.True(t, cfg.Probes.AIChats.Enabled)
}

// TestLoad_NoConfigFileUsesDefaults verifies that when auto-discovery finds no
// config file, Load succeeds with built-in defaults — every probe enabled and
// the file-index patterns populated.
func TestLoad_NoConfigFileUsesDefaults(t *testing.T) {
t.Setenv("HOME", t.TempDir()) // empty home, no bagel.yaml
t.Chdir(t.TempDir()) // empty cwd, no bagel.yaml on "." path
Comment thread
SUSTAPLE117 marked this conversation as resolved.

cfg, err := Load("")
require.NoError(t, err)
require.NotNil(t, cfg)

assert.True(t, cfg.Probes.Git.Enabled)
assert.True(t, cfg.Probes.Cloud.Enabled)
assert.NotEmpty(t, cfg.FileIndex.Patterns)
}

// TestLoad_DiscoveredConfigUnusableFallsBack verifies that when auto-discovery
// cannot turn up a usable config file, Load does not abort the scan: it falls
// back to defaults instead of erroring.
func TestLoad_DiscoveredConfigUnusableFallsBack(t *testing.T) {
dir := t.TempDir()
// A directory named bagel.yaml means there's no readable config file to
// load, standing in for an absent/inaccessible config under auto-discovery.
require.NoError(t, os.Mkdir(filepath.Join(dir, "bagel.yaml"), 0o755))
t.Chdir(dir)
Comment thread
SUSTAPLE117 marked this conversation as resolved.

cfg, err := Load("")
require.NoError(t, err)
require.NotNil(t, cfg)
assert.True(t, cfg.Probes.Git.Enabled)
}

// TestLoad_ExplicitConfigFailsLoudly verifies the opposite contract: when the
// user explicitly names a --config file that cannot be read, Load returns an
// error rather than silently using defaults.
func TestLoad_ExplicitConfigFailsLoudly(t *testing.T) {
missing := filepath.Join(t.TempDir(), "does-not-exist.yaml")
_, err := Load(missing)
require.Error(t, err)
}
Loading