Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add init for ImageRunner mode #737

Merged
merged 5 commits into from
Apr 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions internal/cmd/ini/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/saucelabs/saucectl/internal/cypress"
"github.com/saucelabs/saucectl/internal/espresso"
"github.com/saucelabs/saucectl/internal/flags"
"github.com/saucelabs/saucectl/internal/imagerunner"
"github.com/saucelabs/saucectl/internal/msg"
"github.com/saucelabs/saucectl/internal/playwright"
"github.com/saucelabs/saucectl/internal/puppeteer"
Expand All @@ -39,6 +40,7 @@ type initConfig struct {
frameworkName string
frameworkVersion string
cypressJSON string
dockerImage string
app string
testApp string
otherApps []string
Expand Down Expand Up @@ -95,6 +97,7 @@ func Command() *cobra.Command {
cmd.Flags().StringVarP(&initCfg.frameworkName, "framework", "f", "", "framework to configure")
cmd.Flags().StringVarP(&initCfg.frameworkVersion, "frameworkVersion", "v", "", "framework version to be used")
cmd.Flags().StringVar(&initCfg.cypressJSON, "cypress.config", "", "path to cypress.json file (cypress only)")
cmd.Flags().StringVar(&initCfg.dockerImage, "dockerImage", "", "docker image to use (imagerunner only)")
cmd.Flags().StringVar(&initCfg.app, "app", "", "path to application to test (espresso/xcuitest only)")
cmd.Flags().StringVarP(&initCfg.testApp, "testApp", "t", "", "path to test application (espresso/xcuitest only)")
cmd.Flags().StringSliceVarP(&initCfg.otherApps, "otherApps", "o", []string{}, "path to other applications (espresso/xcuitest only)")
Expand Down Expand Up @@ -156,6 +159,7 @@ func Run(cmd *cobra.Command, initCfg *initConfig) error {
return err
}
displaySummary(files)
displayExtraInfo(initCfg.frameworkName)
return nil
}

Expand Down Expand Up @@ -183,6 +187,8 @@ func batchMode(cmd *cobra.Command, initCfg *initConfig) error {
initCfg, errs = ini.initializeBatchTestcafe(initCfg)
case xcuitest.Kind:
initCfg, errs = ini.initializeBatchXcuitest(cmd.Flags(), initCfg)
case imagerunner.Kind:
initCfg, errs = ini.initializeBatchImageRunner(initCfg)
default:
println()
color.HiRed("Invalid framework selected")
Expand Down Expand Up @@ -212,5 +218,6 @@ func batchMode(cmd *cobra.Command, initCfg *initConfig) error {
return err
}
displaySummary(files)
displayExtraInfo(initCfg.frameworkName)
return nil
}
37 changes: 31 additions & 6 deletions internal/cmd/ini/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
Expand All @@ -19,12 +20,17 @@ import (
)

var configurators = map[string]func(cfg *initConfig) interface{}{
"cypress": configureCypress,
"espresso": configureEspresso,
"playwright": configurePlaywright,
"puppeteer": configurePuppeteer,
"testcafe": configureTestcafe,
"xcuitest": configureXCUITest,
"cypress": configureCypress,
"espresso": configureEspresso,
"playwright": configurePlaywright,
"puppeteer": configurePuppeteer,
"testcafe": configureTestcafe,
"xcuitest": configureXCUITest,
"imagerunner": configureImageRunner,
}

var extraInfoDisplay = map[string]func(){
"imagerunner": displayExtraInfoImageRunner,
}

var sauceignores = map[string]string{
Expand Down Expand Up @@ -98,6 +104,14 @@ func displaySummary(files []string) {
println()
}

func displayExtraInfo(framework string) {
fn, present := extraInfoDisplay[framework]
if !present {
return
}
fn()
}

func completeBasic(toComplete string) []string {
files, _ := filepath.Glob(fmt.Sprintf("%s%s", toComplete, "*"))
return files
Expand Down Expand Up @@ -136,6 +150,17 @@ func extValidator(framework, frameworkVersion string) survey.Validator {
}
}

func dockerImageValidator() survey.Validator {
re := regexp.MustCompile(`^([\w.\-_]+((:\d+|)(/[a-z0-9._-]+/[a-z0-9._-]+))|)(/|)([a-z0-9.\-_]+(/[a-z0-9.\-_]+|))(:([\w.\-_]{1,127})|)$`)
return func(s interface{}) error {
str := s.(string)
if re.MatchString(str) {
return nil
}
return fmt.Errorf("%s is not a valid docker image", str)
}
}

func getMajorVersion(frameworkVersion string) int {
version := strings.Split(frameworkVersion, ".")[0]
v, err := strconv.Atoi(version)
Expand Down
54 changes: 54 additions & 0 deletions internal/cmd/ini/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -624,3 +624,57 @@ func TestCommon_getMajorVersion(t *testing.T) {
})
}
}

func Test_dockerImageValidator(t *testing.T) {
tests := []struct {
image string
want error
}{
{
image: "alpine",
want: nil,
},
{
image: "alpine:latest",
want: nil,
},
{
image: "_/alpine",
want: nil,
},
{
image: "_/alpine:latest",
want: nil,
},
{
image: "alpine:3.7",
want: nil,
},
{
image: "docker.example.com/gmr/alpine:3.7",
want: nil,
},
{
image: "docker.example.com:5000/gmr/alpine:latest",
want: nil,
},
{
image: "pse/anabroker:latest",
want: nil,
},
{
image: "buggy::latest",
want: errors.New("buggy::latest is not a valid docker image"),
},
{
image: "buggy:",
want: errors.New("buggy: is not a valid docker image"),
},
}
val := dockerImageValidator()
for _, tt := range tests {
t.Run(tt.image, func(t *testing.T) {
assert.Equalf(t, tt.want, val(tt.image), "dockerImageValidator()")
})
}
}
46 changes: 46 additions & 0 deletions internal/cmd/ini/imagerunner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package ini

import (
"fmt"

"github.com/fatih/color"
"github.com/saucelabs/saucectl/internal/config"
"github.com/saucelabs/saucectl/internal/imagerunner"
)

func configureImageRunner(cfg *initConfig) interface{} {
return imagerunner.Project{
TypeDef: config.TypeDef{
APIVersion: imagerunner.APIVersion,
Kind: imagerunner.Kind,
},
Sauce: config.SauceConfig{
Region: cfg.region,
},
Suites: []imagerunner.Suite{
{
Name: fmt.Sprintf("imagerunner - %s", cfg.dockerImage),
Image: cfg.dockerImage,
ImagePullAuth: imagerunner.ImagePullAuth{
User: "${DOCKER_USERNAME}",
Token: "${DOCKER_PASSWORD}",
},
},
},
Artifacts: config.Artifacts{
Download: config.ArtifactDownload{
When: cfg.artifactWhen,
Directory: "./artifacts",
Match: []string{"*"},
},
},
}
}

func displayExtraInfoImageRunner() {
println()
color.HiGreen("Before running your tests, you need to set the following environment variables:")
color.Green(" - DOCKER_USERNAME")
color.Green(" - DOCKER_PASSWORD")
println()
}
54 changes: 54 additions & 0 deletions internal/cmd/ini/initializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/saucelabs/saucectl/internal/framework"
"github.com/saucelabs/saucectl/internal/http"
"github.com/saucelabs/saucectl/internal/iam"
"github.com/saucelabs/saucectl/internal/imagerunner"
"github.com/saucelabs/saucectl/internal/msg"
"github.com/saucelabs/saucectl/internal/playwright"
"github.com/saucelabs/saucectl/internal/puppeteer"
Expand Down Expand Up @@ -83,6 +84,8 @@ func (ini *initializer) configure() (*initConfig, error) {
return ini.initializeEspresso()
case xcuitest.Kind:
return ini.initializeXCUITest()
case imagerunner.Kind:
return ini.initializeImageRunner()
default:
return &initConfig{}, fmt.Errorf("unsupported framework %v", fName)
}
Expand Down Expand Up @@ -414,6 +417,18 @@ func (ini *initializer) askFile(message string, val survey.Validator, comp compl
survey.WithStdio(ini.stdio.In, ini.stdio.Out, ini.stdio.Err))
}

func (ini *initializer) askDockerImage(message string, val survey.Validator, targetValue *string) error {
q := &survey.Input{
Message: message,
}

return survey.AskOne(q, targetValue,
survey.WithShowCursor(true),
survey.WithValidator(survey.Required),
survey.WithValidator(val),
survey.WithStdio(ini.stdio.In, ini.stdio.Out, ini.stdio.Err))
}

func (ini *initializer) initializeCypress() (*initConfig, error) {
cfg := &initConfig{frameworkName: cypress.Kind}

Expand Down Expand Up @@ -585,6 +600,22 @@ func (ini *initializer) initializeXCUITest() (*initConfig, error) {
return cfg, nil
}

func (ini *initializer) initializeImageRunner() (*initConfig, error) {
cfg := &initConfig{frameworkName: imagerunner.Kind}

err := ini.askDockerImage("Docker Image to use:", dockerImageValidator(), &cfg.dockerImage)
if err != nil {
return &initConfig{}, err
}

err = ini.askDownloadWhen(cfg)
if err != nil {
return &initConfig{}, err
}

return cfg, nil
}

func checkFrameworkVersion(metadatas []framework.Metadata, frameworkName, frameworkVersion string) error {
var supported []string
for _, fm := range metadatas {
Expand Down Expand Up @@ -927,3 +958,26 @@ func (ini *initializer) initializeBatchXcuitest(f *pflag.FlagSet, initCfg *initC
}
return initCfg, errs
}

func (ini *initializer) initializeBatchImageRunner(initCfg *initConfig) (*initConfig, []error) {
initCfg.frameworkName = imagerunner.Kind
var errs []error
var err error

if initCfg.dockerImage == "" {
errs = append(errs, errors.New(msg.MissingDockerImage))
}
if initCfg.dockerImage != "" {
verifier := dockerImageValidator()
if err = verifier(initCfg.dockerImage); err != nil {
errs = append(errs, fmt.Errorf("dockerImage: %s", err))
}
}
if initCfg.artifactWhenStr != "" {
initCfg.artifactWhenStr = strings.ToLower(initCfg.artifactWhenStr)
if initCfg.artifactWhen, err = checkArtifactDownloadSetting(initCfg.artifactWhenStr); err != nil {
errs = append(errs, err)
}
}
return initCfg, errs
}
Loading