Spaces:
Paused
Paused
| // Copyright 2026 Woodpecker Authors | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package context | |
| import ( | |
| "context" | |
| "fmt" | |
| "os" | |
| "github.com/rs/zerolog/log" | |
| "github.com/urfave/cli/v3" | |
| "go.woodpecker-ci.org/woodpecker/v3/cli/common" | |
| "go.woodpecker-ci.org/woodpecker/v3/cli/internal/config" | |
| "go.woodpecker-ci.org/woodpecker/v3/cli/output" | |
| ) | |
| // Command exports the context command set. | |
| var Command = &cli.Command{ | |
| Name: "context", | |
| Aliases: []string{"ctx"}, | |
| Usage: "manage contexts", | |
| Description: "Contexts can be used to manage users on one or multiple servers.\nTo create a new context run the setup command", | |
| Commands: []*cli.Command{ | |
| listCommand, | |
| useCommand, | |
| deleteCommand, | |
| renameCommand, | |
| }, | |
| } | |
| var listCommand = &cli.Command{ | |
| Name: "list", | |
| Aliases: []string{"ls"}, | |
| Usage: "list all contexts", | |
| Flags: append(common.OutputFlags("table"), []cli.Flag{ | |
| &cli.BoolFlag{ | |
| Name: "output-no-headers", | |
| Usage: "do not print headers in output", | |
| }, | |
| }...), | |
| Action: listContexts, | |
| } | |
| var useCommand = &cli.Command{ | |
| Name: "use", | |
| Usage: "set the current context", | |
| ArgsUsage: "<context-name>", | |
| Action: useContext, | |
| } | |
| var deleteCommand = &cli.Command{ | |
| Name: "delete", | |
| Aliases: []string{"rm"}, | |
| Usage: "delete a context", | |
| ArgsUsage: "<context-name>", | |
| Action: deleteContext, | |
| } | |
| var renameCommand = &cli.Command{ | |
| Name: "rename", | |
| Usage: "rename a context", | |
| ArgsUsage: "<old-name> <new-name>", | |
| Action: renameContext, | |
| } | |
| func listContexts(_ context.Context, c *cli.Command) error { | |
| contexts, err := config.LoadContexts() | |
| if err != nil { | |
| return err | |
| } | |
| if len(contexts.Contexts) == 0 { | |
| fmt.Println("No contexts found. Run 'woodpecker-cli setup' to create one.") | |
| return nil | |
| } | |
| _, outOpt := output.ParseOutputOptions(c.String("output")) | |
| out := os.Stdout | |
| noHeader := c.Bool("output-no-headers") | |
| table := output.NewTable(out) | |
| // Add custom field mapping | |
| table.AddFieldFn("Name", func(obj any) string { | |
| c, ok := obj.(config.Context) | |
| if !ok { | |
| return "???" | |
| } | |
| if contexts.CurrentContext == c.Name { | |
| return c.Name + " *" | |
| } | |
| return c.Name | |
| }) | |
| table.AddFieldAlias("ServerURL", "Server URL") | |
| table.AddFieldAlias("LogLevel", "Log Level") | |
| table.AddFieldAlias("Name", "Name (selected)") | |
| cols := []string{"Name (selected)", "Server URL"} | |
| if len(outOpt) > 0 { | |
| cols = outOpt | |
| } | |
| if !noHeader { | |
| table.WriteHeader(cols) | |
| } | |
| for _, c := range contexts.Contexts { | |
| if err := table.Write(cols, c); err != nil { | |
| return err | |
| } | |
| } | |
| return table.Flush() | |
| } | |
| func useContext(_ context.Context, c *cli.Command) error { | |
| contextName := c.Args().First() | |
| if contextName == "" { | |
| return fmt.Errorf("context name is required") | |
| } | |
| err := config.SetCurrentContext(contextName) | |
| if err != nil { | |
| return err | |
| } | |
| log.Info().Msgf("Switched to context '%s'", contextName) | |
| return nil | |
| } | |
| func deleteContext(_ context.Context, c *cli.Command) error { | |
| contextName := c.Args().First() | |
| if contextName == "" { | |
| return fmt.Errorf("context name is required") | |
| } | |
| err := config.DeleteContext(c, contextName) | |
| if err != nil { | |
| return err | |
| } | |
| log.Info().Msgf("Context '%s' deleted", contextName) | |
| return nil | |
| } | |
| func renameContext(_ context.Context, c *cli.Command) error { | |
| if c.Args().Len() < 2 { //nolint:mnd // min args | |
| return fmt.Errorf("both old name and new name are required") | |
| } | |
| oldName := c.Args().Get(0) | |
| newName := c.Args().Get(1) | |
| err := config.RenameContext(oldName, newName) | |
| if err != nil { | |
| return err | |
| } | |
| log.Info().Msgf("Context renamed from '%s' to '%s'", oldName, newName) | |
| return nil | |
| } | |