305 lines
10 KiB
Go
305 lines
10 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"git.hangman-lab.top/zhi/HarborForge.Cli/internal/commands"
|
|
"git.hangman-lab.top/zhi/HarborForge.Cli/internal/help"
|
|
"git.hangman-lab.top/zhi/HarborForge.Cli/internal/mode"
|
|
"git.hangman-lab.top/zhi/HarborForge.Cli/internal/output"
|
|
)
|
|
|
|
func main() {
|
|
args := os.Args[1:]
|
|
|
|
// Parse global flags first
|
|
args = parseGlobalFlags(args)
|
|
|
|
if len(args) == 0 {
|
|
fmt.Print(help.RenderTopHelp(commands.Version, topGroups()))
|
|
return
|
|
}
|
|
|
|
switch args[0] {
|
|
case "--help", "-h":
|
|
fmt.Print(help.RenderTopHelp(commands.Version, topGroups()))
|
|
case "--help-brief":
|
|
fmt.Print(help.RenderTopHelpBrief(commands.Version, topGroups()))
|
|
case "version":
|
|
handleLeafOrRun("version", args[1:], commands.RunVersion)
|
|
case "health":
|
|
handleLeafOrRun("health", args[1:], commands.RunHealth)
|
|
case "config":
|
|
handleConfig(args[1:])
|
|
default:
|
|
if group, ok := findGroup(args[0]); ok {
|
|
handleGroup(group, args[1:])
|
|
return
|
|
}
|
|
fmt.Fprintf(os.Stderr, "unknown command: %s\n", args[0])
|
|
fmt.Fprintf(os.Stderr, "Run 'hf --help' for usage.\n")
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
// parseGlobalFlags extracts --json from anywhere in the args and returns remaining args.
|
|
func parseGlobalFlags(args []string) []string {
|
|
var remaining []string
|
|
for _, a := range args {
|
|
switch a {
|
|
case "--json":
|
|
output.JSONMode = true
|
|
default:
|
|
remaining = append(remaining, a)
|
|
}
|
|
}
|
|
return remaining
|
|
}
|
|
|
|
func handleLeafOrRun(name string, args []string, run func()) {
|
|
if isHelpFlagOnly(args) {
|
|
fmt.Printf("hf %s\n", name)
|
|
return
|
|
}
|
|
if len(args) > 0 {
|
|
output.Errorf("unknown arguments for %s: %v", name, args)
|
|
}
|
|
run()
|
|
}
|
|
|
|
func handleConfig(args []string) {
|
|
if isHelpFlagOnly(args) {
|
|
runConfigHelp()
|
|
return
|
|
}
|
|
if len(args) == 0 {
|
|
commands.RunConfigShow()
|
|
return
|
|
}
|
|
for i := 0; i < len(args); i++ {
|
|
switch args[i] {
|
|
case "--url":
|
|
if i+1 >= len(args) {
|
|
output.Error("usage: hf config --url <hf-url>")
|
|
}
|
|
commands.RunConfigURL(args[i+1])
|
|
return
|
|
case "--acc-mgr-token":
|
|
if i+1 >= len(args) {
|
|
output.Error("usage: hf config --acc-mgr-token <token>")
|
|
}
|
|
commands.RunConfigAccMgrToken(args[i+1])
|
|
return
|
|
default:
|
|
output.Errorf("unknown config flag: %s", args[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func runConfigHelp() {
|
|
fmt.Println("hf config - View and manage CLI configuration")
|
|
fmt.Println()
|
|
fmt.Println("Usage:")
|
|
fmt.Println(" hf config Show current config")
|
|
fmt.Println(" hf config --url <hf-url> Set HarborForge API URL")
|
|
if !mode.IsPaddedCell() {
|
|
fmt.Println(" hf config --acc-mgr-token <token> Set account-manager token")
|
|
}
|
|
}
|
|
|
|
func handleGroup(group help.Group, args []string) {
|
|
if len(args) == 0 || isHelpFlagOnly(args) {
|
|
fmt.Print(help.RenderGroupHelp(group.Name, group.SubCommands))
|
|
return
|
|
}
|
|
if len(args) == 1 && args[0] == "--help-brief" {
|
|
fmt.Print(help.RenderGroupHelpBrief(group.Name, group.SubCommands))
|
|
return
|
|
}
|
|
|
|
sub, ok := findSubCommand(group, args[0])
|
|
if !ok {
|
|
output.Errorf("unknown %s subcommand: %s", group.Name, args[0])
|
|
}
|
|
|
|
if len(args) > 1 && isHelpFlagOnly(args[1:]) {
|
|
if !sub.Permitted {
|
|
fmt.Println(help.RenderNotPermitted(group.Name, sub.Name))
|
|
return
|
|
}
|
|
fmt.Printf("hf %s %s\n", group.Name, sub.Name)
|
|
return
|
|
}
|
|
|
|
if !sub.Permitted {
|
|
fmt.Println(help.RenderNotPermitted(group.Name, sub.Name))
|
|
return
|
|
}
|
|
|
|
output.Errorf("hf %s %s is recognized but not implemented yet", group.Name, sub.Name)
|
|
}
|
|
|
|
func isHelpFlagOnly(args []string) bool {
|
|
return len(args) == 1 && (args[0] == "--help" || args[0] == "-h")
|
|
}
|
|
|
|
func findGroup(name string) (help.Group, bool) {
|
|
for _, group := range topGroups() {
|
|
if group.Name == name {
|
|
return group, true
|
|
}
|
|
}
|
|
return help.Group{}, false
|
|
}
|
|
|
|
func findSubCommand(group help.Group, name string) (help.Command, bool) {
|
|
for _, cmd := range group.SubCommands {
|
|
if cmd.Name == name {
|
|
return cmd, true
|
|
}
|
|
}
|
|
return help.Command{}, false
|
|
}
|
|
|
|
// topGroups returns the full command tree for help rendering.
|
|
// TODO: permission awareness will be added when auth introspection is available.
|
|
func topGroups() []help.Group {
|
|
return []help.Group{
|
|
{Name: "version", Description: "Show CLI version", Permitted: true},
|
|
{Name: "health", Description: "Check API health", Permitted: true},
|
|
{Name: "config", Description: "View and manage CLI configuration", Permitted: true},
|
|
{
|
|
Name: "user",
|
|
Description: "Manage users",
|
|
Permitted: true,
|
|
SubCommands: []help.Command{
|
|
{Name: "create", Description: "Create a user account (uses account-manager token flow)", Permitted: false},
|
|
{Name: "list", Description: "List users", Permitted: false},
|
|
{Name: "get", Description: "Show a user by username", Permitted: false},
|
|
{Name: "update", Description: "Update a user", Permitted: false},
|
|
{Name: "activate", Description: "Activate a user", Permitted: false},
|
|
{Name: "deactivate", Description: "Deactivate a user", Permitted: false},
|
|
{Name: "delete", Description: "Delete a user", Permitted: false},
|
|
},
|
|
},
|
|
{
|
|
Name: "role",
|
|
Description: "Manage roles and permissions",
|
|
Permitted: true,
|
|
SubCommands: []help.Command{
|
|
{Name: "list", Description: "List roles", Permitted: false},
|
|
{Name: "get", Description: "Show a role by name", Permitted: false},
|
|
{Name: "create", Description: "Create a role", Permitted: false},
|
|
{Name: "update", Description: "Update a role", Permitted: false},
|
|
{Name: "delete", Description: "Delete a role", Permitted: false},
|
|
{Name: "set-permissions", Description: "Replace role permissions", Permitted: false},
|
|
{Name: "add-permissions", Description: "Add permissions to a role", Permitted: false},
|
|
{Name: "remove-permissions", Description: "Remove permissions from a role", Permitted: false},
|
|
},
|
|
},
|
|
{
|
|
Name: "permission",
|
|
Description: "List permissions",
|
|
Permitted: true,
|
|
SubCommands: []help.Command{
|
|
{Name: "list", Description: "List permissions", Permitted: false},
|
|
},
|
|
},
|
|
{
|
|
Name: "project",
|
|
Description: "Manage projects",
|
|
Permitted: true,
|
|
SubCommands: []help.Command{
|
|
{Name: "list", Description: "List projects", Permitted: false},
|
|
{Name: "get", Description: "Show a project by code", Permitted: false},
|
|
{Name: "create", Description: "Create a project", Permitted: false},
|
|
{Name: "update", Description: "Update a project", Permitted: false},
|
|
{Name: "delete", Description: "Delete a project", Permitted: false},
|
|
{Name: "members", Description: "List project members", Permitted: false},
|
|
{Name: "add-member", Description: "Add a project member", Permitted: false},
|
|
{Name: "remove-member", Description: "Remove a project member", Permitted: false},
|
|
},
|
|
},
|
|
{
|
|
Name: "milestone",
|
|
Description: "Manage milestones",
|
|
Permitted: true,
|
|
SubCommands: []help.Command{
|
|
{Name: "list", Description: "List milestones", Permitted: false},
|
|
{Name: "get", Description: "Show a milestone by code", Permitted: false},
|
|
{Name: "create", Description: "Create a milestone", Permitted: false},
|
|
{Name: "update", Description: "Update a milestone", Permitted: false},
|
|
{Name: "delete", Description: "Delete a milestone", Permitted: false},
|
|
{Name: "progress", Description: "Show milestone progress", Permitted: false},
|
|
},
|
|
},
|
|
{
|
|
Name: "task",
|
|
Description: "Manage tasks",
|
|
Permitted: true,
|
|
SubCommands: []help.Command{
|
|
{Name: "list", Description: "List tasks", Permitted: false},
|
|
{Name: "get", Description: "Show a task by code", Permitted: false},
|
|
{Name: "create", Description: "Create a task", Permitted: false},
|
|
{Name: "update", Description: "Update a task", Permitted: false},
|
|
{Name: "transition", Description: "Transition a task to a new status", Permitted: false},
|
|
{Name: "take", Description: "Assign a task to the current user", Permitted: false},
|
|
{Name: "delete", Description: "Delete a task", Permitted: false},
|
|
{Name: "search", Description: "Search tasks", Permitted: false},
|
|
},
|
|
},
|
|
{
|
|
Name: "meeting",
|
|
Description: "Manage meetings",
|
|
Permitted: true,
|
|
SubCommands: []help.Command{
|
|
{Name: "list", Description: "List meetings", Permitted: false},
|
|
{Name: "get", Description: "Show a meeting by code", Permitted: false},
|
|
{Name: "create", Description: "Create a meeting", Permitted: false},
|
|
{Name: "update", Description: "Update a meeting", Permitted: false},
|
|
{Name: "attend", Description: "Attend a meeting", Permitted: false},
|
|
{Name: "delete", Description: "Delete a meeting", Permitted: false},
|
|
},
|
|
},
|
|
{
|
|
Name: "support",
|
|
Description: "Manage support tickets",
|
|
Permitted: true,
|
|
SubCommands: []help.Command{
|
|
{Name: "list", Description: "List support tickets", Permitted: false},
|
|
{Name: "get", Description: "Show a support ticket by code", Permitted: false},
|
|
{Name: "create", Description: "Create a support ticket", Permitted: false},
|
|
{Name: "update", Description: "Update a support ticket", Permitted: false},
|
|
{Name: "take", Description: "Assign a support ticket to the current user", Permitted: false},
|
|
{Name: "transition", Description: "Transition a support ticket to a new status", Permitted: false},
|
|
{Name: "delete", Description: "Delete a support ticket", Permitted: false},
|
|
},
|
|
},
|
|
{
|
|
Name: "propose",
|
|
Description: "Manage proposals",
|
|
Permitted: true,
|
|
SubCommands: []help.Command{
|
|
{Name: "list", Description: "List proposals", Permitted: false},
|
|
{Name: "get", Description: "Show a proposal by code", Permitted: false},
|
|
{Name: "create", Description: "Create a proposal", Permitted: false},
|
|
{Name: "update", Description: "Update a proposal", Permitted: false},
|
|
{Name: "accept", Description: "Accept a proposal", Permitted: false},
|
|
{Name: "reject", Description: "Reject a proposal", Permitted: false},
|
|
{Name: "reopen", Description: "Reopen a proposal", Permitted: false},
|
|
},
|
|
},
|
|
{
|
|
Name: "monitor",
|
|
Description: "Monitor servers and API keys",
|
|
Permitted: true,
|
|
SubCommands: []help.Command{
|
|
{Name: "overview", Description: "Show monitor overview", Permitted: false},
|
|
{Name: "server", Description: "Manage monitor servers", Permitted: false},
|
|
{Name: "api-key", Description: "Manage monitor API keys", Permitted: false},
|
|
},
|
|
},
|
|
}
|
|
}
|