From 876fdb5a856787ddee98d92d16c754890850577d Mon Sep 17 00:00:00 2001 From: Joe Corall Date: Tue, 24 Mar 2026 07:53:03 -0400 Subject: [PATCH] [minor] align all sitectl features in a coherent SDK --- Makefile | 4 +- cmd/extensions.go | 38 +++---- cmd/extensions_test.go | 4 +- cmd/root.go | 2 +- go.mod | 4 +- go.sum | 4 +- scripts/gen-docs-snippets/main.go | 167 ------------------------------ 7 files changed, 23 insertions(+), 200 deletions(-) delete mode 100644 scripts/gen-docs-snippets/main.go diff --git a/Makefile b/Makefile index 8c81504..b7e9f79 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build deps lint test work install docs-snippets +.PHONY: build deps lint test work install BINARY_NAME=sitectl-drupal INSTALL_DIR ?= $(or $(dir $(shell which $(BINARY_NAME) 2>/dev/null)),/usr/local/bin/) @@ -29,5 +29,3 @@ test: build work: ./scripts/use-go-work.sh -docs-snippets: work - go run ./scripts/gen-docs-snippets/ diff --git a/cmd/extensions.go b/cmd/extensions.go index b1b1799..f938cb2 100644 --- a/cmd/extensions.go +++ b/cmd/extensions.go @@ -21,7 +21,6 @@ import ( ) var drupalComponentName string -var drupalRootfsPath string const ( cachePageWarningThreshold = int64(1 << 30) @@ -148,18 +147,17 @@ var componentExtensionSetCmd = &cobra.Command{ }, } -var debugExtensionCmd = &cobra.Command{ - Use: "__debug", - Short: "Internal debug extension command", - Hidden: true, - RunE: func(cmd *cobra.Command, args []string) error { - rendered, err := renderDrupalDebug(cmd.Context()) - if err != nil { - return err - } - _, err = fmt.Fprintln(cmd.OutOrStdout(), rendered) - return err - }, +// drupalDebugRunner implements plugin.DebugRunner for the drupal plugin. +type drupalDebugRunner struct { + rootfsPath string +} + +func (r *drupalDebugRunner) BindFlags(cmd *cobra.Command) { + cmd.Flags().StringVar(&r.rootfsPath, "drupal-rootfs", "", "Drupal rootfs path override") +} + +func (r *drupalDebugRunner) Render(cmd *cobra.Command, ctx *config.Context) (string, error) { + return renderDrupalDebugBody(cmd.Context(), ctx, r.rootfsPath) } func init() { @@ -169,19 +167,13 @@ func init() { componentExtensionCmd.AddCommand(componentExtensionDescribeCmd) componentExtensionCmd.AddCommand(componentExtensionReconcileCmd) componentExtensionCmd.AddCommand(componentExtensionSetCmd) - - debugExtensionCmd.Flags().StringVar(&drupalRootfsPath, "drupal-rootfs", "", "Drupal rootfs path override") } -func renderDrupalDebug(runCtx context.Context) (string, error) { +func renderDrupalDebugBody(runCtx context.Context, ctx *config.Context, rootfsOverride string) (string, error) { slog.Debug("starting plugin debug", "plugin", "drupal") if sdk == nil { return "", fmt.Errorf("plugin sdk is not initialized") } - ctx, err := sdk.GetContext() - if err != nil { - return "", err - } slog.Debug("resolved plugin context", "plugin", "drupal", "context", ctx.Name, "project_dir", ctx.ProjectDir) slog.Debug("creating file accessor", "plugin", "drupal") files, err := sdk.GetFileAccessor() @@ -190,7 +182,7 @@ func renderDrupalDebug(runCtx context.Context) (string, error) { } defer files.Close() - rootfs := strings.TrimSpace(drupalRootfsPath) + rootfs := strings.TrimSpace(rootfsOverride) if rootfs == "" { rootfs = ctx.EffectiveDrupalRootfs() } @@ -262,8 +254,8 @@ func renderDrupalDebug(runCtx context.Context) (string, error) { } body = append(body, "", strings.Join(patchLines, "\n")) - slog.Debug("finished plugin debug", "plugin", "drupal") - return debugui.RenderPanel("drupal", strings.Join(body, "\n")), nil + slog.Debug("finished plugin debug body", "plugin", "drupal") + return strings.Join(body, "\n"), nil } func renderCachePageSummary(runCtx context.Context) (string, error) { diff --git a/cmd/extensions_test.go b/cmd/extensions_test.go index 0d4d538..a3ef488 100644 --- a/cmd/extensions_test.go +++ b/cmd/extensions_test.go @@ -196,9 +196,9 @@ func TestRenderDrupalDebugRequiresSDK(t *testing.T) { sdk = nil defer func() { sdk = original }() - _, err := renderDrupalDebug(context.Background()) + _, err := renderDrupalDebugBody(context.Background(), &config.Context{}, "") if err == nil { - t.Fatal("expected renderDrupalDebug() error") + t.Fatal("expected renderDrupalDebugBody() error") } if !strings.Contains(err.Error(), "plugin sdk is not initialized") { t.Fatalf("unexpected error: %v", err) diff --git a/cmd/root.go b/cmd/root.go index 72c63a0..f629778 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -21,7 +21,7 @@ func RegisterCommands(s *plugin.SDK) { sdk.AddCommand(sdk.GetDiscoveryMetadataCommand()) sdk.AddCommand(componentExtensionCmd) sdk.RegisterCreateRunner(createDefinition(), createRunner{}) - sdk.AddCommand(debugExtensionCmd) + sdk.RegisterDebugHandler(&drupalDebugRunner{}) sdk.AddCommand(drushCmd) sdk.AddCommand(loginCmd) sdk.AddCommand(syncCmd) diff --git a/go.mod b/go.mod index a0ea322..9d6d4e4 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,8 @@ module github.com/libops/sitectl-drupal go 1.25.8 require ( - github.com/libops/sitectl v0.15.0 + github.com/libops/sitectl v0.16.0 github.com/spf13/cobra v1.10.2 - github.com/spf13/pflag v1.0.10 gopkg.in/yaml.v3 v3.0.1 ) @@ -56,6 +55,7 @@ require ( github.com/pkg/sftp v1.13.10 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/sahilm/fuzzy v0.1.1 // indirect + github.com/spf13/pflag v1.0.10 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.64.0 // indirect diff --git a/go.sum b/go.sum index 093bee8..ddccae7 100644 --- a/go.sum +++ b/go.sum @@ -82,8 +82,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/libops/sitectl v0.15.0 h1:YZrBcpvY3fAZlLeCFs9OndDHiam7l9nABy2hDpUllSI= -github.com/libops/sitectl v0.15.0/go.mod h1:Q4mIOPKbV1CJAYJ/x0e+ZxKQ2M/zOrqiWE7YmL5kaH4= +github.com/libops/sitectl v0.16.0 h1:Ayx/X9aEv2dbu4rQPVPVsyFlw0zJJ1+V9IArdwD6jUE= +github.com/libops/sitectl v0.16.0/go.mod h1:Q4mIOPKbV1CJAYJ/x0e+ZxKQ2M/zOrqiWE7YmL5kaH4= github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-runewidth v0.0.20 h1:WcT52H91ZUAwy8+HUkdM3THM6gXqXuLJi9O3rjcQQaQ= diff --git a/scripts/gen-docs-snippets/main.go b/scripts/gen-docs-snippets/main.go deleted file mode 100644 index 13d3a3c..0000000 --- a/scripts/gen-docs-snippets/main.go +++ /dev/null @@ -1,167 +0,0 @@ -// gen-docs-snippets generates MDX snippet files for each sitectl-drupal command. -// Run via: make docs-snippets -// Output goes to ../sitectl-docs/snippets/commands/ -package main - -import ( - "fmt" - "os" - "path/filepath" - "strings" - - drupalcmd "github.com/libops/sitectl-drupal/cmd" - "github.com/libops/sitectl/pkg/plugin" - "github.com/spf13/cobra" - "github.com/spf13/pflag" -) - -const ( - displayPrefix = "sitectl drupal" - outputDir = "../sitectl-docs/snippets/commands" - autoGenHeader = "{/* Auto-generated from source. Run `make docs-snippets` to update. */}\n\n" -) - -func main() { - sdk := plugin.NewSDK(plugin.Metadata{ - Name: "drupal", - Description: "Drupal utilities and migration tools", - }) - drupalcmd.RegisterCommands(sdk) - root := sdk.RootCmd - root.DisableAutoGenTag = true - - if err := os.MkdirAll(outputDir, 0o755); err != nil { - fmt.Fprintf(os.Stderr, "create output dir: %v\n", err) - os.Exit(1) - } - - var count int - walkCommands(root, func(cmd *cobra.Command) { - slug := commandSlug(cmd) - path := filepath.Join(outputDir, slug+".mdx") - if err := os.WriteFile(path, []byte(renderSnippet(cmd)), 0o644); err != nil { - fmt.Fprintf(os.Stderr, "write %s: %v\n", path, err) - os.Exit(1) - } - fmt.Println(path) - count++ - }) - fmt.Printf("generated %d snippets\n", count) -} - -func walkCommands(cmd *cobra.Command, fn func(*cobra.Command)) { - for _, sub := range cmd.Commands() { - if skipCommand(sub) { - continue - } - fn(sub) - walkCommands(sub, fn) - } -} - -func skipCommand(cmd *cobra.Command) bool { - if cmd.Hidden { - return true - } - name := cmd.Name() - if name == "help" || name == "completion" { - return true - } - return false -} - -func commandSlug(cmd *cobra.Command) string { - path := cmd.CommandPath() - prefix := strings.ReplaceAll(displayPrefix, " ", "-") - if strings.HasPrefix(path, displayPrefix+" ") { - rel := path[len(displayPrefix)+1:] - return strings.ToLower(prefix + "-" + strings.ReplaceAll(rel, " ", "-")) - } - return strings.ToLower(prefix) -} - -func buildUseLine(cmd *cobra.Command) string { - // cmd.CommandPath() already includes the correct display name via CommandDisplayNameAnnotation - path := cmd.CommandPath() - - var fullPath string - if path == displayPrefix || strings.HasPrefix(path, displayPrefix+" ") { - fullPath = path - } else { - fullPath = displayPrefix + " " + path - } - - // Append args from Use (everything after the command name) - useParts := strings.Fields(cmd.Use) - if len(useParts) > 1 { - fullPath += " " + strings.Join(useParts[1:], " ") - } - - // For group commands (no RunE), append - if !cmd.Runnable() && cmd.HasAvailableSubCommands() { - fullPath += " " - } - - return fullPath -} - -func collectLocalFlags(cmd *cobra.Command) []*pflag.Flag { - var flags []*pflag.Flag - cmd.Flags().VisitAll(func(f *pflag.Flag) { - if !f.Hidden { - flags = append(flags, f) - } - }) - return flags -} - -func renderSnippet(cmd *cobra.Command) string { - var b strings.Builder - b.WriteString(autoGenHeader) - - // Long description, falling back to Short - desc := strings.TrimSpace(cmd.Long) - if desc == "" { - desc = strings.TrimSpace(cmd.Short) - } - if desc != "" { - b.WriteString(desc) - b.WriteString("\n\n") - } - - // Usage code block - b.WriteString("```bash\n") - b.WriteString(buildUseLine(cmd)) - b.WriteString("\n```\n") - - // Aliases - if len(cmd.Aliases) > 0 { - b.WriteString("\n**Aliases:** `") - b.WriteString(strings.Join(cmd.Aliases, "`, `")) - b.WriteString("`\n") - } - - // Flags table (skip for DisableFlagParsing commands — they accept arbitrary args) - if !cmd.DisableFlagParsing { - flags := collectLocalFlags(cmd) - if len(flags) > 0 { - b.WriteString("\n| Flag | Default | Description |\n") - b.WriteString("|------|---------|-------------|\n") - for _, f := range flags { - flagStr := "--" + f.Name - if f.Shorthand != "" { - flagStr = "-" + f.Shorthand + ", " + flagStr - } - defVal := f.DefValue - if defVal == "" { - defVal = " " - } else { - defVal = "`" + defVal + "`" - } - fmt.Fprintf(&b, "| `%s` | %s | %s |\n", flagStr, defVal, f.Usage) - } - } - } - - return b.String() -}