refactor: simplify action function signatures (#1083)

This change reduces the interfaces by removing
obsolete parameters from functions.
Obsolete parameters does not means unused ones, but
parameters which could be retrieved from other parameters
instead.

This should simplify logic and maintainability for these
functions.

Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
Markus Wolf 2022-03-29 19:42:11 +02:00 committed by GitHub
parent 31d3603173
commit 5f673cbb6d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 109 additions and 99 deletions

View file

@ -31,7 +31,7 @@ type readAction func(step *model.Step, actionDir string, actionPath string, read
type actionYamlReader func(filename string) (io.Reader, io.Closer, error) type actionYamlReader func(filename string) (io.Reader, io.Closer, error)
type fileWriter func(filename string, data []byte, perm fs.FileMode) error type fileWriter func(filename string, data []byte, perm fs.FileMode) error
type runAction func(step actionStep, actionDir string, actionPath string, actionRepository string, actionRef string, localAction bool) common.Executor type runAction func(step actionStep, actionDir string, remoteAction *remoteAction) common.Executor
//go:embed res/trampoline.js //go:embed res/trampoline.js
var trampoline embed.FS var trampoline embed.FS
@ -98,7 +98,7 @@ func readActionImpl(step *model.Step, actionDir string, actionPath string, readF
return action, err return action, err
} }
func runActionImpl(step actionStep, actionDir string, actionPath string, actionRepository string, actionRef string, localAction bool) common.Executor { func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction) common.Executor {
rc := step.getRunContext() rc := step.getRunContext()
stepModel := step.getStepModel() stepModel := step.getStepModel()
return func(ctx context.Context) error { return func(ctx context.Context) error {
@ -111,19 +111,24 @@ func runActionImpl(step actionStep, actionDir string, actionPath string, actionR
rc.ActionRef = parentActionRef rc.ActionRef = parentActionRef
rc.ActionRepository = parentActionRepository rc.ActionRepository = parentActionRepository
}() }()
rc.ActionRef = actionRef
rc.ActionRepository = actionRepository actionPath := ""
if remoteAction != nil {
rc.ActionRef = remoteAction.Ref
rc.ActionRepository = remoteAction.Repo
if remoteAction.Path != "" {
actionPath = remoteAction.Path
}
} else {
rc.ActionRef = ""
rc.ActionRepository = ""
}
action := step.getActionModel() action := step.getActionModel()
log.Debugf("About to run action %v", action) log.Debugf("About to run action %v", action)
populateEnvsFromInput(step.getEnv(), action, rc) populateEnvsFromInput(step.getEnv(), action, rc)
actionLocation := "" actionLocation := path.Join(actionDir, actionPath)
if actionPath != "" {
actionLocation = path.Join(actionDir, actionPath)
} else {
actionLocation = actionDir
}
actionName, containerActionDir := getContainerActionPaths(stepModel, actionLocation, rc) actionName, containerActionDir := getContainerActionPaths(stepModel, actionLocation, rc)
log.Debugf("type=%v actionDir=%s actionPath=%s workdir=%s actionCacheDir=%s actionName=%s containerActionDir=%s", stepModel.Type(), actionDir, actionPath, rc.Config.Workdir, rc.ActionCacheDir(), actionName, containerActionDir) log.Debugf("type=%v actionDir=%s actionPath=%s workdir=%s actionCacheDir=%s actionName=%s containerActionDir=%s", stepModel.Type(), actionDir, actionPath, rc.Config.Workdir, rc.ActionCacheDir(), actionName, containerActionDir)
@ -156,9 +161,16 @@ func runActionImpl(step actionStep, actionDir string, actionPath string, actionR
log.Debugf("executing remote job container: %s", containerArgs) log.Debugf("executing remote job container: %s", containerArgs)
return rc.execJobContainer(containerArgs, *step.getEnv(), "", "")(ctx) return rc.execJobContainer(containerArgs, *step.getEnv(), "", "")(ctx)
case model.ActionRunsUsingDocker: case model.ActionRunsUsingDocker:
return execAsDocker(ctx, action, actionName, containerActionDir, actionLocation, rc, step, localAction) location := actionLocation
if remoteAction == nil {
location = containerActionDir
}
return execAsDocker(ctx, step, actionName, location, remoteAction == nil)
case model.ActionRunsUsingComposite: case model.ActionRunsUsingComposite:
return execAsComposite(ctx, step, actionDir, rc, containerActionDir, actionName, actionPath, action, maybeCopyToActionDir) if err := maybeCopyToActionDir(); err != nil {
return err
}
return execAsComposite(step)(ctx)
default: default:
return fmt.Errorf(fmt.Sprintf("The runs.using key must be one of: %v, got %s", []string{ return fmt.Errorf(fmt.Sprintf("The runs.using key must be one of: %v, got %s", []string{
model.ActionRunsUsingDocker, model.ActionRunsUsingDocker,
@ -189,7 +201,10 @@ func removeGitIgnore(directory string) error {
// 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, action *model.Action, actionName string, containerLocation string, actionLocation string, rc *RunContext, step step, localAction bool) error { func execAsDocker(ctx context.Context, step actionStep, actionName string, basedir string, localAction bool) error {
rc := step.getRunContext()
action := step.getActionModel()
var prepImage common.Executor var prepImage common.Executor
var image string var image string
if strings.HasPrefix(action.Runs.Image, "docker://") { if strings.HasPrefix(action.Runs.Image, "docker://") {
@ -199,10 +214,6 @@ func execAsDocker(ctx context.Context, action *model.Action, actionName string,
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)
basedir := actionLocation
if localAction {
basedir = containerLocation
}
contextDir := filepath.Join(basedir, action.Runs.Main) contextDir := filepath.Join(basedir, action.Runs.Main)
anyArchExists, err := container.ImageExistsLocally(ctx, image, "any") anyArchExists, err := container.ImageExistsLocally(ctx, image, "any")
@ -229,7 +240,7 @@ func execAsDocker(ctx context.Context, action *model.Action, actionName string,
log.Debugf("image '%s' for architecture '%s' will be built from context '%s", image, rc.Config.ContainerArchitecture, contextDir) log.Debugf("image '%s' for architecture '%s' will be built from context '%s", image, rc.Config.ContainerArchitecture, contextDir)
var actionContainer container.Container var actionContainer container.Container
if localAction { if localAction {
actionContainer = step.getRunContext().JobContainer actionContainer = rc.JobContainer
} }
prepImage = container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{ prepImage = container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{
ContextDir: contextDir, ContextDir: contextDir,
@ -241,7 +252,7 @@ func execAsDocker(ctx context.Context, action *model.Action, actionName string,
log.Debugf("image '%s' for architecture '%s' already exists", image, rc.Config.ContainerArchitecture) log.Debugf("image '%s' for architecture '%s' already exists", image, rc.Config.ContainerArchitecture)
} }
} }
eval := step.getRunContext().NewStepExpressionEvaluator(step) eval := rc.NewStepExpressionEvaluator(step)
cmd, err := shellquote.Split(eval.Interpolate(step.getStepModel().With["args"])) cmd, err := shellquote.Split(eval.Interpolate(step.getStepModel().With["args"]))
if err != nil { if err != nil {
return err return err
@ -348,12 +359,11 @@ func newStepContainer(ctx context.Context, step step, image string, cmd []string
return stepContainer return stepContainer
} }
func execAsComposite(ctx context.Context, step step, _ string, rc *RunContext, containerActionDir string, actionName string, _ string, action *model.Action, maybeCopyToActionDir func() error) error { func execAsComposite(step actionStep) common.Executor {
err := maybeCopyToActionDir() rc := step.getRunContext()
action := step.getActionModel()
if err != nil { return func(ctx context.Context) error {
return err
}
// Disable some features of composite actions, only for feature parity with github // Disable some features of composite actions, only for feature parity with github
for _, compositeStep := range action.Runs.Steps { for _, compositeStep := range action.Runs.Steps {
if err := compositeStep.Validate(rc.Config.CompositeRestrictions); err != nil { if err := compositeStep.Validate(rc.Config.CompositeRestrictions); err != nil {
@ -398,7 +408,8 @@ func execAsComposite(ctx context.Context, step step, _ string, rc *RunContext, c
} }
compositerc.Inputs = inputs compositerc.Inputs = inputs
compositerc.ExprEval = compositerc.NewExpressionEvaluator() compositerc.ExprEval = compositerc.NewExpressionEvaluator()
err = compositerc.CompositeExecutor()(ctx)
err := compositerc.compositeExecutor()(ctx)
// Map outputs to parent rc // Map outputs to parent rc
eval = compositerc.NewStepExpressionEvaluator(step) eval = compositerc.NewStepExpressionEvaluator(step)
@ -419,6 +430,7 @@ func execAsComposite(ctx context.Context, step step, _ string, rc *RunContext, c
} }
return err return err
} }
}
func populateEnvsFromInput(env *map[string]string, action *model.Action, rc *RunContext) { func populateEnvsFromInput(env *map[string]string, action *model.Action, rc *RunContext) {
for inputID, input := range action.Inputs { for inputID, input := range action.Inputs {

View file

@ -201,9 +201,7 @@ func TestActionRunner(t *testing.T) {
ee.On("Interpolate", "default value").Return("default value") ee.On("Interpolate", "default value").Return("default value")
tt.step.getRunContext().ExprEval = ee tt.step.getRunContext().ExprEval = ee
_, localAction := tt.step.(*stepActionRemote) err := runActionImpl(tt.step, "dir", newRemoteAction("org/repo/path@ref"))(ctx)
err := runActionImpl(tt.step, "dir", "path", "repo", "ref", localAction)(ctx)
assert.Nil(t, err) assert.Nil(t, err)
ee.AssertExpectations(t) ee.AssertExpectations(t)

View file

@ -295,7 +295,7 @@ func (rc *RunContext) Executor() common.Executor {
} }
// Executor returns a pipeline executor for all the steps in the job // Executor returns a pipeline executor for all the steps in the job
func (rc *RunContext) CompositeExecutor() common.Executor { func (rc *RunContext) compositeExecutor() common.Executor {
steps := make([]common.Executor, 0) steps := make([]common.Executor, 0)
sf := &stepFactoryImpl{} sf := &stepFactoryImpl{}

View file

@ -58,7 +58,7 @@ func (sal *stepActionLocal) main() common.Executor {
sal.action = actionModel sal.action = actionModel
log.Debugf("Read action %v from '%s'", sal.action, "Unknown") log.Debugf("Read action %v from '%s'", sal.action, "Unknown")
return sal.runAction(sal, actionDir, "", "", "", true)(ctx) return sal.runAction(sal, actionDir, nil)(ctx)
}) })
} }

View file

@ -14,8 +14,8 @@ type stepActionLocalMocks struct {
mock.Mock mock.Mock
} }
func (salm *stepActionLocalMocks) runAction(step actionStep, actionDir string, actionPath string, actionRepository string, actionRef string, localAction bool) common.Executor { func (salm *stepActionLocalMocks) runAction(step actionStep, actionDir string, remoteAction *remoteAction) common.Executor {
args := salm.Called(step, actionDir, actionPath, actionRepository, actionRef, localAction) args := salm.Called(step, actionDir, remoteAction)
return args.Get(0).(func(context.Context) error) return args.Get(0).(func(context.Context) error)
} }
@ -76,7 +76,7 @@ func TestStepActionLocalTest(t *testing.T) {
return nil return nil
}) })
salm.On("runAction", sal, "/tmp/path/to/action", "", "", "", true).Return(func(ctx context.Context) error { salm.On("runAction", sal, "/tmp/path/to/action", (*remoteAction)(nil)).Return(func(ctx context.Context) error {
return nil return nil
}) })

View file

@ -86,7 +86,7 @@ func (sar *stepActionRemote) main() common.Executor {
log.Debugf("Read action %v from '%s'", sar.action, "Unknown") log.Debugf("Read action %v from '%s'", sar.action, "Unknown")
return err return err
}, },
sar.runAction(sar, actionDir, remoteAction.Path, remoteAction.Repo, remoteAction.Ref, false), sar.runAction(sar, actionDir, remoteAction),
)(ctx) )(ctx)
}) })
} }

View file

@ -20,8 +20,8 @@ func (sarm *stepActionRemoteMocks) readAction(step *model.Step, actionDir string
return args.Get(0).(*model.Action), args.Error(1) return args.Get(0).(*model.Action), args.Error(1)
} }
func (sarm *stepActionRemoteMocks) runAction(step actionStep, actionDir string, actionPath string, actionRepository string, actionRef string, localAction bool) common.Executor { func (sarm *stepActionRemoteMocks) runAction(step actionStep, actionDir string, remoteAction *remoteAction) common.Executor {
args := sarm.Called(step, actionDir, actionPath, actionRepository, actionRef, localAction) args := sarm.Called(step, actionDir, remoteAction)
return args.Get(0).(func(context.Context) error) return args.Get(0).(func(context.Context) error)
} }
@ -48,7 +48,7 @@ func TestStepActionRemoteTest(t *testing.T) {
sar := &stepActionRemote{ sar := &stepActionRemote{
RunContext: &RunContext{ RunContext: &RunContext{
Config: &Config{ Config: &Config{
GitHubInstance: "https://github.com", GitHubInstance: "github.com",
}, },
Run: &model.Run{ Run: &model.Run{
JobID: "1", JobID: "1",
@ -79,7 +79,7 @@ func TestStepActionRemoteTest(t *testing.T) {
cm.On("UpdateFromPath", &sar.env).Return(func(ctx context.Context) error { return nil }) cm.On("UpdateFromPath", &sar.env).Return(func(ctx context.Context) error { return nil })
sarm.On("readAction", sar.Step, suffixMatcher("act/remote-action@v1"), "", mock.Anything, mock.Anything).Return(&model.Action{}, nil) sarm.On("readAction", sar.Step, suffixMatcher("act/remote-action@v1"), "", mock.Anything, mock.Anything).Return(&model.Action{}, nil)
sarm.On("runAction", sar, suffixMatcher("act/remote-action@v1"), "", "action", "v1", false).Return(func(ctx context.Context) error { return nil }) sarm.On("runAction", sar, suffixMatcher("act/remote-action@v1"), newRemoteAction(sar.Step.Uses)).Return(func(ctx context.Context) error { return nil })
err := sar.main()(ctx) err := sar.main()(ctx)