Skip to content

feat(registry): configurable driver registries via TOML config#360

Open
zeroshade wants to merge 27 commits intomainfrom
feat/configurable-registries
Open

feat(registry): configurable driver registries via TOML config#360
zeroshade wants to merge 27 commits intomainfrom
feat/configurable-registries

Conversation

@zeroshade
Copy link
Copy Markdown
Member

Summary

Adds support for configuring driver registries via TOML config files, allowing users to add custom registries at both the global (~/.config/columnar/dbc/config.toml) and project (dbc.toml) level.

What's New

  • Global registry config (~/.config/columnar/dbc/config.toml): loaded on every command via ConfigureRegistries() called in main()
  • Project registry config (dbc.toml): [[registries]] section respected by sync and add commands
  • Priority order: project → global → built-in defaults (first-match-wins, URL-deduplicated)
  • replace_defaults = true: opt-in flag to suppress built-in registries entirely
  • DBC_BASE_URL env var: still overrides everything (unchanged behavior)
  • Backward compatible: existing dbc.toml files without [[registries]] work unchanged

Config Format

Global (~/.config/columnar/dbc/config.toml):

[[registries]]
url = "https://my-registry.example.com"
name = "my-registry"

# replace_defaults = true  # omit built-in registries

Project (dbc.toml):

[[registries]]
url = "https://project-registry.example.com"
name = "project"

[drivers]
[drivers.my-driver]
version = ">=1.0.0"

Implementation Notes

  • URL validation requires http/https scheme and non-empty host
  • defaultRegistries is snapshotted eagerly in init() (after drivers.go init runs); env-sensitivity documented in comments
  • add.go decodes dbc.toml once (single file open) for both registry config and driver list
  • remove intentionally omits registry wiring — it never queries a registry

@zeroshade zeroshade requested a review from amoeba April 17, 2026 16:17
@zeroshade zeroshade force-pushed the feat/configurable-registries branch from 5a8bf36 to 5ac1ddd Compare April 17, 2026 16:19
@zeroshade zeroshade force-pushed the feat/configurable-registries branch from 5ac1ddd to 0813c82 Compare April 17, 2026 22:14
Add RegistryEntry and GlobalConfig structs with TOML tags, and
loadGlobalConfig() function that parses config.toml from a directory,
validates URLs with url.Parse (not mustParseURL), and returns nil,nil
for missing files. 7 subtests cover valid configs, missing file,
invalid URL, empty URL, and empty registries.
- Add SetProjectRegistries() to dbc package for project-level registry merging
- Snapshot defaultRegistries in ConfigureRegistries for proper re-merge ordering
- Inject SetProjectRegistries in sync driversListMsg handler before getDriverRegistry
- Pre-load dbc.toml in add Init() to set project registries before getDriverRegistry
- Add tests: TestSyncWithProjectRegistries, TestSyncWithProjectRegistriesBackwardCompat
- Add tests: TestAddWithProjectRegistries, TestAddWithProjectRegistriesBackwardCompat, TestAddWithInvalidProjectRegistryURL
…leanup

- Add u.Host == "" check after url.Parse in loadGlobalConfig and SetProjectRegistries to catch hostless URLs like "my-registry"
- Add TestSetProjectRegistries with 6 subtests covering merge precedence, replace_defaults, DBC_BASE_URL no-op, and error cases
- Update TestConfigureRegistries subtests to save/restore defaultRegistries and globalConfig alongside registries
- Use defer preF.Close() in add.go instead of manual close in two branches
@zeroshade zeroshade force-pushed the feat/configurable-registries branch from 0813c82 to 79e6f5c Compare April 22, 2026 21:33
@zeroshade zeroshade force-pushed the feat/configurable-registries branch from 79e6f5c to 40e5ad2 Compare April 22, 2026 21:39
@zeroshade zeroshade requested a review from kentkwu April 26, 2026 18:21
Copy link
Copy Markdown
Member

@amoeba amoeba left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a quick code review over the new pieces and left some comments. Even if we don't have an immediate use case for this, I think having it in dbc is useful.

Some other more general thoughts:

  1. Would we want CLI integration for this? I think it would be useful for dbc to be able to do all the work to show/add/remove registries from the project and user config.
  2. I didn't see any tests for how dbc install will work with this. Presumably dbc install will respect the new fields in the user config.
  3. Do we need to define a default priority order for registries to handle name conflicts? We have a lot of the same concerns as conda does with channels. I'm wishing for more tests in this PR for the interaction between the default, user, and project registries around name conflicts.

Comment thread registry_config.go

func SetProjectRegistries(entries []RegistryEntry, replaceDefaults *bool) error {
if os.Getenv("DBC_BASE_URL") != "" {
return nil
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should warn the user here.

Comment thread registry_config.go
return nil
}
if replaceDefaults != nil && *replaceDefaults && len(entries) == 0 {
return fmt.Errorf("replace_defaults = true requires at least one [[registries]] entry; omit replace_defaults or add a registry entry")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this error would be better surfaced earlier, such as when we initially parse config.toml or dbc.toml. How this is now, I think this would error like this,

error configuring project registries: replace_defaults = true requires at least one [[registries]] entry; omit replace_defaults or add a registry entry

As a user, it's unclear what I should do to fix it. Which file is my problem in?

If we validated this earlier, I bet we'd have enough context to know which file has the issue and we could tell them.

Comment thread registry_config.go
}
for _, e := range entries {
if e.URL == "" {
return fmt.Errorf("registry entry has empty url")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these checks needed or is this the best place to handle this? I see loadGlobalConfig already does validation and that seems like a better place. i.e., I much prefer being able to know that any []RegistryEntry I might get is always valid so I'd rather error before creating a RegistryEntry.

Comment thread cmd/dbc/main.go
})
}

func boolPtr(b bool) *bool { return &b }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this the best place for this def?

Comment thread cmd/dbc/main.go
}

if configDir, err := internal.GetUserConfigPath(); err != nil {
fmt.Fprintf(os.Stderr, "warning: failed to locate config directory: %v\n", err)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want to emit a warning? Won't this warn if the folder isn't found? Seems like we should be okay with that.

The warning when the registry config fails to load once found is fine.

Comment thread .gitignore
Comment on lines +52 to +54

# Sisyphus workflow artifacts (plans, evidence, notepads)
.sisyphus/
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this just a tool you use? can we revert this?

Comment thread cmd/dbc/main.go
if configDir, err := internal.GetUserConfigPath(); err != nil {
fmt.Fprintf(os.Stderr, "warning: failed to locate config directory: %v\n", err)
} else if err := dbc.ConfigureRegistries(configDir); err != nil {
fmt.Fprintf(os.Stderr, "warning: failed to load registry config: %v\n", err)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the error here includes the file with the issue. Whenever we show an error about a TOML file, we need to show the user the path to it.

Comment thread registry_config.go
Comment on lines +121 to +122
if u.Scheme != "http" && u.Scheme != "https" {
return Registry{}, false
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the validation in here even needed? In the parent call, we already error when a RegistryEntry is invalid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants