Merge pull request #38 from marccampbell/optional-docker-pull
Add flag to skip pulling images already present
This commit is contained in:
commit
8186f00560
|
@ -43,6 +43,7 @@ type RunnerConfig struct {
|
||||||
EventName string // name of event to run
|
EventName string // name of event to run
|
||||||
EventPath string // path to JSON file to use for event.json in containers, relative to WorkingDir
|
EventPath string // path to JSON file to use for event.json in containers, relative to WorkingDir
|
||||||
ReuseContainers bool // reuse containers to maintain state
|
ReuseContainers bool // reuse containers to maintain state
|
||||||
|
ForcePull bool // force pulling of the image, if already present
|
||||||
}
|
}
|
||||||
|
|
||||||
type environmentApplier interface {
|
type environmentApplier interface {
|
||||||
|
|
|
@ -49,10 +49,25 @@ func (runner *runnerImpl) addImageExecutor(action *model.Action, executors *[]co
|
||||||
|
|
||||||
case *model.UsesDockerImage:
|
case *model.UsesDockerImage:
|
||||||
image = uses.Image
|
image = uses.Image
|
||||||
|
|
||||||
|
pull := runner.config.ForcePull
|
||||||
|
if !pull {
|
||||||
|
imageExists, err := container.ImageExistsLocally(runner.config.Ctx, image)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("unable to determine if image already exists for image %q", image)
|
||||||
|
}
|
||||||
|
|
||||||
|
if imageExists {
|
||||||
|
pull = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pull {
|
||||||
*executors = append(*executors, container.NewDockerPullExecutor(container.NewDockerPullExecutorInput{
|
*executors = append(*executors, container.NewDockerPullExecutor(container.NewDockerPullExecutorInput{
|
||||||
DockerExecutorInput: in,
|
DockerExecutorInput: in,
|
||||||
Image: image,
|
Image: image,
|
||||||
}))
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
case *model.UsesPath:
|
case *model.UsesPath:
|
||||||
contextDir := filepath.Join(runner.config.WorkingDir, uses.String())
|
contextDir := filepath.Join(runner.config.WorkingDir, uses.String())
|
||||||
|
|
|
@ -31,6 +31,7 @@ func Execute(ctx context.Context, version string) {
|
||||||
rootCmd.Flags().StringP("action", "a", "", "run action")
|
rootCmd.Flags().StringP("action", "a", "", "run action")
|
||||||
rootCmd.Flags().BoolVarP(&runnerConfig.ReuseContainers, "reuse", "r", false, "reuse action containers to maintain state")
|
rootCmd.Flags().BoolVarP(&runnerConfig.ReuseContainers, "reuse", "r", false, "reuse action containers to maintain state")
|
||||||
rootCmd.Flags().StringVarP(&runnerConfig.EventPath, "event", "e", "", "path to event JSON file")
|
rootCmd.Flags().StringVarP(&runnerConfig.EventPath, "event", "e", "", "path to event JSON file")
|
||||||
|
rootCmd.Flags().BoolVarP(&runnerConfig.ForcePull, "pull", "p", false, "pull docker image(s) if already present")
|
||||||
rootCmd.PersistentFlags().BoolP("verbose", "v", false, "verbose output")
|
rootCmd.PersistentFlags().BoolP("verbose", "v", false, "verbose output")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&runnerConfig.Dryrun, "dryrun", "n", false, "dryrun mode")
|
rootCmd.PersistentFlags().BoolVarP(&runnerConfig.Dryrun, "dryrun", "n", false, "dryrun mode")
|
||||||
rootCmd.PersistentFlags().StringVarP(&runnerConfig.WorkflowPath, "file", "f", "./.github/main.workflow", "path to workflow file")
|
rootCmd.PersistentFlags().StringVarP(&runnerConfig.WorkflowPath, "file", "f", "./.github/main.workflow", "path to workflow file")
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package container
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/api/types/filters"
|
||||||
|
"github.com/docker/docker/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ImageExistsLocally returns a boolean indicating if an image with the
|
||||||
|
// requested name (and tag) exist in the local docker image store
|
||||||
|
func ImageExistsLocally(ctx context.Context, imageName string) (bool, error) {
|
||||||
|
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
cli.NegotiateAPIVersion(ctx)
|
||||||
|
|
||||||
|
filters := filters.NewArgs()
|
||||||
|
filters.Add("reference", imageName)
|
||||||
|
|
||||||
|
imageListOptions := types.ImageListOptions{
|
||||||
|
Filters: filters,
|
||||||
|
}
|
||||||
|
|
||||||
|
images, err := cli.ImageList(ctx, imageListOptions)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(images) > 0, nil
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package container
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io/ioutil"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/docker/api/types"
|
||||||
|
"github.com/docker/docker/client"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
log.SetLevel(log.DebugLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestImageExistsLocally(t *testing.T) {
|
||||||
|
// to help make this test reliable and not flaky, we need to have
|
||||||
|
// an image that will exist, and onew that won't exist
|
||||||
|
|
||||||
|
exists, err := ImageExistsLocally(context.TODO(), "library/alpine:this-random-tag-will-never-exist")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, false, exists)
|
||||||
|
|
||||||
|
// pull an image
|
||||||
|
cli, err := client.NewClientWithOpts(client.FromEnv)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
cli.NegotiateAPIVersion(context.TODO())
|
||||||
|
|
||||||
|
// Chose alpine latest because it's so small
|
||||||
|
// maybe we should build an image instead so that tests aren't reliable on dockerhub
|
||||||
|
reader, err := cli.ImagePull(context.TODO(), "alpine:latest", types.ImagePullOptions{})
|
||||||
|
assert.Nil(t, err)
|
||||||
|
defer reader.Close()
|
||||||
|
_, err = ioutil.ReadAll(reader)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
exists, err = ImageExistsLocally(context.TODO(), "alpine:latest")
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, true, exists)
|
||||||
|
}
|
Loading…
Reference in New Issue