Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Best way to support an "extends other config" field #46

Closed
milesj opened this issue Jun 16, 2022 · 2 comments
Closed

Best way to support an "extends other config" field #46

milesj opened this issue Jun 16, 2022 · 2 comments

Comments

@milesj
Copy link

milesj commented Jun 16, 2022

@SergioBenitez

Many tools and their config files support the concept of extending additional config files through a field within the file, with the values being a relative file system path (extends: './other/config.yml') or URL (extends: 'https://domain.com/config.yml'). With this approach, the extends file is applied before the file doing the extending, so that the current document can override or merge when necessary. This is pretty great for composibility and reusability.

However, this seems to be extremely difficult in Figment, and I'm curious on the best way to approach it. The current problems are:

  • We can't use merge() or join() because we don't know what file to extend until after the config has been parsed and extracted.
  • We can't use a provider since it doesn't have access to the currently parsed config from the previous provider.
  • We can't use a profile because it still needs a way to be resolved.

I have a working solution to this problem but it requires resolving and parsing the config twice, as demonstrated here: https://github.com/moonrepo/moon/pull/142/files#diff-752c2babea244e138a59a074967c9c3bb0faf51bf0a413ac4128505e2b58fb7fR146 The second figment extraction contains an additional merge() for the extending file (which is requested via URL).

In an ideal world, something like this would be pretty great.

Figment::from(Serialized::defaults(WorkspaceConfig::default()))
    .merge(Yaml::file(&path))
    .merge_first(Yaml::from_field("extends"))
    .extract()
@SergioBenitez
Copy link
Owner

SergioBenitez commented Jun 18, 2022

Since a Figment is itself a Provider, I wonder if we need any special support for this. How does this look?

let mut fig = Figment::from(Yaml::file(path));
if let Ok(path) = layer.find_value("extends").map(|v| v.as_str()) {
    fig = Figment::from(Yaml::file(path)).merge(fig);
}

fig.extract()

If you want path to be relative to where it was declared, then use the value.tag() to retrieve the location via Figment.get_metadata() and make the path relative to it using figment::util::diff_paths.

@SergioBenitez
Copy link
Owner

Closing due to inactivity.

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

No branches or pull requests

2 participants