Ship wp-ops as a trellis-cli plugin (trellis ops) - #188
Merged
Conversation
trellis-cli registers any executable on $PATH named `trellis-*` as a subcommand and execs it with the remaining argv, so shipping wp-ops as a `trellis ops` plugin needs no plugin API — just a second name for the same binary. What it does need is for the binary to notice which name it was called under. Two things followed from that, both keyed off filepath.Base(os.Args[0]): Help text and suggestions now render against the invoked name. Telling someone who typed `trellis ops` to "Run 'wp-ops backup'" points them at a command they may not know exists. Root's Long help became a template (rootLong) rather than a literal string; output under bare wp-ops is byte-for-byte what it was. Listing views scope to @platform trellis under the plugin name — 27 commands across 6 categories instead of all 74. Someone at a `trellis` prompt is not looking for the image converters or the release scripts. Deliberately narrow: an explicit --platform wins, a category with nothing Trellis-tagged still lists in full rather than claiming to be empty, --json stays the whole catalog because it is a contract for external tooling, and execution is never scoped — name any command and it runs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LEJsmBJKcH4dXK3LUDr6zN
The entire trellis-cli integration is a second symlink to the same binary. wp-ops ships as a goreleaser-generated cask, so it belongs in .goreleaser.yml rather than hand-edited into imagewize/homebrew-tap, whose Casks/wp-ops.rb is stamped "DO NOT EDIT". homebrew_casks has no field for a second `binary` stanza with a target, so this goes through custom_block. Verified by rendering the cask with a snapshot build. The name must be exactly `trellis-ops`: the plugin finder splits the filename on "-", drops the first segment, and joins the rest with spaces, so `trellis-wp-ops` would register the three-word `trellis wp ops`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LEJsmBJKcH4dXK3LUDr6zN
README gains a "trellis-cli plugin" section under the CLI docs, including the manual symlink for people who build from source rather than installing the cask. trellis-extensions-evaluation.md's Path A was written as a proposal and recommended the name `trellis-wpops`. Rewritten to describe what actually shipped as `trellis ops`, with the cask mechanics that the original (which assumed a formula) got wrong, and the verified finding that plugin commands run outside a Trellis project while core ones do not. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LEJsmBJKcH4dXK3LUDr6zN
New feature, nothing breaking, so a minor bump. The version is read out of CHANGELOG.md's first `## [X.Y.Z]` heading at runtime (go/cmd/version.go getVersion, go/cmd/env.go embeddedVersion), so this heading is the whole bump — there is no second copy to keep in sync. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LEJsmBJKcH4dXK3LUDr6zN
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Version:
5.6.0This release adds a trellis-cli plugin integration for wp-ops, exposing the full command catalog as
trellis ops <...>without any new plugin API, separate binary, or additional repository. trellis-cli discovers plugins by scanning$PATHfortrellis-*executables and exec'ing them with the remaining argv, so the entire integration is a second symlink to the same binary — the Homebrew cask now installstrellis-opsalongsidewp-opsvia acustom_blockin.goreleaser.yml. A newgo/cmd/invoked.goreadsfilepath.Base(os.Args[0])to detect which name was used, and every help string, usage line, and did-you-mean suggestion acrossroot.go,list.go,dispatch.go,docs.go,search.go, andserverside.gonow renders against that name rather than a hardcodedwp-ops. Undertrellis ops, listing views scope to the 27 commands tagged@platform trellisacross 6 categories instead of the full 74, while execution and--jsonoutput remain deliberately unscoped. Output under barewp-opsis byte-for-byte unchanged, and the change is covered by 92 lines of new tests ingo/cmd/invoked_test.go.Plugin Integration and Packaging:
trellis-opssymlink to the Homebrew cask (.goreleaser.yml), making every wp-ops command reachable astrellis ops <...>from inside trellis-cli. The name must be exactlytrellis-ops: the finder splits on-and joins remaining segments with spaces, sotrellis-wp-opswould register as the three-wordtrellis wp ops.ln -s "$(command -v wp-ops)" /usr/local/bin/trellis-ops) for source builds, along with the trellis-cli v1.19.0+ andload_plugins: truerequirements.$PATHbefore trellis-cli resolves a project, sotrellis opsruns anywhere; playbook commands continue to locate the Trellis directory through wp-ops's owndetect.TrellisDir.Invocation-Aware CLI Behavior:
rootCmd.Longfrom a literal string intorootLong(name), a template rendered atExecute()time with column-40 alignment preserved and a guard for the widertrellis opsprefix.defaultPlatform(), which applies an implicit@platform trellisfilter to listing views when invoked as a plugin; an explicit--platformflag always overrides it.--jsonreturns the complete catalog since it serves as a contract for external tooling.Documentation:
CHANGELOG.mdwith the trellis-cli discovery mechanics and naming constraints, including whyopswas chosen (segments matching core root commands are silently skipped byisUnderCoreRootCommands).docs/trellis-extensions-evaluation.md(139 lines changed) to reflect the implemented plugin approach.Files Changed:
.goreleaser.yml(Modified)CHANGELOG.md(Modified)README.md(Modified)docs/trellis-extensions-evaluation.md(Modified)go/cmd/dispatch.go(Modified)go/cmd/docs.go(Modified)go/cmd/list.go(Modified)go/cmd/root.go(Modified)go/cmd/search.go(Modified)go/cmd/serverside.go(Modified)go/cmd/trellis.go(Modified)go/cmd/invoked.go(Added)go/cmd/invoked_test.go(Added)