cache dir for remote actions
This commit is contained in:
parent
94591c58d7
commit
88041afb87
5 changed files with 76 additions and 111 deletions
|
@ -171,7 +171,7 @@ func (cr *containerReference) remove() common.Executor {
|
|||
Force: true,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
logger.Error(errors.WithStack(err))
|
||||
}
|
||||
|
||||
logger.Debugf("Removed container: %v", cr.id)
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
package container
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/nektos/act/pkg/common"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type rawFormatter struct{}
|
||||
|
||||
func (f *rawFormatter) Format(entry *logrus.Entry) ([]byte, error) {
|
||||
return []byte(entry.Message), nil
|
||||
}
|
||||
|
||||
func TestNewDockerRunExecutor(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping slower test")
|
||||
}
|
||||
|
||||
noopLogger := logrus.New()
|
||||
noopLogger.SetOutput(ioutil.Discard)
|
||||
|
||||
buf := &bytes.Buffer{}
|
||||
logger := logrus.New()
|
||||
logger.SetOutput(buf)
|
||||
logger.SetFormatter(&rawFormatter{})
|
||||
|
||||
ctx := common.WithLogger(context.Background(), logger)
|
||||
|
||||
runner := NewDockerRunExecutor(NewDockerRunExecutorInput{
|
||||
Image: "hello-world",
|
||||
Stdout: buf,
|
||||
})
|
||||
|
||||
puller := NewDockerPullExecutor(NewDockerPullExecutorInput{
|
||||
Image: "hello-world",
|
||||
})
|
||||
|
||||
pipeline := common.NewPipelineExecutor(puller, runner)
|
||||
err := pipeline(ctx)
|
||||
assert.NoError(t, err)
|
||||
|
||||
actual := buf.String()
|
||||
assert.Contains(t, actual, `docker pull hello-world`)
|
||||
assert.Contains(t, actual, `docker run image=hello-world entrypoint=[] cmd=[]`)
|
||||
assert.Contains(t, actual, `Hello from Docker!`)
|
||||
}
|
|
@ -38,6 +38,7 @@ func (sc *StepContext) NewExpressionEvaluator() ExpressionEvaluator {
|
|||
vm := sc.RunContext.newVM()
|
||||
configers := []func(*otto.Otto){
|
||||
sc.vmEnv(),
|
||||
sc.vmInputs(),
|
||||
}
|
||||
for _, configer := range configers {
|
||||
configer(vm)
|
||||
|
@ -241,6 +242,16 @@ func (sc *StepContext) vmEnv() func(*otto.Otto) {
|
|||
}
|
||||
}
|
||||
|
||||
func (sc *StepContext) vmInputs() func(*otto.Otto) {
|
||||
inputs := make(map[string]string)
|
||||
for k, v := range sc.Step.With {
|
||||
inputs[k] = v
|
||||
}
|
||||
return func(vm *otto.Otto) {
|
||||
_ = vm.Set("inputs", inputs)
|
||||
}
|
||||
}
|
||||
|
||||
func (rc *RunContext) vmJob() func(*otto.Otto) {
|
||||
job := rc.getJobContext()
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ func (rc *RunContext) GetEnv() map[string]string {
|
|||
}
|
||||
|
||||
func (rc *RunContext) jobContainerName() string {
|
||||
return createContainerName(filepath.Base(rc.Config.Workdir), rc.Run.String())
|
||||
return createContainerName("act", rc.Run.String())
|
||||
}
|
||||
|
||||
func (rc *RunContext) startJobContainer() common.Executor {
|
||||
|
@ -74,7 +74,7 @@ func (rc *RunContext) startJobContainer() common.Executor {
|
|||
|
||||
rc.JobContainer = container.NewContainer(&container.NewContainerInput{
|
||||
Cmd: nil,
|
||||
Entrypoint: []string{"/bin/cat"},
|
||||
Entrypoint: []string{"/usr/bin/tail", "-f", "/dev/null"},
|
||||
WorkingDir: "/github/workspace",
|
||||
Image: image,
|
||||
Name: name,
|
||||
|
@ -83,6 +83,7 @@ func (rc *RunContext) startJobContainer() common.Executor {
|
|||
},
|
||||
Binds: []string{
|
||||
fmt.Sprintf("%s:%s", rc.Config.Workdir, "/github/workspace"),
|
||||
fmt.Sprintf("%s:%s", rc.ActionDir(), "/github/home/.act"),
|
||||
fmt.Sprintf("%s:%s", "/var/run/docker.sock", "/var/run/docker.sock"),
|
||||
},
|
||||
Stdout: logWriter,
|
||||
|
@ -98,10 +99,6 @@ func (rc *RunContext) startJobContainer() common.Executor {
|
|||
Name: "workflow/event.json",
|
||||
Mode: 644,
|
||||
Body: rc.EventJSON,
|
||||
}, &container.FileEntry{
|
||||
Name: "home/.actions/.keep",
|
||||
Mode: 644,
|
||||
Body: "",
|
||||
}),
|
||||
)(ctx)
|
||||
}
|
||||
|
@ -121,6 +118,18 @@ func (rc *RunContext) stopJobContainer() common.Executor {
|
|||
}
|
||||
}
|
||||
|
||||
// ActionDir is for rc
|
||||
func (rc *RunContext) ActionDir() string {
|
||||
var xdgCache string
|
||||
var ok bool
|
||||
if xdgCache, ok = os.LookupEnv("XDG_CACHE_HOME"); !ok {
|
||||
if home, ok := os.LookupEnv("HOME"); ok {
|
||||
xdgCache = fmt.Sprintf("%s/.cache", home)
|
||||
}
|
||||
}
|
||||
return filepath.Join(xdgCache, "act")
|
||||
}
|
||||
|
||||
// Executor returns a pipeline executor for all the steps in the job
|
||||
func (rc *RunContext) Executor() common.Executor {
|
||||
steps := make([]common.Executor, 0)
|
||||
|
@ -210,10 +219,14 @@ func createContainerName(parts ...string) string {
|
|||
name := make([]string, 0)
|
||||
pattern := regexp.MustCompile("[^a-zA-Z0-9]")
|
||||
partLen := (30 / len(parts)) - 1
|
||||
for _, part := range parts {
|
||||
name = append(name, trimToLen(pattern.ReplaceAllString(part, "-"), partLen))
|
||||
for i, part := range parts {
|
||||
if i == len(parts)-1 {
|
||||
name = append(name, pattern.ReplaceAllString(part, "-"))
|
||||
} else {
|
||||
name = append(name, trimToLen(pattern.ReplaceAllString(part, "-"), partLen))
|
||||
}
|
||||
}
|
||||
return strings.Join(name, "-")
|
||||
return trimToLen(strings.Trim(strings.Join(name, "-"), "-"), 30)
|
||||
}
|
||||
|
||||
func trimToLen(s string, l int) string {
|
||||
|
|
|
@ -49,54 +49,37 @@ func (sc *StepContext) Executor() common.Executor {
|
|||
)
|
||||
|
||||
case model.StepTypeUsesActionLocal:
|
||||
actionDir := filepath.Join(rc.Config.Workdir, step.Uses)
|
||||
return common.NewPipelineExecutor(
|
||||
sc.setupEnv(),
|
||||
sc.setupAction(),
|
||||
sc.runAction(),
|
||||
sc.setupAction(actionDir),
|
||||
sc.runAction(actionDir),
|
||||
)
|
||||
case model.StepTypeUsesActionRemote:
|
||||
remoteAction := newRemoteAction(step.Uses)
|
||||
if remoteAction.Org == "actions" && remoteAction.Repo == "checkout" {
|
||||
return func(ctx context.Context) error {
|
||||
common.Logger(ctx).Debugf("Skipping actions/checkout")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
actionDir := rc.ActionDir()
|
||||
return common.NewPipelineExecutor(
|
||||
common.NewGitCloneExecutor(common.NewGitCloneExecutorInput{
|
||||
URL: remoteAction.CloneURL(),
|
||||
Ref: remoteAction.Ref,
|
||||
Dir: actionDir,
|
||||
}),
|
||||
sc.setupEnv(),
|
||||
sc.setupAction(actionDir),
|
||||
sc.runAction(actionDir),
|
||||
)
|
||||
/*
|
||||
case model.StepTypeUsesActionRemote:
|
||||
remoteAction := newRemoteAction(step.Uses)
|
||||
if remoteAction.Org == "actions" && remoteAction.Repo == "checkout" {
|
||||
return func(ctx context.Context) error {
|
||||
common.Logger(ctx).Debugf("Skipping actions/checkout")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
cloneDir, err := ioutil.TempDir(rc.Tempdir, remoteAction.Repo)
|
||||
if err != nil {
|
||||
return common.NewErrorExecutor(err)
|
||||
}
|
||||
return common.NewPipelineExecutor(
|
||||
common.NewGitCloneExecutor(common.NewGitCloneExecutorInput{
|
||||
URL: remoteAction.CloneURL(),
|
||||
Ref: remoteAction.Ref,
|
||||
Dir: cloneDir,
|
||||
}),
|
||||
sc.setupEnv(),
|
||||
sc.setupAction(),
|
||||
applyWith(containerSpec, step),
|
||||
rc.pullImage(containerSpec),
|
||||
rc.runContainer(containerSpec),
|
||||
)
|
||||
*/
|
||||
}
|
||||
|
||||
return common.NewErrorExecutor(fmt.Errorf("Unable to determine how to run job:%s step:%+v", rc.Run, step))
|
||||
}
|
||||
|
||||
func applyWith(containerSpec *model.ContainerSpec, step *model.Step) common.Executor {
|
||||
return func(ctx context.Context) error {
|
||||
if entrypoint, ok := step.With["entrypoint"]; ok {
|
||||
containerSpec.Entrypoint = entrypoint
|
||||
}
|
||||
if args, ok := step.With["args"]; ok {
|
||||
containerSpec.Args = args
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (sc *StepContext) setupEnv() common.Executor {
|
||||
rc := sc.RunContext
|
||||
job := rc.Run.Job()
|
||||
|
@ -160,6 +143,13 @@ func (sc *StepContext) newStepContainer(ctx context.Context, image string, cmd [
|
|||
for k, v := range sc.Env {
|
||||
envList = append(envList, fmt.Sprintf("%s=%s", k, v))
|
||||
}
|
||||
stepEE := sc.NewExpressionEvaluator()
|
||||
for i, v := range cmd {
|
||||
cmd[i] = stepEE.Interpolate(v)
|
||||
}
|
||||
for i, v := range entrypoint {
|
||||
entrypoint[i] = stepEE.Interpolate(v)
|
||||
}
|
||||
stepContainer := container.NewContainer(&container.NewContainerInput{
|
||||
Cmd: cmd,
|
||||
Entrypoint: entrypoint,
|
||||
|
@ -184,8 +174,8 @@ func (sc *StepContext) runUsesContainer() common.Executor {
|
|||
step := sc.Step
|
||||
return func(ctx context.Context) error {
|
||||
image := strings.TrimPrefix(step.Uses, "docker://")
|
||||
cmd := strings.Fields(rc.ExprEval.Interpolate(step.With["args"]))
|
||||
entrypoint := strings.Fields(rc.ExprEval.Interpolate(step.With["entrypoint"]))
|
||||
cmd := strings.Fields(step.With["args"])
|
||||
entrypoint := strings.Fields(step.With["entrypoint"])
|
||||
stepContainer := sc.newStepContainer(ctx, image, cmd, entrypoint)
|
||||
|
||||
return common.NewPipelineExecutor(
|
||||
|
@ -199,10 +189,7 @@ func (sc *StepContext) runUsesContainer() common.Executor {
|
|||
}
|
||||
}
|
||||
|
||||
func (sc *StepContext) setupAction() common.Executor {
|
||||
rc := sc.RunContext
|
||||
step := sc.Step
|
||||
actionDir := filepath.Join(rc.Config.Workdir, step.Uses)
|
||||
func (sc *StepContext) setupAction(actionDir string) common.Executor {
|
||||
return func(ctx context.Context) error {
|
||||
f, err := os.Open(filepath.Join(actionDir, "action.yml"))
|
||||
if os.IsNotExist(err) {
|
||||
|
@ -220,7 +207,7 @@ func (sc *StepContext) setupAction() common.Executor {
|
|||
}
|
||||
}
|
||||
|
||||
func (sc *StepContext) runAction() common.Executor {
|
||||
func (sc *StepContext) runAction(actionDir string) common.Executor {
|
||||
rc := sc.RunContext
|
||||
step := sc.Step
|
||||
return func(ctx context.Context) error {
|
||||
|
@ -236,7 +223,13 @@ func (sc *StepContext) runAction() common.Executor {
|
|||
|
||||
switch action.Runs.Using {
|
||||
case model.ActionRunsUsingNode12:
|
||||
return rc.execJobContainer([]string{"node", action.Runs.Main}, sc.Env)(ctx)
|
||||
basePath := "."
|
||||
if strings.HasPrefix(actionDir, rc.Config.Workdir) {
|
||||
basePath = fmt.Sprintf("/github/workspace/%s", strings.TrimPrefix(actionDir, rc.Config.Workdir))
|
||||
} else if strings.HasPrefix(actionDir, rc.ActionDir()) {
|
||||
basePath = fmt.Sprintf("/github/home/.act/%s", strings.TrimPrefix(actionDir, rc.ActionDir()))
|
||||
}
|
||||
return rc.execJobContainer([]string{"node", fmt.Sprintf("%s/%s", basePath, action.Runs.Main)}, sc.Env)(ctx)
|
||||
case model.ActionRunsUsingDocker:
|
||||
var prepImage common.Executor
|
||||
var image string
|
||||
|
@ -245,7 +238,7 @@ func (sc *StepContext) runAction() common.Executor {
|
|||
} else {
|
||||
image = fmt.Sprintf("%s:%s", regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(step.Uses, "-"), "latest")
|
||||
image = strings.TrimLeft(image, "-")
|
||||
contextDir := filepath.Join(rc.Config.Workdir, step.Uses, action.Runs.Main)
|
||||
contextDir := filepath.Join(actionDir, action.Runs.Main)
|
||||
prepImage = container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{
|
||||
ContextDir: contextDir,
|
||||
ImageTag: image,
|
||||
|
|
Loading…
Reference in a new issue