Clap 3 → Clap 4 Upgrade#3431
Conversation
Ooh, this is clever. If this works then that's the lifeline we need! |
a35c681 to
ec065f5
Compare
itowlson
left a comment
There was a problem hiding this comment.
I really like the way this gets around that accursed hyphen values problem. There are a couple of seemingly unrelated changes that I'm a bit sceptical about, and I would like to see the clever trick made a touch easier to grasp. But I'm stoked that we may finally be shot of Clap 3!
Incidentally it looks like this doesn't touch src/clap_markdown. It's possible we could use official clap_markdown - v3 vs v4 was the main reason for forking it. But I did do a bunch of tweaks post-forking and so it may be that the upstream crate won't work for us. Anyway something to be aware of.
|
Edit: Fixed via rebase |
|
@itowlson in the last commit here, I removed the vendored clap-markdown code. The main difference AFAICT is that you modified the vendored code to sort the command output. Since upstream doesn't do this, I added a |
cea70a5 to
3ac72ea
Compare
Very nice - glad to see the back of that. Thank you! |
|
@itowlson Lastly, the last commit refactors the parsing code (its a bit more readable now IMO). Additionally added a test to ensure its correctly splitting up and trigger arguments. If that looks good, feel free to approve (I believe I addressed everything). |
There was a problem hiding this comment.
Huh, weird. This didn't seem to cause errors in CI. But thanks for catching it!
|
Oops, yeah i goofed. Should be fixed now. |
itowlson
left a comment
There was a problem hiding this comment.
Nice. The parsing logic is much clearer now, and the test is reassuring! Brilliant work by you and Lann to get this done without changing the user experience!
Signed-off-by: Brian Hardock <brian.hardock@fermyon.com>
Signed-off-by: Brian Hardock <brian.hardock@fermyon.com>
Signed-off-by: Brian Hardock <brian.hardock@fermyon.com>
Signed-off-by: Brian Hardock <brian.hardock@fermyon.com>

Supersedes #3249
Summary
This PR upgrades the Spin CLI from clap 3.2 to clap 4.6.0, along with all associated API and behavioral changes required by the new major version.
Dependency Changes
clapclap_lexFeature Flag Changes
["deprecated", "derive", "env"]→["derive", "env", "string", "wrap_help"]deprecated(clap 4 no longer has a deprecation compatibility layer)stringforString-based value handlingwrap_helpfor automatic terminal-width help wrappingwrap_helpfeatureclapas a dependency (for sharedCLAP_STYLES)API Migration Changes
IntoApp→CommandFactoryThe
IntoApptrait was renamed toCommandFactoryin clap 4. All imports and usages updated.takes_value = falseRemovedIn clap 4, boolean fields (
bool) no longer needtakes_value = false— this is the default behavior. Removed from all boolean flag definitions across:UpCommand(insecure,direct_mounts,build)PluginCommands(yes_to_all,override_compatibility_check,all,downgrade)RegistryCommands(insecure,build,password_stdin)TemplateCommands(verbose)NewCommand(init,accept_defaults,no_vcs,allow_overwrite)BuildCommand(skip_target_checks)FactorsTriggerCommand(disable_cache,debug_info)conflicts_with/requiresUse Field NamesClap 4 requires using the Rust field name (with underscores) instead of the kebab-case CLI name:
conflicts_with = "template-id"→conflicts_with = "template_id"requires = "tls-key"→requires = "tls_key"requires = "tls-cert"→requires = "tls_cert"Simplified
longAttributesWhere the
longname matches the field name's kebab-case form, explicitlong = "..."has been simplified to justlong:long = "insecure"→long(on fields namedinsecure)long = "version"→long,long = "downgrade"→long, etc.long = "init"→long,long = "values-file"→long, etc.Command<'_>Lifetime RemovedClap 4's
Commandno longer carries a lifetime parameter. Allclap::Command<'_>references changed toclap::Command.multiple_values(true)→action(ArgAction::Append)The
multiple_valuesAPI was replaced with explicitArgAction::Appendfor collecting multiple values..about(s.as_str())→.about(&s)Minor API change in how string references are passed to
about().Architectural Changes
SpinAppMoved tosrc/lib.rsThe
SpinAppenum,TriggerCommands, and all supporting code (run(),build_info(),PluginHelpEntry,plugin_help_entries()) moved fromsrc/bin/spin.rstosrc/lib.rs. The binary (src/bin/spin.rs) is now a thin wrapper that callsspin_cli::run().This enables other code (e.g.,
external.rs,maintenance.rs) to accessSpinApp::command()viacrate::SpinAppwithout needing the command to be passed as a parameter.cmdParameter Removed from SubcommandsSeveral subcommand
runmethods no longer take aclap::Commandparameter:DeployCommand::run(self, cmd)→DeployCommand::run(self)LoginCommand::run(self, cmd)→LoginCommand::run(self)MaintenanceCommands::run(&self, app)→MaintenanceCommands::run(&self)execute_external_subcommand(subcmd, cmd)→execute_external_subcommand(args)These now call
crate::SpinApp::command()directly when needed.UpCommandRefactored with Custom Parserspin uphas a unique requirement: it must accept both its own flags and arbitrary trigger-specific flags that it passes through. Clap 3'sallow_hyphen_values = truehandled this implicitly, but clap 4 requires explicit handling.The solution:
UpCommandis now a newtype wrapper:pub struct UpCommand(UpCommandInner)UpCommandInner(private) holds the actual#[derive(Parser)]fieldssrc/commands/up/parsing.rs(new module) implements customArgs,FromArgMatches,Parser, andCommandFactoryforUpCommandclap_lexto split arguments: recognized flags go toUpCommandInner, everything else becomestrigger_argstrigger_argschanged from#[clap(hide = true)]to#[clap(skip)]since it's populated by the custom parserUpCommand::run_as_flag()for thespin build --upflowColored Help Output (CLAP_STYLES)
A new
CLAP_STYLESconstant incrates/common/src/cli.rsprovides consistent colored terminal output:Applied to
SpinAppandFactorsTriggerCommand.Help Heading Casing
Trigger option help headings changed from
"TRIGGER OPTIONS"to"Trigger Options"to match clap 4's default styling conventions.Files Changed
Cargo.tomlcrates/common/Cargo.tomlcrates/common/src/cli.rsCLAP_STYLESconstantcrates/common/src/lib.rspub mod clicrates/trigger/Cargo.tomlwrap_helpfeaturecrates/trigger/src/cli.rscrates/trigger-http/src/lib.rsrequiresfield name fixcrates/expressions/src/template.rssrc/lib.rssrc/bin/spin.rssrc/commands/up.rssrc/commands/up/parsing.rssrc/commands/build.rssrc/commands/cloud.rscmdparametersrc/commands/external.rscmdparameter, usesSpinApp::command()src/commands/maintenance.rscmdparameter, usesSpinApp::command()src/commands/new.rssrc/commands/plugins.rssrc/commands/registry.rssrc/commands/templates.rsCLI Behavior Changes
wrap_helpfeature)