feat: add bug-report flag (#1056)
* feat: add bug-report flag * fix: use docker host CPU count * feat: add config files to bug-report Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
a970145c95
commit
5d7027dc3f
98
cmd/root.go
98
cmd/root.go
|
@ -3,6 +3,7 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -19,6 +20,7 @@ import (
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/artifacts"
|
"github.com/nektos/act/pkg/artifacts"
|
||||||
"github.com/nektos/act/pkg/common"
|
"github.com/nektos/act/pkg/common"
|
||||||
|
"github.com/nektos/act/pkg/container"
|
||||||
"github.com/nektos/act/pkg/model"
|
"github.com/nektos/act/pkg/model"
|
||||||
"github.com/nektos/act/pkg/runner"
|
"github.com/nektos/act/pkg/runner"
|
||||||
)
|
)
|
||||||
|
@ -39,6 +41,8 @@ func Execute(ctx context.Context, version string) {
|
||||||
rootCmd.Flags().BoolP("list", "l", false, "list workflows")
|
rootCmd.Flags().BoolP("list", "l", false, "list workflows")
|
||||||
rootCmd.Flags().BoolP("graph", "g", false, "draw workflows")
|
rootCmd.Flags().BoolP("graph", "g", false, "draw workflows")
|
||||||
rootCmd.Flags().StringP("job", "j", "", "run job")
|
rootCmd.Flags().StringP("job", "j", "", "run job")
|
||||||
|
rootCmd.Flags().BoolP("bug-report", "", false, "Display system information for bug report")
|
||||||
|
|
||||||
rootCmd.Flags().StringArrayVarP(&input.secrets, "secret", "s", []string{}, "secret to make available to actions with optional value (e.g. -s mysecret=foo or -s mysecret)")
|
rootCmd.Flags().StringArrayVarP(&input.secrets, "secret", "s", []string{}, "secret to make available to actions with optional value (e.g. -s mysecret=foo or -s mysecret)")
|
||||||
rootCmd.Flags().StringArrayVarP(&input.envs, "env", "", []string{}, "env to make available to actions with optional value (e.g. --env myenv=foo or --env myenv)")
|
rootCmd.Flags().StringArrayVarP(&input.envs, "env", "", []string{}, "env to make available to actions with optional value (e.g. --env myenv=foo or --env myenv)")
|
||||||
rootCmd.Flags().StringArrayVarP(&input.platforms, "platform", "P", []string{}, "custom image to use per platform (e.g. -P ubuntu-18.04=nektos/act-environments-ubuntu:18.04)")
|
rootCmd.Flags().StringArrayVarP(&input.platforms, "platform", "P", []string{}, "custom image to use per platform (e.g. -P ubuntu-18.04=nektos/act-environments-ubuntu:18.04)")
|
||||||
|
@ -105,14 +109,94 @@ func args() []string {
|
||||||
|
|
||||||
args := make([]string, 0)
|
args := make([]string, 0)
|
||||||
for _, f := range actrc {
|
for _, f := range actrc {
|
||||||
args = append(args, readArgsFile(f)...)
|
args = append(args, readArgsFile(f, true)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
args = append(args, os.Args[1:]...)
|
args = append(args, os.Args[1:]...)
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
func readArgsFile(file string) []string {
|
func bugReport(ctx context.Context, version string) error {
|
||||||
|
var commonSocketPaths = []string{
|
||||||
|
"/var/run/docker.sock",
|
||||||
|
"/var/run/podman/podman.sock",
|
||||||
|
"$HOME/.colima/docker.sock",
|
||||||
|
"$XDG_RUNTIME_DIR/docker.sock",
|
||||||
|
`\\.\pipe\docker_engine`,
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf := func(key, val string) string {
|
||||||
|
return fmt.Sprintf("%-24s%s\n", key, val)
|
||||||
|
}
|
||||||
|
|
||||||
|
report := sprintf("act version:", version)
|
||||||
|
report += sprintf("GOOS:", runtime.GOOS)
|
||||||
|
report += sprintf("GOARCH:", runtime.GOARCH)
|
||||||
|
report += sprintf("NumCPU:", fmt.Sprint(runtime.NumCPU()))
|
||||||
|
|
||||||
|
var dockerHost string
|
||||||
|
if dockerHost = os.Getenv("DOCKER_HOST"); dockerHost == "" {
|
||||||
|
dockerHost = "DOCKER_HOST environment variable is unset/empty."
|
||||||
|
}
|
||||||
|
|
||||||
|
report += sprintf("Docker host:", dockerHost)
|
||||||
|
report += fmt.Sprintln("Sockets found:")
|
||||||
|
for _, p := range commonSocketPaths {
|
||||||
|
if strings.HasPrefix(p, `$`) {
|
||||||
|
v := strings.Split(p, `/`)[0]
|
||||||
|
p = strings.Replace(p, v, os.Getenv(strings.TrimPrefix(v, `$`)), 1)
|
||||||
|
}
|
||||||
|
if _, err := os.Stat(p); err != nil {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
report += fmt.Sprintf("\t%s\n", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := container.GetHostInfo(ctx)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(report)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
report += sprintf("Config files:", "")
|
||||||
|
for _, c := range configLocations() {
|
||||||
|
args := readArgsFile(c, false)
|
||||||
|
if len(args) > 0 {
|
||||||
|
report += fmt.Sprintf("\t%s:\n", c)
|
||||||
|
for _, l := range args {
|
||||||
|
report += fmt.Sprintf("\t\t%s\n", l)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
report += fmt.Sprintln("Docker Engine:")
|
||||||
|
|
||||||
|
report += sprintf("\tEngine version:", info.ServerVersion)
|
||||||
|
report += sprintf("\tEngine runtime:", info.DefaultRuntime)
|
||||||
|
report += sprintf("\tCgroup version:", info.CgroupVersion)
|
||||||
|
report += sprintf("\tCgroup driver:", info.CgroupDriver)
|
||||||
|
report += sprintf("\tStorage driver:", info.Driver)
|
||||||
|
report += sprintf("\tRegistry URI:", info.IndexServerAddress)
|
||||||
|
|
||||||
|
report += sprintf("\tOS:", info.OperatingSystem)
|
||||||
|
report += sprintf("\tOS type:", info.OSType)
|
||||||
|
report += sprintf("\tOS version:", info.OSVersion)
|
||||||
|
report += sprintf("\tOS arch:", info.Architecture)
|
||||||
|
report += sprintf("\tOS kernel:", info.KernelVersion)
|
||||||
|
report += sprintf("\tOS CPU:", fmt.Sprint(info.NCPU))
|
||||||
|
report += sprintf("\tOS memory:", fmt.Sprintf("%d MB", info.MemTotal/1024/1024))
|
||||||
|
|
||||||
|
report += fmt.Sprintln("\tSecurity options:")
|
||||||
|
for _, secopt := range info.SecurityOptions {
|
||||||
|
report += fmt.Sprintf("\t\t%s\n", secopt)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(report)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readArgsFile(file string, split bool) []string {
|
||||||
args := make([]string, 0)
|
args := make([]string, 0)
|
||||||
f, err := os.Open(file)
|
f, err := os.Open(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -127,8 +211,10 @@ func readArgsFile(file string) []string {
|
||||||
scanner := bufio.NewScanner(f)
|
scanner := bufio.NewScanner(f)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
arg := strings.TrimSpace(scanner.Text())
|
arg := strings.TrimSpace(scanner.Text())
|
||||||
if strings.HasPrefix(arg, "-") {
|
if strings.HasPrefix(arg, "-") && split {
|
||||||
args = append(args, regexp.MustCompile(`\s`).Split(arg, 2)...)
|
args = append(args, regexp.MustCompile(`\s`).Split(arg, 2)...)
|
||||||
|
} else if !split {
|
||||||
|
args = append(args, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return args
|
return args
|
||||||
|
@ -162,6 +248,10 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
||||||
log.SetFormatter(&log.JSONFormatter{})
|
log.SetFormatter(&log.JSONFormatter{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ok, _ := cmd.Flags().GetBool("bug-report"); ok {
|
||||||
|
return bugReport(ctx, cmd.Version)
|
||||||
|
}
|
||||||
|
|
||||||
if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" && input.containerArchitecture == "" {
|
if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" && input.containerArchitecture == "" {
|
||||||
l := log.New()
|
l := log.New()
|
||||||
l.SetFormatter(&log.TextFormatter{
|
l.SetFormatter(&log.TextFormatter{
|
||||||
|
@ -256,7 +346,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
||||||
if err := defaultImageSurvey(cfgLocations[0]); err != nil {
|
if err := defaultImageSurvey(cfgLocations[0]); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
input.platforms = readArgsFile(cfgLocations[0])
|
input.platforms = readArgsFile(cfgLocations[0], true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -201,10 +201,7 @@ type containerReference struct {
|
||||||
input *NewContainerInput
|
input *NewContainerInput
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDockerClient(ctx context.Context) (*client.Client, error) {
|
func GetDockerClient(ctx context.Context) (cli *client.Client, err error) {
|
||||||
var err error
|
|
||||||
var cli *client.Client
|
|
||||||
|
|
||||||
// TODO: this should maybe need to be a global option, not hidden in here?
|
// TODO: this should maybe need to be a global option, not hidden in here?
|
||||||
// though i'm not sure how that works out when there's another Executor :D
|
// though i'm not sure how that works out when there's another Executor :D
|
||||||
// I really would like something that works on OSX native for eg
|
// I really would like something that works on OSX native for eg
|
||||||
|
@ -232,6 +229,22 @@ func GetDockerClient(ctx context.Context) (*client.Client, error) {
|
||||||
return cli, err
|
return cli, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetHostInfo(ctx context.Context) (info types.Info, err error) {
|
||||||
|
var cli *client.Client
|
||||||
|
cli, err = GetDockerClient(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return info, err
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
info, err = cli.Info(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return info, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (cr *containerReference) connect() common.Executor {
|
func (cr *containerReference) connect() common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
if cr.cli != nil {
|
if cr.cli != nil {
|
||||||
|
|
|
@ -9,9 +9,11 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
|
||||||
"github.com/nektos/act/pkg/model"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
|
"github.com/nektos/act/pkg/common"
|
||||||
|
"github.com/nektos/act/pkg/container"
|
||||||
|
"github.com/nektos/act/pkg/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Runner provides capabilities to run GitHub actions
|
// Runner provides capabilities to run GitHub actions
|
||||||
|
@ -171,7 +173,15 @@ func (runner *runnerImpl) NewPlanExecutor(plan *model.Plan) common.Executor {
|
||||||
}
|
}
|
||||||
pipeline = append(pipeline, common.NewParallelExecutor(maxParallel, stageExecutor...))
|
pipeline = append(pipeline, common.NewParallelExecutor(maxParallel, stageExecutor...))
|
||||||
}
|
}
|
||||||
return common.NewParallelExecutor(runtime.NumCPU(), pipeline...)(ctx)
|
var ncpu int
|
||||||
|
info, err := container.GetHostInfo(ctx)
|
||||||
|
if err != nil {
|
||||||
|
log.Errorf("failed to obtain container engine info: %s", err)
|
||||||
|
ncpu = 1 // sane default?
|
||||||
|
} else {
|
||||||
|
ncpu = info.NCPU
|
||||||
|
}
|
||||||
|
return common.NewParallelExecutor(ncpu, pipeline...)(ctx)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue