Files
zeekayandHanzo Dev 1ab6e799c1 cd: the module is github.com/hanzoai/cd, where it is actually hosted
go.mod still declared `module github.com/hanzoai/deploy` after the repo was
renamed. A Go module path is not cosmetic — it is the resolvable location. So
`go get github.com/hanzoai/cd` could not work, and anything importing this
module had to spell a name that no longer exists at that address. The build log
of v3.6.0 is where it surfaced: the compiler was still emitting
github.com/hanzoai/deploy/cmd/cd/commands.

3541 import paths across 690 .go, 19 .proto, 4 .yaml, 3 .sh, 2 .mod, Procfile
and Makefile. Plus the 62 ghcr.io/hanzoai/deploy image references, moved to
ghcr.io/hanzoai/cd to match hanzo.yml's build target — a distinct string from
the module path, replaced separately so neither could clobber the other.

go mod tidy clean, CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build ./... clean.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-28 21:16:24 -07:00

86 lines
2.8 KiB
Go

package admin
import (
"context"
"fmt"
"os/signal"
"syscall"
"github.com/spf13/cobra"
"k8s.io/client-go/tools/clientcmd"
"github.com/hanzoai/cd/util/cli"
"github.com/hanzoai/cd/cmd/cd/commands/headless"
"github.com/hanzoai/cd/cmd/cd/commands/initialize"
"github.com/hanzoai/cd/common"
cdclient "github.com/hanzoai/cd/pkg/apiclient"
"github.com/hanzoai/cd/util/errors"
)
// DashboardConfig holds the configuration for starting the dashboard
type DashboardConfig struct {
Port int
Address string
ClientOpts *cdclient.ClientOptions
ClientConfig clientcmd.ClientConfig
Context string
}
type dashboard struct {
startLocalServer func(ctx context.Context, clientOpts *cdclient.ClientOptions, contextName string, port *int, address *string, clientConfig clientcmd.ClientConfig) (func(), error)
}
// NewDashboard initializes a new dashboard with default dependencies
func NewDashboard() *dashboard {
return &dashboard{
startLocalServer: headless.MaybeStartLocalServer,
}
}
// Run runs the dashboard and blocks until context is done
func (ds *dashboard) Run(ctx context.Context, config *DashboardConfig) error {
ctx, stop := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
defer stop()
config.ClientOpts.Core = true
println("starting dashboard")
shutDownFunc, err := ds.startLocalServer(ctx, config.ClientOpts, config.Context, &config.Port, &config.Address, config.ClientConfig)
if err != nil {
return fmt.Errorf("could not start dashboard: %w", err)
}
fmt.Printf("Hanzo CD UI is available at http://%s:%d\n", config.Address, config.Port)
<-ctx.Done()
stop() // unregister the signal handler as soon as we receive a signal
println("signal received, shutting down dashboard")
if shutDownFunc != nil {
shutDownFunc()
}
println("clean shutdown")
return nil
}
func NewDashboardCommand(clientOpts *cdclient.ClientOptions) *cobra.Command {
config := &DashboardConfig{ClientOpts: clientOpts}
cmd := &cobra.Command{
Use: "dashboard",
Short: "Starts Hanzo CD Web UI locally",
Run: func(cmd *cobra.Command, _ []string) {
config.Context = initialize.RetrieveContextIfChanged(cmd.Flag("context"))
errors.CheckError(NewDashboard().Run(cmd.Context(), config))
},
Example: `# Start the Hanzo CD Web UI locally on the default port and address
$ cd admin dashboard
# Start the Hanzo CD Web UI locally on a custom port and address
$ cd admin dashboard --port 8080 --address 127.0.0.1
# Start the Hanzo CD Web UI with GZip compression
$ cd admin dashboard --redis-compress gzip
`,
}
config.ClientConfig = cli.AddKubectlFlagsToSet(cmd.Flags())
cmd.Flags().IntVar(&config.Port, "port", common.DefaultPortAPIServer, "Listen on given port")
cmd.Flags().StringVar(&config.Address, "address", common.DefaultAddressAdminDashboard, "Listen on given address")
return cmd
}