|
2 | 2 |
|
3 | 3 | /// Expands the Ops command descriptors into a consumer macro. |
4 | 4 | /// |
5 | | -/// Each row owns the command module, parsed Clap variant, contract metadata, and |
6 | | -/// JSON handler binding. Consumers select the fields they need while preserving |
7 | | -/// command-owned dynamic output and Lab predicates. |
| 5 | +/// Each row binds a command module to its parsed Clap variant and JSON handler. |
| 6 | +/// That is the whole descriptor: module registration and JSON dispatch are the |
| 7 | +/// only two things a `Commands` variant needs from this table. |
| 8 | +/// |
| 9 | +/// Contract metadata (a `CommandSpec`) is deliberately **not** a column here. It |
| 10 | +/// lives once, in [`ops_command_spec`], because `spec.rs` splices the ops rows |
| 11 | +/// into a hand-ordered `COMMANDS` array at fifteen non-contiguous positions — |
| 12 | +/// a shape this block-emitting macro cannot produce. Carrying a second copy of |
| 13 | +/// the spec expressions in this table bought nothing: neither consumer ever |
| 14 | +/// referenced it, so the copies expanded to no code while still requiring every |
| 15 | +/// safety-metadata edit to be made twice. |
| 16 | +/// |
| 17 | +/// Registry/parser parity is enforced by |
| 18 | +/// `cli_surface::tests::command_registry_manifest_and_docs_metadata_align`, |
| 19 | +/// which asserts a bijection between the clap subcommand set and |
| 20 | +/// `COMMAND_SPECS`. That guard is stronger than macro co-location: it catches a |
| 21 | +/// missing spec for *any* command, not just the ops family. |
8 | 22 | #[macro_export] |
9 | 23 | macro_rules! ops_command_descriptors { |
10 | 24 | ($consumer:ident) => { |
11 | 25 | $consumer! { |
12 | | - (ssh, Ssh, crate::commands::ssh::SshArgs, command_spec("ssh", CommandJsonFamily::Ops), crate::commands::ssh::run), |
13 | | - (server, Server, crate::commands::server::ServerArgs, CommandSpec { subcommand_safety: SERVER_SUBCOMMAND_SAFETY, ..command_spec("server", CommandJsonFamily::Ops) }, crate::commands::server::run), |
14 | | - (db, Db, crate::commands::db::DbArgs, CommandSpec { subcommand_safety: DB_SUBCOMMAND_SAFETY, ..command_spec("db", CommandJsonFamily::Ops) }, crate::commands::db::run), |
15 | | - (file, File, crate::commands::file::FileArgs, CommandSpec { subcommand_safety: FILE_SUBCOMMAND_SAFETY, ..command_spec("file", CommandJsonFamily::Ops) }, crate::commands::file::run), |
16 | | - (logs, Logs, crate::commands::logs::LogsArgs, command_spec("logs", CommandJsonFamily::Ops), crate::commands::logs::run), |
17 | | - (triage, Triage, crate::commands::triage::TriageArgs, command_spec_with_safety("triage", CommandJsonFamily::Ops, operator_safety(None, TRIAGE_DANGEROUS_FLAGS)), crate::commands::triage::run), |
18 | | - (deploy, Deploy, crate::commands::deploy::DeployArgs, command_spec_with_safety("deploy", CommandJsonFamily::Ops, operator_safety(Some("--dry-run"), DEPLOY_DANGEROUS_FLAGS)), crate::commands::deploy::run), |
19 | | - (harvest, Harvest, crate::commands::harvest::HarvestArgs, command_spec_with_safety("harvest", CommandJsonFamily::Ops, operator_safety(Some("--dry-run"), &["--apply"])), crate::commands::harvest::run), |
20 | | - (daemon, Daemon, crate::commands::daemon::DaemonArgs, command_spec("daemon", CommandJsonFamily::Ops), crate::commands::daemon::run), |
21 | | - (schedule, Schedule, crate::commands::schedule::ScheduleArgs, command_spec("schedule", CommandJsonFamily::Ops), crate::commands::schedule::run), |
22 | | - (status, Status, crate::commands::status::StatusArgs, command_spec("status", CommandJsonFamily::Ops), crate::commands::status::run), |
23 | | - (git, Git, crate::commands::git::GitArgs, CommandSpec { subcommand_safety: GIT_SUBCOMMAND_SAFETY, ..command_spec("git", CommandJsonFamily::Ops) }, crate::commands::git::run), |
24 | | - (self_cmd, SelfCmd, crate::commands::self_cmd::SelfArgs, CommandSpec { subcommand_safety: SELF_SUBCOMMAND_SAFETY, ..command_spec_with_output_notes("self", CommandJsonFamily::Ops, "inspects the active Homeboy runtime and renders built-in CLI documentation") }, crate::commands::self_cmd::run), |
25 | | - (api, Api, crate::commands::api::ApiArgs, CommandSpec { subcommand_safety: API_SUBCOMMAND_SAFETY, ..command_spec("api", CommandJsonFamily::Ops) }, crate::commands::api::run), |
26 | | - (upgrade, Upgrade, crate::commands::upgrade::UpgradeArgs, command_spec_with_output_notes_and_safety("upgrade", CommandJsonFamily::Ops, "upgrades the active Homeboy binary, extensions, runners, and services unless --check or skip flags are used", operator_safety(None, UPGRADE_DANGEROUS_FLAGS)), crate::commands::upgrade::run), |
| 26 | + (ssh, Ssh, crate::commands::ssh::run), |
| 27 | + (server, Server, crate::commands::server::run), |
| 28 | + (db, Db, crate::commands::db::run), |
| 29 | + (file, File, crate::commands::file::run), |
| 30 | + (logs, Logs, crate::commands::logs::run), |
| 31 | + (triage, Triage, crate::commands::triage::run), |
| 32 | + (deploy, Deploy, crate::commands::deploy::run), |
| 33 | + (harvest, Harvest, crate::commands::harvest::run), |
| 34 | + (daemon, Daemon, crate::commands::daemon::run), |
| 35 | + (schedule, Schedule, crate::commands::schedule::run), |
| 36 | + (status, Status, crate::commands::status::run), |
| 37 | + (git, Git, crate::commands::git::run), |
| 38 | + (self_cmd, SelfCmd, crate::commands::self_cmd::run), |
| 39 | + (api, Api, crate::commands::api::run), |
| 40 | + (upgrade, Upgrade, crate::commands::upgrade::run), |
27 | 41 | } |
28 | 42 | }; |
29 | 43 | } |
30 | 44 |
|
31 | | -/// Commands-free spec table for the ops command family. |
| 45 | +/// Canonical `CommandSpec` table for the ops command family. |
| 46 | +/// |
| 47 | +/// This is the single source of truth for ops contract metadata. It is expanded |
| 48 | +/// inside `command_contract` (`spec.rs`), which cannot name `crate::commands` |
| 49 | +/// types, so it deliberately holds no Args type or handler binding — those live |
| 50 | +/// in [`ops_command_descriptors`], which is expanded only on the CLI side. |
32 | 51 | /// |
33 | | -/// This mirrors the `$spec` field of [`ops_command_descriptors`] but omits the |
34 | | -/// `crate::commands` Args type and handler binding, so it can be expanded inside |
35 | | -/// `command_contract` (e.g. `spec.rs`) without depending on the `commands` |
36 | | -/// module. The full descriptor macro (with Args + handler) is expanded only on |
37 | | -/// the CLI side. |
| 52 | +/// The per-name arms exist because `spec.rs` interleaves these rows with |
| 53 | +/// non-ops entries in one hand-ordered array; a single block-emitting arm could |
| 54 | +/// not be spliced into those positions. |
38 | 55 | #[macro_export] |
39 | 56 | macro_rules! ops_command_spec { |
40 | 57 | (ssh) => { command_spec("ssh", CommandJsonFamily::Ops) }; |
|
0 commit comments