Read localaction's from container (#719)

Fix localaction tests (missing checkout)

Co-authored-by: Ryan (hackercat) <me@hackerc.at>
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
ChristopherHX 2021-08-03 19:39:56 +02:00 committed by GitHub
parent 531ea02fb9
commit 0ff204b615
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 65 additions and 16 deletions

View file

@ -20,6 +20,7 @@ import (
// NewDockerBuildExecutorInput the input for the NewDockerBuildExecutor function // NewDockerBuildExecutorInput the input for the NewDockerBuildExecutor function
type NewDockerBuildExecutorInput struct { type NewDockerBuildExecutorInput struct {
ContextDir string ContextDir string
Container Container
ImageTag string ImageTag string
Platform string Platform string
} }
@ -46,8 +47,12 @@ func NewDockerBuildExecutor(input NewDockerBuildExecutorInput) common.Executor {
Remove: true, Remove: true,
Platform: input.Platform, Platform: input.Platform,
} }
var buildContext io.ReadCloser
buildContext, err := createBuildContext(input.ContextDir, "Dockerfile") if input.Container != nil {
buildContext, err = input.Container.GetContainerArchive(ctx, input.ContextDir+"/.")
} else {
buildContext, err = createBuildContext(input.ContextDir, "Dockerfile")
}
if err != nil { if err != nil {
return err return err
} }

View file

@ -66,6 +66,7 @@ type Container interface {
Create(capAdd []string, capDrop []string) common.Executor Create(capAdd []string, capDrop []string) common.Executor
Copy(destPath string, files ...*FileEntry) common.Executor Copy(destPath string, files ...*FileEntry) common.Executor
CopyDir(destPath string, srcPath string, useGitIgnore bool) common.Executor CopyDir(destPath string, srcPath string, useGitIgnore bool) common.Executor
GetContainerArchive(ctx context.Context, srcPath string) (io.ReadCloser, error)
Pull(forcePull bool) common.Executor Pull(forcePull bool) common.Executor
Start(attach bool) common.Executor Start(attach bool) common.Executor
Exec(command []string, env map[string]string, user string) common.Executor Exec(command []string, env map[string]string, user string) common.Executor
@ -150,6 +151,11 @@ func (cr *containerReference) CopyDir(destPath string, srcPath string, useGitIgn
).IfNot(common.Dryrun) ).IfNot(common.Dryrun)
} }
func (cr *containerReference) GetContainerArchive(ctx context.Context, srcPath string) (io.ReadCloser, error) {
a, _, err := cr.cli.CopyFromContainer(ctx, cr.id, srcPath)
return a, err
}
func (cr *containerReference) UpdateFromEnv(srcPath string, env *map[string]string) common.Executor { func (cr *containerReference) UpdateFromEnv(srcPath string, env *map[string]string) common.Executor {
return cr.extractEnv(srcPath, env).IfNot(common.Dryrun) return cr.extractEnv(srcPath, env).IfNot(common.Dryrun)
} }

View file

@ -1,7 +1,10 @@
package runner package runner
import ( import (
"archive/tar"
"context" "context"
"io"
// Go told me to? // Go told me to?
_ "embed" _ "embed"
"fmt" "fmt"
@ -77,8 +80,8 @@ func (sc *StepContext) Executor() common.Executor {
case model.StepTypeUsesActionLocal: case model.StepTypeUsesActionLocal:
actionDir := filepath.Join(rc.Config.Workdir, step.Uses) actionDir := filepath.Join(rc.Config.Workdir, step.Uses)
return common.NewPipelineExecutor( return common.NewPipelineExecutor(
sc.setupAction(actionDir, ""), sc.setupAction(actionDir, "", true),
sc.runAction(actionDir, ""), sc.runAction(actionDir, "", true),
) )
case model.StepTypeUsesActionRemote: case model.StepTypeUsesActionRemote:
remoteAction := newRemoteAction(step.Uses) remoteAction := newRemoteAction(step.Uses)
@ -116,8 +119,8 @@ func (sc *StepContext) Executor() common.Executor {
} }
return common.NewPipelineExecutor( return common.NewPipelineExecutor(
ntErr, ntErr,
sc.setupAction(actionDir, remoteAction.Path), sc.setupAction(actionDir, remoteAction.Path, false),
sc.runAction(actionDir, remoteAction.Path), sc.runAction(actionDir, remoteAction.Path, false),
) )
case model.StepTypeInvalid: case model.StepTypeInvalid:
return common.NewErrorExecutor(fmt.Errorf("Invalid run/uses syntax for job:%s step:%+v", rc.Run, step)) return common.NewErrorExecutor(fmt.Errorf("Invalid run/uses syntax for job:%s step:%+v", rc.Run, step))
@ -330,13 +333,35 @@ func (sc *StepContext) runUsesContainer() common.Executor {
//go:embed res/trampoline.js //go:embed res/trampoline.js
var trampoline []byte var trampoline []byte
func (sc *StepContext) setupAction(actionDir string, actionPath string) common.Executor { func (sc *StepContext) setupAction(actionDir string, actionPath string, localAction bool) common.Executor {
return func(ctx context.Context) error { return func(ctx context.Context) error {
f, err := os.Open(filepath.Join(actionDir, actionPath, "action.yml")) var readFile func(filename string) (io.Reader, io.Closer, error)
if localAction {
_, cpath := sc.getContainerActionPaths(sc.Step, path.Join(actionDir, actionPath), sc.RunContext)
readFile = func(filename string) (io.Reader, io.Closer, error) {
tars, err := sc.RunContext.JobContainer.GetContainerArchive(ctx, path.Join(cpath, filename))
if err != nil {
return nil, nil, os.ErrNotExist
}
treader := tar.NewReader(tars)
if _, err := treader.Next(); err != nil {
return nil, nil, os.ErrNotExist
}
return treader, tars, nil
}
} else {
readFile = func(filename string) (io.Reader, io.Closer, error) {
f, err := os.Open(filepath.Join(actionDir, actionPath, filename))
return f, f, err
}
}
reader, closer, err := readFile("action.yml")
if os.IsNotExist(err) { if os.IsNotExist(err) {
f, err = os.Open(filepath.Join(actionDir, actionPath, "action.yaml")) reader, closer, err = readFile("action.yaml")
if err != nil { if err != nil {
if _, err2 := os.Stat(filepath.Join(actionDir, actionPath, "Dockerfile")); err2 == nil { if _, closer, err2 := readFile("Dockerfile"); err2 == nil {
closer.Close()
sc.Action = &model.Action{ sc.Action = &model.Action{
Name: "(Synthetic)", Name: "(Synthetic)",
Runs: model.ActionRuns{ Runs: model.ActionRuns{
@ -381,9 +406,10 @@ func (sc *StepContext) setupAction(actionDir string, actionPath string) common.E
} else if err != nil { } else if err != nil {
return err return err
} }
defer closer.Close()
sc.Action, err = model.ReadAction(f) sc.Action, err = model.ReadAction(reader)
log.Debugf("Read action %v from '%s'", sc.Action, f.Name()) log.Debugf("Read action %v from '%s'", sc.Action, "Unknown")
return err return err
} }
} }
@ -420,7 +446,7 @@ func (sc *StepContext) getContainerActionPaths(step *model.Step, actionDir strin
} }
// nolint: gocyclo // nolint: gocyclo
func (sc *StepContext) runAction(actionDir string, actionPath string) common.Executor { func (sc *StepContext) runAction(actionDir string, actionPath string, localAction bool) common.Executor {
rc := sc.RunContext rc := sc.RunContext
step := sc.Step step := sc.Step
return func(ctx context.Context) error { return func(ctx context.Context) error {
@ -461,7 +487,7 @@ func (sc *StepContext) runAction(actionDir string, actionPath string) common.Exe
log.Debugf("executing remote job container: %s", containerArgs) log.Debugf("executing remote job container: %s", containerArgs)
return rc.execJobContainer(containerArgs, sc.Env)(ctx) return rc.execJobContainer(containerArgs, sc.Env)(ctx)
case model.ActionRunsUsingDocker: case model.ActionRunsUsingDocker:
return sc.execAsDocker(ctx, action, actionName, actionDir, actionPath, rc, step) return sc.execAsDocker(ctx, action, actionName, containerActionDir, actionLocation, rc, step, localAction)
case model.ActionRunsUsingComposite: case model.ActionRunsUsingComposite:
return sc.execAsComposite(ctx, step, actionDir, rc, containerActionDir, actionName, actionPath, action, maybeCopyToActionDir) return sc.execAsComposite(ctx, step, actionDir, rc, containerActionDir, actionName, actionPath, action, maybeCopyToActionDir)
default: default:
@ -474,7 +500,7 @@ func (sc *StepContext) runAction(actionDir string, actionPath string) common.Exe
} }
} }
func (sc *StepContext) execAsDocker(ctx context.Context, action *model.Action, actionName string, actionDir string, actionPath string, rc *RunContext, step *model.Step) error { func (sc *StepContext) execAsDocker(ctx context.Context, action *model.Action, actionName string, containerLocation string, actionLocation string, rc *RunContext, step *model.Step, localAction bool) error {
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://") {
@ -483,7 +509,11 @@ func (sc *StepContext) execAsDocker(ctx context.Context, action *model.Action, a
image = fmt.Sprintf("%s:%s", regexp.MustCompile("[^a-zA-Z0-9]").ReplaceAllString(actionName, "-"), "latest") image = fmt.Sprintf("%s:%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)
contextDir := filepath.Join(actionDir, actionPath, action.Runs.Main) basedir := actionLocation
if localAction {
basedir = containerLocation
}
contextDir := filepath.Join(basedir, action.Runs.Main)
anyArchExists, err := container.ImageExistsLocally(ctx, image, "any") anyArchExists, err := container.ImageExistsLocally(ctx, image, "any")
if err != nil { if err != nil {
@ -507,9 +537,14 @@ func (sc *StepContext) execAsDocker(ctx context.Context, action *model.Action, a
if !correctArchExists { if !correctArchExists {
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 = nil
if localAction {
actionContainer = sc.RunContext.JobContainer
}
prepImage = container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{ prepImage = container.NewDockerBuildExecutor(container.NewDockerBuildExecutorInput{
ContextDir: contextDir, ContextDir: contextDir,
ImageTag: image, ImageTag: image,
Container: actionContainer,
Platform: rc.Config.ContainerArchitecture, Platform: rc.Config.ContainerArchitecture,
}) })
} else { } else {

View file

@ -22,6 +22,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [check] needs: [check]
steps: steps:
- uses: actions/checkout@v2
- uses: ./actions/action1 - uses: ./actions/action1
with: with:
args: echo 'build' args: echo 'build'

View file

@ -5,6 +5,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2
- uses: ./actions/action1 - uses: ./actions/action1
with: with:
args: echo 'build' args: echo 'build'

View file

@ -5,6 +5,7 @@ jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2
- uses: ./uses-composite/composite_action - uses: ./uses-composite/composite_action
id: composite id: composite
with: with: