Skip to content

Commit 5bd59b8

Browse files
authored
✨ Show org in prompt (#442)
1 parent dfc5722 commit 5bd59b8

File tree

5 files changed

+188
-1
lines changed

5 files changed

+188
-1
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ Use "bk [command] --help" for more information about a command.
5757

5858
You'll need to run `bk configure` first to set up your organization and API token.
5959

60+
### Shell Prompt Integration
61+
62+
Want to display your current Buildkite organization in your shell prompt? Check out our [Shell Prompt Integration Guide](/docs/shell-prompt-integration.md) for detailed instructions for Zsh, Bash, and Powerlevel10k.
63+
6064
## 💬 Feedback
6165

6266
We'd love to hear any feedback and questions you might have. Please [file an issue on GitHub](https://github.com/buildkite/cli/issues) and let us know!

docs/images/prompt.png

675 KB
Loading

docs/shell-prompt-integration.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
### Shell Prompt Integration
2+
3+
The Buildkite CLI offers a shell prompt integration that displays your current Buildkite organization directly in your prompt.
4+
5+
![bk cli prompt](./images/prompt.png)
6+
7+
#### Zsh (Vanilla)
8+
9+
1. Create a prompt function in `~/.buildkite/zsh_prompt.zsh`:
10+
11+
```zsh
12+
_buildkite_ps1() {
13+
local org=$(bk use 2>&1 | grep "Using configuration for" | sed -E "s/Using configuration for \`(.*)\`/\1/")
14+
if [[ -n "$org" ]]; then
15+
echo -n " (bk:$org)"
16+
fi
17+
}
18+
19+
# Modify your existing prompt to include the Buildkite organization
20+
PROMPT='%n@%m %1~$(_buildkite_ps1)%# '
21+
```
22+
23+
2. Source the script in your `.zshrc`:
24+
25+
```zsh
26+
source $HOME/.buildkite/zsh_prompt.zsh
27+
```
28+
29+
#### Zsh (Powerlevel10k)
30+
31+
1. Add the following function to `~/.buildkite/zsh_prompt.zsh`:
32+
33+
```zsh
34+
_buildkite_ps1() {
35+
# Cache the prompt output for 5 seconds to avoid running bk too frequently
36+
if [[ -z "$BK_PROMPT_CACHE" ]] || [[ $(($EPOCHSECONDS % 5)) -eq 0 ]]; then
37+
local org=$(bk use 2>&1 | grep "Using configuration for" | sed -E "s/Using configuration for \`(.*)\`/\1/")
38+
if [[ -n "$org" ]]; then
39+
BK_PROMPT_CACHE="%F{magenta}(bk:$org)%f"
40+
else
41+
BK_PROMPT_CACHE="%F{yellow}(bk:not configured)%f"
42+
fi
43+
fi
44+
echo -n "$BK_PROMPT_CACHE"
45+
}
46+
47+
# Wrap the bk command to clear prompt cache when switching orgs
48+
bk() {
49+
command bk "$@"
50+
if [[ "$1" == "use" ]]; then
51+
unset BK_PROMPT_CACHE
52+
fi
53+
}
54+
```
55+
56+
2. Source this script in your `.zshrc`:
57+
58+
```zsh
59+
source $HOME/.buildkite/zsh_prompt.zsh
60+
```
61+
62+
3. Add the Buildkite organization to your prompt elements in `~/.p10k.zsh`:
63+
64+
```zsh
65+
typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
66+
# ... other existing elements
67+
buildkite_org
68+
)
69+
```
70+
71+
#### Bash
72+
73+
1. Create a prompt function in `~/.buildkite/bash_prompt.sh`:
74+
75+
```bash
76+
_buildkite_ps1() {
77+
local org=$(bk use 2>&1 | grep "Using configuration for" | sed -E "s/Using configuration for \`(.*)\`/\1/")
78+
if [[ -n "$org" ]]; then
79+
echo -n " (bk:$org)"
80+
fi
81+
}
82+
83+
# Modify your PS1 to include the Buildkite organization
84+
export PS1='\u@\h \w$(_buildkite_ps1)\$ '
85+
```
86+
87+
2. Source the script in your `.bashrc`:
88+
89+
```bash
90+
source $HOME/.buildkite/bash_prompt.sh
91+
```
92+
93+
#### Features
94+
95+
- Displays current Buildkite organization in your shell prompt
96+
- Caches organization info to minimize performance impact
97+
- Works across different projects and directories
98+
- Supports quick organization switching with `bk use`
99+
100+
#### Troubleshooting
101+
102+
- Ensure you've run `bk configure` to set up your organization
103+
- Verify the `.bk.yaml` in your project's root directory
104+
- Check that you're using a locally built `bk` binary in development projects
105+
106+
#### Performance Considerations
107+
108+
The prompt integration uses a lightweight method to retrieve the current organization. However, to minimize any potential performance impact:
109+
- The script caches the organization name
110+
- The command is only run periodically or when switching organizations
111+
- You can customize the caching mechanism if needed

pkg/cmd/prompt/prompt.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package prompt
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"strings"
7+
8+
"github.com/buildkite/cli/v3/pkg/cmd/factory"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
func NewCmdPrompt(f *factory.Factory) *cobra.Command {
13+
var format string
14+
var shellType string
15+
16+
cmd := &cobra.Command{
17+
Use: "prompt",
18+
Hidden: true, // Hide from general help as it's meant for shell integration
19+
Short: "Print shell prompt integration",
20+
RunE: func(cmd *cobra.Command, args []string) error {
21+
org := f.Config.OrganizationSlug()
22+
if org == "" {
23+
return nil // No org configured, return empty
24+
}
25+
26+
// Get token scopes to potentially show warnings
27+
scopes := f.Config.GetTokenScopes()
28+
var warnings []string
29+
if len(scopes) < 3 { // Example threshold
30+
warnings = append(warnings, "!")
31+
}
32+
33+
// Format the prompt based on shell type
34+
switch shellType {
35+
case "bash":
36+
if format == "" {
37+
format = "\\[\\033[35m\\](bk:%s%s)\\[\\033[0m\\]" // Purple color by default
38+
}
39+
fmt.Printf(format, org, strings.Join(warnings, ""))
40+
case "zsh":
41+
if format == "" {
42+
format = "%%F{magenta}(bk:%s%s)%%f"
43+
}
44+
fmt.Printf(format, org, strings.Join(warnings, ""))
45+
case "fish":
46+
if format == "" {
47+
format = "set_color magenta;echo -n '(bk:%s%s)';set_color normal"
48+
}
49+
fmt.Printf(format, org, strings.Join(warnings, ""))
50+
}
51+
52+
return nil
53+
},
54+
}
55+
56+
cmd.Flags().StringVar(&format, "format", "", "Custom format string for the prompt")
57+
cmd.Flags().StringVar(&shellType, "shell", detectShell(), "Shell type (bash, zsh, or fish)")
58+
59+
return cmd
60+
}
61+
62+
func detectShell() string {
63+
shell := os.Getenv("SHELL")
64+
if strings.Contains(shell, "zsh") {
65+
return "zsh"
66+
} else if strings.Contains(shell, "fish") {
67+
return "fish"
68+
}
69+
return "bash"
70+
}

pkg/cmd/root/root.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
jobCmd "github.com/buildkite/cli/v3/pkg/cmd/job"
1616
pipelineCmd "github.com/buildkite/cli/v3/pkg/cmd/pipeline"
1717
packageCmd "github.com/buildkite/cli/v3/pkg/cmd/pkg"
18+
promptCmd "github.com/buildkite/cli/v3/pkg/cmd/prompt"
1819
useCmd "github.com/buildkite/cli/v3/pkg/cmd/use"
1920
"github.com/buildkite/cli/v3/pkg/cmd/user"
2021
versionCmd "github.com/buildkite/cli/v3/pkg/cmd/version"
@@ -52,8 +53,9 @@ func NewCmdRoot(f *factory.Factory) (*cobra.Command, error) {
5253
cmd.AddCommand(configureCmd.NewCmdConfigure(f))
5354
cmd.AddCommand(initCmd.NewCmdInit(f))
5455
cmd.AddCommand(jobCmd.NewCmdJob(f))
55-
cmd.AddCommand(pipelineCmd.NewCmdPipeline(f))
5656
cmd.AddCommand(packageCmd.NewCmdPackage(f))
57+
cmd.AddCommand(pipelineCmd.NewCmdPipeline(f))
58+
cmd.AddCommand(promptCmd.NewCmdPrompt(f))
5759
cmd.AddCommand(useCmd.NewCmdUse(f))
5860
cmd.AddCommand(user.CommandUser(f))
5961
cmd.AddCommand(versionCmd.NewCmdVersion(f))

0 commit comments

Comments
 (0)