carlos / platform Public

CLI management for deploy destinations (.carlos/config) Feature Request open

Named deploy destinations landed in 1bcc593 (carlos deploy -d <name>, --destination on every verb that takes --console, CARLOS_DESTINATION, and "destinations" / "default" in .carlos/config). The only way to manage them is still hand-editing the file. This discussion proposes CLI commands to fill that gap.

What works today

Commands that save to .carlos/config write into the selected destination, and create its block if it doesn't exist yet:

CARLOS_DESTINATION=exciting carlos auth default --project https://carlos.exciting.io
CARLOS_DESTINATION=tito     carlos auth default --project https://<tito console>

After that, carlos deploy -d tito at a terminal asks for the account, app and artifact, and offers to save them into the tito block.

Gaps

  1. carlos auth default has no -d. -d was added only where --console already existed, and auth default has no --console flag. The environment variable is the only way to select a destination there.
  2. Nothing sets "default". Once a file has two destinations, every command in that checkout refuses until you pass -d or edit the file.
  3. No list or remove. To see which destinations exist, or which one is the default, you have to read the JSON.
  4. Converting a single-console file changes behaviour silently. Adding one destination to a file that already has top-level console, account and app keys makes that block apply everywhere, because a file with a single block uses it. The destination's keys then override the top-level ones without any prompt.

Proposal

  • carlos auth default [--project] -d <name> <url> writes the console into that destination.
  • carlos destinations, working on the nearest project file by default and on ~/.carlos/config with --global: - list shows each destination's name, console, account, app and artifact, marks the default, and names the file it came from. - add <name> --console <url> [--account a] [--app a] [--kind k] [--artifact p] [--target t] adds a destination and refuses if the name is already taken. - set <name> key=value... or flag edits change an existing destination. - default <name> sets the default. - remove <name> deletes a destination and refuses to remove the current default unless another one is named. - rename <old> <new> renames a destination and keeps the default pointing at it.
  • Converting on the first add: when the first destination is added to a file whose top level has console, account or app, offer to move those keys into a named block (for example --from-current <name>) and make it the default. The existing behaviour stays the same and the new destination becomes the second one. Refuse without a terminal unless the flag is given.
  • Docs: add the command to docs/site/cli.md. The docsite gate requires a heading for every new command.

Open questions

  • Should this live under carlos destinations or carlos config destinations? Other .carlos/config keys (app, update_check, message_prompt) also have no management command, so a general carlos config command might be the better home.
  • Should add check the console, for example by requiring a credential for it or offering auth login, or only check the URL's format?

A note on the name and placement of the "default" key, raised after this discussion was opened. The key has been left as it is for now.

Idea: move it inside destinations ("destinations": {"default": "exciting", "exciting": {…}}). We decided against it:

  • Mixed values: the object would hold one string among the destination blocks. Listing, error messages and any JSON schema would have to skip it, and the Go code would need a custom JSON parser instead of reading a plain map of blocks.
  • A reserved name: nobody could call a destination default, and "default": {…} would be ambiguous: a destination with that name, or a malformed pointer?

Related idea: a destination literally named default becomes the default, with no pointer. It reads well (-d default), but you'd have to rename a real destination to make it the default, and the file would stop saying where it deploys.

The better change is probably a rename: keep the key at the top level but call it "default_destination". A bare "default" next to console, app and artifact doesn't say what it's the default of. The rename is cheap while few files use it. If this becomes a carlos destinations default <name> command, it's a good moment to rename, perhaps still reading "default" for compatibility.

Most of this has now shipped, in 1643418 (branch config-destinations-cli). The command lives under carlos config destinations, not carlos destinations, because the other .carlos/config keys may get management commands later.

Done:

  • carlos config destinations has list (the bare command), add, set, default [<name>], remove and rename. The default follows a rename. set --<key> "" removes that key from the destination.
  • It edits the nearest project .carlos/config, or creates ./.carlos/config if there is none. --global edits ~/.carlos/config, and it refuses to edit that file without the flag.
  • Converting a single-console file: when the first destination is added to a file with a top-level console, account or app, those keys move into a named destination, which becomes the default. It asks for the name at a terminal; elsewhere you pass --from-current <name>. Shared keys like artifact stay at the top of the file.
  • Adding a second destination records the first as the default. Removing the default is refused while two or more others would remain; if only one would remain, it becomes the default.
  • add warns if this machine isn't logged in to the console, but still writes the destination.
  • carlos auth default takes -d.

Still open: renaming "default" to "default_destination" (see the previous reply). It hasn't been done yet.