refactor: remove github.com/pkg/errors dependency (#1077)
* refactor: split out common/git * refactor: move git options to separate func * refactor: remove github.com/pkg/errors dependency * fix(golangci-lint): forbid github.com/pkg/errors * style: fix typo * style: fix typo Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
8a473943c3
commit
2aa0699aec
13 changed files with 134 additions and 98 deletions
|
@ -1,4 +1,4 @@
|
||||||
# Minimum golangci-lint version required: v1.42.0
|
# Minimum golangci-lint version required: v1.46.0
|
||||||
run:
|
run:
|
||||||
timeout: 3m
|
timeout: 3m
|
||||||
|
|
||||||
|
@ -22,9 +22,11 @@ linters-settings:
|
||||||
list-type: blacklist
|
list-type: blacklist
|
||||||
include-go-root: true
|
include-go-root: true
|
||||||
packages:
|
packages:
|
||||||
|
- github.com/pkg/errors
|
||||||
- gotest.tools/v3/assert
|
- gotest.tools/v3/assert
|
||||||
- log
|
- log
|
||||||
packages-with-error-message:
|
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'
|
- gotest.tools/v3: 'Please keep tests unified using only github.com/stretchr/testify'
|
||||||
- log: 'Please keep logging unified using only github.com/sirupsen/logrus'
|
- log: 'Please keep logging unified using only github.com/sirupsen/logrus'
|
||||||
|
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -20,7 +20,6 @@ require (
|
||||||
github.com/moby/buildkit v0.10.3
|
github.com/moby/buildkit v0.10.3
|
||||||
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799
|
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799
|
||||||
github.com/opencontainers/selinux v1.10.1
|
github.com/opencontainers/selinux v1.10.1
|
||||||
github.com/pkg/errors v0.9.1
|
|
||||||
github.com/rhysd/actionlint v1.6.13
|
github.com/rhysd/actionlint v1.6.13
|
||||||
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
|
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06
|
||||||
github.com/sirupsen/logrus v1.8.1
|
github.com/sirupsen/logrus v1.8.1
|
||||||
|
@ -58,6 +57,7 @@ require (
|
||||||
github.com/moby/sys/mountinfo v0.6.0 // indirect
|
github.com/moby/sys/mountinfo v0.6.0 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/runc v1.1.1 // 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/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rivo/uniseg v0.2.0 // indirect
|
github.com/rivo/uniseg v0.2.0 // indirect
|
||||||
github.com/robfig/cron v1.2.0 // indirect
|
github.com/robfig/cron v1.2.0 // indirect
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package common
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -12,13 +13,14 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"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/config"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
"github.com/go-git/go-git/v5/plumbing/transport/http"
|
||||||
"github.com/go-ini/ini"
|
"github.com/go-ini/ini"
|
||||||
"github.com/mattn/go-isatty"
|
"github.com/mattn/go-isatty"
|
||||||
"github.com/pkg/errors"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -29,8 +31,28 @@ var (
|
||||||
githubSSHRegex = regexp.MustCompile(`github.com[:/](.+)/(.+?)(?:.git)?$`)
|
githubSSHRegex = regexp.MustCompile(`github.com[:/](.+)/(.+?)(?:.git)?$`)
|
||||||
|
|
||||||
cloneLock sync.Mutex
|
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
|
// FindGitRevision get the current git revision
|
||||||
func FindGitRevision(file string) (shortSha string, sha string, err error) {
|
func FindGitRevision(file string) (shortSha string, sha string, err error) {
|
||||||
gitDir, err := findGitDirectory(file)
|
gitDir, err := findGitDirectory(file)
|
||||||
|
@ -222,7 +244,7 @@ func findGitDirectory(fromFile string) (string, error) {
|
||||||
if err == nil && fi.Mode().IsDir() {
|
if err == nil && fi.Mode().IsDir() {
|
||||||
return gitPath, nil
|
return gitPath, nil
|
||||||
} else if dir == "/" || dir == "C:\\" || dir == "c:\\" {
|
} else if dir == "/" || dir == "C:\\" || dir == "c:\\" {
|
||||||
return "", errors.New("unable to find git repo")
|
return "", &Error{err: ErrNoRepo}
|
||||||
}
|
}
|
||||||
|
|
||||||
return findGitDirectory(filepath.Dir(dir))
|
return findGitDirectory(filepath.Dir(dir))
|
||||||
|
@ -277,11 +299,27 @@ func CloneIfRequired(ctx context.Context, refName plumbing.ReferenceName, input
|
||||||
return r, nil
|
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
|
// NewGitCloneExecutor creates an executor to clone git repos
|
||||||
// nolint:gocyclo
|
// nolint:gocyclo
|
||||||
func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor {
|
func NewGitCloneExecutor(input NewGitCloneExecutorInput) common.Executor {
|
||||||
return func(ctx context.Context) error {
|
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.Infof(" \u2601 git clone '%s' # ref=%s", input.URL, input.Ref)
|
||||||
logger.Debugf(" cloning %s to %s", input.URL, input.Dir)
|
logger.Debugf(" cloning %s to %s", input.URL, input.Dir)
|
||||||
|
|
||||||
|
@ -295,15 +333,7 @@ func NewGitCloneExecutor(input NewGitCloneExecutorInput) Executor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fetch latest changes
|
// fetch latest changes
|
||||||
fetchOptions := git.FetchOptions{
|
fetchOptions, pullOptions := gitOptions(input.Token)
|
||||||
RefSpecs: []config.RefSpec{"refs/*:refs/*", "HEAD:refs/heads/HEAD"},
|
|
||||||
}
|
|
||||||
if input.Token != "" {
|
|
||||||
fetchOptions.Auth = &http.BasicAuth{
|
|
||||||
Username: "token",
|
|
||||||
Password: input.Token,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err = r.Fetch(&fetchOptions)
|
err = r.Fetch(&fetchOptions)
|
||||||
if err != nil && !errors.Is(err, git.NoErrAlreadyUpToDate) {
|
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) {
|
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
|
// 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{
|
if err = w.Pull(&pullOptions); err != nil && err != git.NoErrAlreadyUpToDate {
|
||||||
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" {
|
|
||||||
logger.Debugf("Unable to pull %s: %v", refName, err)
|
logger.Debugf("Unable to pull %s: %v", refName, err)
|
||||||
}
|
}
|
||||||
logger.Debugf("Cloned %s to %s", input.URL, input.Dir)
|
logger.Debugf("Cloned %s to %s", input.URL, input.Dir)
|
|
@ -1,4 +1,4 @@
|
||||||
package common
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
@ -173,25 +173,26 @@ func TestGitFindRef(t *testing.T) {
|
||||||
|
|
||||||
func TestGitCloneExecutor(t *testing.T) {
|
func TestGitCloneExecutor(t *testing.T) {
|
||||||
for name, tt := range map[string]struct {
|
for name, tt := range map[string]struct {
|
||||||
Err, URL, Ref string
|
Err error
|
||||||
|
URL, Ref string
|
||||||
}{
|
}{
|
||||||
"tag": {
|
"tag": {
|
||||||
Err: "",
|
Err: nil,
|
||||||
URL: "https://github.com/actions/checkout",
|
URL: "https://github.com/actions/checkout",
|
||||||
Ref: "v2",
|
Ref: "v2",
|
||||||
},
|
},
|
||||||
"branch": {
|
"branch": {
|
||||||
Err: "",
|
Err: nil,
|
||||||
URL: "https://github.com/anchore/scan-action",
|
URL: "https://github.com/anchore/scan-action",
|
||||||
Ref: "act-fails",
|
Ref: "act-fails",
|
||||||
},
|
},
|
||||||
"sha": {
|
"sha": {
|
||||||
Err: "",
|
Err: nil,
|
||||||
URL: "https://github.com/actions/checkout",
|
URL: "https://github.com/actions/checkout",
|
||||||
Ref: "5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f", // v2
|
Ref: "5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f", // v2
|
||||||
},
|
},
|
||||||
"short-sha": {
|
"short-sha": {
|
||||||
Err: "short SHA references are not supported: 5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f",
|
Err: &Error{ErrShortRef, "5a4ac9002d0be2fb38bd78e4b4dbde5606d7042f"},
|
||||||
URL: "https://github.com/actions/checkout",
|
URL: "https://github.com/actions/checkout",
|
||||||
Ref: "5a4ac90", // v2
|
Ref: "5a4ac90", // v2
|
||||||
},
|
},
|
||||||
|
@ -204,10 +205,11 @@ func TestGitCloneExecutor(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
err := clone(context.Background())
|
err := clone(context.Background())
|
||||||
if tt.Err == "" {
|
if tt.Err != nil {
|
||||||
assert.Empty(t, err)
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, tt.Err, err)
|
||||||
} else {
|
} else {
|
||||||
assert.EqualError(t, err, tt.Err)
|
assert.Empty(t, err)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -4,10 +4,10 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/docker/distribution/reference"
|
"github.com/docker/distribution/reference"
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/pkg/errors"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
"github.com/nektos/act/pkg/common"
|
||||||
|
@ -37,7 +37,7 @@ func NewDockerPullExecutor(input NewDockerPullExecutorInput) common.Executor {
|
||||||
imageExists, err := ImageExistsLocally(ctx, input.Image, input.Platform)
|
imageExists, err := ImageExistsLocally(ctx, input.Image, input.Platform)
|
||||||
log.Debugf("Image exists? %v", imageExists)
|
log.Debugf("Image exists? %v", imageExists)
|
||||||
if err != nil {
|
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 {
|
if !imageExists {
|
||||||
|
|
|
@ -28,7 +28,6 @@ import (
|
||||||
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
specs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
|
|
||||||
"github.com/Masterminds/semver"
|
"github.com/Masterminds/semver"
|
||||||
"github.com/pkg/errors"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
|
|
||||||
|
@ -236,11 +235,11 @@ func GetDockerClient(ctx context.Context) (cli client.APIClient, err error) {
|
||||||
cli, err = client.NewClientWithOpts(client.FromEnv)
|
cli, err = client.NewClientWithOpts(client.FromEnv)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, fmt.Errorf("failed to connect to docker daemon: %w", err)
|
||||||
}
|
}
|
||||||
cli.NegotiateAPIVersion(ctx)
|
cli.NegotiateAPIVersion(ctx)
|
||||||
|
|
||||||
return cli, err
|
return cli, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetHostInfo(ctx context.Context) (info types.Info, err error) {
|
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 {
|
func (cr *containerReference) Close() common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
if cr.cli != nil {
|
if cr.cli != nil {
|
||||||
cr.cli.Close()
|
err := cr.cli.Close()
|
||||||
cr.cli = nil
|
cr.cli = nil
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to close client: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -292,7 +294,7 @@ func (cr *containerReference) find() common.Executor {
|
||||||
All: true,
|
All: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return fmt.Errorf("failed to list containers: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, c := range containers {
|
for _, c := range containers {
|
||||||
|
@ -321,7 +323,7 @@ func (cr *containerReference) remove() common.Executor {
|
||||||
Force: true,
|
Force: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
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)
|
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)
|
desiredPlatform := strings.SplitN(cr.input.Platform, `/`, 2)
|
||||||
|
|
||||||
if len(desiredPlatform) != 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{
|
platSpecs = &specs.Platform{
|
||||||
|
@ -387,7 +389,7 @@ func (cr *containerReference) create(capAdd []string, capDrop []string) common.E
|
||||||
UsernsMode: container.UsernsMode(input.UsernsMode),
|
UsernsMode: container.UsernsMode(input.UsernsMode),
|
||||||
}, nil, platSpecs, input.Name)
|
}, nil, platSpecs, input.Name)
|
||||||
if err != nil {
|
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("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)
|
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 {
|
func (cr *containerReference) extractEnv(srcPath string, env *map[string]string) common.Executor {
|
||||||
if singleLineEnvPattern == nil {
|
if singleLineEnvPattern == nil {
|
||||||
|
@ -405,7 +407,7 @@ func (cr *containerReference) extractEnv(srcPath string, env *map[string]string)
|
||||||
// SOME_VAR=data=moredata
|
// SOME_VAR=data=moredata
|
||||||
// SOME_VAR=datamoredata
|
// SOME_VAR=datamoredata
|
||||||
singleLineEnvPattern = regexp.MustCompile(`^([^=]*)\=(.*)$`)
|
singleLineEnvPattern = regexp.MustCompile(`^([^=]*)\=(.*)$`)
|
||||||
mulitiLineEnvPattern = regexp.MustCompile(`^([^<]+)<<(\w+)$`)
|
multiLineEnvPattern = regexp.MustCompile(`^([^<]+)<<(\w+)$`)
|
||||||
}
|
}
|
||||||
|
|
||||||
localEnv := *env
|
localEnv := *env
|
||||||
|
@ -415,10 +417,11 @@ func (cr *containerReference) extractEnv(srcPath string, env *map[string]string)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
defer envTar.Close()
|
defer envTar.Close()
|
||||||
|
|
||||||
reader := tar.NewReader(envTar)
|
reader := tar.NewReader(envTar)
|
||||||
_, err = reader.Next()
|
_, err = reader.Next()
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
return errors.WithStack(err)
|
return fmt.Errorf("failed to read tar archive: %w", err)
|
||||||
}
|
}
|
||||||
s := bufio.NewScanner(reader)
|
s := bufio.NewScanner(reader)
|
||||||
multiLineEnvKey := ""
|
multiLineEnvKey := ""
|
||||||
|
@ -439,9 +442,9 @@ func (cr *containerReference) extractEnv(srcPath string, env *map[string]string)
|
||||||
}
|
}
|
||||||
multiLineEnvContent += line
|
multiLineEnvContent += line
|
||||||
}
|
}
|
||||||
if mulitiLineEnvStart := mulitiLineEnvPattern.FindStringSubmatch(line); mulitiLineEnvStart != nil {
|
if multiLineEnvStart := multiLineEnvPattern.FindStringSubmatch(line); multiLineEnvStart != nil {
|
||||||
multiLineEnvKey = mulitiLineEnvStart[1]
|
multiLineEnvKey = multiLineEnvStart[1]
|
||||||
multiLineEnvDelimiter = mulitiLineEnvStart[2]
|
multiLineEnvDelimiter = multiLineEnvStart[2]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
env = &localEnv
|
env = &localEnv
|
||||||
|
@ -486,14 +489,14 @@ func (cr *containerReference) extractPath(env *map[string]string) common.Executo
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
pathTar, _, err := cr.cli.CopyFromContainer(ctx, cr.id, localEnv["GITHUB_PATH"])
|
pathTar, _, err := cr.cli.CopyFromContainer(ctx, cr.id, localEnv["GITHUB_PATH"])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return fmt.Errorf("failed to copy from container: %w", err)
|
||||||
}
|
}
|
||||||
defer pathTar.Close()
|
defer pathTar.Close()
|
||||||
|
|
||||||
reader := tar.NewReader(pathTar)
|
reader := tar.NewReader(pathTar)
|
||||||
_, err = reader.Next()
|
_, err = reader.Next()
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
return errors.WithStack(err)
|
return fmt.Errorf("failed to read tar archive: %w", err)
|
||||||
}
|
}
|
||||||
s := bufio.NewScanner(reader)
|
s := bufio.NewScanner(reader)
|
||||||
for s.Scan() {
|
for s.Scan() {
|
||||||
|
@ -547,14 +550,14 @@ func (cr *containerReference) exec(cmd []string, env map[string]string, user, wo
|
||||||
AttachStdout: true,
|
AttachStdout: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
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{
|
resp, err := cr.cli.ContainerExecAttach(ctx, idResp.ID, types.ExecStartCheck{
|
||||||
Tty: isTerminal,
|
Tty: isTerminal,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return fmt.Errorf("failed to attach to exec: %w", err)
|
||||||
}
|
}
|
||||||
defer resp.Close()
|
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)
|
inspectResp, err := cr.cli.ContainerExecInspect(ctx, idResp.ID)
|
||||||
if err != nil {
|
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
|
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)
|
logger.Debugf("Extracting content from '%s' to '%s'", tarFile.Name(), dstPath)
|
||||||
_, err = tarFile.Seek(0, 0)
|
_, err = tarFile.Seek(0, 0)
|
||||||
if err != nil {
|
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{})
|
err = cr.cli.CopyToContainer(ctx, cr.id, dstPath, tarFile, types.CopyToContainerOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return fmt.Errorf("failed to copy content to container: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -715,7 +721,7 @@ func (cr *containerReference) copyContent(dstPath string, files ...*FileEntry) c
|
||||||
logger.Debugf("Extracting content to '%s'", dstPath)
|
logger.Debugf("Extracting content to '%s'", dstPath)
|
||||||
err := cr.cli.CopyToContainer(ctx, cr.id, dstPath, &buf, types.CopyToContainerOptions{})
|
err := cr.cli.CopyToContainer(ctx, cr.id, dstPath, &buf, types.CopyToContainerOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return fmt.Errorf("failed to copy content to container: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -729,7 +735,7 @@ func (cr *containerReference) attach() common.Executor {
|
||||||
Stderr: true,
|
Stderr: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return fmt.Errorf("failed to attach to container: %w", err)
|
||||||
}
|
}
|
||||||
isTerminal := term.IsTerminal(int(os.Stdout.Fd()))
|
isTerminal := term.IsTerminal(int(os.Stdout.Fd()))
|
||||||
|
|
||||||
|
@ -762,7 +768,7 @@ func (cr *containerReference) start() common.Executor {
|
||||||
logger.Debugf("Starting container: %v", cr.id)
|
logger.Debugf("Starting container: %v", cr.id)
|
||||||
|
|
||||||
if err := cr.cli.ContainerStart(ctx, cr.id, types.ContainerStartOptions{}); err != nil {
|
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)
|
logger.Debugf("Started container: %v", cr.id)
|
||||||
|
@ -778,7 +784,7 @@ func (cr *containerReference) wait() common.Executor {
|
||||||
select {
|
select {
|
||||||
case err := <-errCh:
|
case err := <-errCh:
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithStack(err)
|
return fmt.Errorf("failed to wait for container: %w", err)
|
||||||
}
|
}
|
||||||
case status := <-statusCh:
|
case status := <-statusCh:
|
||||||
statusCode = status.StatusCode
|
statusCode = status.StatusCode
|
||||||
|
|
|
@ -15,7 +15,6 @@ import (
|
||||||
"github.com/go-git/go-git/v5/plumbing/filemode"
|
"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/gitignore"
|
||||||
"github.com/go-git/go-git/v5/plumbing/format/index"
|
"github.com/go-git/go-git/v5/plumbing/format/index"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type fileCollectorHandler interface {
|
type fileCollectorHandler interface {
|
||||||
|
@ -151,7 +150,7 @@ func (fc *fileCollector) collectFiles(ctx context.Context, submodulePath []strin
|
||||||
if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
|
if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||||
linkName, err := fc.Fs.Readlink(file)
|
linkName, err := fc.Fs.Readlink(file)
|
||||||
if err != nil {
|
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)
|
return fc.Handler.WriteFile(path, fi, linkName, nil)
|
||||||
} else if !fi.Mode().IsRegular() {
|
} else if !fi.Mode().IsRegular() {
|
||||||
|
|
|
@ -3,7 +3,8 @@ package model
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
"github.com/nektos/act/pkg/common/git"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -85,8 +86,8 @@ func withDefaultBranch(b string, event map[string]interface{}) map[string]interf
|
||||||
return event
|
return event
|
||||||
}
|
}
|
||||||
|
|
||||||
var findGitRef = common.FindGitRef
|
var findGitRef = git.FindGitRef
|
||||||
var findGitRevision = common.FindGitRevision
|
var findGitRevision = git.FindGitRevision
|
||||||
|
|
||||||
func (ghc *GithubContext) SetRefAndSha(defaultBranch string, repoPath string) {
|
func (ghc *GithubContext) SetRefAndSha(defaultBranch string, repoPath string) {
|
||||||
// https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows
|
// https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -130,16 +129,16 @@ func NewWorkflowPlanner(path string, noWorkflowRecurse bool) (WorkflowPlanner, e
|
||||||
log.Debugf("Reading workflow '%s'", f.Name())
|
log.Debugf("Reading workflow '%s'", f.Name())
|
||||||
workflow, err := ReadWorkflow(f)
|
workflow, err := ReadWorkflow(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.Close()
|
_ = f.Close()
|
||||||
if err == io.EOF {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
_, err = f.Seek(0, 0)
|
_, err = f.Seek(0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
f.Close()
|
_ = f.Close()
|
||||||
return nil, errors.WithMessagef(err, "error occurring when resetting io pointer, %s", wf.workflowFileInfo.Name())
|
return nil, fmt.Errorf("error occurring when resetting io pointer in '%s': %w", wf.workflowFileInfo.Name(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
workflow.File = wf.workflowFileInfo.Name()
|
workflow.File = wf.workflowFileInfo.Name()
|
||||||
|
@ -155,7 +154,7 @@ func NewWorkflowPlanner(path string, noWorkflowRecurse bool) (WorkflowPlanner, e
|
||||||
}
|
}
|
||||||
|
|
||||||
wp.workflows = append(wp.workflows, workflow)
|
wp.workflows = append(wp.workflows, workflow)
|
||||||
f.Close()
|
_ = f.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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/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-1.yml", "", false},
|
||||||
{"invalid-job-name/valid-2.yml", "", false},
|
{"invalid-job-name/valid-2.yml", "", false},
|
||||||
{"empty-workflow", "unable to read workflow, push.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", "unable to read workflow 'fail.yml': file is empty: EOF", false},
|
||||||
{"nested", "", true},
|
{"nested", "", true},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,14 +11,13 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/kballard/go-shellquote"
|
"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/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"
|
||||||
|
"github.com/nektos/act/pkg/common/git"
|
||||||
"github.com/nektos/act/pkg/container"
|
"github.com/nektos/act/pkg/container"
|
||||||
"github.com/nektos/act/pkg/exprparser"
|
"github.com/nektos/act/pkg/exprparser"
|
||||||
"github.com/nektos/act/pkg/model"
|
"github.com/nektos/act/pkg/model"
|
||||||
|
@ -476,7 +475,7 @@ func (rc *RunContext) getGithubContext() *model.GithubContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
repoPath := rc.Config.Workdir
|
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 {
|
if err != nil {
|
||||||
log.Warningf("unable to get git repo: %v", err)
|
log.Warningf("unable to get git repo: %v", err)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package runner
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -12,8 +13,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
"github.com/nektos/act/pkg/common"
|
||||||
|
"github.com/nektos/act/pkg/common/git"
|
||||||
"github.com/nektos/act/pkg/model"
|
"github.com/nektos/act/pkg/model"
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
gogit "github.com/go-git/go-git/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepActionRemote struct {
|
type stepActionRemote struct {
|
||||||
|
@ -29,7 +32,7 @@ type stepActionRemote struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
stepActionRemoteNewCloneExecutor = common.NewGitCloneExecutor
|
stepActionRemoteNewCloneExecutor = git.NewGitCloneExecutor
|
||||||
)
|
)
|
||||||
|
|
||||||
func (sar *stepActionRemote) prepareActionExecutor() common.Executor {
|
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, "/", "-"))
|
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(),
|
URL: sar.remoteAction.CloneURL(),
|
||||||
Ref: sar.remoteAction.Ref,
|
Ref: sar.remoteAction.Ref,
|
||||||
Dir: actionDir,
|
Dir: actionDir,
|
||||||
|
@ -62,13 +65,13 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor {
|
||||||
})
|
})
|
||||||
var ntErr common.Executor
|
var ntErr common.Executor
|
||||||
if err := gitClone(ctx); err != nil {
|
if err := gitClone(ctx); err != nil {
|
||||||
if err.Error() == "short SHA references are not supported" {
|
if errors.Is(err, git.ErrShortRef) {
|
||||||
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",
|
||||||
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())
|
sar.Step.Uses, sar.remoteAction.Ref, err.(*git.Error).Commit())
|
||||||
} else if err.Error() != "some refs were not updated" {
|
} else if errors.Is(err, gogit.ErrForceNeeded) { // TODO: figure out if it will be easy to shadow/alias go-git err's
|
||||||
return err
|
|
||||||
} else {
|
|
||||||
ntErr = common.NewInfoExecutor("Non-terminating error while running 'git clone': %v", err)
|
ntErr = common.NewInfoExecutor("Non-terminating error while running 'git clone': %v", err)
|
||||||
|
} else {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,9 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/nektos/act/pkg/common"
|
"github.com/nektos/act/pkg/common"
|
||||||
|
"github.com/nektos/act/pkg/common/git"
|
||||||
"github.com/nektos/act/pkg/model"
|
"github.com/nektos/act/pkg/model"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
@ -123,7 +125,7 @@ func TestStepActionRemote(t *testing.T) {
|
||||||
clonedAction := false
|
clonedAction := false
|
||||||
|
|
||||||
origStepAtionRemoteNewCloneExecutor := stepActionRemoteNewCloneExecutor
|
origStepAtionRemoteNewCloneExecutor := stepActionRemoteNewCloneExecutor
|
||||||
stepActionRemoteNewCloneExecutor = func(input common.NewGitCloneExecutorInput) common.Executor {
|
stepActionRemoteNewCloneExecutor = func(input git.NewGitCloneExecutorInput) common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
clonedAction = true
|
clonedAction = true
|
||||||
return nil
|
return nil
|
||||||
|
@ -208,7 +210,7 @@ func TestStepActionRemotePre(t *testing.T) {
|
||||||
sarm := &stepActionRemoteMocks{}
|
sarm := &stepActionRemoteMocks{}
|
||||||
|
|
||||||
origStepAtionRemoteNewCloneExecutor := stepActionRemoteNewCloneExecutor
|
origStepAtionRemoteNewCloneExecutor := stepActionRemoteNewCloneExecutor
|
||||||
stepActionRemoteNewCloneExecutor = func(input common.NewGitCloneExecutorInput) common.Executor {
|
stepActionRemoteNewCloneExecutor = func(input git.NewGitCloneExecutorInput) common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
clonedAction = true
|
clonedAction = true
|
||||||
return nil
|
return nil
|
||||||
|
|
Loading…
Reference in a new issue