Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 27 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The Boot.dev CLI requires an up-to-date Golang installation, and only works on L

**Option 1**: [The webi installer](https://webinstall.dev/golang/) is the simplest way for most people. Just run this in your terminal:

```bash
```sh
curl -sS https://webi.sh/golang | sh
```

Expand All @@ -38,14 +38,14 @@ Run `go version` on your command line to make sure the installation worked. If i

You can ensure it exists by attempting to run `go` using its full filepath. For example, if you think it's in `~/.local/opt/go/bin`, you can run `~/.local/opt/go/bin/go version`. If that works, then you just need to add `~/.local/opt/go/bin` to your `PATH` and reload your shell:

```bash
```sh
# For Linux/WSL
echo 'export PATH=$PATH:$HOME/.local/opt/go/bin' >> ~/.bashrc
# next, reload your shell configuration
source ~/.bashrc
```

```bash
```sh
# For Mac OS
echo 'export PATH=$PATH:$HOME/.local/opt/go/bin' >> ~/.zshrc
# next, reload your shell configuration
Expand All @@ -56,7 +56,7 @@ source ~/.zshrc

This command will download, build, and install the `bootdev` command into your Go toolchain's `bin` directory. Go ahead and run it:

```bash
```sh
go install github.com/bootdotdev/bootdev@latest
```

Expand All @@ -66,14 +66,14 @@ Run `bootdev --version` on your command line to make sure the installation worke

If you're getting a "command not found" error for `bootdev help`, it's most likely because the directory containing the `bootdev` program isn't in your [`PATH`](https://opensource.com/article/17/6/set-path-linux). You need to add the directory to your `PATH` by modifying your shell's configuration file. You probably need to add `$HOME/go/bin` (the default `GOBIN` directory where `go` installs programs) to your `PATH`:

```bash
```sh
# For Linux/WSL
echo 'export PATH=$PATH:$HOME/go/bin' >> ~/.bashrc
# next, reload your shell configuration
source ~/.bashrc
```

```bash
```sh
# For Mac OS
echo 'export PATH=$PATH:$HOME/go/bin' >> ~/.zshrc
# next, reload your shell configuration
Expand All @@ -86,7 +86,7 @@ Run `bootdev login` to authenticate with your Boot.dev account. After authentica

## Configuration

The Boot.dev CLI offers a couple of configuration options that are stored in a config file (default is `~/.bootdev.yaml`).
The Boot.dev CLI offers a couple of configuration options that are stored in a config file (default is `~/.bootdev.yaml`, or `$XDG_CONFIG_HOME/bootdev/config.yaml` if `XDG_CONFIG_HOME` is set).

All commands have `-h`/`--help` flags if you want to see available options on the command line.

Expand All @@ -96,44 +96,44 @@ For lessons with HTTP tests, you can configure the CLI with a base URL that over

- To set the base URL run:

```bash
bootdev config base_url <url>
```
```sh
bootdev config base_url <url>
```

_Make sure you include the protocol scheme (`http://`) in the URL._
_Make sure you include the protocol scheme (`http://`) in the URL._

- To get the current base URL (the default is an empty string), run:

```bash
bootdev config base_url
```
```sh
bootdev config base_url
```

- To reset the base URL and revert to using the lessons' defaults, run:

```bash
bootdev config base_url --reset
```
```sh
bootdev config base_url --reset
```

### CLI colors

The CLI text output is rendered with extra colors: green (e.g., success messages), red (e.g., error messages), and gray (e.g., secondary text).

- To customize these colors, run:

```bash
bootdev config colors --red <value> --green <value> --gray <value>
```
```sh
bootdev config colors --red <value> --green <value> --gray <value>
```

_You can use an [ANSI color code](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) or a hex string as the `<value>`._
_You can use an [ANSI color code](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) or a hex string as the `<value>`._

- To get the current colors, run:

```bash
bootdev config colors
```
```sh
bootdev config colors
```

- To reset the colors to their default values, run:

```bash
bootdev config colors --reset
```
```sh
bootdev config colors --reset
```
2 changes: 1 addition & 1 deletion client/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ func fetchWithAuth(method string, url string) ([]byte, error) {
return nil, err
}
if code == 402 {
return nil, fmt.Errorf("To run and submit the tests for this lesson, you must have an active Boot.dev membership\nhttps://boot.dev/pricing")
return nil, fmt.Errorf("to run and submit the tests for this lesson, you must have an active Boot.dev membership\nhttps://boot.dev/pricing")
}
if code != 200 {
return nil, fmt.Errorf("failed to %s to %s\nResponse: %d %s", method, url, code, string(body))
Expand Down
2 changes: 1 addition & 1 deletion client/lessons.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func SubmitCLILesson(uuid string, results []CLIStepResult) (*VerificationResultS
return nil, err
}
if code == 402 {
return nil, fmt.Errorf("To run and submit the tests for this lesson, you must have an active Boot.dev membership\nhttps://boot.dev/pricing")
return nil, fmt.Errorf("to run and submit the tests for this lesson, you must have an active Boot.dev membership\nhttps://boot.dev/pricing")
}
if code != 200 {
return nil, fmt.Errorf("failed to submit CLI lesson (code %v): %s", code, string(resp))
Expand Down
58 changes: 39 additions & 19 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"context"
"fmt"
"os"
"path"
"path/filepath"
"time"

api "github.com/bootdotdev/bootdev/client"
Expand Down Expand Up @@ -34,14 +34,13 @@ func Execute(currentVersion string) error {

func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default $HOME/.bootdev.yaml)")
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default $HOME/.bootdev.yaml or $XDG_CONFIG_HOME/bootdev/config.yaml)")
}

func readViperConfig(paths []string) error {
for _, path := range paths {
_, err := os.Stat(path)
if err == nil {
viper.SetConfigFile(path)
for _, p := range paths {
if _, err := os.Stat(p); err == nil {
viper.SetConfigFile(p)
break
}
}
Expand All @@ -57,24 +56,45 @@ func initConfig() {
viper.SetDefault("last_refresh", 0)
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
err := viper.ReadInConfig()
cobra.CheckErr(err)
viper.SetConfigFile(filepath.Clean(cfgFile))
cobra.CheckErr(viper.ReadInConfig())
} else {
// Find home directory.
// find home dir
home, err := os.UserHomeDir()
cobra.CheckErr(err)

// viper's built in config path thing sucks, let's do it ourselves
defaultPath := path.Join(home, ".bootdev.yaml")
configPaths := []string{}
configPaths = append(configPaths, path.Join(home, ".config", "bootdev", "config.yaml"))
configPaths = append(configPaths, defaultPath)
// collect paths where existing config files may be located
var configPaths []string

// first check XDG_CONFIG_HOME if set
xdgConfigHome := os.Getenv("XDG_CONFIG_HOME")
var xdgEnvPath string
if xdgConfigHome != "" {
xdgEnvPath = filepath.Join(xdgConfigHome, "bootdev", "config.yaml")
configPaths = append(configPaths, xdgEnvPath)
}

// then check legacy hard-coded "XDG" path, then home dotfile
xdgLegacyPath := filepath.Join(home, ".config", "bootdev", "config.yaml")
homeDotfilePath := filepath.Join(home, ".bootdev.yaml")

configPaths = append(configPaths, xdgLegacyPath)
configPaths = append(configPaths, homeDotfilePath)

if err := readViperConfig(configPaths); err != nil {
viper.SafeWriteConfigAs(defaultPath)
viper.SetConfigFile(defaultPath)
err = viper.ReadInConfig()
cobra.CheckErr(err)
// no existing config found; try to create a new one
// respect XDG_CONFIG_HOME if set, otherwise use dotfile in home dir
var newConfigPath string
if xdgEnvPath != "" {
newConfigPath = xdgEnvPath
cobra.CheckErr(os.MkdirAll(filepath.Dir(newConfigPath), 0o755))
} else {
newConfigPath = homeDotfilePath
}

cobra.CheckErr(viper.SafeWriteConfigAs(newConfigPath))
viper.SetConfigFile(newConfigPath)
cobra.CheckErr(viper.ReadInConfig())
}
}

Expand Down