diff --git a/act/runner/run_context.go b/act/runner/run_context.go index eacc231b..79399862 100755 --- a/act/runner/run_context.go +++ b/act/runner/run_context.go @@ -11,6 +11,7 @@ import ( "runtime" "strings" + "github.com/mitchellh/go-homedir" log "github.com/sirupsen/logrus" "github.com/nektos/act/pkg/common" @@ -170,9 +171,11 @@ func (rc *RunContext) stopJobContainer() common.Executor { func (rc *RunContext) ActionCacheDir() string { var xdgCache string var ok bool - if xdgCache, ok = os.LookupEnv("XDG_CACHE_HOME"); !ok { - if home, ok := os.LookupEnv("HOME"); ok { - xdgCache = fmt.Sprintf("%s/.cache", home) + if xdgCache, ok = os.LookupEnv("XDG_CACHE_HOME"); !ok || xdgCache == "" { + if home, err := homedir.Dir(); err == nil { + xdgCache = filepath.Join(home, ".cache") + } else if xdgCache, err = filepath.Abs("."); err != nil { + log.Fatal(err) } } return filepath.Join(xdgCache, "act") @@ -378,19 +381,19 @@ func createContainerName(parts ...string) string { if i == len(parts)-1 { name = append(name, pattern.ReplaceAllString(part, "-")) } else { - // If any part has a '-' on the end it is likely part of a matrix job. - // Let's preserve the number to prevent clashes in container names. - re := regexp.MustCompile("-[0-9]+$") - num := re.FindStringSubmatch(part) - if len(num) > 0 { - name = append(name, trimToLen(pattern.ReplaceAllString(part, "-"), partLen-len(num[0]))) - name = append(name, num[0]) - } else { - name = append(name, trimToLen(pattern.ReplaceAllString(part, "-"), partLen)) + // If any part has a '-' on the end it is likely part of a matrix job. + // Let's preserve the number to prevent clashes in container names. + re := regexp.MustCompile("-[0-9]+$") + num := re.FindStringSubmatch(part) + if len(num) > 0 { + name = append(name, trimToLen(pattern.ReplaceAllString(part, "-"), partLen-len(num[0]))) + name = append(name, num[0]) + } else { + name = append(name, trimToLen(pattern.ReplaceAllString(part, "-"), partLen)) } } } - return strings.ReplaceAll(strings.Trim(strings.Join(name, "-"), "-"),"--","-") + return strings.ReplaceAll(strings.Trim(strings.Join(name, "-"), "-"), "--", "-") } func trimToLen(s string, l int) string { diff --git a/cmd/root.go b/cmd/root.go index 6cf1c32c..8dd08f43 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -14,6 +14,7 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/andreaskoch/go-fswatch" "github.com/joho/godotenv" + "github.com/mitchellh/go-homedir" gitignore "github.com/sabhiram/go-gitignore" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -67,15 +68,35 @@ func Execute(ctx context.Context, version string) { } -func args() []string { - args := make([]string, 0) - actrc := []string{ - filepath.Join(os.Getenv("HOME"), ".actrc"), +func configLocations() []string { + home, err := homedir.Dir() + if err != nil { + log.Fatal(err) + } + + // reference: https://specifications.freedesktop.org/basedir-spec/latest/ar01s03.html + var actrcXdg string + if xdg, ok := os.LookupEnv("XDG_CONFIG_HOME"); ok && xdg != "" { + actrcXdg = filepath.Join(xdg, ".actrc") + } else { + actrcXdg = filepath.Join(home, ".config", ".actrc") + } + + return []string{ + filepath.Join(home, ".actrc"), + actrcXdg, filepath.Join(".", ".actrc"), } +} + +func args() []string { + actrc := configLocations() + + args := make([]string, 0) for _, f := range actrc { args = append(args, readArgsFile(f)...) } + args = append(args, os.Args[1:]...) return args } @@ -196,53 +217,21 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str return err } - // check platforms + // Check if platforms flag is set, if not, run default image survey if len(input.platforms) == 0 { - actrcHome := filepath.Join(os.Getenv("HOME"), ".actrc") - actrcCwd := filepath.Join(".", ".actrc") - _, errHome := os.Stat(actrcHome) - _, errCwd := os.Stat(actrcCwd) - if os.IsNotExist(errHome) && os.IsNotExist(errCwd) { - var answer string - confirmation := &survey.Select{ - Message: "Please choose the default image you want to use with act:\n\n - Large size image: +20GB Docker image, includes almost all tools used on GitHub Actions (IMPORTANT: currently only ubuntu-18.04 platform is available)\n - Medium size image: ~500MB, includes only necessary tools to bootstrap actions and aims to be compatible with all actions\n - Micro size image: <200MB, contains only NodeJS required to bootstrap actions, doesn't work with all actions\n\nDefault image and other options can be changed manually in ~/.actrc (please refer to https://github.com/nektos/act#configuration for additional information about file structure)", - Help: "If you want to know why act asks you that, please go to https://github.com/nektos/act/issues/107", - Default: "Medium", - Options: []string{"Large", "Medium", "Micro"}, + cfgFound := false + cfgLocations := configLocations() + for _, v := range cfgLocations { + _, err := os.Stat(v) + if os.IsExist(err) { + cfgFound = true } - - err := survey.AskOne(confirmation, &answer) - if err != nil { - log.Error(err) - os.Exit(1) - } - var option string - switch answer { - case "Large": - option = "-P ubuntu-18.04=nektos/act-environments-ubuntu:18.04" - case "Medium": - option = "-P ubuntu-latest=catthehacker/ubuntu:act-latest\n-P ubuntu-20.04=catthehacker/ubuntu:act-20.04\n-P ubuntu-18.04=catthehacker/ubuntu:act-18.04\nubuntu-16.04=catthehacker/ubuntu:act-16.04" - case "Micro": - option = "-P ubuntu-latest=node:12.20.1-buster-slim\n-P ubuntu-20.04=node:12.20.1-buster-slim\n-P ubuntu-18.04=node:12.20.1-buster-slim\n-P ubuntu-16.04=node:12.20.1-stretch-slim" - } - - f, err := os.Create(actrcHome) - if err != nil { + } + if !cfgFound && len(cfgLocations) > 0 { + if err := defaultImageSurvey(cfgLocations[0]); err != nil { log.Fatal(err) } - - _, err = f.WriteString(option) - if err != nil { - log.Fatal(err) - _ = f.Close() - } - - err = f.Close() - if err != nil { - log.Fatal(err) - } - - input.platforms = readArgsFile(actrcHome) + input.platforms = readArgsFile(cfgLocations[0]) } } @@ -281,6 +270,49 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str } } +func defaultImageSurvey(actrc string) error { + var answer string + confirmation := &survey.Select{ + Message: "Please choose the default image you want to use with act:\n\n - Large size image: +20GB Docker image, includes almost all tools used on GitHub Actions (IMPORTANT: currently only ubuntu-18.04 platform is available)\n - Medium size image: ~500MB, includes only necessary tools to bootstrap actions and aims to be compatible with all actions\n - Micro size image: <200MB, contains only NodeJS required to bootstrap actions, doesn't work with all actions\n\nDefault image and other options can be changed manually in ~/.actrc (please refer to https://github.com/nektos/act#configuration for additional information about file structure)", + Help: "If you want to know why act asks you that, please go to https://github.com/nektos/act/issues/107", + Default: "Medium", + Options: []string{"Large", "Medium", "Micro"}, + } + + err := survey.AskOne(confirmation, &answer) + if err != nil { + return err + } + + var option string + switch answer { + case "Large": + option = "-P ubuntu-18.04=nektos/act-environments-ubuntu:18.04" + case "Medium": + option = "-P ubuntu-latest=catthehacker/ubuntu:act-latest\n-P ubuntu-20.04=catthehacker/ubuntu:act-20.04\n-P ubuntu-18.04=catthehacker/ubuntu:act-18.04\nubuntu-16.04=catthehacker/ubuntu:act-16.04" + case "Micro": + option = "-P ubuntu-latest=node:12.20.1-buster-slim\n-P ubuntu-20.04=node:12.20.1-buster-slim\n-P ubuntu-18.04=node:12.20.1-buster-slim\n-P ubuntu-16.04=node:12.20.1-stretch-slim" + } + + f, err := os.Create(actrc) + if err != nil { + return err + } + + _, err = f.WriteString(option) + if err != nil { + _ = f.Close() + return err + } + + err = f.Close() + if err != nil { + return err + } + + return nil +} + func watchAndRun(ctx context.Context, fn common.Executor) error { recurse := true checkIntervalInSeconds := 2