Skip to content

config: define config scopes in configuration#51162

Merged
tgamblin merged 14 commits intodevelopfrom
named-include-scopes
Nov 3, 2025
Merged

config: define config scopes in configuration#51162
tgamblin merged 14 commits intodevelopfrom
named-include-scopes

Conversation

@tgamblin
Copy link
Copy Markdown
Member

@tgamblin tgamblin commented Aug 15, 2025

This reworks the hard-coded configuration scopes in Spack to be defined in configuration. This allows scope hierarchy to be defined in one place and overridden in any config scope with sufficient precedence.

Config scopes as config

All configuration now stems from $spack/etc/spack and $spack/etc/spack/defaults.

  • Scopes included in configuration can be named, which allows the builtin site, user, system, etc. scopes to be configuration rather than hard-coded.
  • $spack/etc/spack/defaults is the lowest priority
  • $spack/etc/spack includes other scopes, like ~/.spack, at lower precedence than itself.
  • You can override any scopes but default with include::, e.g. include::[] in an environment allows you to ignore everything but defaults entirely.

Here is $spack/etc/spack/include.yaml:

include:
  # user configuration scope
  - name: "user"
    path: "~/.spack"
    optional: true
    when: '"SPACK_DISABLE_LOCAL_CONFIG" not in env'

  # site configuration scope
  - name: "site"
    path: "$spack/etc/spack/site"
    optional: true

  # system configuration scope
  - name: "system"
    path: "/etc/spack"
    optional: true
    when: '"SPACK_DISABLE_LOCAL_CONFIG" not in env'

Seeing and overriding scopes

As before, you can see precedence with spack config scopes

> spack config scopes -vp
command_line     internal      active
spack            path          active  /Users/gamblin2/Workspace/src/spack/etc/spack/
user             include,path  active  /Users/gamblin2/.spack/
site             include,path  active  /Users/gamblin2/Workspace/src/spack/etc/spack/site/
defaults         path          active  /Users/gamblin2/Workspace/src/spack/etc/spack/defaults/
defaults:darwin  include,path  active  /Users/gamblin2/Workspace/src/spack/etc/spack/defaults/darwin/
defaults:base    include,path  active  /Users/gamblin2/Workspace/src/spack/etc/spack/defaults/base/
_builtin         internal      active

system doesn't appear here b/c it's optional and it will only appear when it exists on the host machine.

There is a new -v / --verbose option to spack config scopes that will show the scope type and whether a scope is active (i.e. not overridden). If a scope is overridden, it still appears in the output, but it is dimmed, e.g.:

Screenshot 2025-10-26 at 2 33 07 AM

or simply:

Screenshot 2025-10-26 at 2 33 33 AM

You can see that the include:: in the environment here overrides everything but defaults. This allows users to make insulated environments that don't use any local configuration. The fact that defaults remain is a special case, as :: in other contexts can override things set in defaults. Spack can't function without the defaults configuration scope, so here, we disallow it. You can still override defaults with :: in other config sections, you just have to be more specific.

site and spack scopes

What was the site scope ($spack/etc/spack) is now the spack scope, and the site scope is at ($spack/etc/spack/site) so that scripts using, e.g. spack config --scope site set ... will still work. The spack scope is higher precedence than the user scope, something people have wanted for a long time, while the site scope is lower precedence than user, as it always has been.

  • allow scopes to specify their own name in config
  • rework incremental config initialization to work when configs are included recursively
  • remove hard-coded scope initialization
  • rework defaults scope so that precedence is preserved (already had base -- just move everything there to get this)
  • tests
  • Add ways to override scopes easily
  • Think about what :: means and whether we should preserve defaults (currently we do)

@tgamblin tgamblin mentioned this pull request Aug 15, 2025
1 task
@alalazo

This comment was marked as outdated.

@alalazo

This comment was marked as outdated.

@psakievich
Copy link
Copy Markdown
Contributor

#51165 is a related effort.

@tgamblin tgamblin added this to the v1.1.0 milestone Oct 16, 2025
@tgamblin tgamblin force-pushed the named-include-scopes branch 5 times, most recently from a78ac1c to d24504d Compare October 26, 2025 09:55
@tgamblin tgamblin marked this pull request as ready for review October 26, 2025 19:54
@tgamblin tgamblin force-pushed the named-include-scopes branch from 03a954a to 8a37a27 Compare October 27, 2025 08:20
Copy link
Copy Markdown
Contributor

@psakievich psakievich left a comment

Choose a reason for hiding this comment

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

Playing around with this today. Working well on all my tests so far. I tested

  • config isolation in an environment spack:include::[]
  • how that behaves with spack -E
  • new option spack config scopes -v

One thing I noticed is running spack config scopes -v does not issue a warning with duplicate scopes of the same name and just ommitts the duplicate scope. Other commands do issue a warning like this

$ spack cd -e
==> Warning: Ignoring duplicate included scope: test

I think we should unify that behavior or indicate in some manner that a scope is getting skipped. So far this is the only issue I've found. I'll do some more testing, but so far this is looking really good.

NVM I missed it. The warning DOES show up. I just didn't see it.

@psakievich psakievich self-requested a review October 28, 2025 20:47
@tgamblin
Copy link
Copy Markdown
Member Author

tgamblin commented Oct 28, 2025

config isolation in an environment spack:config::[]

You probably want to play with this using include::[] instead, as the mechanism is a bit different and include::[] is what's introduced here. include::[] takes out all the sections, not just config.

@psakievich
Copy link
Copy Markdown
Contributor

config isolation in an environment spack:config::[]

You probably want to play with this using include::[] instead, as the mechanism is a bit different and include::[] is what's introduced here. include::[] takes out all the sections, not just config.

Typo. This what I tested. I am just spinning in and out of config like I'm on a fair ride I suppose. I updated my comment.

@psakievich
Copy link
Copy Markdown
Contributor

If yes, we are special casing this configuration file, which might be confusing. At that point it's the same as the file I proposed in the comment, but it's within the Spack installation by default.

@alalazo I think not being in the Spack installation was the only thing I didn't like about your proposal. To me keeping the special case internal to the Spack installation helps guard the feature I really want, which is sharing is optional, dependency on the home directory is optional.

@psakievich psakievich self-requested a review October 28, 2025 21:21
Copy link
Copy Markdown
Contributor

@psakievich psakievich left a comment

Choose a reason for hiding this comment

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

I don't see anything beyond docs truly missing from this PR. I would really like it if there was a way to pop a scope from the CLI.

For instances, I would love to be able to download a spack instance, spack config scopes pop user and just have it get commented out or something. Explicitly disable it for the spack instance. Personally I would love an easy way to disable/pop everything but site and the spack scopes out the gate.

This maybe better suited for the spack isolate command we discussed though.

@alalazo
Copy link
Copy Markdown
Member

alalazo commented Oct 29, 2025

I think not being in the Spack installation was the only thing I didn't like about your proposal. To me keeping the special case internal to the Spack installation helps guard the feature I really want, which is sharing is optional, dependency on the home directory is optional.

Agreed. The comment you're replying to is from August, and is outdated. We agreed on the current implementation in the last two-three meetings about this PR 🙂

Copy link
Copy Markdown
Member

@alalazo alalazo left a comment

Choose a reason for hiding this comment

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

The PR LGTM 👍 I think the choice to always keep the default configuration is the correct one.

The main request is to add docs for the new behavior (can be minimal, and expanded in a following PR, but we should avoid forgetting it).

A minor comment is that I find the difference between:

$ spack config scopes -v

and

$ spack config scopes -v packages

confusing. I expected the second command to grey out anything that doesn't affect packages configuration, but it seems it only adds a packages.yaml to some of the paths. Right now it feels a bit redundant, and similar to -p. Would it be easy to make the extra "packages" grey out more scopes if they don't matter for that section of the configuration?

Signed-off-by: Todd Gamblin <[email protected]>
Signed-off-by: Todd Gamblin <[email protected]>
This was lost in the restructure; allow it as an optional override var on includes.

Signed-off-by: Todd Gamblin <[email protected]>
@tgamblin tgamblin force-pushed the named-include-scopes branch from 621a539 to 7a94365 Compare November 3, 2025 00:41
@tgamblin
Copy link
Copy Markdown
Member Author

tgamblin commented Nov 3, 2025

@alalazo @psakievich take another look -- I think all the comments here are addressed.

Copy link
Copy Markdown
Member

@alalazo alalazo left a comment

Choose a reason for hiding this comment

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

Nitpick comments + a few typos. I really like:

Image

I think this is ready to be merged, once we fix the typos.

Signed-off-by: Todd Gamblin <[email protected]>
@tgamblin tgamblin force-pushed the named-include-scopes branch from 5c555b7 to 756d537 Compare November 3, 2025 17:29
@tgamblin
Copy link
Copy Markdown
Member Author

tgamblin commented Nov 3, 2025

Ok @alalazo all fixed.

@tgamblin tgamblin enabled auto-merge (squash) November 3, 2025 19:01
@tgamblin tgamblin disabled auto-merge November 3, 2025 19:38
@tgamblin tgamblin merged commit dc7e4a2 into develop Nov 3, 2025
31 of 32 checks passed
@tgamblin tgamblin deleted the named-include-scopes branch November 3, 2025 19:44
hippo91 pushed a commit to hippo91/spack that referenced this pull request Nov 4, 2025
This reworks the hard-coded configuration scopes in Spack to be defined
in configuration. This allows scope hierarchy to be defined in one place
and overridden in any config scope with sufficient precedence.

## Config scopes as config

All configuration now stems from `$spack/etc/spack` and
`$spack/etc/spack/defaults`.

* Scopes included in configuration can be named, which allows the
  builtin `site`, `user`, `system`, etc. scopes to be configuration
  rather than hard-coded.

* `$spack/etc/spack/defaults` is the lowest priority

* `$spack/etc/spack` includes other scopes, like `~/.spack`,
  at lower precedence than itself.

* You can override any scopes but default with `include::`,
  e.g. `include::[]` in an environment allows you to ignore everything
  but defaults entirely.

Here is `$spack/etc/spack/include.yaml`:

```yaml
include:
  # user configuration scope
  - name: "user"
    path: "~/.spack"
    optional: true
    when: '"SPACK_DISABLE_LOCAL_CONFIG" not in env'

  # site configuration scope
  - name: "site"
    path: "$spack/etc/spack/site"
    optional: true

  # system configuration scope
  - name: "system"
    path: "/etc/spack"
    optional: true
    when: '"SPACK_DISABLE_LOCAL_CONFIG" not in env'
```

## Seeing and overriding scopes

As before, you can see precedence with `spack config scopes`

```
command_line     internal      active
spack            path          active  /Users/gamblin2/Workspace/src/spack/etc/spack/
user             include,path  active  /Users/gamblin2/.spack/
site             include,path  active  /Users/gamblin2/Workspace/src/spack/etc/spack/site/
defaults         path          active  /Users/gamblin2/Workspace/src/spack/etc/spack/defaults/
defaults:darwin  include,path  active  /Users/gamblin2/Workspace/src/spack/etc/spack/defaults/darwin/
defaults:base    include,path  active  /Users/gamblin2/Workspace/src/spack/etc/spack/defaults/base/
_builtin         internal      active
```

`system` doesn't appear here b/c it's optional and it will only appear
when it exists on the host machine.

There is a new `-v` / `--verbose` option to `spack config scopes` that will
show the scope type and whether a scope is active (i.e. not overridden).
If a scope is overridden, it still appears in the output, but dimmed.
This allows users to make insulated environments that don't use any local
configuration.

The fact that defaults remain is a special case, as `::` in other contexts
*can* override things set in defaults.  Spack can't function without the
`defaults` configuration scope, so here, we disallow it. You can still
override defaults with `::` in other config sections, you just have to be
more specific.

## `site` and `spack` scopes

What was the site scope (`$spack/etc/spack`) is now the `spack` scope, and
the `site` scope is at (`$spack/etc/spack/site`) so that scripts using, e.g.
`spack config --scope site set ...` will still work. The `spack` scope is
*higher* precedence than the `user` scope, something people have wanted for
a long time, while the `site` scope is lower precedence than `user`, as it
always has been.

- [x] allow scopes to specify their own name in config
- [x] rework incremental config initialization to work when configs are
      included recursively
- [x] remove hard-coded scope initialization
- [x] rework defaults scope so that precedence is preserved (already
      had `base` -- just move everything there to get this)
- [x] tests
- [x] Override scopes easily with `include::`
- [x] Preserve defaults with `include::`

---------

Signed-off-by: Todd Gamblin <[email protected]>
kshea21 pushed a commit to kshea21/spack that referenced this pull request Nov 4, 2025
This reworks the hard-coded configuration scopes in Spack to be defined
in configuration. This allows scope hierarchy to be defined in one place
and overridden in any config scope with sufficient precedence.

## Config scopes as config

All configuration now stems from `$spack/etc/spack` and
`$spack/etc/spack/defaults`.

* Scopes included in configuration can be named, which allows the
  builtin `site`, `user`, `system`, etc. scopes to be configuration
  rather than hard-coded.

* `$spack/etc/spack/defaults` is the lowest priority

* `$spack/etc/spack` includes other scopes, like `~/.spack`,
  at lower precedence than itself.

* You can override any scopes but default with `include::`,
  e.g. `include::[]` in an environment allows you to ignore everything
  but defaults entirely.

Here is `$spack/etc/spack/include.yaml`:

```yaml
include:
  # user configuration scope
  - name: "user"
    path: "~/.spack"
    optional: true
    when: '"SPACK_DISABLE_LOCAL_CONFIG" not in env'

  # site configuration scope
  - name: "site"
    path: "$spack/etc/spack/site"
    optional: true

  # system configuration scope
  - name: "system"
    path: "/etc/spack"
    optional: true
    when: '"SPACK_DISABLE_LOCAL_CONFIG" not in env'
```

## Seeing and overriding scopes

As before, you can see precedence with `spack config scopes`

```
command_line     internal      active
spack            path          active  /Users/gamblin2/Workspace/src/spack/etc/spack/
user             include,path  active  /Users/gamblin2/.spack/
site             include,path  active  /Users/gamblin2/Workspace/src/spack/etc/spack/site/
defaults         path          active  /Users/gamblin2/Workspace/src/spack/etc/spack/defaults/
defaults:darwin  include,path  active  /Users/gamblin2/Workspace/src/spack/etc/spack/defaults/darwin/
defaults:base    include,path  active  /Users/gamblin2/Workspace/src/spack/etc/spack/defaults/base/
_builtin         internal      active
```

`system` doesn't appear here b/c it's optional and it will only appear
when it exists on the host machine.

There is a new `-v` / `--verbose` option to `spack config scopes` that will
show the scope type and whether a scope is active (i.e. not overridden).
If a scope is overridden, it still appears in the output, but dimmed.
This allows users to make insulated environments that don't use any local
configuration.

The fact that defaults remain is a special case, as `::` in other contexts
*can* override things set in defaults.  Spack can't function without the
`defaults` configuration scope, so here, we disallow it. You can still
override defaults with `::` in other config sections, you just have to be
more specific.

## `site` and `spack` scopes

What was the site scope (`$spack/etc/spack`) is now the `spack` scope, and
the `site` scope is at (`$spack/etc/spack/site`) so that scripts using, e.g.
`spack config --scope site set ...` will still work. The `spack` scope is
*higher* precedence than the `user` scope, something people have wanted for
a long time, while the `site` scope is lower precedence than `user`, as it
always has been.

- [x] allow scopes to specify their own name in config
- [x] rework incremental config initialization to work when configs are
      included recursively
- [x] remove hard-coded scope initialization
- [x] rework defaults scope so that precedence is preserved (already
      had `base` -- just move everything there to get this)
- [x] tests
- [x] Override scopes easily with `include::`
- [x] Preserve defaults with `include::`

---------

Signed-off-by: Todd Gamblin <[email protected]>
tgamblin added a commit that referenced this pull request Nov 5, 2025
#51162 allows users to specify configuration scopes as configuration, but it also
changes the `spack` scope to be the default edit scope. This can be extremely confusing
to users, as it causes `spack compiler find`, `spack external find`, `spack config add`,
etc. to be written into the spack instance by default instad of into `~/.spack`.

`~/.spack` is a better choice if it's configured, as we do not know if the user
actually owns the spack instance. It's also what people are used to.

- [x] Introduce a new `prefer_modify: true` option on `include:` that allows an
  including scope to hand off edit precedence to an included scope.
- [x] Make the default `spack` scope specify the user scope as `prefer_modify:`.
- [x] Add documentation and update `include:` docs with `versionadded` directives.

Signed-off-by: Todd Gamblin <[email protected]>
tgamblin added a commit that referenced this pull request Nov 5, 2025
#51162 allows users to specify configuration scopes as configuration, but it also
changes the `spack` scope to be the default edit scope. This can be extremely confusing
to users, as it causes `spack compiler find`, `spack external find`, `spack config add`,
etc. to be written into the spack instance by default instead of into `~/.spack`.

`~/.spack` is a better choice if it's configured, as we do not know if the user
actually owns the spack instance. It's also what people are used to, and it's going
to cause a lot of consternation if we switch this default up on people.

This PR introduces a new `prefer_modify: true` option on `include:` that allows the
including scope to hand off edit precedence to an included scope. The including scope
is still modifiable if specified explicitly by name (e.g., `--scope spack`) but if it
is selected by default, we'll edit its `prefer_modify` scope instead.

- [x] Add `prefer_modify:` option to `include:`
- [x] Make the default `spack` scope specify the user scope as `prefer_modify:`.
- [x] Add documentation and update `include:` docs with `versionadded` directives.
- [x] make the `user` scope `prefer_modify:` in `$spack/etc/spack/include.yaml`

Signed-off-by: Todd Gamblin <[email protected]>
tgamblin added a commit that referenced this pull request Nov 5, 2025
#51162 allows users to specify configuration scopes as configuration, but it also
changes the `spack` scope to be the default edit scope. This can be extremely confusing
to users, as it causes `spack compiler find`, `spack external find`, `spack config add`,
etc. to be written into the spack instance by default instead of into `~/.spack`.

`~/.spack` is a better choice if it's configured, as we do not know if the user
actually owns the spack instance. It's also what people are used to, and it's going
to cause a lot of consternation if we switch this default up on people.

This PR introduces a new `prefer_modify: true` option on `include:` that allows the
including scope to hand off edit precedence to an included scope. The including scope
is still modifiable if specified explicitly by name (e.g., `--scope spack`) but if it
is selected by default, we'll edit its `prefer_modify` scope instead.

- [x] Add `prefer_modify:` option to `include:`
- [x] Make the default `spack` scope specify the user scope as `prefer_modify:`.
- [x] Add documentation and update `include:` docs with `versionadded` directives.
- [x] make the `user` scope `prefer_modify:` in `$spack/etc/spack/include.yaml`

Signed-off-by: Todd Gamblin <[email protected]>
becker33 pushed a commit that referenced this pull request Nov 6, 2025
* `config`: use `prefer_modify: true` to adjust edit preferences

#51162 allows users to specify configuration scopes as configuration, but it also
changes the `spack` scope to be the default edit scope. This can be extremely confusing
to users, as it causes `spack compiler find`, `spack external find`, `spack config add`,
etc. to be written into the spack instance by default instead of into `~/.spack`.

`~/.spack` is a better choice if it's configured, as we do not know if the user
actually owns the spack instance. It's also what people are used to, and it's going
to cause a lot of consternation if we switch this default up on people.

This PR introduces a new `prefer_modify: true` option on `include:` that allows the
including scope to hand off edit precedence to an included scope. The including scope
is still modifiable if specified explicitly by name (e.g., `--scope spack`) but if it
is selected by default, we'll edit its `prefer_modify` scope instead.

- [x] Add `prefer_modify:` option to `include:`
- [x] Make the default `spack` scope specify the user scope as `prefer_modify:`.
- [x] Add documentation and update `include:` docs with `versionadded` directives.
- [x] make the `user` scope `prefer_modify:` in `$spack/etc/spack/include.yaml`

---------

Signed-off-by: Todd Gamblin <[email protected]>
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.

5 participants