mirror of
https://gitea.com/gitea/act_runner.git
synced 2026-03-25 00:05:03 +01:00
feat: make use new action cache the new default for downloading actions (#12)
* remove legacy action caching * migrate tests * clear old legacy action cache when run
This commit is contained in:
@@ -58,7 +58,6 @@ type Input struct {
|
|||||||
actionOfflineMode bool
|
actionOfflineMode bool
|
||||||
logPrefixJobID bool
|
logPrefixJobID bool
|
||||||
networkName string
|
networkName string
|
||||||
useNewActionCache bool
|
|
||||||
localRepository []string
|
localRepository []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
50
cmd/root.go
50
cmd/root.go
@@ -102,7 +102,6 @@ func Execute(ctx context.Context, version string) {
|
|||||||
rootCmd.PersistentFlags().StringVarP(&input.actionCachePath, "action-cache-path", "", filepath.Join(CacheHomeDir, "act"), "Defines the path where the actions get cached and host workspaces created.")
|
rootCmd.PersistentFlags().StringVarP(&input.actionCachePath, "action-cache-path", "", filepath.Join(CacheHomeDir, "act"), "Defines the path where the actions get cached and host workspaces created.")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&input.actionOfflineMode, "action-offline-mode", "", false, "If action contents exists, it will not be fetch and pull again. If turn on this, will turn off force pull")
|
rootCmd.PersistentFlags().BoolVarP(&input.actionOfflineMode, "action-offline-mode", "", false, "If action contents exists, it will not be fetch and pull again. If turn on this, will turn off force pull")
|
||||||
rootCmd.PersistentFlags().StringVarP(&input.networkName, "network", "", "host", "Sets a docker network name. Defaults to host.")
|
rootCmd.PersistentFlags().StringVarP(&input.networkName, "network", "", "host", "Sets a docker network name. Defaults to host.")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&input.useNewActionCache, "use-new-action-cache", "", false, "Enable using the new Action Cache for storing Actions locally")
|
|
||||||
rootCmd.PersistentFlags().StringArrayVarP(&input.localRepository, "local-repository", "", []string{}, "Replaces the specified repository and ref with a local folder (e.g. https://github.com/test/test@v0=/home/act/test or test/test@v0=/home/act/test, the latter matches any hosts or protocols)")
|
rootCmd.PersistentFlags().StringArrayVarP(&input.localRepository, "local-repository", "", []string{}, "Replaces the specified repository and ref with a local folder (e.g. https://github.com/test/test@v0=/home/act/test or test/test@v0=/home/act/test, the latter matches any hosts or protocols)")
|
||||||
rootCmd.SetArgs(args())
|
rootCmd.SetArgs(args())
|
||||||
|
|
||||||
@@ -393,6 +392,16 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
|||||||
vars := newSecrets(input.vars)
|
vars := newSecrets(input.vars)
|
||||||
_ = readEnvs(input.Varfile(), vars)
|
_ = readEnvs(input.Varfile(), vars)
|
||||||
|
|
||||||
|
log.Debugf("Cleaning up %s old action cache format", input.actionCachePath)
|
||||||
|
entries, _ := os.ReadDir(input.actionCachePath)
|
||||||
|
for _, entry := range entries {
|
||||||
|
if strings.Contains(entry.Name(), "@") {
|
||||||
|
fullPath := filepath.Join(input.actionCachePath, entry.Name())
|
||||||
|
log.Debugf("Removing %s", fullPath)
|
||||||
|
_ = os.RemoveAll(fullPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
matrixes := parseMatrix(input.matrix)
|
matrixes := parseMatrix(input.matrix)
|
||||||
log.Debugf("Evaluated matrix inclusions: %v", matrixes)
|
log.Debugf("Evaluated matrix inclusions: %v", matrixes)
|
||||||
|
|
||||||
@@ -588,31 +597,26 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
|||||||
Matrix: matrixes,
|
Matrix: matrixes,
|
||||||
ContainerNetworkMode: docker_container.NetworkMode(input.networkName),
|
ContainerNetworkMode: docker_container.NetworkMode(input.networkName),
|
||||||
}
|
}
|
||||||
if input.useNewActionCache || len(input.localRepository) > 0 {
|
if input.actionOfflineMode {
|
||||||
if input.actionOfflineMode {
|
config.ActionCache = &runner.GoGitActionCacheOfflineMode{
|
||||||
config.ActionCache = &runner.GoGitActionCacheOfflineMode{
|
Parent: runner.GoGitActionCache{
|
||||||
Parent: runner.GoGitActionCache{
|
|
||||||
Path: config.ActionCacheDir,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
config.ActionCache = &runner.GoGitActionCache{
|
|
||||||
Path: config.ActionCacheDir,
|
Path: config.ActionCacheDir,
|
||||||
}
|
},
|
||||||
}
|
|
||||||
if len(input.localRepository) > 0 {
|
|
||||||
localRepositories := map[string]string{}
|
|
||||||
for _, l := range input.localRepository {
|
|
||||||
k, v, _ := strings.Cut(l, "=")
|
|
||||||
localRepositories[k] = v
|
|
||||||
}
|
|
||||||
config.ActionCache = &runner.LocalRepositoryCache{
|
|
||||||
Parent: config.ActionCache,
|
|
||||||
LocalRepositories: localRepositories,
|
|
||||||
CacheDirCache: map[string]string{},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if len(input.localRepository) > 0 {
|
||||||
|
localRepositories := map[string]string{}
|
||||||
|
for _, l := range input.localRepository {
|
||||||
|
k, v, _ := strings.Cut(l, "=")
|
||||||
|
localRepositories[k] = v
|
||||||
|
}
|
||||||
|
config.ActionCache = &runner.LocalRepositoryCache{
|
||||||
|
Parent: config.ActionCache,
|
||||||
|
LocalRepositories: localRepositories,
|
||||||
|
CacheDirCache: map[string]string{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
r, err := runner.New(config)
|
r, err := runner.New(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -699,6 +699,9 @@ func (cr *containerReference) waitForCommand(ctx context.Context, isTerminal boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cr *containerReference) CopyTarStream(ctx context.Context, destPath string, tarStream io.Reader) error {
|
func (cr *containerReference) CopyTarStream(ctx context.Context, destPath string, tarStream io.Reader) error {
|
||||||
|
if common.Dryrun(ctx) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// Mkdir
|
// Mkdir
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
tw := tar.NewWriter(buf)
|
tw := tar.NewWriter(buf)
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ func (e *HostEnvironment) Copy(destPath string, files ...*FileEntry) common.Exec
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *HostEnvironment) CopyTarStream(ctx context.Context, destPath string, tarStream io.Reader) error {
|
func (e *HostEnvironment) CopyTarStream(ctx context.Context, destPath string, tarStream io.Reader) error {
|
||||||
|
if common.Dryrun(ctx) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if err := os.RemoveAll(destPath); err != nil {
|
if err := os.RemoveAll(destPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ func readActionImpl(ctx context.Context, step *model.Step, actionDir string, act
|
|||||||
return action, err
|
return action, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func maybeCopyToActionDir(ctx context.Context, step actionStep, actionDir string, actionPath string, containerActionDir string) error {
|
func maybeCopyToActionDir(ctx context.Context, step actionStep, actionPath string, containerActionDir string) error {
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
rc := step.getRunContext()
|
rc := step.getRunContext()
|
||||||
stepModel := step.getStepModel()
|
stepModel := step.getStepModel()
|
||||||
@@ -133,21 +133,13 @@ func maybeCopyToActionDir(ctx context.Context, step actionStep, actionDir string
|
|||||||
containerActionDirCopy += `/`
|
containerActionDirCopy += `/`
|
||||||
}
|
}
|
||||||
|
|
||||||
if rc.Config != nil && rc.Config.ActionCache != nil {
|
raction := step.(*stepActionRemote)
|
||||||
raction := step.(*stepActionRemote)
|
ta, err := rc.getActionCache().GetTarArchive(ctx, raction.cacheDir, raction.resolvedSha, "")
|
||||||
ta, err := rc.Config.ActionCache.GetTarArchive(ctx, raction.cacheDir, raction.resolvedSha, "")
|
if err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer ta.Close()
|
|
||||||
return rc.JobContainer.CopyTarStream(ctx, containerActionDirCopy, ta)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := removeGitIgnore(ctx, actionDir); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer ta.Close()
|
||||||
return rc.JobContainer.CopyDir(containerActionDirCopy, actionDir+"/", rc.Config.UseGitIgnore)(ctx)
|
return rc.JobContainer.CopyTarStream(ctx, containerActionDirCopy, ta)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction) common.Executor {
|
func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction) common.Executor {
|
||||||
@@ -176,7 +168,7 @@ func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction
|
|||||||
|
|
||||||
switch action.Runs.Using {
|
switch action.Runs.Using {
|
||||||
case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20:
|
case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20:
|
||||||
if err := maybeCopyToActionDir(ctx, step, actionDir, actionPath, containerActionDir); err != nil {
|
if err := maybeCopyToActionDir(ctx, step, actionPath, containerActionDir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
containerArgs := []string{rc.GetNodeToolFullPath(ctx), path.Join(containerActionDir, action.Runs.Main)}
|
containerArgs := []string{rc.GetNodeToolFullPath(ctx), path.Join(containerActionDir, action.Runs.Main)}
|
||||||
@@ -186,13 +178,13 @@ func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction
|
|||||||
|
|
||||||
return rc.execJobContainer(containerArgs, *step.getEnv(), "", "")(ctx)
|
return rc.execJobContainer(containerArgs, *step.getEnv(), "", "")(ctx)
|
||||||
case model.ActionRunsUsingDocker:
|
case model.ActionRunsUsingDocker:
|
||||||
location := actionLocation
|
|
||||||
if remoteAction == nil {
|
if remoteAction == nil {
|
||||||
location = containerActionDir
|
actionDir = ""
|
||||||
|
actionPath = containerActionDir
|
||||||
}
|
}
|
||||||
return execAsDocker(ctx, step, actionName, location, remoteAction == nil, "entrypoint")
|
return execAsDocker(ctx, step, actionName, actionDir, actionPath, remoteAction == nil, "entrypoint")
|
||||||
case model.ActionRunsUsingComposite:
|
case model.ActionRunsUsingComposite:
|
||||||
if err := maybeCopyToActionDir(ctx, step, actionDir, actionPath, containerActionDir); err != nil {
|
if err := maybeCopyToActionDir(ctx, step, actionPath, containerActionDir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,27 +215,10 @@ func setupActionEnv(ctx context.Context, step actionStep, _ *remoteAction) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/nektos/act/issues/228#issuecomment-629709055
|
|
||||||
// files in .gitignore are not copied in a Docker container
|
|
||||||
// this causes issues with actions that ignore other important resources
|
|
||||||
// such as `node_modules` for example
|
|
||||||
func removeGitIgnore(ctx context.Context, directory string) error {
|
|
||||||
gitIgnorePath := path.Join(directory, ".gitignore")
|
|
||||||
if _, err := os.Stat(gitIgnorePath); err == nil {
|
|
||||||
// .gitignore exists
|
|
||||||
common.Logger(ctx).Debugf("Removing %s before docker cp", gitIgnorePath)
|
|
||||||
err := os.Remove(gitIgnorePath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: break out parts of function to reduce complexicity
|
// TODO: break out parts of function to reduce complexicity
|
||||||
//
|
//
|
||||||
//nolint:gocyclo
|
//nolint:gocyclo
|
||||||
func execAsDocker(ctx context.Context, step actionStep, actionName string, basedir string, localAction bool, entrypointType string) error {
|
func execAsDocker(ctx context.Context, step actionStep, actionName, basedir, subpath string, localAction bool, entrypointType string) error {
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
rc := step.getRunContext()
|
rc := step.getRunContext()
|
||||||
action := step.getActionModel()
|
action := step.getActionModel()
|
||||||
@@ -260,7 +235,7 @@ func execAsDocker(ctx context.Context, step actionStep, actionName string, based
|
|||||||
image = fmt.Sprintf("%s-dockeraction:%s", regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(actionName, "-"), "latest")
|
image = fmt.Sprintf("%s-dockeraction:%s", regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(actionName, "-"), "latest")
|
||||||
image = fmt.Sprintf("act-%s", strings.TrimLeft(image, "-"))
|
image = fmt.Sprintf("act-%s", strings.TrimLeft(image, "-"))
|
||||||
image = strings.ToLower(image)
|
image = strings.ToLower(image)
|
||||||
contextDir, fileName := filepath.Split(filepath.Join(basedir, action.Runs.Image))
|
contextDir, fileName := path.Split(path.Join(subpath, action.Runs.Image))
|
||||||
|
|
||||||
anyArchExists, err := container.ImageExistsLocally(ctx, image, "any")
|
anyArchExists, err := container.ImageExistsLocally(ctx, image, "any")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -291,16 +266,16 @@ func execAsDocker(ctx context.Context, step actionStep, actionName string, based
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer buildContext.Close()
|
defer buildContext.Close()
|
||||||
} else if rc.Config.ActionCache != nil {
|
} else {
|
||||||
rstep := step.(*stepActionRemote)
|
rstep := step.(*stepActionRemote)
|
||||||
buildContext, err = rc.Config.ActionCache.GetTarArchive(ctx, rstep.cacheDir, rstep.resolvedSha, contextDir)
|
buildContext, err = rc.getActionCache().GetTarArchive(ctx, rstep.cacheDir, rstep.resolvedSha, contextDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer buildContext.Close()
|
defer buildContext.Close()
|
||||||
}
|
}
|
||||||
prepImage = container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{
|
prepImage = container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{
|
||||||
ContextDir: contextDir,
|
ContextDir: filepath.Join(basedir, contextDir),
|
||||||
Dockerfile: fileName,
|
Dockerfile: fileName,
|
||||||
ImageTag: image,
|
ImageTag: image,
|
||||||
BuildContext: buildContext,
|
BuildContext: buildContext,
|
||||||
@@ -324,6 +299,7 @@ func execAsDocker(ctx context.Context, step actionStep, actionName string, based
|
|||||||
if len(entrypoint) == 0 {
|
if len(entrypoint) == 0 {
|
||||||
if entrypointType == "pre-entrypoint" && action.Runs.PreEntrypoint != "" {
|
if entrypointType == "pre-entrypoint" && action.Runs.PreEntrypoint != "" {
|
||||||
entrypoint, err = shellquote.Split(action.Runs.PreEntrypoint)
|
entrypoint, err = shellquote.Split(action.Runs.PreEntrypoint)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -545,7 +521,7 @@ func runPreStep(step actionStep) common.Executor {
|
|||||||
|
|
||||||
switch action.Runs.Using {
|
switch action.Runs.Using {
|
||||||
case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20:
|
case model.ActionRunsUsingNode12, model.ActionRunsUsingNode16, model.ActionRunsUsingNode20:
|
||||||
if err := maybeCopyToActionDir(ctx, step, actionDir, actionPath, containerActionDir); err != nil {
|
if err := maybeCopyToActionDir(ctx, step, actionPath, containerActionDir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,11 +533,11 @@ func runPreStep(step actionStep) common.Executor {
|
|||||||
return rc.execJobContainer(containerArgs, *step.getEnv(), "", "")(ctx)
|
return rc.execJobContainer(containerArgs, *step.getEnv(), "", "")(ctx)
|
||||||
|
|
||||||
case model.ActionRunsUsingDocker:
|
case model.ActionRunsUsingDocker:
|
||||||
location := actionLocation
|
|
||||||
if remoteAction == nil {
|
if remoteAction == nil {
|
||||||
location = containerActionDir
|
actionDir = ""
|
||||||
|
actionPath = containerActionDir
|
||||||
}
|
}
|
||||||
return execAsDocker(ctx, step, actionName, location, remoteAction == nil, "pre-entrypoint")
|
return execAsDocker(ctx, step, actionName, actionDir, actionPath, remoteAction == nil, "pre-entrypoint")
|
||||||
|
|
||||||
case model.ActionRunsUsingComposite:
|
case model.ActionRunsUsingComposite:
|
||||||
if step.getCompositeSteps() == nil {
|
if step.getCompositeSteps() == nil {
|
||||||
@@ -662,14 +638,14 @@ func runPostStep(step actionStep) common.Executor {
|
|||||||
return rc.execJobContainer(containerArgs, *step.getEnv(), "", "")(ctx)
|
return rc.execJobContainer(containerArgs, *step.getEnv(), "", "")(ctx)
|
||||||
|
|
||||||
case model.ActionRunsUsingDocker:
|
case model.ActionRunsUsingDocker:
|
||||||
location := actionLocation
|
|
||||||
if remoteAction == nil {
|
if remoteAction == nil {
|
||||||
location = containerActionDir
|
actionDir = ""
|
||||||
|
actionPath = containerActionDir
|
||||||
}
|
}
|
||||||
return execAsDocker(ctx, step, actionName, location, remoteAction == nil, "post-entrypoint")
|
return execAsDocker(ctx, step, actionName, actionDir, actionPath, remoteAction == nil, "post-entrypoint")
|
||||||
|
|
||||||
case model.ActionRunsUsingComposite:
|
case model.ActionRunsUsingComposite:
|
||||||
if err := maybeCopyToActionDir(ctx, step, actionDir, actionPath, containerActionDir); err != nil {
|
if err := maybeCopyToActionDir(ctx, step, actionPath, containerActionDir); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -227,7 +227,10 @@ func TestActionRunner(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
cm := &containerMock{}
|
cm := &containerMock{}
|
||||||
cm.On("CopyDir", "/var/run/act/actions/dir/", "dir/", false).Return(func(_ context.Context) error { return nil })
|
cm.Mock.On("CopyTarStream", ctx, "/var/run/act/actions/dir/", mock.Anything).Return(nil)
|
||||||
|
|
||||||
|
cacheMock := &TestRepositoryCache{}
|
||||||
|
cacheMock.Mock.On("GetTarArchive", ctx, "", "", "").Return(io.NopCloser(io.MultiReader()))
|
||||||
|
|
||||||
envMatcher := mock.MatchedBy(func(env map[string]string) bool {
|
envMatcher := mock.MatchedBy(func(env map[string]string) bool {
|
||||||
for k, v := range tt.expectedEnv {
|
for k, v := range tt.expectedEnv {
|
||||||
@@ -241,6 +244,7 @@ func TestActionRunner(t *testing.T) {
|
|||||||
cm.On("Exec", []string{"node", "/var/run/act/actions/dir/path"}, envMatcher, "", "").Return(func(_ context.Context) error { return nil })
|
cm.On("Exec", []string{"node", "/var/run/act/actions/dir/path"}, envMatcher, "", "").Return(func(_ context.Context) error { return nil })
|
||||||
|
|
||||||
tt.step.getRunContext().JobContainer = cm
|
tt.step.getRunContext().JobContainer = cm
|
||||||
|
tt.step.getRunContext().Config.ActionCache = cacheMock
|
||||||
|
|
||||||
err := runActionImpl(tt.step, "dir", newRemoteAction("org/repo/path@ref"))(ctx)
|
err := runActionImpl(tt.step, "dir", newRemoteAction("org/repo/path@ref"))(ctx)
|
||||||
|
|
||||||
|
|||||||
@@ -73,3 +73,12 @@ func (cm *containerMock) GetContainerArchive(ctx context.Context, srcPath string
|
|||||||
}
|
}
|
||||||
return args.Get(0).(io.ReadCloser), err
|
return args.Get(0).(io.ReadCloser), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cm *containerMock) CopyTarStream(ctx context.Context, destPath string, tarStream io.Reader) error {
|
||||||
|
args := cm.Mock.Called(ctx, destPath, tarStream)
|
||||||
|
err, hasErr := args.Get(0).(error)
|
||||||
|
if !hasErr {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,16 +3,11 @@ package runner
|
|||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -32,27 +27,20 @@ func newRemoteReusableWorkflowExecutor(rc *RunContext) common.Executor {
|
|||||||
// instead we will just use {owner}-{repo}@{ref} as our target directory. This should also improve performance when we are using
|
// instead we will just use {owner}-{repo}@{ref} as our target directory. This should also improve performance when we are using
|
||||||
// multiple reusable workflows from the same repository and ref since for each workflow we won't have to clone it again
|
// multiple reusable workflows from the same repository and ref since for each workflow we won't have to clone it again
|
||||||
filename := fmt.Sprintf("%s/%s@%s", remoteReusableWorkflow.Org, remoteReusableWorkflow.Repo, remoteReusableWorkflow.Ref)
|
filename := fmt.Sprintf("%s/%s@%s", remoteReusableWorkflow.Org, remoteReusableWorkflow.Repo, remoteReusableWorkflow.Ref)
|
||||||
workflowDir := fmt.Sprintf("%s/%s", rc.ActionCacheDir(), safeFilename(filename))
|
|
||||||
|
|
||||||
if rc.Config.ActionCache != nil {
|
return newActionCacheReusableWorkflowExecutor(rc, filename, remoteReusableWorkflow)
|
||||||
return newActionCacheReusableWorkflowExecutor(rc, filename, remoteReusableWorkflow)
|
|
||||||
}
|
|
||||||
|
|
||||||
return common.NewPipelineExecutor(
|
|
||||||
newMutexExecutor(cloneIfRequired(rc, *remoteReusableWorkflow, workflowDir)),
|
|
||||||
newReusableWorkflowExecutor(rc, workflowDir, fmt.Sprintf("./.github/workflows/%s", remoteReusableWorkflow.Filename)),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func newActionCacheReusableWorkflowExecutor(rc *RunContext, filename string, remoteReusableWorkflow *remoteReusableWorkflow) common.Executor {
|
func newActionCacheReusableWorkflowExecutor(rc *RunContext, filename string, remoteReusableWorkflow *remoteReusableWorkflow) common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
ghctx := rc.getGithubContext(ctx)
|
ghctx := rc.getGithubContext(ctx)
|
||||||
remoteReusableWorkflow.URL = ghctx.ServerURL
|
remoteReusableWorkflow.URL = ghctx.ServerURL
|
||||||
sha, err := rc.Config.ActionCache.Fetch(ctx, filename, remoteReusableWorkflow.CloneURL(), remoteReusableWorkflow.Ref, ghctx.Token)
|
cache := rc.getActionCache()
|
||||||
|
sha, err := cache.Fetch(ctx, filename, remoteReusableWorkflow.CloneURL(), remoteReusableWorkflow.Ref, ghctx.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
archive, err := rc.Config.ActionCache.GetTarArchive(ctx, filename, sha, fmt.Sprintf(".github/workflows/%s", remoteReusableWorkflow.Filename))
|
archive, err := cache.GetTarArchive(ctx, filename, sha, fmt.Sprintf(".github/workflows/%s", remoteReusableWorkflow.Filename))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -79,40 +67,6 @@ func newActionCacheReusableWorkflowExecutor(rc *RunContext, filename string, rem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
executorLock sync.Mutex
|
|
||||||
)
|
|
||||||
|
|
||||||
func newMutexExecutor(executor common.Executor) common.Executor {
|
|
||||||
return func(ctx context.Context) error {
|
|
||||||
executorLock.Lock()
|
|
||||||
defer executorLock.Unlock()
|
|
||||||
|
|
||||||
return executor(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func cloneIfRequired(rc *RunContext, remoteReusableWorkflow remoteReusableWorkflow, targetDirectory string) common.Executor {
|
|
||||||
return common.NewConditionalExecutor(
|
|
||||||
func(_ context.Context) bool {
|
|
||||||
_, err := os.Stat(targetDirectory)
|
|
||||||
notExists := errors.Is(err, fs.ErrNotExist)
|
|
||||||
return notExists
|
|
||||||
},
|
|
||||||
func(ctx context.Context) error {
|
|
||||||
remoteReusableWorkflow.URL = rc.getGithubContext(ctx).ServerURL
|
|
||||||
return git.NewGitCloneExecutor(git.NewGitCloneExecutorInput{
|
|
||||||
URL: remoteReusableWorkflow.CloneURL(),
|
|
||||||
Ref: remoteReusableWorkflow.Ref,
|
|
||||||
Dir: targetDirectory,
|
|
||||||
Token: rc.Config.Token,
|
|
||||||
OfflineMode: rc.Config.ActionOfflineMode,
|
|
||||||
})(ctx)
|
|
||||||
},
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newReusableWorkflowExecutor(rc *RunContext, directory string, workflow string) common.Executor {
|
func newReusableWorkflowExecutor(rc *RunContext, directory string, workflow string) common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
planner, err := model.NewWorkflowPlanner(path.Join(directory, workflow), true)
|
planner, err := model.NewWorkflowPlanner(path.Join(directory, workflow), true)
|
||||||
|
|||||||
@@ -627,6 +627,15 @@ func (rc *RunContext) ActionCacheDir() string {
|
|||||||
return filepath.Join(xdgCache, "act")
|
return filepath.Join(xdgCache, "act")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rc *RunContext) getActionCache() ActionCache {
|
||||||
|
if rc.Config.ActionCache == nil {
|
||||||
|
rc.Config.ActionCache = &GoGitActionCache{
|
||||||
|
Path: rc.ActionCacheDir(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc.Config.ActionCache
|
||||||
|
}
|
||||||
|
|
||||||
// Interpolate outputs after a job is done
|
// Interpolate outputs after a job is done
|
||||||
func (rc *RunContext) interpolateOutputs() common.Executor {
|
func (rc *RunContext) interpolateOutputs() common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package runner
|
|||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@@ -12,10 +11,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
gogit "github.com/go-git/go-git/v5"
|
|
||||||
|
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,10 +29,6 @@ type stepActionRemote struct {
|
|||||||
resolvedSha string
|
resolvedSha string
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
stepActionRemoteNewCloneExecutor = git.NewGitCloneExecutor
|
|
||||||
)
|
|
||||||
|
|
||||||
func (sar *stepActionRemote) prepareActionExecutor() common.Executor {
|
func (sar *stepActionRemote) prepareActionExecutor() common.Executor {
|
||||||
return func(ctx context.Context) error {
|
return func(ctx context.Context) error {
|
||||||
if sar.remoteAction != nil && sar.action != nil {
|
if sar.remoteAction != nil && sar.action != nil {
|
||||||
@@ -63,84 +55,46 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor {
|
|||||||
github.Token = sar.RunContext.Config.ReplaceGheActionTokenWithGithubCom
|
github.Token = sar.RunContext.Config.ReplaceGheActionTokenWithGithubCom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sar.RunContext.Config.ActionCache != nil {
|
cache := sar.RunContext.getActionCache()
|
||||||
cache := sar.RunContext.Config.ActionCache
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
sar.cacheDir = fmt.Sprintf("%s/%s", sar.remoteAction.Org, sar.remoteAction.Repo)
|
sar.cacheDir = fmt.Sprintf("%s/%s", sar.remoteAction.Org, sar.remoteAction.Repo)
|
||||||
repoURL := sar.remoteAction.URL + "/" + sar.cacheDir
|
repoURL := sar.remoteAction.URL + "/" + sar.cacheDir
|
||||||
repoRef := sar.remoteAction.Ref
|
repoRef := sar.remoteAction.Ref
|
||||||
sar.resolvedSha, err = cache.Fetch(ctx, sar.cacheDir, repoURL, repoRef, github.Token)
|
sar.resolvedSha, err = cache.Fetch(ctx, sar.cacheDir, repoURL, repoRef, github.Token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to fetch \"%s\" version \"%s\": %w", repoURL, repoRef, err)
|
return fmt.Errorf("failed to fetch \"%s\" version \"%s\": %w", repoURL, repoRef, err)
|
||||||
}
|
|
||||||
|
|
||||||
remoteReader := func(ctx context.Context) actionYamlReader {
|
|
||||||
return func(filename string) (io.Reader, io.Closer, error) {
|
|
||||||
spath := path.Join(sar.remoteAction.Path, filename)
|
|
||||||
for i := 0; i < maxSymlinkDepth; i++ {
|
|
||||||
tars, err := cache.GetTarArchive(ctx, sar.cacheDir, sar.resolvedSha, spath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, os.ErrNotExist
|
|
||||||
}
|
|
||||||
treader := tar.NewReader(tars)
|
|
||||||
header, err := treader.Next()
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, os.ErrNotExist
|
|
||||||
}
|
|
||||||
if header.FileInfo().Mode()&os.ModeSymlink == os.ModeSymlink {
|
|
||||||
spath, err = symlinkJoin(spath, header.Linkname, ".")
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return treader, tars, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, nil, fmt.Errorf("max depth %d of symlinks exceeded while reading %s", maxSymlinkDepth, spath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
actionModel, err := sar.readAction(ctx, sar.Step, sar.resolvedSha, sar.remoteAction.Path, remoteReader(ctx), os.WriteFile)
|
|
||||||
sar.action = actionModel
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), safeFilename(sar.Step.Uses))
|
|
||||||
gitClone := stepActionRemoteNewCloneExecutor(git.NewGitCloneExecutorInput{
|
|
||||||
URL: sar.remoteAction.CloneURL(),
|
|
||||||
Ref: sar.remoteAction.Ref,
|
|
||||||
Dir: actionDir,
|
|
||||||
Token: github.Token,
|
|
||||||
OfflineMode: sar.RunContext.Config.ActionOfflineMode,
|
|
||||||
})
|
|
||||||
var ntErr common.Executor
|
|
||||||
if err := gitClone(ctx); err != nil {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteReader := func(_ context.Context) actionYamlReader {
|
remoteReader := func(_ context.Context) actionYamlReader {
|
||||||
return func(filename string) (io.Reader, io.Closer, error) {
|
return func(filename string) (io.Reader, io.Closer, error) {
|
||||||
f, err := os.Open(filepath.Join(actionDir, sar.remoteAction.Path, filename))
|
spath := path.Join(sar.remoteAction.Path, filename)
|
||||||
return f, f, err
|
for i := 0; i < maxSymlinkDepth; i++ {
|
||||||
|
tars, err := cache.GetTarArchive(ctx, sar.cacheDir, sar.resolvedSha, spath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, os.ErrNotExist
|
||||||
|
}
|
||||||
|
treader := tar.NewReader(tars)
|
||||||
|
header, err := treader.Next()
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, os.ErrNotExist
|
||||||
|
}
|
||||||
|
if header.FileInfo().Mode()&os.ModeSymlink == os.ModeSymlink {
|
||||||
|
spath, err = symlinkJoin(spath, header.Linkname, ".")
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return treader, tars, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, nil, fmt.Errorf("max depth %d of symlinks exceeded while reading %s", maxSymlinkDepth, spath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return common.NewPipelineExecutor(
|
actionModel, err := sar.readAction(ctx, sar.Step, sar.resolvedSha, sar.remoteAction.Path, remoteReader(ctx), os.WriteFile)
|
||||||
ntErr,
|
sar.action = actionModel
|
||||||
func(ctx context.Context) error {
|
return err
|
||||||
actionModel, err := sar.readAction(ctx, sar.Step, actionDir, sar.remoteAction.Path, remoteReader(ctx), os.WriteFile)
|
|
||||||
sar.action = actionModel
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
)(ctx)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import (
|
|||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -31,6 +30,20 @@ func (sarm *stepActionRemoteMocks) runAction(step actionStep, actionDir string,
|
|||||||
return args.Get(0).(func(context.Context) error)
|
return args.Get(0).(func(context.Context) error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TestRepositoryCache struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *TestRepositoryCache) Fetch(ctx context.Context, cacheDir, url, ref, token string) (string, error) {
|
||||||
|
args := l.Mock.Called(ctx, cacheDir, url, ref, token)
|
||||||
|
return args.Get(0).(string), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *TestRepositoryCache) GetTarArchive(ctx context.Context, cacheDir, sha, includePrefix string) (io.ReadCloser, error) {
|
||||||
|
args := l.Mock.Called(ctx, cacheDir, sha, includePrefix)
|
||||||
|
return args.Get(0).(io.ReadCloser), nil
|
||||||
|
}
|
||||||
|
|
||||||
func TestStepActionRemote(t *testing.T) {
|
func TestStepActionRemote(t *testing.T) {
|
||||||
table := []struct {
|
table := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -124,23 +137,13 @@ func TestStepActionRemote(t *testing.T) {
|
|||||||
cm := &containerMock{}
|
cm := &containerMock{}
|
||||||
sarm := &stepActionRemoteMocks{}
|
sarm := &stepActionRemoteMocks{}
|
||||||
|
|
||||||
clonedAction := false
|
cacheMock := &TestRepositoryCache{}
|
||||||
|
|
||||||
origStepAtionRemoteNewCloneExecutor := stepActionRemoteNewCloneExecutor
|
|
||||||
stepActionRemoteNewCloneExecutor = func(_ git.NewGitCloneExecutorInput) common.Executor {
|
|
||||||
return func(_ context.Context) error {
|
|
||||||
clonedAction = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer (func() {
|
|
||||||
stepActionRemoteNewCloneExecutor = origStepAtionRemoteNewCloneExecutor
|
|
||||||
})()
|
|
||||||
|
|
||||||
sar := &stepActionRemote{
|
sar := &stepActionRemote{
|
||||||
RunContext: &RunContext{
|
RunContext: &RunContext{
|
||||||
Config: &Config{
|
Config: &Config{
|
||||||
GitHubInstance: "github.com",
|
GitHubInstance: "github.com",
|
||||||
|
ActionCache: cacheMock,
|
||||||
},
|
},
|
||||||
Run: &model.Run{
|
Run: &model.Run{
|
||||||
JobID: "1",
|
JobID: "1",
|
||||||
@@ -159,6 +162,7 @@ func TestStepActionRemote(t *testing.T) {
|
|||||||
}
|
}
|
||||||
sar.RunContext.ExprEval = sar.RunContext.NewExpressionEvaluator(ctx)
|
sar.RunContext.ExprEval = sar.RunContext.NewExpressionEvaluator(ctx)
|
||||||
|
|
||||||
|
cacheMock.Mock.On("Fetch", ctx, mock.AnythingOfType("string"), "https://github.com/remote/action", "v1", "").Return("someval")
|
||||||
suffixMatcher := func(suffix string) interface{} {
|
suffixMatcher := func(suffix string) interface{} {
|
||||||
return mock.MatchedBy(func(actionDir string) bool {
|
return mock.MatchedBy(func(actionDir string) bool {
|
||||||
return strings.HasSuffix(actionDir, suffix)
|
return strings.HasSuffix(actionDir, suffix)
|
||||||
@@ -166,7 +170,7 @@ func TestStepActionRemote(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tt.mocks.read {
|
if tt.mocks.read {
|
||||||
sarm.On("readAction", sar.Step, suffixMatcher("act/remote-action@v1"), "", mock.Anything, mock.Anything).Return(&model.Action{}, nil)
|
sarm.Mock.On("readAction", sar.Step, "someval", "", mock.Anything, mock.Anything).Return(&model.Action{}, nil)
|
||||||
}
|
}
|
||||||
if tt.mocks.run {
|
if tt.mocks.run {
|
||||||
sarm.On("runAction", sar, suffixMatcher("act/remote-action@v1"), newRemoteAction(sar.Step.Uses)).Return(func(_ context.Context) error { return tt.runError })
|
sarm.On("runAction", sar, suffixMatcher("act/remote-action@v1"), newRemoteAction(sar.Step.Uses)).Return(func(_ context.Context) error { return tt.runError })
|
||||||
@@ -196,11 +200,11 @@ func TestStepActionRemote(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, tt.runError, err)
|
assert.Equal(t, tt.runError, err)
|
||||||
assert.Equal(t, tt.mocks.cloned, clonedAction)
|
|
||||||
assert.Equal(t, tt.result, sar.RunContext.StepResults["step"])
|
assert.Equal(t, tt.result, sar.RunContext.StepResults["step"])
|
||||||
|
|
||||||
sarm.AssertExpectations(t)
|
sarm.AssertExpectations(t)
|
||||||
cm.AssertExpectations(t)
|
cm.AssertExpectations(t)
|
||||||
|
cacheMock.Mock.AssertExpectations(t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,25 +226,15 @@ func TestStepActionRemotePre(t *testing.T) {
|
|||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
clonedAction := false
|
cacheMock := &TestRepositoryCache{}
|
||||||
sarm := &stepActionRemoteMocks{}
|
sarm := &stepActionRemoteMocks{}
|
||||||
|
|
||||||
origStepAtionRemoteNewCloneExecutor := stepActionRemoteNewCloneExecutor
|
|
||||||
stepActionRemoteNewCloneExecutor = func(_ git.NewGitCloneExecutorInput) common.Executor {
|
|
||||||
return func(_ context.Context) error {
|
|
||||||
clonedAction = true
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer (func() {
|
|
||||||
stepActionRemoteNewCloneExecutor = origStepAtionRemoteNewCloneExecutor
|
|
||||||
})()
|
|
||||||
|
|
||||||
sar := &stepActionRemote{
|
sar := &stepActionRemote{
|
||||||
Step: tt.stepModel,
|
Step: tt.stepModel,
|
||||||
RunContext: &RunContext{
|
RunContext: &RunContext{
|
||||||
Config: &Config{
|
Config: &Config{
|
||||||
GitHubInstance: "https://github.com",
|
GitHubInstance: "github.com",
|
||||||
|
ActionCache: cacheMock,
|
||||||
},
|
},
|
||||||
Run: &model.Run{
|
Run: &model.Run{
|
||||||
JobID: "1",
|
JobID: "1",
|
||||||
@@ -254,20 +248,15 @@ func TestStepActionRemotePre(t *testing.T) {
|
|||||||
readAction: sarm.readAction,
|
readAction: sarm.readAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
suffixMatcher := func(suffix string) interface{} {
|
sarm.Mock.On("readAction", sar.Step, "someval", "path", mock.Anything, mock.Anything).Return(&model.Action{}, nil)
|
||||||
return mock.MatchedBy(func(actionDir string) bool {
|
cacheMock.Mock.On("Fetch", ctx, mock.AnythingOfType("string"), "https://github.com/org/repo", "ref", "").Return("someval")
|
||||||
return strings.HasSuffix(actionDir, suffix)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
sarm.On("readAction", sar.Step, suffixMatcher("org-repo-path@ref"), "path", mock.Anything, mock.Anything).Return(&model.Action{}, nil)
|
|
||||||
|
|
||||||
err := sar.pre()(ctx)
|
err := sar.pre()(ctx)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, true, clonedAction)
|
|
||||||
|
|
||||||
sarm.AssertExpectations(t)
|
sarm.AssertExpectations(t)
|
||||||
|
cacheMock.Mock.AssertExpectations(t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -289,28 +278,16 @@ func TestStepActionRemotePreThroughAction(t *testing.T) {
|
|||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
clonedAction := false
|
cacheMock := &TestRepositoryCache{}
|
||||||
sarm := &stepActionRemoteMocks{}
|
sarm := &stepActionRemoteMocks{}
|
||||||
|
|
||||||
origStepAtionRemoteNewCloneExecutor := stepActionRemoteNewCloneExecutor
|
|
||||||
stepActionRemoteNewCloneExecutor = func(input git.NewGitCloneExecutorInput) common.Executor {
|
|
||||||
return func(_ context.Context) error {
|
|
||||||
if input.URL == "https://github.com/org/repo" {
|
|
||||||
clonedAction = true
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer (func() {
|
|
||||||
stepActionRemoteNewCloneExecutor = origStepAtionRemoteNewCloneExecutor
|
|
||||||
})()
|
|
||||||
|
|
||||||
sar := &stepActionRemote{
|
sar := &stepActionRemote{
|
||||||
Step: tt.stepModel,
|
Step: tt.stepModel,
|
||||||
RunContext: &RunContext{
|
RunContext: &RunContext{
|
||||||
Config: &Config{
|
Config: &Config{
|
||||||
GitHubInstance: "https://enterprise.github.com",
|
GitHubInstance: "https://enterprise.github.com",
|
||||||
ReplaceGheActionWithGithubCom: []string{"org/repo"},
|
ReplaceGheActionWithGithubCom: []string{"org/repo"},
|
||||||
|
ActionCache: cacheMock,
|
||||||
},
|
},
|
||||||
Run: &model.Run{
|
Run: &model.Run{
|
||||||
JobID: "1",
|
JobID: "1",
|
||||||
@@ -324,20 +301,15 @@ func TestStepActionRemotePreThroughAction(t *testing.T) {
|
|||||||
readAction: sarm.readAction,
|
readAction: sarm.readAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
suffixMatcher := func(suffix string) interface{} {
|
sarm.Mock.On("readAction", sar.Step, mock.AnythingOfType("string"), "path", mock.Anything, mock.Anything).Return(&model.Action{}, nil)
|
||||||
return mock.MatchedBy(func(actionDir string) bool {
|
cacheMock.Mock.On("Fetch", ctx, mock.AnythingOfType("string"), "https://github.com/org/repo", "ref", "").Return("someval")
|
||||||
return strings.HasSuffix(actionDir, suffix)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
sarm.On("readAction", sar.Step, suffixMatcher("org-repo-path@ref"), "path", mock.Anything, mock.Anything).Return(&model.Action{}, nil)
|
|
||||||
|
|
||||||
err := sar.pre()(ctx)
|
err := sar.pre()(ctx)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, true, clonedAction)
|
|
||||||
|
|
||||||
sarm.AssertExpectations(t)
|
sarm.AssertExpectations(t)
|
||||||
|
cacheMock.Mock.AssertExpectations(t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -359,22 +331,9 @@ func TestStepActionRemotePreThroughActionToken(t *testing.T) {
|
|||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
clonedAction := false
|
|
||||||
sarm := &stepActionRemoteMocks{}
|
sarm := &stepActionRemoteMocks{}
|
||||||
|
|
||||||
origStepAtionRemoteNewCloneExecutor := stepActionRemoteNewCloneExecutor
|
cacheMock := &TestRepositoryCache{}
|
||||||
stepActionRemoteNewCloneExecutor = func(input git.NewGitCloneExecutorInput) common.Executor {
|
|
||||||
return func(_ context.Context) error {
|
|
||||||
if input.URL == "https://github.com/org/repo" && input.Token == "PRIVATE_ACTIONS_TOKEN_ON_GITHUB" {
|
|
||||||
clonedAction = true
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer (func() {
|
|
||||||
stepActionRemoteNewCloneExecutor = origStepAtionRemoteNewCloneExecutor
|
|
||||||
})()
|
|
||||||
|
|
||||||
sar := &stepActionRemote{
|
sar := &stepActionRemote{
|
||||||
Step: tt.stepModel,
|
Step: tt.stepModel,
|
||||||
RunContext: &RunContext{
|
RunContext: &RunContext{
|
||||||
@@ -382,6 +341,7 @@ func TestStepActionRemotePreThroughActionToken(t *testing.T) {
|
|||||||
GitHubInstance: "https://enterprise.github.com",
|
GitHubInstance: "https://enterprise.github.com",
|
||||||
ReplaceGheActionWithGithubCom: []string{"org/repo"},
|
ReplaceGheActionWithGithubCom: []string{"org/repo"},
|
||||||
ReplaceGheActionTokenWithGithubCom: "PRIVATE_ACTIONS_TOKEN_ON_GITHUB",
|
ReplaceGheActionTokenWithGithubCom: "PRIVATE_ACTIONS_TOKEN_ON_GITHUB",
|
||||||
|
ActionCache: cacheMock,
|
||||||
},
|
},
|
||||||
Run: &model.Run{
|
Run: &model.Run{
|
||||||
JobID: "1",
|
JobID: "1",
|
||||||
@@ -395,20 +355,15 @@ func TestStepActionRemotePreThroughActionToken(t *testing.T) {
|
|||||||
readAction: sarm.readAction,
|
readAction: sarm.readAction,
|
||||||
}
|
}
|
||||||
|
|
||||||
suffixMatcher := func(suffix string) interface{} {
|
sarm.Mock.On("readAction", sar.Step, mock.AnythingOfType("string"), "path", mock.Anything, mock.Anything).Return(&model.Action{}, nil)
|
||||||
return mock.MatchedBy(func(actionDir string) bool {
|
cacheMock.Mock.On("Fetch", ctx, mock.AnythingOfType("string"), "https://github.com/org/repo", "ref", "PRIVATE_ACTIONS_TOKEN_ON_GITHUB").Return("someval")
|
||||||
return strings.HasSuffix(actionDir, suffix)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
sarm.On("readAction", sar.Step, suffixMatcher("org-repo-path@ref"), "path", mock.Anything, mock.Anything).Return(&model.Action{}, nil)
|
|
||||||
|
|
||||||
err := sar.pre()(ctx)
|
err := sar.pre()(ctx)
|
||||||
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
assert.Equal(t, true, clonedAction)
|
|
||||||
|
|
||||||
sarm.AssertExpectations(t)
|
sarm.AssertExpectations(t)
|
||||||
|
cacheMock.Mock.AssertExpectations(t)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user