Skip to content

Commit

Permalink
Extract config fetching into its own package (#462)
Browse files Browse the repository at this point in the history
My goal here is to be able to pass my own config implementation when
calling RunBazelisk from code without setting environment variables,
because they cause repository rule cache invalidations.

As a side-effect, it helps towards the TODO in core.go to split
functionality into packages.
  • Loading branch information
illicitonion authored Jun 1, 2023
1 parent a4dca9c commit d0e93d2
Show file tree
Hide file tree
Showing 10 changed files with 353 additions and 247 deletions.
5 changes: 3 additions & 2 deletions bazelisk.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,12 @@ import (

func main() {
gcs := &repositories.GCSRepo{}
gitHub := repositories.CreateGitHubRepo(core.GetEnvOrConfig("BAZELISK_GITHUB_TOKEN"))
config := core.MakeDefaultConfig()
gitHub := repositories.CreateGitHubRepo(config.Get("BAZELISK_GITHUB_TOKEN"))
// Fetch LTS releases, release candidates, rolling releases and Bazel-at-commits from GCS, forks from GitHub.
repos := core.CreateRepositories(gcs, gcs, gitHub, gcs, gcs, true)

exitCode, err := core.RunBazelisk(os.Args[1:], repos)
exitCode, err := core.RunBazeliskWithArgsFuncAndConfig(func(string) []string { return os.Args[1:] }, repos, config)
if err != nil {
log.Fatal(err)
}
Expand Down
12 changes: 12 additions & 0 deletions config/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")

go_library(
name = "go_default_library",
srcs = ["config.go"],
importpath = "github.com/bazelbuild/bazelisk/config",
visibility = ["//visibility:public"],
deps = [
"//ws:go_default_library",
"@com_github_mitchellh_go_homedir//:go_default_library",
],
)
130 changes: 130 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package config

import (
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/bazelbuild/bazelisk/ws"
)

const rcFileName = ".bazeliskrc"

// Config allows getting Bazelisk configuration values.
type Config interface {
Get(name string) string
}

// FromEnv returns a Config which gets config values from environment variables.
func FromEnv() Config {
return &fromEnv{}
}

type fromEnv struct{}

func (c *fromEnv) Get(name string) string {
return os.Getenv(name)
}

// FromFile returns a Config which gets config values from a Bazelisk config file.
func FromFile(path string) (Config, error) {
values, err := parseFileConfig(path)
if err != nil {
return nil, err
}
return &static{
values: values,
}, nil
}

type static struct {
values map[string]string
}

func (c *static) Get(name string) string {
return c.values[name]
}

// parseFileConfig parses a .bazeliskrc file as a map of key-value configuration values.
func parseFileConfig(rcFilePath string) (map[string]string, error) {
config := make(map[string]string)

contents, err := ioutil.ReadFile(rcFilePath)
if err != nil {
if os.IsNotExist(err) {
// Non-critical error.
return config, nil
}
return nil, err
}

for _, line := range strings.Split(string(contents), "\n") {
if strings.HasPrefix(line, "#") {
// comments
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) < 2 {
continue
}
key := strings.TrimSpace(parts[0])
config[key] = strings.TrimSpace(parts[1])
}

return config, nil
}

// LocateUserConfigFile locates a .bazeliskrc file in the user's home directory.
func LocateUserConfigFile() (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, rcFileName), nil
}

// LocateWorkspaceConfigFile locates a .bazeliskrc file in the current workspace root.
func LocateWorkspaceConfigFile() (string, error) {
workingDirectory, err := os.Getwd()
if err != nil {
return "", err
}
workspaceRoot := ws.FindWorkspaceRoot(workingDirectory)
if workspaceRoot == "" {
return "", err
}
return filepath.Join(workspaceRoot, rcFileName), nil
}

// Layered returns a Config which gets config values from the first of a series of other Config values which sets the config.
func Layered(configs ...Config) Config {
return &layered{
configs: configs,
}
}

type layered struct {
configs []Config
}

func (c *layered) Get(name string) string {
for _, config := range c.configs {
if value := config.Get(name); value != "" {
return value
}
}
return ""
}

// Null returns a Config with no config values.
func Null() Config {
return &static{}
}

// Static returns a Config with static values.
func Static(values map[string]string) Config {
return &static{
values: values,
}
}
5 changes: 5 additions & 0 deletions core/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ go_library(
visibility = ["//visibility:public"],
x_defs = {"BazeliskVersion": "{STABLE_VERSION}"},
deps = [
"//config:go_default_library",
"//httputil:go_default_library",
"//platforms:go_default_library",
"//versions:go_default_library",
"//ws:go_default_library",
"@com_github_mitchellh_go_homedir//:go_default_library",
],
)
Expand All @@ -24,4 +26,7 @@ go_test(
"repositories_test.go",
],
embed = [":go_default_library"],
deps = [
"//config:go_default_library",
],
)
Loading

0 comments on commit d0e93d2

Please sign in to comment.