diff --git a/.golangci.yml b/.golangci.yml index f48e55c..d31aa34 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,4 +1,4 @@ -# Minimum golangci-lint version required: v1.42.0 +# Minimum golangci-lint version required: v1.46.0 run: timeout: 3m @@ -22,9 +22,11 @@ linters-settings: list-type: blacklist include-go-root: true packages: + - github.com/pkg/errors - gotest.tools/v3/assert - log packages-with-error-message: + - github.com/pkg/errors: 'Please use "errors" package from standard library' - gotest.tools/v3: 'Please keep tests unified using only github.com/stretchr/testify' - log: 'Please keep logging unified using only github.com/sirupsen/logrus' diff --git a/go.mod b/go.mod index 2457c40..0b0a3bb 100644 --- a/go.mod +++ b/go.mod @@ -20,7 +20,6 @@ require ( github.com/moby/buildkit v0.10.3 github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 github.com/opencontainers/selinux v1.10.1 - github.com/pkg/errors v0.9.1 github.com/rhysd/actionlint v1.6.13 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 github.com/sirupsen/logrus v1.8.1 @@ -58,6 +57,7 @@ require ( github.com/moby/sys/mountinfo v0.6.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/runc v1.1.1 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/robfig/cron v1.2.0 // indirect diff --git a/pkg/common/git.go b/pkg/common/git/git.go similarity index 90% rename from pkg/common/git.go rename to pkg/common/git/git.go index 6c1f501..51c8072 100644 --- a/pkg/common/git.go +++ b/pkg/common/git/git.go @@ -1,7 +1,8 @@ -package common +package git import ( "context" + "errors" "fmt" "io" "io/ioutil" @@ -12,13 +13,14 @@ import ( "strings" "sync" - git "github.com/go-git/go-git/v5" + "github.com/nektos/act/pkg/common" + + "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/transport/http" "github.com/go-ini/ini" "github.com/mattn/go-isatty" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) @@ -29,8 +31,28 @@ var ( githubSSHRegex = regexp.MustCompile(`github.com[:/](.+)/(.+?)(?:.git)?$`) cloneLock sync.Mutex + + ErrShortRef = errors.New("short SHA references are not supported") + ErrNoRepo = errors.New("unable to find git repo") ) +type Error struct { + err error + commit string +} + +func (e *Error) Error() string { + return e.err.Error() +} + +func (e *Error) Unwrap() error { + return e.err +} + +func (e *Error) Commit() string { + return e.commit +} + // FindGitRevision get the current git revision func FindGitRevision(file string) (shortSha string, sha string, err error) { gitDir, err := findGitDirectory(file) @@ -222,7 +244,7 @@ func findGitDirectory(fromFile string) (string, error) { if err == nil && fi.Mode().IsDir() { return gitPath, nil } else if dir == "/" || dir == "C:\\" || dir == "c:\\" { - return "", errors.New("unable to find git repo") + return "", &Error{err: ErrNoRepo} } return findGitDirectory(filepath.Dir(dir)) @@ -277,11 +299,27 @@ func CloneIfRequired(ctx context.Context, refName plumbing.ReferenceName, input return r, nil } +func gitOptions(token string) (fetchOptions git.FetchOptions, pullOptions git.PullOptions) { + fetchOptions.RefSpecs = []config.RefSpec{"refs/*:refs/*", "HEAD:refs/heads/HEAD"} + pullOptions.Force = true + + if token != "" { + auth := &http.BasicAuth{ + Username: "token", + Password: token, + } + fetchOptions.Auth = auth + pullOptions.Auth = auth + } + + return fetchOptions, pullOptions +} + // NewGitCloneExecutor creates an executor to clone git repos // nolint:gocyclo -func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor { +func NewGitCloneExecutor(input NewGitCloneExecutorInput) common.Executor { return func(ctx context.Context) error { - logger := Logger(ctx) + logger := common.Logger(ctx) logger.Infof(" \u2601 git clone '%s' # ref=%s", input.URL, input.Ref) logger.Debugf(" cloning %s to %s", input.URL, input.Dir) @@ -295,15 +333,7 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor { } // fetch latest changes - fetchOptions := git.FetchOptions{ - RefSpecs: []config.RefSpec{"refs/*:refs/*", "HEAD:refs/heads/HEAD"}, - } - if input.Token != "" { - fetchOptions.Auth = &http.BasicAuth{ - Username: "token", - Password: input.Token, - } - } + fetchOptions, pullOptions := gitOptions(input.Token) err = r.Fetch(&fetchOptions) if err != nil && !errors.Is(err, git.NoErrAlreadyUpToDate) { @@ -317,7 +347,10 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor { } if hash.String() != input.Ref && strings.HasPrefix(hash.String(), input.Ref) { - return errors.Wrap(errors.New(hash.String()), "short SHA references are not supported") + return &Error{ + err: ErrShortRef, + commit: hash.String(), + } } // At this point we need to know if it's a tag or a branch @@ -365,17 +398,7 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor { } } - pullOptions := git.PullOptions{ - Force: true, - } - if input.Token != "" { - pullOptions.Auth = &http.BasicAuth{ - Username: "token", - Password: input.Token, - } - } - - if err = w.Pull(&pullOptions); err != nil && err.Error() != "already up-to-date" { + if err = w.Pull(&pullOptions); err != nil && err != git.NoErrAlreadyUpToDate { logger.Debugf("Unable to pull %s: %v", refName, err) } logger.Debugf("Cloned %s to %s", input.URL, input.Dir) diff --git a/pkg/common/git_test.go b/pkg/common/git/git_test.go similarity index 96% rename from pkg/common/git_test.go rename to pkg/common/git/git_test.go index 48c6455..932eb14 100644 --- a/pkg/common/git_test.go +++ b/pkg/common/git/git_test.go @@ -1,4 +1,4 @@ -package common +package git import ( "context" @@ -173,25 +173,26 @@ func TestGitFindRef(t *testing.T) { func TestGitCloneExecutor(t *testing.T) { for name, tt := range map[string]struct { - Err, URL, Ref string + Err error + URL, Ref string }{ "tag": { - Err: "", + Err: nil, URL: "https://github.com/actions/checkout", Ref: "v2", }, "branch": { - Err: "", + Err: nil, URL: "https://github.com/anchore/scan-action", Ref: "act-fails", }, "sha": { - Err: "", + Err: nil, URL: "https://github.com/actions/checkout", Ref: "5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f", // v2 }, "short-sha": { - Err: "short SHA references are not supported: 5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f", + Err: &Error{ErrShortRef, "5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f"}, URL: "https://github.com/actions/checkout", Ref: "5a4ac90", // v2 }, @@ -204,10 +205,11 @@ func TestGitCloneExecutor(t *testing.T) { }) err := clone(context.Background()) - if tt.Err == "" { - assert.Empty(t, err) + if tt.Err != nil { + assert.Error(t, err) + assert.Equal(t, tt.Err, err) } else { - assert.EqualError(t, err, tt.Err) + assert.Empty(t, err) } }) } diff --git a/pkg/container/docker_pull.go b/pkg/container/docker_pull.go index e20d686..804f768 100644 --- a/pkg/container/docker_pull.go +++ b/pkg/container/docker_pull.go @@ -4,10 +4,10 @@ import ( "context" "encoding/base64" "encoding/json" + "fmt" "github.com/docker/distribution/reference" "github.com/docker/docker/api/types" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" "github.com/nektos/act/pkg/common" @@ -37,7 +37,7 @@ func NewDockerPullExecutor(input NewDockerPullExecutorInput) common.Executor { imageExists, err := ImageExistsLocally(ctx, input.Image, input.Platform) log.Debugf("Image exists? %v", imageExists) if err != nil { - return errors.WithMessagef(err, "unable to determine if image already exists for image %q (%s)", input.Image, input.Platform) + return fmt.Errorf("unable to determine if image already exists for image '%s' (%s): %w", input.Image, input.Platform, err) } if !imageExists { diff --git a/pkg/container/docker_run.go b/pkg/container/docker_run.go index 26761cf..29ac7ff 100644 --- a/pkg/container/docker_run.go +++ b/pkg/container/docker_run.go @@ -28,7 +28,6 @@ import ( specs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/Masterminds/semver" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" "golang.org/x/term" @@ -236,11 +235,11 @@ func GetDockerClient(ctx context.Context) (cli client.APIClient, err error) { cli, err = client.NewClientWithOpts(client.FromEnv) } if err != nil { - return nil, errors.WithStack(err) + return nil, fmt.Errorf("failed to connect to docker daemon: %w", err) } cli.NegotiateAPIVersion(ctx) - return cli, err + return cli, nil } func GetHostInfo(ctx context.Context) (info types.Info, err error) { @@ -276,8 +275,11 @@ func (cr *containerReference) connect() common.Executor { func (cr *containerReference) Close() common.Executor { return func(ctx context.Context) error { if cr.cli != nil { - cr.cli.Close() + err := cr.cli.Close() cr.cli = nil + if err != nil { + return fmt.Errorf("failed to close client: %w", err) + } } return nil } @@ -292,7 +294,7 @@ func (cr *containerReference) find() common.Executor { All: true, }) if err != nil { - return errors.WithStack(err) + return fmt.Errorf("failed to list containers: %w", err) } for _, c := range containers { @@ -321,7 +323,7 @@ func (cr *containerReference) remove() common.Executor { Force: true, }) if err != nil { - logger.Error(errors.WithStack(err)) + logger.Error(fmt.Errorf("failed to remove container: %w", err)) } logger.Debugf("Removed container: %v", cr.id) @@ -369,7 +371,7 @@ func (cr *containerReference) create(capAdd []string, capDrop []string) common.E desiredPlatform := strings.SplitN(cr.input.Platform, `/`, 2) if len(desiredPlatform) != 2 { - logger.Panicf("Incorrect container platform option. %s is not a valid platform.", cr.input.Platform) + return fmt.Errorf("incorrect container platform option '%s'", cr.input.Platform) } platSpecs = &specs.Platform{ @@ -387,7 +389,7 @@ func (cr *containerReference) create(capAdd []string, capDrop []string) common.E UsernsMode: container.UsernsMode(input.UsernsMode), }, nil, platSpecs, input.Name) if err != nil { - return errors.WithStack(err) + return fmt.Errorf("failed to create container: %w", err) } logger.Debugf("Created container name=%s id=%v from image %v (platform: %s)", input.Name, resp.ID, input.Image, input.Platform) logger.Debugf("ENV ==> %v", input.Env) @@ -397,7 +399,7 @@ func (cr *containerReference) create(capAdd []string, capDrop []string) common.E } } -var singleLineEnvPattern, mulitiLineEnvPattern *regexp.Regexp +var singleLineEnvPattern, multiLineEnvPattern *regexp.Regexp func (cr *containerReference) extractEnv(srcPath string, env *map[string]string) common.Executor { if singleLineEnvPattern == nil { @@ -405,7 +407,7 @@ func (cr *containerReference) extractEnv(srcPath string, env *map[string]string) // SOME_VAR=data=moredata // SOME_VAR=datamoredata singleLineEnvPattern = regexp.MustCompile(`^([^=]*)\=(.*)$`) - mulitiLineEnvPattern = regexp.MustCompile(`^([^<]+)<<(\w+)$`) + multiLineEnvPattern = regexp.MustCompile(`^([^<]+)<<(\w+)$`) } localEnv := *env @@ -415,10 +417,11 @@ func (cr *containerReference) extractEnv(srcPath string, env *map[string]string) return nil } defer envTar.Close() + reader := tar.NewReader(envTar) _, err = reader.Next() if err != nil && err != io.EOF { - return errors.WithStack(err) + return fmt.Errorf("failed to read tar archive: %w", err) } s := bufio.NewScanner(reader) multiLineEnvKey := "" @@ -439,9 +442,9 @@ func (cr *containerReference) extractEnv(srcPath string, env *map[string]string) } multiLineEnvContent += line } - if mulitiLineEnvStart := mulitiLineEnvPattern.FindStringSubmatch(line); mulitiLineEnvStart != nil { - multiLineEnvKey = mulitiLineEnvStart[1] - multiLineEnvDelimiter = mulitiLineEnvStart[2] + if multiLineEnvStart := multiLineEnvPattern.FindStringSubmatch(line); multiLineEnvStart != nil { + multiLineEnvKey = multiLineEnvStart[1] + multiLineEnvDelimiter = multiLineEnvStart[2] } } env = &localEnv @@ -486,14 +489,14 @@ func (cr *containerReference) extractPath(env *map[string]string) common.Executo return func(ctx context.Context) error { pathTar, _, err := cr.cli.CopyFromContainer(ctx, cr.id, localEnv["GITHUB_PATH"]) if err != nil { - return errors.WithStack(err) + return fmt.Errorf("failed to copy from container: %w", err) } defer pathTar.Close() reader := tar.NewReader(pathTar) _, err = reader.Next() if err != nil && err != io.EOF { - return errors.WithStack(err) + return fmt.Errorf("failed to read tar archive: %w", err) } s := bufio.NewScanner(reader) for s.Scan() { @@ -547,14 +550,14 @@ func (cr *containerReference) exec(cmd []string, env map[string]string, user, wo AttachStdout: true, }) if err != nil { - return errors.WithStack(err) + return fmt.Errorf("failed to create exec: %w", err) } resp, err := cr.cli.ContainerExecAttach(ctx, idResp.ID, types.ExecStartCheck{ Tty: isTerminal, }) if err != nil { - return errors.WithStack(err) + return fmt.Errorf("failed to attach to exec: %w", err) } defer resp.Close() @@ -565,14 +568,17 @@ func (cr *containerReference) exec(cmd []string, env map[string]string, user, wo inspectResp, err := cr.cli.ContainerExecInspect(ctx, idResp.ID) if err != nil { - return errors.WithStack(err) + return fmt.Errorf("failed to inspect exec: %w", err) } - if inspectResp.ExitCode == 0 { + switch inspectResp.ExitCode { + case 0: return nil + case 127: + return fmt.Errorf("exitcode '%d': command not found, please refer to https://github.com/nektos/act/issues/107 for more information", inspectResp.ExitCode) + default: + return fmt.Errorf("exitcode '%d': failure", inspectResp.ExitCode) } - - return fmt.Errorf("exit with `FAILURE`: %v", inspectResp.ExitCode) } } @@ -679,11 +685,11 @@ func (cr *containerReference) copyDir(dstPath string, srcPath string, useGitIgno logger.Debugf("Extracting content from '%s' to '%s'", tarFile.Name(), dstPath) _, err = tarFile.Seek(0, 0) if err != nil { - return errors.WithStack(err) + return fmt.Errorf("failed to seek tar archive: %w", err) } err = cr.cli.CopyToContainer(ctx, cr.id, dstPath, tarFile, types.CopyToContainerOptions{}) if err != nil { - return errors.WithStack(err) + return fmt.Errorf("failed to copy content to container: %w", err) } return nil } @@ -715,7 +721,7 @@ func (cr *containerReference) copyContent(dstPath string, files ...*FileEntry) c logger.Debugf("Extracting content to '%s'", dstPath) err := cr.cli.CopyToContainer(ctx, cr.id, dstPath, &buf, types.CopyToContainerOptions{}) if err != nil { - return errors.WithStack(err) + return fmt.Errorf("failed to copy content to container: %w", err) } return nil } @@ -729,7 +735,7 @@ func (cr *containerReference) attach() common.Executor { Stderr: true, }) if err != nil { - return errors.WithStack(err) + return fmt.Errorf("failed to attach to container: %w", err) } isTerminal := term.IsTerminal(int(os.Stdout.Fd())) @@ -762,7 +768,7 @@ func (cr *containerReference) start() common.Executor { logger.Debugf("Starting container: %v", cr.id) if err := cr.cli.ContainerStart(ctx, cr.id, types.ContainerStartOptions{}); err != nil { - return errors.WithStack(err) + return fmt.Errorf("failed to start container: %w", err) } logger.Debugf("Started container: %v", cr.id) @@ -778,7 +784,7 @@ func (cr *containerReference) wait() common.Executor { select { case err := <-errCh: if err != nil { - return errors.WithStack(err) + return fmt.Errorf("failed to wait for container: %w", err) } case status := <-statusCh: statusCode = status.StatusCode diff --git a/pkg/container/file_collector.go b/pkg/container/file_collector.go index 1e5a8af..84821aa 100644 --- a/pkg/container/file_collector.go +++ b/pkg/container/file_collector.go @@ -15,7 +15,6 @@ import ( "github.com/go-git/go-git/v5/plumbing/filemode" "github.com/go-git/go-git/v5/plumbing/format/gitignore" "github.com/go-git/go-git/v5/plumbing/format/index" - "github.com/pkg/errors" ) type fileCollectorHandler interface { @@ -151,7 +150,7 @@ func (fc *fileCollector) collectFiles(ctx context.Context, submodulePath []strin if fi.Mode()&os.ModeSymlink == os.ModeSymlink { linkName, err := fc.Fs.Readlink(file) if err != nil { - return errors.WithMessagef(err, "unable to readlink %s", file) + return fmt.Errorf("unable to readlink '%s': %w", file, err) } return fc.Handler.WriteFile(path, fi, linkName, nil) } else if !fi.Mode().IsRegular() { diff --git a/pkg/model/github_context.go b/pkg/model/github_context.go index 26e61ae..de8b0f8 100644 --- a/pkg/model/github_context.go +++ b/pkg/model/github_context.go @@ -3,7 +3,8 @@ package model import ( "fmt" - "github.com/nektos/act/pkg/common" + "github.com/nektos/act/pkg/common/git" + log "github.com/sirupsen/logrus" ) @@ -85,8 +86,8 @@ func withDefaultBranch(b string, event map[string]interface{}) map[string]interf return event } -var findGitRef = common.FindGitRef -var findGitRevision = common.FindGitRevision +var findGitRef = git.FindGitRef +var findGitRevision = git.FindGitRevision func (ghc *GithubContext) SetRefAndSha(defaultBranch string, repoPath string) { // https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows diff --git a/pkg/model/planner.go b/pkg/model/planner.go index 47c4c24..fafaa74 100644 --- a/pkg/model/planner.go +++ b/pkg/model/planner.go @@ -10,7 +10,6 @@ import ( "regexp" "sort" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) @@ -130,16 +129,16 @@ func NewWorkflowPlanner(path string, noWorkflowRecurse bool) (WorkflowPlanner, e log.Debugf("Reading workflow '%s'", f.Name()) workflow, err := ReadWorkflow(f) if err != nil { - f.Close() + _ = f.Close() if err == io.EOF { - return nil, errors.WithMessagef(err, "unable to read workflow, %s file is empty", wf.workflowFileInfo.Name()) + return nil, fmt.Errorf("unable to read workflow '%s': file is empty: %w", wf.workflowFileInfo.Name(), err) } return nil, err } _, err = f.Seek(0, 0) if err != nil { - f.Close() - return nil, errors.WithMessagef(err, "error occurring when resetting io pointer, %s", wf.workflowFileInfo.Name()) + _ = f.Close() + return nil, fmt.Errorf("error occurring when resetting io pointer in '%s': %w", wf.workflowFileInfo.Name(), err) } workflow.File = wf.workflowFileInfo.Name() @@ -155,7 +154,7 @@ func NewWorkflowPlanner(path string, noWorkflowRecurse bool) (WorkflowPlanner, e } wp.workflows = append(wp.workflows, workflow) - f.Close() + _ = f.Close() } } diff --git a/pkg/model/planner_test.go b/pkg/model/planner_test.go index 8ba5ca7..551b7b3 100644 --- a/pkg/model/planner_test.go +++ b/pkg/model/planner_test.go @@ -22,8 +22,8 @@ func TestPlanner(t *testing.T) { {"invalid-job-name/invalid-2.yml", "workflow is not valid. 'invalid-job-name-2': Job name '1234invalid-JOB-Name-v123-docker_hub' is invalid. Names must start with a letter or '_' and contain only alphanumeric characters, '-', or '_'", false}, {"invalid-job-name/valid-1.yml", "", false}, {"invalid-job-name/valid-2.yml", "", false}, - {"empty-workflow", "unable to read workflow, push.yml file is empty: EOF", false}, - {"nested", "unable to read workflow, fail.yml file is empty: EOF", false}, + {"empty-workflow", "unable to read workflow 'push.yml': file is empty: EOF", false}, + {"nested", "unable to read workflow 'fail.yml': file is empty: EOF", false}, {"nested", "", true}, } diff --git a/pkg/runner/run_context.go b/pkg/runner/run_context.go index 3e1ee2c..66cfa7b 100644 --- a/pkg/runner/run_context.go +++ b/pkg/runner/run_context.go @@ -11,14 +11,13 @@ import ( "strings" "github.com/kballard/go-shellquote" + "github.com/mitchellh/go-homedir" + "github.com/opencontainers/selinux/go-selinux" + log "github.com/sirupsen/logrus" "github.com/spf13/pflag" - "github.com/mitchellh/go-homedir" - log "github.com/sirupsen/logrus" - - selinux "github.com/opencontainers/selinux/go-selinux" - "github.com/nektos/act/pkg/common" + "github.com/nektos/act/pkg/common/git" "github.com/nektos/act/pkg/container" "github.com/nektos/act/pkg/exprparser" "github.com/nektos/act/pkg/model" @@ -476,7 +475,7 @@ func (rc *RunContext) getGithubContext() *model.GithubContext { } repoPath := rc.Config.Workdir - repo, err := common.FindGithubRepo(repoPath, rc.Config.GitHubInstance, rc.Config.RemoteName) + repo, err := git.FindGithubRepo(repoPath, rc.Config.GitHubInstance, rc.Config.RemoteName) if err != nil { log.Warningf("unable to get git repo: %v", err) } else { diff --git a/pkg/runner/step_action_remote.go b/pkg/runner/step_action_remote.go index 7f55c68..cf1ddea 100644 --- a/pkg/runner/step_action_remote.go +++ b/pkg/runner/step_action_remote.go @@ -2,6 +2,7 @@ package runner import ( "context" + "errors" "fmt" "io" "io/ioutil" @@ -12,8 +13,10 @@ import ( "strings" "github.com/nektos/act/pkg/common" + "github.com/nektos/act/pkg/common/git" "github.com/nektos/act/pkg/model" - "github.com/pkg/errors" + + gogit "github.com/go-git/go-git/v5" ) type stepActionRemote struct { @@ -29,7 +32,7 @@ type stepActionRemote struct { } var ( - stepActionRemoteNewCloneExecutor = common.NewGitCloneExecutor + stepActionRemoteNewCloneExecutor = git.NewGitCloneExecutor ) func (sar *stepActionRemote) prepareActionExecutor() common.Executor { @@ -54,7 +57,7 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor { } actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), strings.ReplaceAll(sar.Step.Uses, "/", "-")) - gitClone := stepActionRemoteNewCloneExecutor(common.NewGitCloneExecutorInput{ + gitClone := stepActionRemoteNewCloneExecutor(git.NewGitCloneExecutorInput{ URL: sar.remoteAction.CloneURL(), Ref: sar.remoteAction.Ref, Dir: actionDir, @@ -62,13 +65,13 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor { }) var ntErr common.Executor if err := gitClone(ctx); err != nil { - if err.Error() == "short SHA references are not supported" { - err = errors.Cause(err) - return fmt.Errorf("Unable to resolve action `%s`, the provided ref `%s` is the shortened version of a commit SHA, which is not supported. Please use the full commit SHA `%s` instead", sar.Step.Uses, sar.remoteAction.Ref, err.Error()) - } else if err.Error() != "some refs were not updated" { - return err - } else { + if errors.Is(err, git.ErrShortRef) { + return fmt.Errorf("Unable to resolve action `%s`, the provided ref `%s` is the shortened version of a commit SHA, which is not supported. Please use the full commit SHA `%s` instead", + sar.Step.Uses, sar.remoteAction.Ref, err.(*git.Error).Commit()) + } else if errors.Is(err, gogit.ErrForceNeeded) { // TODO: figure out if it will be easy to shadow/alias go-git err's ntErr = common.NewInfoExecutor("Non-terminating error while running 'git clone': %v", err) + } else { + return err } } diff --git a/pkg/runner/step_action_remote_test.go b/pkg/runner/step_action_remote_test.go index 209bee5..4292801 100644 --- a/pkg/runner/step_action_remote_test.go +++ b/pkg/runner/step_action_remote_test.go @@ -7,7 +7,9 @@ import ( "testing" "github.com/nektos/act/pkg/common" + "github.com/nektos/act/pkg/common/git" "github.com/nektos/act/pkg/model" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "gopkg.in/yaml.v3" @@ -123,7 +125,7 @@ func TestStepActionRemote(t *testing.T) { clonedAction := false origStepAtionRemoteNewCloneExecutor := stepActionRemoteNewCloneExecutor - stepActionRemoteNewCloneExecutor = func(input common.NewGitCloneExecutorInput) common.Executor { + stepActionRemoteNewCloneExecutor = func(input git.NewGitCloneExecutorInput) common.Executor { return func(ctx context.Context) error { clonedAction = true return nil @@ -208,7 +210,7 @@ func TestStepActionRemotePre(t *testing.T) { sarm := &stepActionRemoteMocks{} origStepAtionRemoteNewCloneExecutor := stepActionRemoteNewCloneExecutor - stepActionRemoteNewCloneExecutor = func(input common.NewGitCloneExecutorInput) common.Executor { + stepActionRemoteNewCloneExecutor = func(input git.NewGitCloneExecutorInput) common.Executor { return func(ctx context.Context) error { clonedAction = true return nil