github.com/nektos/act@v0.2.63/pkg/runner/step_docker.go (about)

     1  package runner
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/kballard/go-shellquote"
     9  	"github.com/nektos/act/pkg/common"
    10  	"github.com/nektos/act/pkg/container"
    11  	"github.com/nektos/act/pkg/model"
    12  )
    13  
    14  type stepDocker struct {
    15  	Step       *model.Step
    16  	RunContext *RunContext
    17  	env        map[string]string
    18  }
    19  
    20  func (sd *stepDocker) pre() common.Executor {
    21  	return func(ctx context.Context) error {
    22  		return nil
    23  	}
    24  }
    25  
    26  func (sd *stepDocker) main() common.Executor {
    27  	sd.env = map[string]string{}
    28  
    29  	return runStepExecutor(sd, stepStageMain, sd.runUsesContainer())
    30  }
    31  
    32  func (sd *stepDocker) post() common.Executor {
    33  	return func(ctx context.Context) error {
    34  		return nil
    35  	}
    36  }
    37  
    38  func (sd *stepDocker) getRunContext() *RunContext {
    39  	return sd.RunContext
    40  }
    41  
    42  func (sd *stepDocker) getGithubContext(ctx context.Context) *model.GithubContext {
    43  	return sd.getRunContext().getGithubContext(ctx)
    44  }
    45  
    46  func (sd *stepDocker) getStepModel() *model.Step {
    47  	return sd.Step
    48  }
    49  
    50  func (sd *stepDocker) getEnv() *map[string]string {
    51  	return &sd.env
    52  }
    53  
    54  func (sd *stepDocker) getIfExpression(_ context.Context, _ stepStage) string {
    55  	return sd.Step.If.Value
    56  }
    57  
    58  func (sd *stepDocker) runUsesContainer() common.Executor {
    59  	rc := sd.RunContext
    60  	step := sd.Step
    61  
    62  	return func(ctx context.Context) error {
    63  		image := strings.TrimPrefix(step.Uses, "docker://")
    64  		eval := rc.NewExpressionEvaluator(ctx)
    65  		cmd, err := shellquote.Split(eval.Interpolate(ctx, step.With["args"]))
    66  		if err != nil {
    67  			return err
    68  		}
    69  
    70  		var entrypoint []string
    71  		if entry := eval.Interpolate(ctx, step.With["entrypoint"]); entry != "" {
    72  			entrypoint = []string{entry}
    73  		}
    74  
    75  		stepContainer := sd.newStepContainer(ctx, image, cmd, entrypoint)
    76  
    77  		return common.NewPipelineExecutor(
    78  			stepContainer.Pull(rc.Config.ForcePull),
    79  			stepContainer.Remove().IfBool(!rc.Config.ReuseContainers),
    80  			stepContainer.Create(rc.Config.ContainerCapAdd, rc.Config.ContainerCapDrop),
    81  			stepContainer.Start(true),
    82  		).Finally(
    83  			stepContainer.Remove().IfBool(!rc.Config.ReuseContainers),
    84  		).Finally(stepContainer.Close())(ctx)
    85  	}
    86  }
    87  
    88  var (
    89  	ContainerNewContainer = container.NewContainer
    90  )
    91  
    92  func (sd *stepDocker) newStepContainer(ctx context.Context, image string, cmd []string, entrypoint []string) container.Container {
    93  	rc := sd.RunContext
    94  	step := sd.Step
    95  
    96  	rawLogger := common.Logger(ctx).WithField("raw_output", true)
    97  	logWriter := common.NewLineWriter(rc.commandHandler(ctx), func(s string) bool {
    98  		if rc.Config.LogOutput {
    99  			rawLogger.Infof("%s", s)
   100  		} else {
   101  			rawLogger.Debugf("%s", s)
   102  		}
   103  		return true
   104  	})
   105  	envList := make([]string, 0)
   106  	for k, v := range sd.env {
   107  		envList = append(envList, fmt.Sprintf("%s=%s", k, v))
   108  	}
   109  
   110  	envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TOOL_CACHE", "/opt/hostedtoolcache"))
   111  	envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_OS", "Linux"))
   112  	envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_ARCH", container.RunnerArch(ctx)))
   113  	envList = append(envList, fmt.Sprintf("%s=%s", "RUNNER_TEMP", "/tmp"))
   114  
   115  	binds, mounts := rc.GetBindsAndMounts()
   116  	stepContainer := ContainerNewContainer(&container.NewContainerInput{
   117  		Cmd:         cmd,
   118  		Entrypoint:  entrypoint,
   119  		WorkingDir:  rc.JobContainer.ToContainerPath(rc.Config.Workdir),
   120  		Image:       image,
   121  		Username:    rc.Config.Secrets["DOCKER_USERNAME"],
   122  		Password:    rc.Config.Secrets["DOCKER_PASSWORD"],
   123  		Name:        createContainerName(rc.jobContainerName(), step.ID),
   124  		Env:         envList,
   125  		Mounts:      mounts,
   126  		NetworkMode: fmt.Sprintf("container:%s", rc.jobContainerName()),
   127  		Binds:       binds,
   128  		Stdout:      logWriter,
   129  		Stderr:      logWriter,
   130  		Privileged:  rc.Config.Privileged,
   131  		UsernsMode:  rc.Config.UsernsMode,
   132  		Platform:    rc.Config.ContainerArchitecture,
   133  	})
   134  	return stepContainer
   135  }