cli: Warn user about implicit seeding policy

To prepare for future changes, warn users if their config file currently
does not explicitly specify a default seeding policy.

Because there are now potentially multiple warnings generated that all
relate to the configuration file, group these together and adjust the
wording to be more uniform.
This commit is contained in:
Adrian Duke 2026-02-05 14:47:46 +00:00 committed by Lorenz Leutgeb
parent cee3659ed5
commit 832598ceb7
6 changed files with 68 additions and 14 deletions

View File

@ -0,0 +1,7 @@
We want to ensure that a warning is printed when the `scope` field is missing in the `seedingPolicy`.
``` alice
$ rad node status
! Warning: Configuration option 'node.seedingPolicy.scope' is not set, and thus takes the value 'all' by default. The default value will change to 'followed' in a future release. Please edit your configuration file, and set it to one of ['all', 'followed'] explicitly.
[..]
```

View File

@ -38,8 +38,8 @@ $ rad debug
"RAD_RNG_SEED": "0" "RAD_RNG_SEED": "0"
}, },
"warnings": [ "warnings": [
"Value of configuration option `node.connect` at index 0 mentions node with address 'ash.radicle.garden:8776', which has been renamed to 'rosa.radicle.xyz:8776'. Please update your configuration.", "Value of configuration option `node.connect` at index 0 mentions node with address 'ash.radicle.garden:8776', which has been renamed to 'rosa.radicle.xyz:8776'. Please edit your configuration file to use the new address.",
"Value of configuration option `preferredSeeds` at index 0 mentions node with address 'seed.radicle.garden:8776', which has been renamed to 'iris.radicle.xyz:8776'. Please update your configuration." "Value of configuration option `preferredSeeds` at index 0 mentions node with address 'seed.radicle.garden:8776', which has been renamed to 'iris.radicle.xyz:8776'. Please edit your configuration file to use the new address."
] ]
} }
``` ```
@ -48,8 +48,8 @@ Also, `rad node status` will warn us:
``` ```
$ rad node status $ rad node status
! Warning: Value of configuration option `node.connect` at index 0 mentions node with address 'ash.radicle.garden:8776', which has been renamed to 'rosa.radicle.xyz:8776'. Please update your configuration. ! Warning: Value of configuration option `node.connect` at index 0 mentions node with address 'ash.radicle.garden:8776', which has been renamed to 'rosa.radicle.xyz:8776'. Please edit your configuration file to use the new address.
! Warning: Value of configuration option `preferredSeeds` at index 0 mentions node with address 'seed.radicle.garden:8776', which has been renamed to 'iris.radicle.xyz:8776'. Please update your configuration. ! Warning: Value of configuration option `preferredSeeds` at index 0 mentions node with address 'seed.radicle.garden:8776', which has been renamed to 'iris.radicle.xyz:8776'. Please edit your configuration file to use the new address.
Node is stopped. Node is stopped.
To start it, run `rad node start`. To start it, run `rad node start`.
``` ```

View File

@ -131,7 +131,7 @@ fn stderr_of(bin: &str, args: &[&str]) -> anyhow::Result<String> {
fn collect_warnings(profile: Option<&Profile>) -> Vec<String> { fn collect_warnings(profile: Option<&Profile>) -> Vec<String> {
match profile { match profile {
Some(profile) => crate::warning::nodes_renamed(&profile.config), Some(profile) => crate::warning::config_warnings(&profile.config),
None => vec!["No Radicle profile found.".to_string()], None => vec!["No Radicle profile found.".to_string()],
} }
} }

View File

@ -257,7 +257,7 @@ pub fn connect_many(
} }
pub fn status(node: &Node, profile: &Profile) -> anyhow::Result<()> { pub fn status(node: &Node, profile: &Profile) -> anyhow::Result<()> {
for warning in crate::warning::nodes_renamed(&profile.config) { for warning in crate::warning::config_warnings(&profile.config) {
term::warning(warning); term::warning(warning);
} }

View File

@ -22,26 +22,52 @@ fn nodes_renamed_for_option(
option: &'static str, option: &'static str,
iter: impl IntoIterator<Item = ConnectAddress>, iter: impl IntoIterator<Item = ConnectAddress>,
) -> Vec<String> { ) -> Vec<String> {
let mut warnings: Vec<String> = vec![]; iter.into_iter().enumerate().fold(Vec::new(), |mut warnings, (i, value)| {
for (i, value) in iter.into_iter().enumerate() {
let old: Address = value.into(); let old: Address = value.into();
if let Some(new) = NODES_RENAMED.get(&old) { if let Some(new) = NODES_RENAMED.get(&old) {
warnings.push(format!( warnings.push(format!(
"Value of configuration option `{option}` at index {i} mentions node with address '{old}', which has been renamed to '{new}'. Please update your configuration." "Value of configuration option `{option}` at index {i} mentions node with address '{old}', which has been renamed to '{new}'. Please edit your configuration file to use the new address."
)); ));
} }
} warnings
})
warnings
} }
pub(crate) fn nodes_renamed(config: &Config) -> Vec<String> { fn nodes_renamed(config: &Config) -> Vec<String> {
let mut warnings = nodes_renamed_for_option("node.connect", config.node.connect.clone()); let mut warnings = nodes_renamed_for_option("node.connect", config.node.connect.clone());
warnings.extend(nodes_renamed_for_option( warnings.extend(nodes_renamed_for_option(
"preferredSeeds", "preferredSeeds",
config.preferred_seeds.clone(), config.preferred_seeds.clone(),
)); ));
warnings
}
fn implicit_seeding_policy_allow_scope(config: &Config) -> Vec<String> {
use radicle::node::config::DefaultSeedingPolicy;
use radicle::node::policy::Scope::*;
let DefaultSeedingPolicy::Allow { scope } = config.node.seeding_policy else {
return vec![];
};
if !scope.is_implicit() {
return vec![];
}
vec![format!(
"Configuration option 'node.seedingPolicy.scope' is not set, and thus takes the value '{}' by default. The default value will change to '{}' in a future release. Please edit your configuration file, and set it to one of ['{}', '{}'] explicitly.",
scope.into_inner(),
Followed,
All,
Followed,
)]
}
pub(crate) fn config_warnings(config: &Config) -> Vec<String> {
let mut warnings = nodes_renamed(config);
warnings.extend(implicit_seeding_policy_allow_scope(config));
warnings warnings
} }

View File

@ -2872,3 +2872,24 @@ fn rad_workflow() {
) )
.unwrap(); .unwrap();
} }
#[test]
fn rad_seed_policy_allow_no_scope() {
let mut environment = Environment::new();
let alice = environment.node_with(Config {
seeding_policy: DefaultSeedingPolicy::Allow {
scope: node::config::Scope::implicit(),
},
..Config::test(Alias::new("alice"))
});
let alice = alice.spawn();
test(
"examples/rad-seed-policy-allow-no-scope.md",
environment.work(&alice),
Some(&alice.home),
[],
)
.unwrap();
}