From 7ae9916de0c82101d6e64791251b2a5ea1f39918 Mon Sep 17 00:00:00 2001 From: "Ryan (hackercat)" Date: Mon, 3 May 2021 16:37:20 +0200 Subject: [PATCH] Add option to allow files/directories in `.gitignore` to be copied to container (#537) * disable gitignore for actions * feat: Add option to allow/disallow paths specified in .gitignore Co-authored-by: Alan Birtles --- README.md | 1 + cmd/input.go | 1 + cmd/root.go | 2 ++ pkg/container/docker_run.go | 23 +++++++++++++---------- pkg/runner/run_context.go | 2 +- pkg/runner/runner.go | 1 + pkg/runner/step_context.go | 2 +- 7 files changed, 20 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index f166d77..5994ff3 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ It will save that information to `~/.actrc`, please refer to [Configuration](#co -r, --reuse reuse action containers to maintain state -s, --secret stringArray secret to make available to actions with optional value (e.g. -s mysecret=foo or -s mysecret) --secret-file string file with list of secrets to read from (e.g. --secret-file .secrets) (default ".secrets") + --use-gitignore Controls whether paths specified in .gitignore should be copied into container (default true) --userns string user namespace to use -v, --verbose verbose output -w, --watch watch the contents of the local repo and run when files change diff --git a/cmd/input.go b/cmd/input.go index b54bc68..0e3451a 100644 --- a/cmd/input.go +++ b/cmd/input.go @@ -27,6 +27,7 @@ type Input struct { privileged bool usernsMode string containerArchitecture string + useGitIgnore bool } func (i *Input) resolve(path string) string { diff --git a/cmd/root.go b/cmd/root.go index 8ef464a..fac8f74 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -49,6 +49,7 @@ func Execute(ctx context.Context, version string) { rootCmd.Flags().StringVar(&input.defaultBranch, "defaultbranch", "", "the name of the main branch") rootCmd.Flags().BoolVar(&input.privileged, "privileged", false, "use privileged mode") rootCmd.Flags().StringVar(&input.usernsMode, "userns", "", "user namespace to use") + rootCmd.Flags().BoolVar(&input.useGitIgnore, "use-gitignore", true, "Controls whether paths specified in .gitignore should be copied into container") rootCmd.PersistentFlags().StringVarP(&input.actor, "actor", "a", "nektos/act", "user that triggered the event") rootCmd.PersistentFlags().StringVarP(&input.workflowsPath, "workflows", "W", "./.github/workflows/", "path to workflow file(s)") rootCmd.PersistentFlags().StringVarP(&input.workdir, "directory", "C", ".", "working directory") @@ -252,6 +253,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str Privileged: input.privileged, UsernsMode: input.usernsMode, ContainerArchitecture: input.containerArchitecture, + UseGitIgnore: input.useGitIgnore, } r, err := runner.New(config) if err != nil { diff --git a/pkg/container/docker_run.go b/pkg/container/docker_run.go index cec98cb..1374c38 100644 --- a/pkg/container/docker_run.go +++ b/pkg/container/docker_run.go @@ -63,7 +63,7 @@ type FileEntry struct { type Container interface { Create() common.Executor Copy(destPath string, files ...*FileEntry) common.Executor - CopyDir(destPath string, srcPath string) common.Executor + CopyDir(destPath string, srcPath string, useGitIgnore bool) common.Executor Pull(forcePull bool) common.Executor Start(attach bool) common.Executor Exec(command []string, env map[string]string) common.Executor @@ -136,13 +136,13 @@ func (cr *containerReference) Copy(destPath string, files ...*FileEntry) common. ).IfNot(common.Dryrun) } -func (cr *containerReference) CopyDir(destPath string, srcPath string) common.Executor { +func (cr *containerReference) CopyDir(destPath string, srcPath string, useGitIgnore bool) common.Executor { return common.NewPipelineExecutor( common.NewInfoExecutor("%sdocker cp src=%s dst=%s", logPrefix, srcPath, destPath), cr.connect(), cr.find(), cr.exec([]string{"mkdir", "-p", destPath}, nil), - cr.copyDir(destPath, srcPath), + cr.copyDir(destPath, srcPath, useGitIgnore), ).IfNot(common.Dryrun) } @@ -448,7 +448,7 @@ func (cr *containerReference) exec(cmd []string, env map[string]string) common.E } // nolint: gocyclo -func (cr *containerReference) copyDir(dstPath string, srcPath string) common.Executor { +func (cr *containerReference) copyDir(dstPath string, srcPath string, useGitIgnore bool) common.Executor { return func(ctx context.Context) error { logger := common.Logger(ctx) tarFile, err := ioutil.TempFile("", "act") @@ -466,12 +466,15 @@ func (cr *containerReference) copyDir(dstPath string, srcPath string) common.Exe } log.Debugf("Stripping prefix:%s src:%s", srcPrefix, srcPath) - ps, err := gitignore.ReadPatterns(polyfill.New(osfs.New(srcPath)), nil) - if err != nil { - log.Debugf("Error loading .gitignore: %v", err) - } + var ignorer gitignore.Matcher + if useGitIgnore { + ps, err := gitignore.ReadPatterns(polyfill.New(osfs.New(srcPath)), nil) + if err != nil { + log.Debugf("Error loading .gitignore: %v", err) + } - ignorer := gitignore.NewMatcher(ps) + ignorer = gitignore.NewMatcher(ps) + } err = filepath.Walk(srcPath, func(file string, fi os.FileInfo, err error) error { if err != nil { @@ -480,7 +483,7 @@ func (cr *containerReference) copyDir(dstPath string, srcPath string) common.Exe sansPrefix := strings.TrimPrefix(file, srcPrefix) split := strings.Split(sansPrefix, string(filepath.Separator)) - if ignorer.Match(split, fi.IsDir()) { + if ignorer != nil && ignorer.Match(split, fi.IsDir()) { if fi.IsDir() { return filepath.SkipDir } diff --git a/pkg/runner/run_context.go b/pkg/runner/run_context.go index 042fb2f..96335fb 100755 --- a/pkg/runner/run_context.go +++ b/pkg/runner/run_context.go @@ -129,7 +129,7 @@ func (rc *RunContext) startJobContainer() common.Executor { rc.stopJobContainer(), rc.JobContainer.Create(), rc.JobContainer.Start(false), - rc.JobContainer.CopyDir(copyToPath, rc.Config.Workdir+string(filepath.Separator)+".").IfBool(copyWorkspace), + rc.JobContainer.CopyDir(copyToPath, rc.Config.Workdir+string(filepath.Separator)+".", rc.Config.UseGitIgnore).IfBool(copyWorkspace), rc.JobContainer.Copy(filepath.Dir(rc.Config.Workdir), &container.FileEntry{ Name: "workflow/event.json", Mode: 0644, diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 9220379..912e2de 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -33,6 +33,7 @@ type Config struct { Privileged bool // use privileged mode UsernsMode string // user namespace to use ContainerArchitecture string // Desired OS/architecture platform for running containers + UseGitIgnore bool // controls if paths in .gitignore should not be copied into container, default true } type runnerImpl struct { diff --git a/pkg/runner/step_context.go b/pkg/runner/step_context.go index 9e49a68..730d5ed 100755 --- a/pkg/runner/step_context.go +++ b/pkg/runner/step_context.go @@ -415,7 +415,7 @@ func (sc *StepContext) runAction(actionDir string, actionPath string) common.Exe if err != nil { return err } - err = rc.JobContainer.CopyDir(containerActionDir+"/", actionDir)(ctx) + err = rc.JobContainer.CopyDir(containerActionDir+"/", actionDir, rc.Config.UseGitIgnore)(ctx) if err != nil { return err }