From 65e3c90cf30d0309005f71da24c73ff5281f29f5 Mon Sep 17 00:00:00 2001 From: Alex Plischke Date: Wed, 11 Dec 2024 12:55:54 -0800 Subject: [PATCH] feat: greatly improve cancellability (#991) * feat: cancellable artifacts command * refactor: obsolete arg * feat: ensure all commands are cancellable * feat: cancellable tunnel validation * feat: cancellable framework metadata retrieval --- internal/apitest/runner.go | 3 +- internal/cmd/apit/deletefile.go | 5 +- internal/cmd/apit/downloadfile.go | 7 ++- internal/cmd/apit/get.go | 5 +- internal/cmd/apit/getsnippet.go | 5 +- internal/cmd/apit/getvariable.go | 5 +- internal/cmd/apit/listfiles.go | 5 +- internal/cmd/apit/setsnippet.go | 5 +- internal/cmd/apit/setvariable.go | 5 +- internal/cmd/apit/uploadfile.go | 5 +- internal/cmd/apit/vault.go | 8 +-- internal/cmd/artifacts/artifactservice.go | 26 +++++----- internal/cmd/artifacts/download.go | 11 ++-- internal/cmd/artifacts/list.go | 9 ++-- internal/cmd/artifacts/upload.go | 4 +- internal/cmd/docker/push.go | 10 ++-- internal/cmd/imagerunner/artifacts.go | 8 +-- internal/cmd/imagerunner/list.go | 8 +-- internal/cmd/imagerunner/logs.go | 10 ++-- internal/cmd/imagerunner/stop.go | 5 +- internal/cmd/ini/cmd.go | 17 +++--- internal/cmd/ini/initializer.go | 52 +++++++++---------- internal/cmd/ini/initializer_test.go | 26 +++++----- internal/cmd/run/apitest.go | 2 +- internal/cmd/run/imagerunner.go | 2 +- internal/http/testcomposer.go | 4 +- internal/http/testcomposer_test.go | 2 +- internal/job/job.go | 2 +- internal/mocks/job.go | 9 ++-- internal/saucecloud/cloud.go | 28 +++++----- internal/saucecloud/cucumber.go | 19 +++---- internal/saucecloud/cypress.go | 19 +++---- internal/saucecloud/espresso.go | 1 + internal/saucecloud/imagerunner.go | 3 +- internal/saucecloud/jobservice.go | 4 +- internal/saucecloud/playwright.go | 19 +++---- internal/saucecloud/replay.go | 5 +- .../retry/saucereportretrier_test.go | 4 +- internal/saucecloud/testcafe.go | 19 +++---- internal/saucecloud/xcuitest.go | 1 + internal/tunnel/tunnel.go | 4 +- 41 files changed, 192 insertions(+), 199 deletions(-) diff --git a/internal/apitest/runner.go b/internal/apitest/runner.go index 513f7b6b7..19081f423 100644 --- a/internal/apitest/runner.go +++ b/internal/apitest/runner.go @@ -133,9 +133,10 @@ func FilterSuites(p *Project, suiteName string) error { } // RunProject runs the tests defined in apitest.Project -func (r *Runner) RunProject() (int, error) { +func (r *Runner) RunProject(ctx context.Context) (int, error) { exitCode := 1 if err := tunnel.Validate( + ctx, r.TunnelService, r.Project.Sauce.Tunnel.Name, r.Project.Sauce.Tunnel.Owner, diff --git a/internal/cmd/apit/deletefile.go b/internal/cmd/apit/deletefile.go index d30959d98..6c5498d38 100644 --- a/internal/cmd/apit/deletefile.go +++ b/internal/cmd/apit/deletefile.go @@ -1,7 +1,6 @@ package apit import ( - "context" "errors" "fmt" @@ -45,7 +44,7 @@ Use [--project] to specify the project by its name or run without [--project] to }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { name := args[0] confirmed, err := confirmDelete(name) @@ -57,7 +56,7 @@ Use [--project] to specify the project by its name or run without [--project] to return nil } - err = apitesterClient.DeleteVaultFile(context.Background(), selectedProject.ID, []string{name}) + err = apitesterClient.DeleteVaultFile(cmd.Context(), selectedProject.ID, []string{name}) if err != nil { return err } diff --git a/internal/cmd/apit/downloadfile.go b/internal/cmd/apit/downloadfile.go index 677b46309..fabcbce25 100644 --- a/internal/cmd/apit/downloadfile.go +++ b/internal/cmd/apit/downloadfile.go @@ -1,7 +1,6 @@ package apit import ( - "context" "errors" "fmt" "io" @@ -47,9 +46,9 @@ Use [--project] to specify the project by its name or run without [--project] to }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { name := args[0] - files, err := apitesterClient.ListVaultFiles(context.Background(), selectedProject.ID) + files, err := apitesterClient.ListVaultFiles(cmd.Context(), selectedProject.ID) if err != nil { return err } @@ -59,7 +58,7 @@ Use [--project] to specify the project by its name or run without [--project] to return fmt.Errorf("project %q has no vault drive file with name %q", selectedProject.ProjectMeta.Name, name) } - bodyReader, err := apitesterClient.GetVaultFileContent(context.Background(), selectedProject.ID, file.ID) + bodyReader, err := apitesterClient.GetVaultFileContent(cmd.Context(), selectedProject.ID, file.ID) if err != nil { return err } diff --git a/internal/cmd/apit/get.go b/internal/cmd/apit/get.go index 1c86f78ab..6420c99f9 100644 --- a/internal/cmd/apit/get.go +++ b/internal/cmd/apit/get.go @@ -1,7 +1,6 @@ package apit import ( - "context" "encoding/json" "fmt" "os" @@ -38,8 +37,8 @@ Use [--project] to specify the project by its name or run without [--project] to }() return nil }, - RunE: func(_ *cobra.Command, _ []string) error { - vault, err := apitesterClient.GetVault(context.Background(), selectedProject.Hooks[0].Identifier) + RunE: func(cmd *cobra.Command, _ []string) error { + vault, err := apitesterClient.GetVault(cmd.Context(), selectedProject.Hooks[0].Identifier) if err != nil { return err } diff --git a/internal/cmd/apit/getsnippet.go b/internal/cmd/apit/getsnippet.go index 382dad45f..b3def2e72 100644 --- a/internal/cmd/apit/getsnippet.go +++ b/internal/cmd/apit/getsnippet.go @@ -1,7 +1,6 @@ package apit import ( - "context" "errors" "fmt" @@ -43,9 +42,9 @@ Use [--project] to specify the project by its name or run without [--project] to }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { name := args[0] - vault, err := apitesterClient.GetVault(context.Background(), selectedProject.Hooks[0].Identifier) + vault, err := apitesterClient.GetVault(cmd.Context(), selectedProject.Hooks[0].Identifier) if err != nil { return err } diff --git a/internal/cmd/apit/getvariable.go b/internal/cmd/apit/getvariable.go index e9b5f38eb..3a351193f 100644 --- a/internal/cmd/apit/getvariable.go +++ b/internal/cmd/apit/getvariable.go @@ -1,7 +1,6 @@ package apit import ( - "context" "errors" "fmt" @@ -42,10 +41,10 @@ Use [--project] to specify the project by its name or run without [--project] to }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { name := args[0] - vault, err := apitesterClient.GetVault(context.Background(), selectedProject.Hooks[0].Identifier) + vault, err := apitesterClient.GetVault(cmd.Context(), selectedProject.Hooks[0].Identifier) if err != nil { return err } diff --git a/internal/cmd/apit/listfiles.go b/internal/cmd/apit/listfiles.go index f6da7d5fa..191ce82a2 100644 --- a/internal/cmd/apit/listfiles.go +++ b/internal/cmd/apit/listfiles.go @@ -1,7 +1,6 @@ package apit import ( - "context" "fmt" "github.com/spf13/cobra" @@ -37,8 +36,8 @@ Use [--project] to specify the project by its name or run without [--project] to }() return nil }, - RunE: func(_ *cobra.Command, _ []string) error { - files, err := apitesterClient.ListVaultFiles(context.Background(), selectedProject.ID) + RunE: func(cmd *cobra.Command, _ []string) error { + files, err := apitesterClient.ListVaultFiles(cmd.Context(), selectedProject.ID) if err != nil { return err } diff --git a/internal/cmd/apit/setsnippet.go b/internal/cmd/apit/setsnippet.go index 9c1b48513..85b8eefcc 100644 --- a/internal/cmd/apit/setsnippet.go +++ b/internal/cmd/apit/setsnippet.go @@ -1,7 +1,6 @@ package apit import ( - "context" "errors" "fmt" "io" @@ -54,7 +53,7 @@ cat snippet2.xml | saucectl apit vault set-snippet snip2 - --project "smoke test }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { name := args[0] fileName := args[1] @@ -70,7 +69,7 @@ cat snippet2.xml | saucectl apit vault set-snippet snip2 - --project "smoke test }, } - err = apitesterClient.PutVault(context.Background(), selectedProject.Hooks[0].Identifier, updateVault) + err = apitesterClient.PutVault(cmd.Context(), selectedProject.Hooks[0].Identifier, updateVault) if err != nil { return err } diff --git a/internal/cmd/apit/setvariable.go b/internal/cmd/apit/setvariable.go index c743b62d2..41a39aad9 100644 --- a/internal/cmd/apit/setvariable.go +++ b/internal/cmd/apit/setvariable.go @@ -1,7 +1,6 @@ package apit import ( - "context" "errors" "fmt" @@ -48,7 +47,7 @@ Use [--project] to specify a project by its name or run without [--project] to c }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { name := args[0] val := args[1] updateVault := apitest.Vault{ @@ -62,7 +61,7 @@ Use [--project] to specify a project by its name or run without [--project] to c Snippets: map[string]string{}, } - err := apitesterClient.PutVault(context.Background(), selectedProject.Hooks[0].Identifier, updateVault) + err := apitesterClient.PutVault(cmd.Context(), selectedProject.Hooks[0].Identifier, updateVault) if err != nil { return err } diff --git a/internal/cmd/apit/uploadfile.go b/internal/cmd/apit/uploadfile.go index 0fafe3e7d..bc6c0a3eb 100644 --- a/internal/cmd/apit/uploadfile.go +++ b/internal/cmd/apit/uploadfile.go @@ -1,7 +1,6 @@ package apit import ( - "context" "errors" "fmt" "os" @@ -45,14 +44,14 @@ Use [--project] to specify the project by its name or run without [--project] to }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { name := args[0] fd, err := os.Open(name) if err != nil { return err } - _, err = apitesterClient.PutVaultFile(context.Background(), selectedProject.ID, name, fd) + _, err = apitesterClient.PutVaultFile(cmd.Context(), selectedProject.ID, name, fd) if err != nil { return err } diff --git a/internal/cmd/apit/vault.go b/internal/cmd/apit/vault.go index 5bbd697e8..1bf48dfb3 100644 --- a/internal/cmd/apit/vault.go +++ b/internal/cmd/apit/vault.go @@ -34,7 +34,7 @@ func VaultCommand(preRunE func(cmd *cobra.Command, args []string) error) *cobra. return err } } - selectedProject, err = resolve(projectName) + selectedProject, err = resolve(cmd.Context(), projectName) if err != nil { return err } @@ -75,8 +75,8 @@ func isTerm(fd uintptr) bool { return isatty.IsTerminal(fd) || isatty.IsCygwinTerminal(fd) } -func resolve(projectName string) (ResolvedProject, error) { - projects, err := apitesterClient.GetProjects(context.Background()) +func resolve(ctx context.Context, projectName string) (ResolvedProject, error) { + projects, err := apitesterClient.GetProjects(ctx) if projectName == "" { if !isTerm(os.Stdin.Fd()) || !isTerm(os.Stdout.Fd()) { return ResolvedProject{}, fmt.Errorf("no project specified, use --project to choose a project by name") @@ -101,7 +101,7 @@ func resolve(projectName string) (ResolvedProject, error) { return ResolvedProject{}, fmt.Errorf("could not find project named %s", projectName) } - hooks, err := apitesterClient.GetHooks(context.Background(), project.ID) + hooks, err := apitesterClient.GetHooks(ctx, project.ID) if err != nil { return ResolvedProject{}, err } diff --git a/internal/cmd/artifacts/artifactservice.go b/internal/cmd/artifacts/artifactservice.go index b8a524da4..343321577 100644 --- a/internal/cmd/artifacts/artifactservice.go +++ b/internal/cmd/artifacts/artifactservice.go @@ -15,13 +15,13 @@ type ArtifactService struct { } // List returns an artifact list -func (s *ArtifactService) List(jobID string) (List, error) { - isRDC, err := s.isRDC(jobID) +func (s *ArtifactService) List(ctx context.Context, jobID string) (List, error) { + isRDC, err := s.isRDC(ctx, jobID) if err != nil { return List{}, err } items, err := s.JobService.ArtifactNames( - context.Background(), jobID, isRDC, + ctx, jobID, isRDC, ) if err != nil { return List{}, err @@ -33,20 +33,20 @@ func (s *ArtifactService) List(jobID string) (List, error) { } // Download does download specified artifacts -func (s *ArtifactService) Download(jobID, filename string) ([]byte, error) { - isRDC, err := s.isRDC(jobID) +func (s *ArtifactService) Download(ctx context.Context, jobID, filename string) ([]byte, error) { + isRDC, err := s.isRDC(ctx, jobID) if err != nil { return nil, err } return s.JobService.Artifact( - context.Background(), jobID, filename, isRDC, + ctx, jobID, filename, isRDC, ) } // Upload does upload the specified artifact -func (s *ArtifactService) Upload(jobID, filename string, content []byte) error { - isRDC, err := s.isRDC(jobID) +func (s *ArtifactService) Upload(ctx context.Context, jobID, filename string, content []byte) error { + isRDC, err := s.isRDC(ctx, jobID) if err != nil { return err } @@ -54,15 +54,13 @@ func (s *ArtifactService) Upload(jobID, filename string, content []byte) error { return errors.New("uploading file to Real Device job is not supported") } - return s.JobService.UploadArtifact( - jobID, false, filename, http.DetectContentType(content), content, - ) + return s.JobService.UploadArtifact(ctx, jobID, false, filename, http.DetectContentType(content), content) } -func (s *ArtifactService) isRDC(jobID string) (bool, error) { - _, err := s.JobService.Job(context.Background(), jobID, false) +func (s *ArtifactService) isRDC(ctx context.Context, jobID string) (bool, error) { + _, err := s.JobService.Job(ctx, jobID, false) if err != nil { - _, err = s.JobService.Job(context.Background(), jobID, true) + _, err = s.JobService.Job(ctx, jobID, true) if err != nil { return false, fmt.Errorf("failed to get the job: %w", err) } diff --git a/internal/cmd/artifacts/download.go b/internal/cmd/artifacts/download.go index 59ed4b317..c389817e6 100644 --- a/internal/cmd/artifacts/download.go +++ b/internal/cmd/artifacts/download.go @@ -1,6 +1,7 @@ package artifacts import ( + "context" "errors" "fmt" "os" @@ -49,10 +50,10 @@ func DownloadCommand() *cobra.Command { }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { jobID := args[0] filePattern := args[1] - return download(jobID, filePattern, targetDir, out) + return download(cmd.Context(), jobID, filePattern, targetDir, out) }, } @@ -63,8 +64,8 @@ func DownloadCommand() *cobra.Command { return cmd } -func download(jobID, filePattern, targetDir, outputFormat string) error { - lst, err := artifactSvc.List(jobID) +func download(ctx context.Context, jobID, filePattern, targetDir, outputFormat string) error { + lst, err := artifactSvc.List(ctx, jobID) if err != nil { return err } @@ -75,7 +76,7 @@ func download(jobID, filePattern, targetDir, outputFormat string) error { bar := newDownloadProgressBar(outputFormat, len(files)) for _, f := range files { _ = bar.Add(1) - body, err := artifactSvc.Download(jobID, f) + body, err := artifactSvc.Download(ctx, jobID, f) if err != nil { return fmt.Errorf("failed to get file: %w", err) } diff --git a/internal/cmd/artifacts/list.go b/internal/cmd/artifacts/list.go index d208d1b66..292da1c9c 100644 --- a/internal/cmd/artifacts/list.go +++ b/internal/cmd/artifacts/list.go @@ -1,6 +1,7 @@ package artifacts import ( + "context" "encoding/json" "errors" "fmt" @@ -93,8 +94,8 @@ func ListCommand() *cobra.Command { }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { - return list(args[0], out) + RunE: func(cmd *cobra.Command, args []string) error { + return list(cmd.Context(), args[0], out) }, } flags := cmd.PersistentFlags() @@ -103,8 +104,8 @@ func ListCommand() *cobra.Command { return cmd } -func list(jobID, outputFormat string) error { - lst, err := artifactSvc.List(jobID) +func list(ctx context.Context, jobID, outputFormat string) error { + lst, err := artifactSvc.List(ctx, jobID) if err != nil { return fmt.Errorf("failed to get artifacts list: %w", err) } diff --git a/internal/cmd/artifacts/upload.go b/internal/cmd/artifacts/upload.go index a47ed34da..f2a9b3aea 100644 --- a/internal/cmd/artifacts/upload.go +++ b/internal/cmd/artifacts/upload.go @@ -47,7 +47,7 @@ func UploadCommand() *cobra.Command { }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { jobID := args[0] filePath := args[1] file, err := os.Open(filePath) @@ -65,7 +65,7 @@ func UploadCommand() *cobra.Command { return fmt.Errorf("failed to read file: %w", err) } - err = artifactSvc.Upload(jobID, finfo.Name(), content) + err = artifactSvc.Upload(cmd.Context(), jobID, finfo.Name(), content) if err != nil { return fmt.Errorf("failed to upload file: %w", err) } diff --git a/internal/cmd/docker/push.go b/internal/cmd/docker/push.go index a36acc29c..614f48b81 100644 --- a/internal/cmd/docker/push.go +++ b/internal/cmd/docker/push.go @@ -47,13 +47,13 @@ func PushCommand() *cobra.Command { _ = tracker.Close() }() }, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { image := args[0] - auth, err := imageRunnerService.RegistryLogin(context.Background(), image) + auth, err := imageRunnerService.RegistryLogin(cmd.Context(), image) if err != nil { return fmt.Errorf("failed to fetch auth token: %v", err) } - return pushDockerImage(image, auth.Username, auth.Password, timeout, quiet) + return pushDockerImage(cmd.Context(), image, auth.Username, auth.Password, timeout, quiet) }, } @@ -64,8 +64,8 @@ func PushCommand() *cobra.Command { return cmd } -func pushDockerImage(imageName, username, password string, timeout time.Duration, quiet bool) error { - ctx, cancel := context.WithTimeout(context.Background(), timeout) +func pushDockerImage(ctx context.Context, imageName, username, password string, timeout time.Duration, quiet bool) error { + ctx, cancel := context.WithTimeout(ctx, timeout) defer cancel() cli, err := client.NewClientWithOpts(client.FromEnv) diff --git a/internal/cmd/imagerunner/artifacts.go b/internal/cmd/imagerunner/artifacts.go index 7126b7426..2a1deb5ba 100644 --- a/internal/cmd/imagerunner/artifacts.go +++ b/internal/cmd/imagerunner/artifacts.go @@ -108,11 +108,11 @@ func downloadCommand() *cobra.Command { }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ID := args[0] filePattern := args[1] - return download(ID, filePattern, targetDir, out) + return download(cmd.Context(), ID, filePattern, targetDir, out) }, } @@ -123,8 +123,8 @@ func downloadCommand() *cobra.Command { return cmd } -func download(ID, filePattern, targetDir, outputFormat string) error { - reader, err := imagerunnerClient.DownloadArtifacts(context.Background(), ID) +func download(ctx context.Context, ID, filePattern, targetDir, outputFormat string) error { + reader, err := imagerunnerClient.DownloadArtifacts(ctx, ID) if err != nil { return fmt.Errorf("failed to fetch artifacts: %w", err) } diff --git a/internal/cmd/imagerunner/list.go b/internal/cmd/imagerunner/list.go index 88071f066..f2906d4ac 100644 --- a/internal/cmd/imagerunner/list.go +++ b/internal/cmd/imagerunner/list.go @@ -36,8 +36,8 @@ func ListCommand() *cobra.Command { }() return nil }, - RunE: func(_ *cobra.Command, _ []string) error { - return list(out) + RunE: func(cmd *cobra.Command, _ []string) error { + return list(cmd.Context(), out) }, } flags := cmd.PersistentFlags() @@ -46,8 +46,8 @@ func ListCommand() *cobra.Command { return cmd } -func list(outputFormat string) error { - containers, err := imagerunnerClient.ListContainers(context.Background()) +func list(ctx context.Context, outputFormat string) error { + containers, err := imagerunnerClient.ListContainers(ctx) if err != nil { return fmt.Errorf("failed to get container list: %v", err) } diff --git a/internal/cmd/imagerunner/logs.go b/internal/cmd/imagerunner/logs.go index 3f7115bbe..a77517183 100644 --- a/internal/cmd/imagerunner/logs.go +++ b/internal/cmd/imagerunner/logs.go @@ -42,8 +42,8 @@ func LogsCommand() *cobra.Command { }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { - return exec(args[0], liveLogs) + RunE: func(cmd *cobra.Command, args []string) error { + return exec(cmd.Context(), args[0], liveLogs) }, } @@ -53,9 +53,9 @@ func LogsCommand() *cobra.Command { return cmd } -func exec(runID string, liveLogs bool) error { +func exec(ctx context.Context, runID string, liveLogs bool) error { if liveLogs { - err := imagerunnerClient.GetLiveLogs(context.Background(), runID) + err := imagerunnerClient.GetLiveLogs(ctx, runID) if err != nil { if errors.Is(err, imgrunner.ErrResourceNotFound) { return fmt.Errorf("could not find log URL for run with ID (%s): %w", runID, err) @@ -64,7 +64,7 @@ func exec(runID string, liveLogs bool) error { return err } - log, err := imagerunnerClient.GetLogs(context.Background(), runID) + log, err := imagerunnerClient.GetLogs(ctx, runID) if err != nil { if errors.Is(err, imgrunner.ErrResourceNotFound) { return fmt.Errorf("could not find log URL for run with ID (%s): %w", runID, err) diff --git a/internal/cmd/imagerunner/stop.go b/internal/cmd/imagerunner/stop.go index 8947272c7..30e905c59 100644 --- a/internal/cmd/imagerunner/stop.go +++ b/internal/cmd/imagerunner/stop.go @@ -1,7 +1,6 @@ package imagerunner import ( - "context" "errors" "fmt" @@ -39,10 +38,10 @@ func StopCommand() *cobra.Command { }() return nil }, - RunE: func(_ *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, args []string) error { ID := args[0] fmt.Printf("Stopping container %s...\n", ID) - if err := imagerunnerClient.StopRun(context.Background(), ID); err != nil { + if err := imagerunnerClient.StopRun(cmd.Context(), ID); err != nil { return fmt.Errorf("failed to stop the container: %v", err) } return nil diff --git a/internal/cmd/ini/cmd.go b/internal/cmd/ini/cmd.go index c5386ee48..bf73ed4f2 100644 --- a/internal/cmd/ini/cmd.go +++ b/internal/cmd/ini/cmd.go @@ -1,7 +1,6 @@ package ini import ( - "context" "errors" "fmt" "os" @@ -134,17 +133,17 @@ func Run(cmd *cobra.Command, cfg *initConfig) error { ini := newInitializer(stdio, creds, cfg) - err = ini.checkCredentials(regionName) + err = ini.checkCredentials(cmd.Context(), regionName) if err != nil { return err } - err = ini.configure() + err = ini.configure(cmd.Context()) if err != nil { return err } - ccy, err := ini.userService.Concurrency(context.Background()) + ccy, err := ini.userService.Concurrency(cmd.Context()) if err != nil { println() color.HiRed("Unable to determine your exact allowed concurrency.\n") @@ -178,13 +177,13 @@ func noPromptMode(cmd *cobra.Command, cfg *initConfig) error { var errs []error switch cfg.frameworkName { case cypress.Kind: - errs = ini.initializeBatchCypress() + errs = ini.initializeBatchCypress(cmd.Context()) case espresso.Kind: - errs = ini.initializeBatchEspresso(cmd.Flags()) + errs = ini.initializeBatchEspresso(cmd.Context(), cmd.Flags()) case playwright.Kind: - errs = ini.initializeBatchPlaywright() + errs = ini.initializeBatchPlaywright(cmd.Context()) case testcafe.Kind: - errs = ini.initializeBatchTestcafe() + errs = ini.initializeBatchTestcafe(cmd.Context()) case xcuitest.Kind: errs = ini.initializeBatchXcuitest(cmd.Flags()) case imagerunner.Kind: @@ -203,7 +202,7 @@ func noPromptMode(cmd *cobra.Command, cfg *initConfig) error { return fmt.Errorf("%s: %d errors occured", cfg.frameworkName, len(errs)) } - ccy, err := ini.userService.Concurrency(context.Background()) + ccy, err := ini.userService.Concurrency(cmd.Context()) if err != nil { println() color.HiRed("Unable to determine your exact allowed concurrency.\n") diff --git a/internal/cmd/ini/initializer.go b/internal/cmd/ini/initializer.go index 54de26e12..ff60f24f3 100644 --- a/internal/cmd/ini/initializer.go +++ b/internal/cmd/ini/initializer.go @@ -73,18 +73,18 @@ func newInitializer(stdio terminal.Stdio, creds iam.Credentials, cfg *initConfig } } -func (ini *initializer) configure() error { +func (ini *initializer) configure(ctx context.Context) error { switch ini.cfg.frameworkName { case cypress.Kind: - return ini.initializeCypress() + return ini.initializeCypress(ctx) case playwright.Kind: - return ini.initializePlaywright() + return ini.initializePlaywright(ctx) case testcafe.Kind: - return ini.initializeTestcafe() + return ini.initializeTestcafe(ctx) case espresso.Kind: - return ini.initializeEspresso() + return ini.initializeEspresso(ctx) case xcuitest.Kind: - return ini.initializeXCUITest() + return ini.initializeXCUITest(ctx) case imagerunner.Kind: return ini.initializeImageRunner() default: @@ -130,8 +130,8 @@ func askRegion(stdio terminal.Stdio) (string, error) { return r, nil } -func (ini *initializer) checkCredentials(region string) error { - _, err := ini.infoReader.Frameworks(context.Background()) +func (ini *initializer) checkCredentials(ctx context.Context, region string) error { + _, err := ini.infoReader.Frameworks(ctx) if err != nil && err.Error() == "unexpected status '401' from test-composer: Unauthorized\n" { println() color.HiRed("It appears that your credentials are incorrect.") @@ -434,8 +434,8 @@ func (ini *initializer) askWorkload() error { return nil } -func (ini *initializer) initializeCypress() error { - frameworkMetadatas, err := ini.infoReader.Versions(context.Background(), ini.cfg.frameworkName) +func (ini *initializer) initializeCypress(ctx context.Context) error { + frameworkMetadatas, err := ini.infoReader.Versions(ctx, ini.cfg.frameworkName) if err != nil { return err } @@ -463,8 +463,8 @@ func (ini *initializer) initializeCypress() error { return ini.askDownloadWhen() } -func (ini *initializer) initializePlaywright() error { - frameworkMetadatas, err := ini.infoReader.Versions(context.Background(), ini.cfg.frameworkName) +func (ini *initializer) initializePlaywright(ctx context.Context) error { + frameworkMetadatas, err := ini.infoReader.Versions(ctx, ini.cfg.frameworkName) if err != nil { return err } @@ -513,8 +513,8 @@ func (ini *initializer) initializePlaywright() error { return ini.askDownloadWhen() } -func (ini *initializer) initializeTestcafe() error { - frameworkMetadatas, err := ini.infoReader.Versions(context.Background(), ini.cfg.frameworkName) +func (ini *initializer) initializeTestcafe(ctx context.Context) error { + frameworkMetadatas, err := ini.infoReader.Versions(ctx, ini.cfg.frameworkName) if err != nil { return err } @@ -536,7 +536,7 @@ func (ini *initializer) initializeTestcafe() error { return nil } -func (ini *initializer) initializeEspresso() error { +func (ini *initializer) initializeEspresso(ctx context.Context) error { err := ini.askFile( "Application to test:", frameworkExtValidator(ini.cfg.frameworkName, ""), @@ -562,7 +562,7 @@ func (ini *initializer) initializeEspresso() error { return err } - virtualDevices, err := ini.vmdReader.GetVirtualDevices(context.Background(), vmd.AndroidEmulator) + virtualDevices, err := ini.vmdReader.GetVirtualDevices(ctx, vmd.AndroidEmulator) if err != nil { println() color.HiRed("saucectl is unable to fetch the emulators list.") @@ -584,7 +584,7 @@ func (ini *initializer) initializeEspresso() error { return nil } -func (ini *initializer) initializeXCUITest() error { +func (ini *initializer) initializeXCUITest(ctx context.Context) error { q := &survey.Select{ Message: "Select target:", Options: []string{ @@ -618,7 +618,7 @@ func (ini *initializer) initializeXCUITest() error { return err } } else if target == "Virtual Devices" { - virtualDevices, err := ini.vmdReader.GetVirtualDevices(context.Background(), vmd.IOSSimulator) + virtualDevices, err := ini.vmdReader.GetVirtualDevices(ctx, vmd.IOSSimulator) if err != nil { println() color.HiRed("saucectl is unable to fetch the simulators list.") @@ -734,7 +734,7 @@ func checkEmulators(vmds []vmd.VirtualDevice, emulator config.Emulator) (config. }, []error{} } -func (ini *initializer) initializeBatchCypress() []error { +func (ini *initializer) initializeBatchCypress(ctx context.Context) []error { var errs []error if ini.cfg.frameworkVersion == "" { @@ -750,7 +750,7 @@ func (ini *initializer) initializeBatchCypress() []error { errs = append(errs, errors.New(msg.MissingBrowserName)) } - frameworkMetadatas, err := ini.infoReader.Versions(context.Background(), ini.cfg.frameworkName) + frameworkMetadatas, err := ini.infoReader.Versions(ctx, ini.cfg.frameworkName) if err != nil { errs = append(errs, err) return errs @@ -793,7 +793,7 @@ func (ini *initializer) initializeBatchCypress() []error { return errs } -func (ini *initializer) initializeBatchEspresso(f *pflag.FlagSet) []error { +func (ini *initializer) initializeBatchEspresso(ctx context.Context, f *pflag.FlagSet) []error { var errs []error var err error @@ -826,7 +826,7 @@ func (ini *initializer) initializeBatchEspresso(f *pflag.FlagSet) []error { } } if f.Changed("emulator") { - emulators, err := ini.vmdReader.GetVirtualDevices(context.Background(), vmd.AndroidEmulator) + emulators, err := ini.vmdReader.GetVirtualDevices(ctx, vmd.AndroidEmulator) if err != nil { errs = append(errs, fmt.Errorf("")) } @@ -841,7 +841,7 @@ func (ini *initializer) initializeBatchEspresso(f *pflag.FlagSet) []error { return errs } -func (ini *initializer) initializeBatchPlaywright() []error { +func (ini *initializer) initializeBatchPlaywright(ctx context.Context) []error { var errs []error if ini.cfg.frameworkVersion == "" { @@ -854,7 +854,7 @@ func (ini *initializer) initializeBatchPlaywright() []error { errs = append(errs, errors.New(msg.MissingBrowserName)) } - frameworkMetadatas, err := ini.infoReader.Versions(context.Background(), ini.cfg.frameworkName) + frameworkMetadatas, err := ini.infoReader.Versions(ctx, ini.cfg.frameworkName) if err != nil { errs = append(errs, err) return errs @@ -890,7 +890,7 @@ func (ini *initializer) initializeBatchPlaywright() []error { return errs } -func (ini *initializer) initializeBatchTestcafe() []error { +func (ini *initializer) initializeBatchTestcafe(ctx context.Context) []error { var errs []error if ini.cfg.frameworkVersion == "" { @@ -903,7 +903,7 @@ func (ini *initializer) initializeBatchTestcafe() []error { errs = append(errs, errors.New(msg.MissingBrowserName)) } - frameworkMetadatas, err := ini.infoReader.Versions(context.Background(), ini.cfg.frameworkName) + frameworkMetadatas, err := ini.infoReader.Versions(ctx, ini.cfg.frameworkName) if err != nil { errs = append(errs, err) return errs diff --git a/internal/cmd/ini/initializer_test.go b/internal/cmd/ini/initializer_test.go index e84f97ecf..a8d54888f 100644 --- a/internal/cmd/ini/initializer_test.go +++ b/internal/cmd/ini/initializer_test.go @@ -757,7 +757,7 @@ func TestConfigure(t *testing.T) { }, }, execution: func(i *initializer, _ *initConfig) error { - return i.configure() + return i.configure(context.Background()) }, expectedState: &initConfig{ frameworkName: espresso.Kind, @@ -826,7 +826,7 @@ func TestConfigure(t *testing.T) { }, }, execution: func(i *initializer, _ *initConfig) error { - return i.configure() + return i.configure(context.Background()) }, expectedState: &initConfig{ frameworkName: cypress.Kind, @@ -1037,7 +1037,7 @@ func Test_initializers(t *testing.T) { }, }, execution: func(i *initializer, _ *initConfig) error { - return i.initializeCypress() + return i.initializeCypress(context.Background()) }, expectedState: &initConfig{ frameworkName: cypress.Kind, @@ -1112,7 +1112,7 @@ func Test_initializers(t *testing.T) { }, }, execution: func(i *initializer, _ *initConfig) error { - return i.initializePlaywright() + return i.initializePlaywright(context.Background()) }, expectedState: &initConfig{ frameworkName: playwright.Kind, @@ -1171,7 +1171,7 @@ func Test_initializers(t *testing.T) { }, }, execution: func(i *initializer, _ *initConfig) error { - return i.initializeTestcafe() + return i.initializeTestcafe(context.Background()) }, expectedState: &initConfig{ frameworkName: testcafe.Kind, @@ -1237,7 +1237,7 @@ func Test_initializers(t *testing.T) { }, }, execution: func(i *initializer, _ *initConfig) error { - return i.initializeXCUITest() + return i.initializeXCUITest(context.Background()) }, expectedState: &initConfig{ frameworkName: xcuitest.Kind, @@ -1303,7 +1303,7 @@ func Test_initializers(t *testing.T) { }, }, execution: func(i *initializer, _ *initConfig) error { - return i.initializeXCUITest() + return i.initializeXCUITest(context.Background()) }, expectedState: &initConfig{ frameworkName: xcuitest.Kind, @@ -1378,7 +1378,7 @@ func Test_initializers(t *testing.T) { }, }, execution: func(i *initializer, _ *initConfig) error { - return i.initializeEspresso() + return i.initializeEspresso(context.Background()) }, expectedState: &initConfig{ frameworkName: espresso.Kind, @@ -1648,7 +1648,7 @@ func Test_checkCredentials(t *testing.T) { FrameworksFn: tt.frameworkFn, }, } - if err := ini.checkCredentials("us-west-1"); !reflect.DeepEqual(err, tt.wantErr) { + if err := ini.checkCredentials(context.Background(), "us-west-1"); !reflect.DeepEqual(err, tt.wantErr) { t.Errorf("checkCredentials() error = %v, wantErr %v", err, tt.wantErr) } }) @@ -2069,7 +2069,7 @@ func Test_initializer_initializeBatchCypress(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ini.cfg = tt.args.initCfg - errs := ini.initializeBatchCypress() + errs := ini.initializeBatchCypress(context.Background()) if !reflect.DeepEqual(ini.cfg, tt.want) { t.Errorf("initializeBatchCypress() got = %v, want %v", ini.cfg, tt.want) } @@ -2205,7 +2205,7 @@ func Test_initializer_initializeBatchTestcafe(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ini.cfg = tt.args.initCfg - errs := ini.initializeBatchTestcafe() + errs := ini.initializeBatchTestcafe(context.Background()) if !reflect.DeepEqual(ini.cfg, tt.want) { t.Errorf("initializeBatchTestcafe() got = %v, want %v", ini.cfg, tt.want) } @@ -2337,7 +2337,7 @@ func Test_initializer_initializeBatchPlaywright(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ini.cfg = tt.args.initCfg - errs := ini.initializeBatchPlaywright() + errs := ini.initializeBatchPlaywright(context.Background()) if !reflect.DeepEqual(ini.cfg, tt.want) { t.Errorf("initializeBatchPlaywright() got = %v, want %v", ini.cfg, tt.want) } @@ -2645,7 +2645,7 @@ func Test_initializer_initializeBatchEspresso(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { ini.cfg = tt.args.initCfg - errs := ini.initializeBatchEspresso(tt.args.flags()) + errs := ini.initializeBatchEspresso(context.Background(), tt.args.flags()) if !reflect.DeepEqual(ini.cfg, tt.want) { t.Errorf("initializeBatchEspresso() got = %v, want %v", ini.cfg, tt.want) } diff --git a/internal/cmd/run/apitest.go b/internal/cmd/run/apitest.go index 01f05e590..71ffc999d 100644 --- a/internal/cmd/run/apitest.go +++ b/internal/cmd/run/apitest.go @@ -74,7 +74,7 @@ func runApitest(cmd *cobra.Command, isCLIDriven bool) (int, error) { Str("region", regio.String()). Str("tunnel", r.Project.Sauce.Tunnel.Name). Msg("Running API Test in Sauce Labs.") - return r.RunProject() + return r.RunProject(cmd.Context()) } func applyApitestFlags(p *apitest.Project) error { diff --git a/internal/cmd/run/imagerunner.go b/internal/cmd/run/imagerunner.go index da681c6b1..bc6833e6f 100644 --- a/internal/cmd/run/imagerunner.go +++ b/internal/cmd/run/imagerunner.go @@ -84,7 +84,7 @@ func runImageRunner(cmd *cobra.Command) (int, error) { Str("region", regio.String()). Str("tunnel", r.Project.Sauce.Tunnel.Name). Msg("Running in Sauce Labs.") - return r.RunProject() + return r.RunProject(cmd.Context()) } func applyImageRunnerFlags(p *imagerunner.Project) error { diff --git a/internal/http/testcomposer.go b/internal/http/testcomposer.go index 03358ad9f..801517b31 100644 --- a/internal/http/testcomposer.go +++ b/internal/http/testcomposer.go @@ -86,7 +86,7 @@ func (c *TestComposer) doJSONResponse(req *retryablehttp.Request, expectStatus i } // UploadAsset uploads an asset to the specified jobID. -func (c *TestComposer) UploadAsset(jobID string, _ bool, fileName string, contentType string, content []byte) error { +func (c *TestComposer) UploadAsset(ctx context.Context, jobID string, fileName string, contentType string, content []byte) error { var b bytes.Buffer w := multipart.NewWriter(&b) h := make(textproto.MIMEHeader) @@ -103,7 +103,7 @@ func (c *TestComposer) UploadAsset(jobID string, _ bool, fileName string, conten return err } - req, err := NewRetryableRequestWithContext(context.Background(), http.MethodPut, + req, err := NewRetryableRequestWithContext(ctx, http.MethodPut, fmt.Sprintf("%s/v1/testcomposer/jobs/%s/assets", c.URL, jobID), &b) if err != nil { return err diff --git a/internal/http/testcomposer_test.go b/internal/http/testcomposer_test.go index dbbdbf087..1add5710d 100644 --- a/internal/http/testcomposer_test.go +++ b/internal/http/testcomposer_test.go @@ -97,7 +97,7 @@ func TestTestComposer_UploadAsset(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if err := tt.client.UploadAsset(tt.args.jobID, false, tt.args.fileName, tt.args.contentType, tt.args.content); (err != nil) != tt.wantErr { + if err := tt.client.UploadAsset(context.Background(), tt.args.jobID, tt.args.fileName, tt.args.contentType, tt.args.content); (err != nil) != tt.wantErr { t.Errorf("UploadArtifact() error = %v, wantErr %v", err, tt.wantErr) } }) diff --git a/internal/job/job.go b/internal/job/job.go index 223e46af7..1db0c1cd0 100644 --- a/internal/job/job.go +++ b/internal/job/job.go @@ -111,7 +111,7 @@ type Service interface { ArtifactNames(ctx context.Context, jobID string, realDevice bool) ([]string, error) // UploadArtifact uploads an artifact to the Job that matches the given jobID. - UploadArtifact(jobID string, realDevice bool, fileName string, contentType string, content []byte) error + UploadArtifact(ctx context.Context, jobID string, realDevice bool, fileName string, contentType string, content []byte) error // DownloadArtifacts downloads artifacts from a Job. Returns a list of // file paths. diff --git a/internal/mocks/job.go b/internal/mocks/job.go index b03b37d41..a40619174 100644 --- a/internal/mocks/job.go +++ b/internal/mocks/job.go @@ -14,7 +14,7 @@ type FakeJobService struct { ReadJobFn func(ctx context.Context, id string) (job.Job, error) PollJobFn func(ctx context.Context, id string, interval time.Duration, timeout time.Duration) (job.Job, error) - UploadAssetFn func(jobID string, realDevice bool, fileName string, contentType string, content []byte) error + UploadAssetFn func(ctx context.Context, jobID string, realDevice bool, fileName string, contentType string, content []byte) error DownloadArtifactFn func(job job.Job, isLastAttempt bool) []string GetJobAssetFileNamesFn func(ctx context.Context, jobID string) ([]string, error) GetJobAssetFileContentFn func(ctx context.Context, jobID, fileName string) ([]byte, error) @@ -24,11 +24,8 @@ func (s *FakeJobService) StartJob(ctx context.Context, opts job.StartOptions) (j return s.StartJobFn(ctx, opts) } -func (s *FakeJobService) UploadArtifact( - jobID string, realDevice bool, fileName string, contentType string, - content []byte, -) error { - return s.UploadAssetFn(jobID, realDevice, fileName, contentType, content) +func (s *FakeJobService) UploadArtifact(ctx context.Context, jobID string, realDevice bool, fileName string, contentType string, content []byte) error { + return s.UploadAssetFn(ctx, jobID, realDevice, fileName, contentType, content) } func (s *FakeJobService) StopJob( diff --git a/internal/saucecloud/cloud.go b/internal/saucecloud/cloud.go index 550932cc7..02572cd00 100644 --- a/internal/saucecloud/cloud.go +++ b/internal/saucecloud/cloud.go @@ -211,7 +211,7 @@ func (r *CloudRunner) findBuild(jobID string, isRDC bool) build.Build { return b } -func (r *CloudRunner) runJob(opts job.StartOptions) (j job.Job, skipped bool, err error) { +func (r *CloudRunner) runJob(ctx context.Context, opts job.StartOptions) (j job.Job, skipped bool, err error) { log.Info(). Str("suite", opts.DisplayName). Msg("Starting suite.") @@ -224,8 +224,8 @@ func (r *CloudRunner) runJob(opts job.StartOptions) (j job.Job, skipped bool, er sigChan := r.registerInterruptOnSignal(j.ID, opts.RealDevice, opts.DisplayName) defer unregisterSignalCapture(sigChan) - r.uploadSauceConfig(j.ID, opts.RealDevice, opts.ConfigFilePath) - r.uploadCLIFlags(j.ID, opts.RealDevice, opts.CLIFlags) + r.uploadSauceConfig(ctx, j.ID, opts.RealDevice, opts.ConfigFilePath) + r.uploadCLIFlags(ctx, j.ID, opts.RealDevice, opts.CLIFlags) // os.Interrupt can arrive before the signal.Notify() is registered. In that case, // if a soft exit is requested during startContainer phase, it gently exits. @@ -328,7 +328,7 @@ func (r *CloudRunner) runJobs(ctx context.Context, jobOpts chan job.StartOptions opts.StartTime = start } - jobData, skipped, err := r.runJob(opts) + jobData, skipped, err := r.runJob(ctx, opts) if jobData.Passed { opts.CurrentPassCount++ @@ -900,8 +900,8 @@ func (r *CloudRunner) logSuiteConsole(res result) { fmt.Println() } -func (r *CloudRunner) validateTunnel(name, owner string, dryRun bool, timeout time.Duration) error { - return tunnel.Validate(r.TunnelService, name, owner, tunnel.NoneFilter, dryRun, timeout) +func (r *CloudRunner) validateTunnel(ctx context.Context, name, owner string, dryRun bool, timeout time.Duration) error { + return tunnel.Validate(ctx, r.TunnelService, name, owner, tunnel.NoneFilter, dryRun, timeout) } // stopSuiteExecution stops the current execution on Sauce Cloud @@ -957,7 +957,7 @@ func unregisterSignalCapture(c chan os.Signal) { } // uploadSauceConfig adds job configuration as an asset. -func (r *CloudRunner) uploadSauceConfig(jobID string, realDevice bool, cfgFile string) { +func (r *CloudRunner) uploadSauceConfig(ctx context.Context, jobID string, realDevice bool, cfgFile string) { // A config file is optional. if cfgFile == "" { return @@ -973,34 +973,34 @@ func (r *CloudRunner) uploadSauceConfig(jobID string, realDevice bool, cfgFile s log.Warn().Msgf("failed to read configuration: %v", err) return } - if err := r.JobService.UploadArtifact(jobID, realDevice, filepath.Base(cfgFile), "text/plain", content); err != nil { + if err := r.JobService.UploadArtifact(ctx, jobID, realDevice, filepath.Base(cfgFile), "text/plain", content); err != nil { log.Warn().Msgf("failed to attach configuration: %v", err) } } // uploadCLIFlags adds commandline parameters as an asset. -func (r *CloudRunner) uploadCLIFlags(jobID string, realDevice bool, content interface{}) { +func (r *CloudRunner) uploadCLIFlags(ctx context.Context, jobID string, realDevice bool, content interface{}) { encoded, err := json.Marshal(content) if err != nil { log.Warn().Msgf("Failed to encode CLI flags: %v", err) return } - if err := r.JobService.UploadArtifact(jobID, realDevice, "flags.json", "text/plain", encoded); err != nil { + if err := r.JobService.UploadArtifact(ctx, jobID, realDevice, "flags.json", "text/plain", encoded); err != nil { log.Warn().Msgf("Failed to report CLI flags: %v", err) } } -func (r *CloudRunner) logFrameworkError(err error) { +func (r *CloudRunner) logFrameworkError(ctx context.Context, err error) { var unavailableErr *framework.UnavailableError if errors.As(err, &unavailableErr) { color.Red(fmt.Sprintf("\n%s\n\n", err.Error())) - fmt.Print(msg.FormatAvailableVersions(unavailableErr.Name, r.getAvailableVersions(unavailableErr.Name))) + fmt.Print(msg.FormatAvailableVersions(unavailableErr.Name, r.getAvailableVersions(ctx, unavailableErr.Name))) } } // getAvailableVersions gets the available cloud version for the framework. -func (r *CloudRunner) getAvailableVersions(frameworkName string) []string { - versions, err := r.MetadataService.Versions(context.Background(), frameworkName) +func (r *CloudRunner) getAvailableVersions(ctx context.Context, frameworkName string) []string { + versions, err := r.MetadataService.Versions(ctx, frameworkName) if err != nil { return nil } diff --git a/internal/saucecloud/cucumber.go b/internal/saucecloud/cucumber.go index f67f6ca88..b509790dc 100644 --- a/internal/saucecloud/cucumber.go +++ b/internal/saucecloud/cucumber.go @@ -23,21 +23,22 @@ type CucumberRunner struct { // RunProject runs the defined tests on sauce cloud func (r *CucumberRunner) RunProject(ctx context.Context) (int, error) { - m, err := r.MetadataSearchStrategy.Find(context.Background(), r.MetadataService, playwright.Kind, r.Project.Playwright.Version) + m, err := r.MetadataSearchStrategy.Find(ctx, r.MetadataService, playwright.Kind, r.Project.Playwright.Version) if err != nil { - r.logFrameworkError(err) + r.logFrameworkError(ctx, err) return 1, err } r.setVersions(m) - if err := r.validateFramework(m); err != nil { + if err := r.validateFramework(ctx, m); err != nil { return 1, err } - if err := r.setNodeRuntime(m); err != nil { + if err := r.setNodeRuntime(ctx, m); err != nil { return 1, err } if err := r.validateTunnel( + ctx, r.Project.Sauce.Tunnel.Name, r.Project.Sauce.Tunnel.Owner, r.Project.DryRun, @@ -75,12 +76,12 @@ func (r *CucumberRunner) setVersions(m framework.Metadata) { } } -func (r *CucumberRunner) validateFramework(m framework.Metadata) error { +func (r *CucumberRunner) validateFramework(ctx context.Context, m framework.Metadata) error { if m.IsDeprecated() && !m.IsFlaggedForRemoval() { - fmt.Print(msg.EOLNotice(playwright.Kind, r.Project.Playwright.Version, m.RemovalDate, r.getAvailableVersions(playwright.Kind))) + fmt.Print(msg.EOLNotice(playwright.Kind, r.Project.Playwright.Version, m.RemovalDate, r.getAvailableVersions(ctx, playwright.Kind))) } if m.IsFlaggedForRemoval() { - fmt.Print(msg.RemovalNotice(playwright.Kind, r.Project.Playwright.Version, r.getAvailableVersions(playwright.Kind))) + fmt.Print(msg.RemovalNotice(playwright.Kind, r.Project.Playwright.Version, r.getAvailableVersions(ctx, playwright.Kind))) } for _, s := range r.Project.Suites { @@ -92,13 +93,13 @@ func (r *CucumberRunner) validateFramework(m framework.Metadata) error { return nil } -func (r *CucumberRunner) setNodeRuntime(metadata framework.Metadata) error { +func (r *CucumberRunner) setNodeRuntime(ctx context.Context, metadata framework.Metadata) error { if !metadata.SupportsRuntime(runtime.NodeRuntime) { r.Project.NodeVersion = "" return nil } - runtimes, err := r.MetadataService.Runtimes(context.Background()) + runtimes, err := r.MetadataService.Runtimes(ctx) if err != nil { return err } diff --git a/internal/saucecloud/cypress.go b/internal/saucecloud/cypress.go index 998a27994..5247c3a05 100644 --- a/internal/saucecloud/cypress.go +++ b/internal/saucecloud/cypress.go @@ -22,21 +22,22 @@ type CypressRunner struct { // RunProject runs the tests defined in cypress.Project. func (r *CypressRunner) RunProject(ctx context.Context) (int, error) { - m, err := r.MetadataSearchStrategy.Find(context.Background(), r.MetadataService, cypress.Kind, r.Project.GetVersion()) + m, err := r.MetadataSearchStrategy.Find(ctx, r.MetadataService, cypress.Kind, r.Project.GetVersion()) if err != nil { - r.logFrameworkError(err) + r.logFrameworkError(ctx, err) return 1, err } r.setVersions(m) - if err := r.validateFramework(m); err != nil { + if err := r.validateFramework(ctx, m); err != nil { return 1, err } - if err := r.setNodeRuntime(m); err != nil { + if err := r.setNodeRuntime(ctx, m); err != nil { return 1, err } if err := r.validateTunnel( + ctx, r.Project.GetSauceCfg().Tunnel.Name, r.Project.GetSauceCfg().Tunnel.Owner, r.Project.IsDryRun(), @@ -63,13 +64,13 @@ func (r *CypressRunner) RunProject(ctx context.Context) (int, error) { return 0, nil } -func (r *CypressRunner) setNodeRuntime(m framework.Metadata) error { +func (r *CypressRunner) setNodeRuntime(ctx context.Context, m framework.Metadata) error { if !m.SupportsRuntime(runtime.NodeRuntime) { r.Project.SetNodeVersion("") return nil } - runtimes, err := r.MetadataService.Runtimes(context.Background()) + runtimes, err := r.MetadataService.Runtimes(ctx) if err != nil { return err } @@ -107,13 +108,13 @@ func (r *CypressRunner) setVersions(m framework.Metadata) { } } -func (r *CypressRunner) validateFramework(m framework.Metadata) error { +func (r *CypressRunner) validateFramework(ctx context.Context, m framework.Metadata) error { cyVersion := r.Project.GetVersion() if m.IsDeprecated() && !m.IsFlaggedForRemoval() { - fmt.Print(msg.EOLNotice(cypress.Kind, cyVersion, m.RemovalDate, r.getAvailableVersions(cypress.Kind))) + fmt.Print(msg.EOLNotice(cypress.Kind, cyVersion, m.RemovalDate, r.getAvailableVersions(ctx, cypress.Kind))) } if m.IsFlaggedForRemoval() { - fmt.Print(msg.RemovalNotice(cypress.Kind, cyVersion, r.getAvailableVersions(cypress.Kind))) + fmt.Print(msg.RemovalNotice(cypress.Kind, cyVersion, r.getAvailableVersions(ctx, cypress.Kind))) } for _, s := range r.Project.GetSuites() { diff --git a/internal/saucecloud/espresso.go b/internal/saucecloud/espresso.go index 7c4b2b01c..ab884081b 100644 --- a/internal/saucecloud/espresso.go +++ b/internal/saucecloud/espresso.go @@ -38,6 +38,7 @@ func (r *EspressoRunner) RunProject(ctx context.Context) (int, error) { exitCode := 1 if err := r.validateTunnel( + ctx, r.Project.Sauce.Tunnel.Name, r.Project.Sauce.Tunnel.Owner, r.Project.DryRun, diff --git a/internal/saucecloud/imagerunner.go b/internal/saucecloud/imagerunner.go index 6961f0c52..b2b0a5a74 100644 --- a/internal/saucecloud/imagerunner.go +++ b/internal/saucecloud/imagerunner.go @@ -83,8 +83,9 @@ type execResult struct { attempts []report.Attempt } -func (r *ImgRunner) RunProject() (int, error) { +func (r *ImgRunner) RunProject(ctx context.Context) (int, error) { if err := tunnel.Validate( + ctx, r.TunnelService, r.Project.Sauce.Tunnel.Name, r.Project.Sauce.Tunnel.Owner, diff --git a/internal/saucecloud/jobservice.go b/internal/saucecloud/jobservice.go index ad06a14be..f560ea449 100644 --- a/internal/saucecloud/jobservice.go +++ b/internal/saucecloud/jobservice.go @@ -70,12 +70,12 @@ func (s JobService) StopJob(ctx context.Context, jobID string, realDevice bool) return s.Resto.StopJob(ctx, jobID, realDevice) } -func (s JobService) UploadArtifact(jobID string, realDevice bool, fileName string, contentType string, content []byte) error { +func (s JobService) UploadArtifact(ctx context.Context, jobID string, realDevice bool, fileName string, contentType string, content []byte) error { if realDevice { return nil } - return s.TestComposer.UploadAsset(jobID, realDevice, fileName, contentType, content) + return s.TestComposer.UploadAsset(ctx, jobID, fileName, contentType, content) } func (s JobService) Job(ctx context.Context, id string, realDevice bool) (job.Job, error) { diff --git a/internal/saucecloud/playwright.go b/internal/saucecloud/playwright.go index 386257f27..131d6c081 100644 --- a/internal/saucecloud/playwright.go +++ b/internal/saucecloud/playwright.go @@ -27,21 +27,22 @@ var PlaywrightBrowserMap = map[string]string{ // RunProject runs the tests defined in cypress.Project. func (r *PlaywrightRunner) RunProject(ctx context.Context) (int, error) { - m, err := r.MetadataSearchStrategy.Find(context.Background(), r.MetadataService, playwright.Kind, r.Project.Playwright.Version) + m, err := r.MetadataSearchStrategy.Find(ctx, r.MetadataService, playwright.Kind, r.Project.Playwright.Version) if err != nil { - r.logFrameworkError(err) + r.logFrameworkError(ctx, err) return 1, err } r.setVersions(m) - if err := r.validateFramework(m); err != nil { + if err := r.validateFramework(ctx, m); err != nil { return 1, err } - if err := r.setNodeRuntime(m); err != nil { + if err := r.setNodeRuntime(ctx, m); err != nil { return 1, err } if err := r.validateTunnel( + ctx, r.Project.Sauce.Tunnel.Name, r.Project.Sauce.Tunnel.Owner, r.Project.DryRun, @@ -68,13 +69,13 @@ func (r *PlaywrightRunner) RunProject(ctx context.Context) (int, error) { return 0, nil } -func (r *PlaywrightRunner) setNodeRuntime(m framework.Metadata) error { +func (r *PlaywrightRunner) setNodeRuntime(ctx context.Context, m framework.Metadata) error { if !m.SupportsRuntime(runtime.NodeRuntime) { r.Project.NodeVersion = "" return nil } - runtimes, err := r.MetadataService.Runtimes(context.Background()) + runtimes, err := r.MetadataService.Runtimes(ctx) if err != nil { return err } @@ -112,12 +113,12 @@ func (r *PlaywrightRunner) setVersions(m framework.Metadata) { } } -func (r *PlaywrightRunner) validateFramework(m framework.Metadata) error { +func (r *PlaywrightRunner) validateFramework(ctx context.Context, m framework.Metadata) error { if m.IsDeprecated() && !m.IsFlaggedForRemoval() { - fmt.Print(msg.EOLNotice(playwright.Kind, r.Project.Playwright.Version, m.RemovalDate, r.getAvailableVersions(playwright.Kind))) + fmt.Print(msg.EOLNotice(playwright.Kind, r.Project.Playwright.Version, m.RemovalDate, r.getAvailableVersions(ctx, playwright.Kind))) } if m.IsFlaggedForRemoval() { - fmt.Print(msg.RemovalNotice(playwright.Kind, r.Project.Playwright.Version, r.getAvailableVersions(playwright.Kind))) + fmt.Print(msg.RemovalNotice(playwright.Kind, r.Project.Playwright.Version, r.getAvailableVersions(ctx, playwright.Kind))) } for i, s := range r.Project.Suites { diff --git a/internal/saucecloud/replay.go b/internal/saucecloud/replay.go index bc50aacbd..1cdeebffa 100644 --- a/internal/saucecloud/replay.go +++ b/internal/saucecloud/replay.go @@ -21,9 +21,9 @@ type ReplayRunner struct { func (r *ReplayRunner) RunProject(ctx context.Context) (int, error) { exitCode := 1 - m, err := r.MetadataSearchStrategy.Find(context.Background(), r.MetadataService, replay.Kind, "latest") + m, err := r.MetadataSearchStrategy.Find(ctx, r.MetadataService, replay.Kind, "latest") if err != nil { - r.logFrameworkError(err) + r.logFrameworkError(ctx, err) return exitCode, err } if r.Project.RunnerVersion == "" { @@ -38,6 +38,7 @@ func (r *ReplayRunner) RunProject(ctx context.Context) (int, error) { } if err := r.validateTunnel( + ctx, r.Project.Sauce.Tunnel.Name, r.Project.Sauce.Tunnel.Owner, r.Project.DryRun, diff --git a/internal/saucecloud/retry/saucereportretrier_test.go b/internal/saucecloud/retry/saucereportretrier_test.go index 2ae86c992..0a29f3050 100644 --- a/internal/saucecloud/retry/saucereportretrier_test.go +++ b/internal/saucecloud/retry/saucereportretrier_test.go @@ -48,9 +48,7 @@ func (f *JobServiceStub) StartJob(context.Context, job.StartOptions) (job.Job, e panic("implement me") } -func (f *JobServiceStub) UploadArtifact( - string, bool, string, string, []byte, -) error { +func (f *JobServiceStub) UploadArtifact(context.Context, string, bool, string, string, []byte) error { panic("implement me") } diff --git a/internal/saucecloud/testcafe.go b/internal/saucecloud/testcafe.go index de0f42d8e..5feb90030 100644 --- a/internal/saucecloud/testcafe.go +++ b/internal/saucecloud/testcafe.go @@ -22,21 +22,22 @@ type TestcafeRunner struct { // RunProject runs the defined tests on sauce cloud func (r *TestcafeRunner) RunProject(ctx context.Context) (int, error) { - m, err := r.MetadataSearchStrategy.Find(context.Background(), r.MetadataService, testcafe.Kind, r.Project.Testcafe.Version) + m, err := r.MetadataSearchStrategy.Find(ctx, r.MetadataService, testcafe.Kind, r.Project.Testcafe.Version) if err != nil { - r.logFrameworkError(err) + r.logFrameworkError(ctx, err) return 1, err } r.setVersions(m) - if err := r.validateFramework(m); err != nil { + if err := r.validateFramework(ctx, m); err != nil { return 1, err } - if err := r.setNodeRuntime(m); err != nil { + if err := r.setNodeRuntime(ctx, m); err != nil { return 1, err } if err := r.validateTunnel( + ctx, r.Project.Sauce.Tunnel.Name, r.Project.Sauce.Tunnel.Owner, r.Project.DryRun, @@ -63,13 +64,13 @@ func (r *TestcafeRunner) RunProject(ctx context.Context) (int, error) { return 0, nil } -func (r *TestcafeRunner) setNodeRuntime(m framework.Metadata) error { +func (r *TestcafeRunner) setNodeRuntime(ctx context.Context, m framework.Metadata) error { if !m.SupportsRuntime(runtime.NodeRuntime) { r.Project.NodeVersion = "" return nil } - runtimes, err := r.MetadataService.Runtimes(context.Background()) + runtimes, err := r.MetadataService.Runtimes(ctx) if err != nil { return err } @@ -107,12 +108,12 @@ func (r *TestcafeRunner) setVersions(m framework.Metadata) { } } -func (r *TestcafeRunner) validateFramework(m framework.Metadata) error { +func (r *TestcafeRunner) validateFramework(ctx context.Context, m framework.Metadata) error { if m.IsDeprecated() && !m.IsFlaggedForRemoval() { - fmt.Print(msg.EOLNotice(testcafe.Kind, r.Project.Testcafe.Version, m.RemovalDate, r.getAvailableVersions(testcafe.Kind))) + fmt.Print(msg.EOLNotice(testcafe.Kind, r.Project.Testcafe.Version, m.RemovalDate, r.getAvailableVersions(ctx, testcafe.Kind))) } if m.IsFlaggedForRemoval() { - fmt.Print(msg.RemovalNotice(testcafe.Kind, r.Project.Testcafe.Version, r.getAvailableVersions(testcafe.Kind))) + fmt.Print(msg.RemovalNotice(testcafe.Kind, r.Project.Testcafe.Version, r.getAvailableVersions(ctx, testcafe.Kind))) } for _, s := range r.Project.Suites { diff --git a/internal/saucecloud/xcuitest.go b/internal/saucecloud/xcuitest.go index 5b8c2f1a1..1d115759e 100644 --- a/internal/saucecloud/xcuitest.go +++ b/internal/saucecloud/xcuitest.go @@ -61,6 +61,7 @@ func (r *XcuitestRunner) RunProject(ctx context.Context) (int, error) { exitCode := 1 if err := r.validateTunnel( + ctx, r.Project.Sauce.Tunnel.Name, r.Project.Sauce.Tunnel.Owner, r.Project.DryRun, diff --git a/internal/tunnel/tunnel.go b/internal/tunnel/tunnel.go index 3bbb31804..634c671ff 100644 --- a/internal/tunnel/tunnel.go +++ b/internal/tunnel/tunnel.go @@ -26,7 +26,7 @@ type Service interface { IsTunnelRunning(ctx context.Context, id, parent string, filter Filter, wait time.Duration) error } -func Validate(service Service, name string, owner string, filter Filter, dryRun bool, timeout time.Duration) error { +func Validate(ctx context.Context, service Service, name string, owner string, filter Filter, dryRun bool, timeout time.Duration) error { if name == "" { return nil } @@ -41,7 +41,7 @@ func Validate(service Service, name string, owner string, filter Filter, dryRun } log.Info().Str("timeout", timeout.String()).Str("tunnel", name).Msg("Performing tunnel readiness check...") - if err := service.IsTunnelRunning(context.Background(), name, owner, filter, timeout); err != nil { + if err := service.IsTunnelRunning(ctx, name, owner, filter, timeout); err != nil { return err }