Skip to content

Commit

Permalink
Merge pull request #3000 from buildkite/fix-homedir
Browse files Browse the repository at this point in the history
Prefer $HOME on all platforms
  • Loading branch information
DrJosh9000 authored Sep 17, 2024
2 parents 4c4e729 + 6a6dfa0 commit b00fade
Show file tree
Hide file tree
Showing 16 changed files with 98 additions and 37 deletions.
6 changes: 3 additions & 3 deletions clicommand/agent_start.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
"github.com/buildkite/agent/v3/internal/experiments"
"github.com/buildkite/agent/v3/internal/job/hook"
"github.com/buildkite/agent/v3/internal/job/shell"
"github.com/buildkite/agent/v3/internal/utils"
"github.com/buildkite/agent/v3/internal/osutil"
"github.com/buildkite/agent/v3/logger"
"github.com/buildkite/agent/v3/metrics"
"github.com/buildkite/agent/v3/process"
Expand Down Expand Up @@ -1133,7 +1133,7 @@ var AgentStartCommand = cli.Command{

// confirm the BuildPath is exists. The bootstrap is going to write to it when a job executes,
// so we may as well check that'll work now and fail early if it's a problem
if !utils.FileExists(agentConf.BuildPath) {
if !osutil.FileExists(agentConf.BuildPath) {
l.Info("Build Path doesn't exist, creating it (%s)", agentConf.BuildPath)
// Actual file permissions will be reduced by umask, and won't be 0777 unless the user has manually changed the umask to 000
if err := os.MkdirAll(agentConf.BuildPath, 0o777); err != nil {
Expand Down Expand Up @@ -1383,7 +1383,7 @@ func agentLifecycleHook(hookName string, log logger.Logger, cfg AgentStartConfig
}

func defaultSocketsPath() string {
home, err := os.UserHomeDir()
home, err := osutil.UserHomeDir()
if err != nil {
return filepath.Join(os.TempDir(), "buildkite-sockets")
}
Expand Down
4 changes: 2 additions & 2 deletions cliconfig/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"os"
"strings"

"github.com/buildkite/agent/v3/internal/utils"
"github.com/buildkite/agent/v3/internal/osutil"
)

type File struct {
Expand Down Expand Up @@ -60,7 +60,7 @@ func (f *File) Load() error {
}

func (f File) AbsolutePath() (string, error) {
return utils.NormalizeFilePath(f.Path)
return osutil.NormalizeFilePath(f.Path)
}

func (f File) Exists() bool {
Expand Down
6 changes: 3 additions & 3 deletions cliconfig/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"strings"
"time"

"github.com/buildkite/agent/v3/internal/utils"
"github.com/buildkite/agent/v3/internal/osutil"
"github.com/buildkite/agent/v3/logger"
"github.com/oleiade/reflections"
"github.com/urfave/cli"
Expand Down Expand Up @@ -372,7 +372,7 @@ func (l Loader) normalizeField(fieldName string, normalization string) error {

// Normalize the field to be a filepath
if valueAsString, ok := value.(string); ok {
normalizedPath, err := utils.NormalizeFilePath(valueAsString)
normalizedPath, err := osutil.NormalizeFilePath(valueAsString)
if err != nil {
return err
}
Expand All @@ -392,7 +392,7 @@ func (l Loader) normalizeField(fieldName string, normalization string) error {

// Normalize the field to be a command
if valueAsString, ok := value.(string); ok {
normalizedCommandPath, err := utils.NormalizeCommand(valueAsString)
normalizedCommandPath, err := osutil.NormalizeCommand(valueAsString)
if err != nil {
return err
}
Expand Down
16 changes: 8 additions & 8 deletions internal/job/checkout.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (

"github.com/buildkite/agent/v3/internal/experiments"
"github.com/buildkite/agent/v3/internal/job/shell"
"github.com/buildkite/agent/v3/internal/utils"
"github.com/buildkite/agent/v3/internal/osutil"
"github.com/buildkite/agent/v3/tracetools"
"github.com/buildkite/roko"
)
Expand Down Expand Up @@ -80,7 +80,7 @@ func (e *Executor) removeCheckoutDir() error {
func (e *Executor) createCheckoutDir() error {
checkoutPath, _ := e.shell.Env.Get("BUILDKITE_BUILD_CHECKOUT_PATH")

if !utils.FileExists(checkoutPath) {
if !osutil.FileExists(checkoutPath) {
e.shell.Commentf("Creating \"%s\"", checkoutPath)
// Actual file permissions will be reduced by umask, and won't be 0777 unless the user has manually changed the umask to 000
if err := os.MkdirAll(checkoutPath, 0777); err != nil {
Expand Down Expand Up @@ -258,7 +258,7 @@ func (e *Executor) CheckoutPhase(ctx context.Context) error {
}

func hasGitSubmodules(sh *shell.Shell) bool {
return utils.FileExists(filepath.Join(sh.Getwd(), ".gitmodules"))
return osutil.FileExists(filepath.Join(sh.Getwd(), ".gitmodules"))
}

func hasGitCommit(ctx context.Context, sh *shell.Shell, gitDir string, commit string) bool {
Expand All @@ -283,7 +283,7 @@ func (e *Executor) updateGitMirror(ctx context.Context, repository string) (stri
isMainRepository := repository == e.Repository

// Create the mirrors path if it doesn't exist
if baseDir := filepath.Dir(mirrorDir); !utils.FileExists(baseDir) {
if baseDir := filepath.Dir(mirrorDir); !osutil.FileExists(baseDir) {
e.shell.Commentf("Creating \"%s\"", baseDir)
// Actual file permissions will be reduced by umask, and won't be 0777 unless the user has manually changed the umask to 000
if err := os.MkdirAll(baseDir, 0777); err != nil {
Expand All @@ -309,7 +309,7 @@ func (e *Executor) updateGitMirror(ctx context.Context, repository string) (stri
defer mirrorCloneLock.Unlock()

// If we don't have a mirror, we need to clone it
if !utils.FileExists(mirrorDir) {
if !osutil.FileExists(mirrorDir) {
e.shell.Commentf("Cloning a mirror of the repository to %q", mirrorDir)
flags := "--mirror " + e.GitCloneMirrorFlags
if err := gitClone(ctx, e.shell, flags, repository, mirrorDir); err != nil {
Expand Down Expand Up @@ -455,7 +455,7 @@ func (e *Executor) getOrUpdateMirrorDir(ctx context.Context, repository string)
e.shell.Commentf("Skipping update and using existing mirror for repository %s at %s.", repository, mirrorDir)

// Check if specified mirrorDir exists, otherwise the clone will fail.
if !utils.FileExists(mirrorDir) {
if !osutil.FileExists(mirrorDir) {
// Fall back to a clean clone, rather than failing the clone and therefore the build
e.shell.Commentf("No existing mirror found for repository %s at %s.", repository, mirrorDir)
mirrorDir = ""
Expand Down Expand Up @@ -507,7 +507,7 @@ func (e *Executor) defaultCheckoutPhase(ctx context.Context) error {

// Does the git directory exist?
existingGitDir := filepath.Join(e.shell.Getwd(), ".git")
if utils.FileExists(existingGitDir) {
if osutil.FileExists(existingGitDir) {
// Update the origin of the repository so we can gracefully handle
// repository renames
if _, err := e.updateRemoteURL(ctx, "", e.Repository); err != nil {
Expand Down Expand Up @@ -647,7 +647,7 @@ func (e *Executor) defaultCheckoutPhase(ctx context.Context) error {

// Tests use a local temp path for the repository, real repositories don't. Handle both.
var repositoryPath string
if !utils.FileExists(repository) {
if !osutil.FileExists(repository) {
repositoryPath = filepath.Join(e.ExecutorConfig.GitMirrorsPath, dirForRepository(repository))
} else {
repositoryPath = repository
Expand Down
12 changes: 6 additions & 6 deletions internal/job/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ import (
"github.com/buildkite/agent/v3/internal/file"
"github.com/buildkite/agent/v3/internal/job/hook"
"github.com/buildkite/agent/v3/internal/job/shell"
"github.com/buildkite/agent/v3/internal/osutil"
"github.com/buildkite/agent/v3/internal/redact"
"github.com/buildkite/agent/v3/internal/replacer"
"github.com/buildkite/agent/v3/internal/shellscript"
"github.com/buildkite/agent/v3/internal/tempfile"
"github.com/buildkite/agent/v3/internal/utils"
"github.com/buildkite/agent/v3/kubernetes"
"github.com/buildkite/agent/v3/process"
"github.com/buildkite/agent/v3/tracetools"
Expand Down Expand Up @@ -338,7 +338,7 @@ func (e *Executor) executeHook(ctx context.Context, hookCfg HookConfig) error {
}
hookName += " " + hookCfg.Name

if !utils.FileExists(hookCfg.Path) {
if !osutil.FileExists(hookCfg.Path) {
if e.Debug {
e.shell.Commentf("Skipping %s hook, no script at \"%s\"", hookName, hookCfg.Path)
}
Expand Down Expand Up @@ -420,7 +420,7 @@ func logOpenedHookInfo(l shell.Logger, debug bool, hookName, path string) {
} else {
l.Errorf("The %s hook failed to run the %s process has the hook file open", hookName, procPath)
}
case utils.FileExists("/dev/fd"):
case osutil.FileExists("/dev/fd"):
isOpened, err := file.IsOpened(l, debug, path)
if err == nil {
if isOpened {
Expand Down Expand Up @@ -715,7 +715,7 @@ func dirForRepository(repository string) string {

// Given a repository, it will add the host to the set of SSH known_hosts on the machine
func addRepositoryHostToSSHKnownHosts(ctx context.Context, sh *shell.Shell, repository string) {
if utils.FileExists(repository) {
if osutil.FileExists(repository) {
return
}

Expand Down Expand Up @@ -965,7 +965,7 @@ func (e *Executor) defaultCommandPhase(ctx context.Context) error {

scriptFileName := strings.Replace(e.Command, "\n", "", -1)
pathToCommand, err := filepath.Abs(filepath.Join(e.shell.Getwd(), scriptFileName))
commandIsScript := err == nil && utils.FileExists(pathToCommand)
commandIsScript := err == nil && osutil.FileExists(pathToCommand)
span.AddAttributes(map[string]string{"hook.command": pathToCommand})

// If the command isn't a script, then it's something we need
Expand Down Expand Up @@ -1039,7 +1039,7 @@ func (e *Executor) defaultCommandPhase(ctx context.Context) error {
// shouldn't be vulnerable to this!
if e.ExecutorConfig.CommandEval {
// Make script executable
if err = utils.ChmodExecutable(pathToCommand); err != nil {
if err = osutil.ChmodExecutable(pathToCommand); err != nil {
e.shell.Warningf("Error marking script %q as executable: %v", pathToCommand, err)
return err
}
Expand Down
4 changes: 2 additions & 2 deletions internal/job/hook/hook.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"runtime"

"github.com/buildkite/agent/v3/internal/job/shell"
"github.com/buildkite/agent/v3/internal/utils"
"github.com/buildkite/agent/v3/internal/osutil"
)

// Find returns the absolute path to the best matching hook file in a path, or
Expand All @@ -23,7 +23,7 @@ func Find(hookDir string, name string) (string, error) {
}
}
// otherwise chech for th default shell script
if p := filepath.Join(hookDir, name); utils.FileExists(p) {
if p := filepath.Join(hookDir, name); osutil.FileExists(p) {
return p, nil
}
// Don't wrap os.ErrNotExist without checking callers handle it.
Expand Down
3 changes: 2 additions & 1 deletion internal/job/knownhosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"time"

"github.com/buildkite/agent/v3/internal/job/shell"
"github.com/buildkite/agent/v3/internal/osutil"
"golang.org/x/crypto/ssh/knownhosts"
)

Expand All @@ -19,7 +20,7 @@ type knownHosts struct {
}

func findKnownHosts(sh *shell.Shell) (*knownHosts, error) {
userHomePath, err := os.UserHomeDir()
userHomePath, err := osutil.UserHomeDir()
if err != nil {
return nil, fmt.Errorf("Could not find the current users home directory (%s)", err)
}
Expand Down
8 changes: 4 additions & 4 deletions internal/job/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (

"github.com/buildkite/agent/v3/agent/plugin"
"github.com/buildkite/agent/v3/internal/job/hook"
"github.com/buildkite/agent/v3/internal/utils"
"github.com/buildkite/agent/v3/internal/osutil"
"github.com/buildkite/roko"
)

Expand Down Expand Up @@ -162,7 +162,7 @@ func (e *Executor) VendoredPluginPhase(ctx context.Context) error {
return fmt.Errorf("Failed to resolve vendored plugin path for plugin %s: %w", p.Name(), err)
}

if !utils.FileExists(pluginLocation) {
if !osutil.FileExists(pluginLocation) {
return fmt.Errorf("Vendored plugin path %s doesn't exist", p.Location)
}

Expand Down Expand Up @@ -324,7 +324,7 @@ func (e *Executor) checkoutPlugin(ctx context.Context, p *plugin.Plugin) (*plugi
// that means a potentially slow and unnecessary clone on every build step. Sigh. I think the
// tradeoff is favourable for just blowing away an existing clone if we want least-hassle
// guarantee that the user will get the latest version of their plugin branch/tag/whatever.
if e.ExecutorConfig.PluginsAlwaysCloneFresh && utils.FileExists(pluginDirectory) {
if e.ExecutorConfig.PluginsAlwaysCloneFresh && osutil.FileExists(pluginDirectory) {
e.shell.Commentf("BUILDKITE_PLUGINS_ALWAYS_CLONE_FRESH is true; removing previous checkout of plugin %s", p.Label())
err = os.RemoveAll(pluginDirectory)
if err != nil {
Expand All @@ -333,7 +333,7 @@ func (e *Executor) checkoutPlugin(ctx context.Context, p *plugin.Plugin) (*plugi
}
}

if utils.FileExists(pluginGitDirectory) {
if osutil.FileExists(pluginGitDirectory) {
// It'd be nice to show the current commit of the plugin, so
// let's figure that out.
headCommit, err := gitRevParseInWorkingDirectory(ctx, e.shell, pluginDirectory, "--short=7", "HEAD")
Expand Down
2 changes: 2 additions & 0 deletions internal/osutil/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package osutil provides some OS-level helper functions.
package osutil
2 changes: 1 addition & 1 deletion internal/utils/file.go → internal/osutil/file.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package utils
package osutil

import (
"fmt"
Expand Down
12 changes: 12 additions & 0 deletions internal/osutil/homedir.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package osutil

import "os"

// UserHomeDir is similar to os.UserHomeDir, but prefers $HOME when available
// over other options (such as USERPROFILE on Windows).
func UserHomeDir() (string, error) {
if h := os.Getenv("HOME"); h != "" {
return h, nil
}
return os.UserHomeDir()
}
50 changes: 50 additions & 0 deletions internal/osutil/homedir_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package osutil

import (
"os"
"runtime"
"testing"
)

func TestUserHomeDir(t *testing.T) {
// not parallel because it messes with env vars
origHome := os.Getenv("HOME")
origUserProfile := os.Getenv("USERPROFILE")
t.Cleanup(func() {
os.Setenv("HOME", origHome)
os.Setenv("USERPROFILE", origUserProfile)
})

type testCase struct {
home, userProfile, want string
}

tests := []testCase{
{
// Prefer $HOME on all platforms
home: "home",
userProfile: "userProfile",
want: "home",
},
}
if runtime.GOOS == "windows" {
// Windows can use %USERPROFILE% as a treat when $HOME is unavailable
tests = append(tests, testCase{
home: "",
userProfile: "userProfile",
want: "userProfile",
})
}

for _, test := range tests {
os.Setenv("HOME", test.home)
os.Setenv("USERPROFILE", test.userProfile)
got, err := UserHomeDir()
if err != nil {
t.Errorf("HOME=%q USERPROFILE=%q UserHomeDir() error = %v", test.home, test.userProfile, err)
}
if got != test.want {
t.Errorf("HOME=%q USERPROFILE=%q UserHomeDir() = %q, want %q", test.home, test.userProfile, got, test.want)
}
}
}
2 changes: 1 addition & 1 deletion internal/utils/path.go → internal/osutil/path.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package utils
package osutil

import (
"errors"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package utils
package osutil

import (
"os"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//go:build windows
// +build windows

package utils
package osutil

import (
"os"
Expand Down
4 changes: 0 additions & 4 deletions internal/utils/doc.go

This file was deleted.

0 comments on commit b00fade

Please sign in to comment.