github.com/nektos/act@v0.2.63/pkg/runner/step_action_local.go (about) 1 package runner 2 3 import ( 4 "archive/tar" 5 "context" 6 "errors" 7 "fmt" 8 "io" 9 "io/fs" 10 "os" 11 "path" 12 "path/filepath" 13 14 "github.com/nektos/act/pkg/common" 15 "github.com/nektos/act/pkg/model" 16 ) 17 18 type stepActionLocal struct { 19 Step *model.Step 20 RunContext *RunContext 21 compositeRunContext *RunContext 22 compositeSteps *compositeSteps 23 runAction runAction 24 readAction readAction 25 env map[string]string 26 action *model.Action 27 } 28 29 func (sal *stepActionLocal) pre() common.Executor { 30 sal.env = map[string]string{} 31 32 return func(ctx context.Context) error { 33 return nil 34 } 35 } 36 37 func (sal *stepActionLocal) main() common.Executor { 38 return runStepExecutor(sal, stepStageMain, func(ctx context.Context) error { 39 if common.Dryrun(ctx) { 40 return nil 41 } 42 43 actionDir := filepath.Join(sal.getRunContext().Config.Workdir, sal.Step.Uses) 44 45 localReader := func(ctx context.Context) actionYamlReader { 46 _, cpath := getContainerActionPaths(sal.Step, path.Join(actionDir, ""), sal.RunContext) 47 return func(filename string) (io.Reader, io.Closer, error) { 48 spath := path.Join(cpath, filename) 49 for i := 0; i < maxSymlinkDepth; i++ { 50 tars, err := sal.RunContext.JobContainer.GetContainerArchive(ctx, spath) 51 if errors.Is(err, fs.ErrNotExist) { 52 return nil, nil, err 53 } else if err != nil { 54 return nil, nil, fs.ErrNotExist 55 } 56 treader := tar.NewReader(tars) 57 header, err := treader.Next() 58 if errors.Is(err, io.EOF) { 59 return nil, nil, os.ErrNotExist 60 } else if err != nil { 61 return nil, nil, err 62 } 63 if header.FileInfo().Mode()&os.ModeSymlink == os.ModeSymlink { 64 spath, err = symlinkJoin(spath, header.Linkname, cpath) 65 if err != nil { 66 return nil, nil, err 67 } 68 } else { 69 return treader, tars, nil 70 } 71 } 72 return nil, nil, fmt.Errorf("max depth %d of symlinks exceeded while reading %s", maxSymlinkDepth, spath) 73 } 74 } 75 76 actionModel, err := sal.readAction(ctx, sal.Step, actionDir, "", localReader(ctx), os.WriteFile) 77 if err != nil { 78 return err 79 } 80 81 sal.action = actionModel 82 83 return sal.runAction(sal, actionDir, nil)(ctx) 84 }) 85 } 86 87 func (sal *stepActionLocal) post() common.Executor { 88 return runStepExecutor(sal, stepStagePost, runPostStep(sal)).If(hasPostStep(sal)).If(shouldRunPostStep(sal)) 89 } 90 91 func (sal *stepActionLocal) getRunContext() *RunContext { 92 return sal.RunContext 93 } 94 95 func (sal *stepActionLocal) getGithubContext(ctx context.Context) *model.GithubContext { 96 return sal.getRunContext().getGithubContext(ctx) 97 } 98 99 func (sal *stepActionLocal) getStepModel() *model.Step { 100 return sal.Step 101 } 102 103 func (sal *stepActionLocal) getEnv() *map[string]string { 104 return &sal.env 105 } 106 107 func (sal *stepActionLocal) getIfExpression(_ context.Context, stage stepStage) string { 108 switch stage { 109 case stepStageMain: 110 return sal.Step.If.Value 111 case stepStagePost: 112 return sal.action.Runs.PostIf 113 } 114 return "" 115 } 116 117 func (sal *stepActionLocal) getActionModel() *model.Action { 118 return sal.action 119 } 120 121 func (sal *stepActionLocal) getCompositeRunContext(ctx context.Context) *RunContext { 122 if sal.compositeRunContext == nil { 123 actionDir := filepath.Join(sal.RunContext.Config.Workdir, sal.Step.Uses) 124 _, containerActionDir := getContainerActionPaths(sal.getStepModel(), actionDir, sal.RunContext) 125 126 sal.compositeRunContext = newCompositeRunContext(ctx, sal.RunContext, sal, containerActionDir) 127 sal.compositeSteps = sal.compositeRunContext.compositeExecutor(sal.action) 128 } 129 return sal.compositeRunContext 130 } 131 132 func (sal *stepActionLocal) getCompositeSteps() *compositeSteps { 133 return sal.compositeSteps 134 }