a04141c444
fixes #12
186 lines
5.2 KiB
Go
186 lines
5.2 KiB
Go
package actions
|
|
|
|
import (
|
|
"archive/tar"
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
|
|
"github.com/nektos/act/common"
|
|
"github.com/nektos/act/container"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func (runner *runnerImpl) newActionExecutor(actionName string) common.Executor {
|
|
action, err := runner.workflows.getAction(actionName)
|
|
if err != nil {
|
|
return common.NewErrorExecutor(err)
|
|
}
|
|
|
|
env := make(map[string]string)
|
|
for _, applier := range []environmentApplier{action, runner} {
|
|
applier.applyEnvironment(env)
|
|
}
|
|
env["GITHUB_ACTION"] = actionName
|
|
|
|
logger := newActionLogger(actionName, runner.config.Dryrun)
|
|
log.Debugf("Using '%s' for action '%s'", action.Uses, actionName)
|
|
|
|
in := container.DockerExecutorInput{
|
|
Ctx: runner.config.Ctx,
|
|
Logger: logger,
|
|
Dryrun: runner.config.Dryrun,
|
|
}
|
|
|
|
var image string
|
|
executors := make([]common.Executor, 0)
|
|
if imageRef, ok := parseImageReference(action.Uses); ok {
|
|
executors = append(executors, container.NewDockerPullExecutor(container.NewDockerPullExecutorInput{
|
|
DockerExecutorInput: in,
|
|
Image: imageRef,
|
|
}))
|
|
image = imageRef
|
|
} else if contextDir, imageTag, ok := parseImageLocal(runner.config.WorkingDir, action.Uses); ok {
|
|
executors = append(executors, container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{
|
|
DockerExecutorInput: in,
|
|
ContextDir: contextDir,
|
|
ImageTag: imageTag,
|
|
}))
|
|
image = imageTag
|
|
} else if cloneURL, ref, path, ok := parseImageGithub(action.Uses); ok {
|
|
cloneDir := filepath.Join(os.TempDir(), "act", action.Uses)
|
|
executors = append(executors, common.NewGitCloneExecutor(common.NewGitCloneExecutorInput{
|
|
URL: cloneURL,
|
|
Ref: ref,
|
|
Dir: cloneDir,
|
|
Logger: logger,
|
|
Dryrun: runner.config.Dryrun,
|
|
}))
|
|
|
|
contextDir := filepath.Join(cloneDir, path)
|
|
imageTag := fmt.Sprintf("%s:%s", filepath.Base(cloneURL.Path), ref)
|
|
|
|
executors = append(executors, container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{
|
|
DockerExecutorInput: in,
|
|
ContextDir: contextDir,
|
|
ImageTag: imageTag,
|
|
}))
|
|
image = imageTag
|
|
} else {
|
|
return common.NewErrorExecutor(fmt.Errorf("unable to determine executor type for image '%s'", action.Uses))
|
|
}
|
|
|
|
ghReader, err := runner.createGithubTarball()
|
|
if err != nil {
|
|
return common.NewErrorExecutor(err)
|
|
}
|
|
|
|
envList := make([]string, 0)
|
|
for k, v := range env {
|
|
envList = append(envList, fmt.Sprintf("%s=%s", k, v))
|
|
}
|
|
executors = append(executors, container.NewDockerRunExecutor(container.NewDockerRunExecutorInput{
|
|
DockerExecutorInput: in,
|
|
Cmd: action.Args,
|
|
Entrypoint: action.Runs,
|
|
Image: image,
|
|
WorkingDir: "/github/workspace",
|
|
Env: envList,
|
|
Name: runner.createContainerName(actionName),
|
|
Binds: []string{
|
|
fmt.Sprintf("%s:%s", runner.config.WorkingDir, "/github/workspace"),
|
|
fmt.Sprintf("%s:%s", runner.tempDir, "/github/home"),
|
|
fmt.Sprintf("%s:%s", "/var/run/docker.sock", "/var/run/docker.sock"),
|
|
},
|
|
Content: map[string]io.Reader{"/github": ghReader},
|
|
ReuseContainers: runner.config.ReuseContainers,
|
|
}))
|
|
|
|
return common.NewPipelineExecutor(executors...)
|
|
}
|
|
|
|
func (runner *runnerImpl) applyEnvironment(env map[string]string) {
|
|
repoPath := runner.config.WorkingDir
|
|
|
|
_, workflowName, _ := runner.workflows.getWorkflow(runner.config.EventName)
|
|
|
|
env["HOME"] = "/github/home"
|
|
env["GITHUB_ACTOR"] = "nektos/act"
|
|
env["GITHUB_EVENT_PATH"] = "/github/workflow/event.json"
|
|
env["GITHUB_WORKSPACE"] = "/github/workspace"
|
|
env["GITHUB_WORKFLOW"] = workflowName
|
|
env["GITHUB_EVENT_NAME"] = runner.config.EventName
|
|
|
|
_, rev, err := common.FindGitRevision(repoPath)
|
|
if err != nil {
|
|
log.Warningf("unable to get git revision: %v", err)
|
|
} else {
|
|
env["GITHUB_SHA"] = rev
|
|
}
|
|
|
|
repo, err := common.FindGithubRepo(repoPath)
|
|
if err != nil {
|
|
log.Warningf("unable to get git repo: %v", err)
|
|
} else {
|
|
env["GITHUB_REPOSITORY"] = repo
|
|
}
|
|
|
|
ref, err := common.FindGitRef(repoPath)
|
|
if err != nil {
|
|
log.Warningf("unable to get git ref: %v", err)
|
|
} else {
|
|
env["GITHUB_REF"] = ref
|
|
}
|
|
|
|
}
|
|
|
|
func (runner *runnerImpl) createGithubTarball() (io.Reader, error) {
|
|
var buf bytes.Buffer
|
|
tw := tar.NewWriter(&buf)
|
|
var files = []struct {
|
|
Name string
|
|
Mode int64
|
|
Body string
|
|
}{
|
|
{"workflow/event.json", 0644, runner.eventJSON},
|
|
}
|
|
for _, file := range files {
|
|
log.Debugf("Writing entry to tarball %s len:%d", file.Name, len(runner.eventJSON))
|
|
hdr := &tar.Header{
|
|
Name: file.Name,
|
|
Mode: file.Mode,
|
|
Size: int64(len(runner.eventJSON)),
|
|
}
|
|
if err := tw.WriteHeader(hdr); err != nil {
|
|
return nil, err
|
|
}
|
|
if _, err := tw.Write([]byte(runner.eventJSON)); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
if err := tw.Close(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &buf, nil
|
|
|
|
}
|
|
|
|
func (runner *runnerImpl) createContainerName(actionName string) string {
|
|
containerName := regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(actionName, "-")
|
|
|
|
prefix := fmt.Sprintf("%s-", trimToLen(filepath.Base(runner.config.WorkingDir), 10))
|
|
suffix := ""
|
|
containerName = trimToLen(containerName, 30-(len(prefix)+len(suffix)))
|
|
return fmt.Sprintf("%s%s%s", prefix, containerName, suffix)
|
|
}
|
|
|
|
func trimToLen(s string, l int) string {
|
|
if len(s) > l {
|
|
return s[:l]
|
|
}
|
|
return s
|
|
}
|