Skip to content

Commit

Permalink
refactor: Encapsulate artifact downloading (#936)
Browse files Browse the repository at this point in the history
* Add Downloader wrapper

* Extract artifact downloading out of api clients

* Move test to new package

* lint

* lint
  • Loading branch information
mhan83 authored Aug 16, 2024
1 parent 0644bea commit 04e0196
Show file tree
Hide file tree
Showing 14 changed files with 181 additions and 183 deletions.
3 changes: 1 addition & 2 deletions internal/cmd/artifacts/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"time"

"github.com/saucelabs/saucectl/internal/artifacts"
"github.com/saucelabs/saucectl/internal/config"
"github.com/saucelabs/saucectl/internal/credentials"
"github.com/saucelabs/saucectl/internal/http"
"github.com/saucelabs/saucectl/internal/region"
Expand Down Expand Up @@ -45,7 +44,7 @@ func Command(preRun func(cmd *cobra.Command, args []string)) *cobra.Command {
creds := credentials.Get()
url := reg.APIBaseURL()
restoClient := http.NewResto(url, creds.Username, creds.AccessKey, restoTimeout)
rdcClient := http.NewRDCService(url, creds.Username, creds.AccessKey, rdcTimeout, config.ArtifactDownload{})
rdcClient := http.NewRDCService(url, creds.Username, creds.AccessKey, rdcTimeout)
testcompClient := http.NewTestComposer(url, creds, testComposerTimeout)

artifactSvc = saucecloud.NewArtifactService(&restoClient, &rdcClient, &testcompClient)
Expand Down
2 changes: 1 addition & 1 deletion internal/cmd/ini/initializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ type initializer struct {
func newInitializer(stdio terminal.Stdio, creds iam.Credentials, cfg *initConfig) *initializer {
r := region.FromString(cfg.region)
tc := http.NewTestComposer(r.APIBaseURL(), creds, testComposerTimeout)
rc := http.NewRDCService(r.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout, config.ArtifactDownload{})
rc := http.NewRDCService(r.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout)
rs := http.NewResto(r.APIBaseURL(), creds.Username, creds.AccessKey, restoTimeout)
us := http.NewUserService(r.APIBaseURL(), creds, 5*time.Second)

Expand Down
8 changes: 5 additions & 3 deletions internal/cmd/run/cucumber.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/saucelabs/saucectl/internal/http"
"github.com/saucelabs/saucectl/internal/region"
"github.com/saucelabs/saucectl/internal/saucecloud"
"github.com/saucelabs/saucectl/internal/saucecloud/downloader"
"github.com/saucelabs/saucectl/internal/saucecloud/retry"
"github.com/saucelabs/saucectl/internal/segment"
"github.com/saucelabs/saucectl/internal/usage"
Expand Down Expand Up @@ -116,14 +117,15 @@ func runCucumber(cmd *cobra.Command, isCLIDriven bool) (int, error) {
creds := regio.Credentials()

restoClient := http.NewResto(regio.APIBaseURL(), creds.Username, creds.AccessKey, 0)
restoClient.ArtifactConfig = p.Artifacts.Download
testcompClient := http.NewTestComposer(regio.APIBaseURL(), creds, testComposerTimeout)
webdriverClient := http.NewWebdriver(regio.WebDriverBaseURL(), creds, webdriverTimeout)
appsClient := *http.NewAppStore(regio.APIBaseURL(), creds.Username, creds.AccessKey, gFlags.appStoreTimeout)
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout, config.ArtifactDownload{})
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout)
insightsClient := http.NewInsightsService(regio.APIBaseURL(), creds, insightsTimeout)
iamClient := http.NewUserService(regio.APIBaseURL(), creds, iamTimeout)

vdcDownloader := downloader.NewArtifactDownloader(&restoClient, p.Artifacts.Download)

log.Info().Msg("Running Playwright-Cucumberjs in Sauce Labs")
r := saucecloud.CucumberRunner{
Project: p,
Expand All @@ -137,7 +139,7 @@ func runCucumber(cmd *cobra.Command, isCLIDriven bool) (int, error) {
VDCWriter: &testcompClient,
VDCStopper: &restoClient,
RDCStopper: &rdcClient,
VDCDownloader: &restoClient,
VDCDownloader: &vdcDownloader,
},
TunnelService: &restoClient,
MetadataService: &testcompClient,
Expand Down
8 changes: 5 additions & 3 deletions internal/cmd/run/cypress.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/saucelabs/saucectl/internal/msg"
"github.com/saucelabs/saucectl/internal/region"
"github.com/saucelabs/saucectl/internal/saucecloud"
"github.com/saucelabs/saucectl/internal/saucecloud/downloader"
"github.com/saucelabs/saucectl/internal/saucecloud/retry"
"github.com/saucelabs/saucectl/internal/segment"
"github.com/saucelabs/saucectl/internal/usage"
Expand Down Expand Up @@ -151,14 +152,15 @@ func runCypress(cmd *cobra.Command, cflags cypressFlags, isCLIDriven bool) (int,
creds := regio.Credentials()

restoClient := http.NewResto(regio.APIBaseURL(), creds.Username, creds.AccessKey, 0)
restoClient.ArtifactConfig = p.GetArtifactsCfg().Download
testcompClient := http.NewTestComposer(regio.APIBaseURL(), creds, testComposerTimeout)
webdriverClient := http.NewWebdriver(regio.WebDriverBaseURL(), creds, webdriverTimeout)
appsClient := *http.NewAppStore(regio.APIBaseURL(), creds.Username, creds.AccessKey, gFlags.appStoreTimeout)
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout, config.ArtifactDownload{})
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout)
insightsClient := http.NewInsightsService(regio.APIBaseURL(), creds, insightsTimeout)
iamClient := http.NewUserService(regio.APIBaseURL(), creds, iamTimeout)

vdcDownloader := downloader.NewArtifactDownloader(&restoClient, p.GetArtifactsCfg().Download)

log.Info().Msg("Running Cypress in Sauce Labs")
r := saucecloud.CypressRunner{
Project: p,
Expand All @@ -172,7 +174,7 @@ func runCypress(cmd *cobra.Command, cflags cypressFlags, isCLIDriven bool) (int,
VDCWriter: &testcompClient,
VDCStopper: &restoClient,
RDCStopper: &rdcClient,
VDCDownloader: &restoClient,
VDCDownloader: &vdcDownloader,
},
MetadataService: &testcompClient,
TunnelService: &restoClient,
Expand Down
11 changes: 7 additions & 4 deletions internal/cmd/run/espresso.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/saucelabs/saucectl/internal/framework"
"github.com/saucelabs/saucectl/internal/region"
"github.com/saucelabs/saucectl/internal/saucecloud"
"github.com/saucelabs/saucectl/internal/saucecloud/downloader"
"github.com/saucelabs/saucectl/internal/saucecloud/retry"
"github.com/saucelabs/saucectl/internal/segment"
"github.com/saucelabs/saucectl/internal/usage"
Expand Down Expand Up @@ -137,14 +138,16 @@ func runEspressoInCloud(p espresso.Project, regio region.Region) (int, error) {

creds := regio.Credentials()
restoClient := http.NewResto(regio.APIBaseURL(), creds.Username, creds.AccessKey, 0)
restoClient.ArtifactConfig = p.Artifacts.Download
testcompClient := http.NewTestComposer(regio.APIBaseURL(), creds, testComposerTimeout)
webdriverClient := http.NewWebdriver(regio.WebDriverBaseURL(), creds, webdriverTimeout)
appsClient := *http.NewAppStore(regio.APIBaseURL(), creds.Username, creds.AccessKey, gFlags.appStoreTimeout)
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout, p.Artifacts.Download)
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout)
insightsClient := http.NewInsightsService(regio.APIBaseURL(), creds, insightsTimeout)
iamClient := http.NewUserService(regio.APIBaseURL(), creds, iamTimeout)

vdcDownloader := downloader.NewArtifactDownloader(&restoClient, p.Artifacts.Download)
rdcDownloader := downloader.NewArtifactDownloader(&rdcClient, p.Artifacts.Download)

r := saucecloud.EspressoRunner{
Project: p,
CloudRunner: saucecloud.CloudRunner{
Expand All @@ -157,8 +160,8 @@ func runEspressoInCloud(p espresso.Project, regio region.Region) (int, error) {
VDCWriter: &testcompClient,
VDCStopper: &restoClient,
RDCStopper: &rdcClient,
VDCDownloader: &restoClient,
RDCDownloader: &rdcClient,
VDCDownloader: &vdcDownloader,
RDCDownloader: &rdcDownloader,
},
TunnelService: &restoClient,
MetadataService: &testcompClient,
Expand Down
8 changes: 5 additions & 3 deletions internal/cmd/run/playwright.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/saucelabs/saucectl/internal/playwright"
"github.com/saucelabs/saucectl/internal/region"
"github.com/saucelabs/saucectl/internal/saucecloud"
"github.com/saucelabs/saucectl/internal/saucecloud/downloader"
"github.com/saucelabs/saucectl/internal/saucecloud/retry"
"github.com/saucelabs/saucectl/internal/segment"
"github.com/saucelabs/saucectl/internal/usage"
Expand Down Expand Up @@ -162,14 +163,15 @@ func runPlaywright(cmd *cobra.Command, pf playwrightFlags, isCLIDriven bool) (in
creds := regio.Credentials()

restoClient := http.NewResto(regio.APIBaseURL(), creds.Username, creds.AccessKey, 0)
restoClient.ArtifactConfig = p.Artifacts.Download
testcompClient := http.NewTestComposer(regio.APIBaseURL(), creds, testComposerTimeout)
webdriverClient := http.NewWebdriver(regio.WebDriverBaseURL(), creds, webdriverTimeout)
appsClient := *http.NewAppStore(regio.APIBaseURL(), creds.Username, creds.AccessKey, gFlags.appStoreTimeout)
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout, config.ArtifactDownload{})
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout)
insightsClient := http.NewInsightsService(regio.APIBaseURL(), creds, insightsTimeout)
iamClient := http.NewUserService(regio.APIBaseURL(), creds, iamTimeout)

vdcDownloader := downloader.NewArtifactDownloader(&restoClient, p.Artifacts.Download)

log.Info().Msg("Running Playwright in Sauce Labs")
r := saucecloud.PlaywrightRunner{
Project: p,
Expand All @@ -183,7 +185,7 @@ func runPlaywright(cmd *cobra.Command, pf playwrightFlags, isCLIDriven bool) (in
VDCWriter: &testcompClient,
VDCStopper: &restoClient,
RDCStopper: &rdcClient,
VDCDownloader: &restoClient,
VDCDownloader: &vdcDownloader,
},
TunnelService: &restoClient,
MetadataService: &testcompClient,
Expand Down
8 changes: 5 additions & 3 deletions internal/cmd/run/replay.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/saucelabs/saucectl/internal/puppeteer/replay"
"github.com/saucelabs/saucectl/internal/region"
"github.com/saucelabs/saucectl/internal/saucecloud"
"github.com/saucelabs/saucectl/internal/saucecloud/downloader"
"github.com/saucelabs/saucectl/internal/saucecloud/retry"
"github.com/saucelabs/saucectl/internal/segment"
"github.com/saucelabs/saucectl/internal/usage"
Expand Down Expand Up @@ -125,14 +126,15 @@ func runPuppeteerReplayInSauce(p replay.Project, regio region.Region) (int, erro

creds := regio.Credentials()
restoClient := http.NewResto(regio.APIBaseURL(), creds.Username, creds.AccessKey, 0)
restoClient.ArtifactConfig = p.Artifacts.Download
testcompClient := http.NewTestComposer(regio.APIBaseURL(), creds, testComposerTimeout)
webdriverClient := http.NewWebdriver(regio.WebDriverBaseURL(), creds, webdriverTimeout)
appsClient := *http.NewAppStore(regio.APIBaseURL(), creds.Username, creds.AccessKey, gFlags.appStoreTimeout)
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout, config.ArtifactDownload{})
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout)
insightsClient := http.NewInsightsService(regio.APIBaseURL(), creds, insightsTimeout)
iamClient := http.NewUserService(regio.APIBaseURL(), creds, iamTimeout)

vdcDownloader := downloader.NewArtifactDownloader(&restoClient, p.Artifacts.Download)

r := saucecloud.ReplayRunner{
Project: p,
CloudRunner: saucecloud.CloudRunner{
Expand All @@ -145,7 +147,7 @@ func runPuppeteerReplayInSauce(p replay.Project, regio region.Region) (int, erro
VDCWriter: &testcompClient,
VDCStopper: &restoClient,
RDCStopper: &rdcClient,
VDCDownloader: &restoClient,
VDCDownloader: &vdcDownloader,
},
TunnelService: &restoClient,
MetadataService: &testcompClient,
Expand Down
8 changes: 5 additions & 3 deletions internal/cmd/run/testcafe.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/saucelabs/saucectl/internal/msg"
"github.com/saucelabs/saucectl/internal/region"
"github.com/saucelabs/saucectl/internal/saucecloud"
"github.com/saucelabs/saucectl/internal/saucecloud/downloader"
"github.com/saucelabs/saucectl/internal/saucecloud/retry"
"github.com/saucelabs/saucectl/internal/segment"
"github.com/saucelabs/saucectl/internal/testcafe"
Expand Down Expand Up @@ -185,14 +186,15 @@ func runTestcafe(cmd *cobra.Command, tcFlags testcafeFlags, isCLIDriven bool) (i
creds := regio.Credentials()

restoClient := http.NewResto(regio.APIBaseURL(), creds.Username, creds.AccessKey, 0)
restoClient.ArtifactConfig = p.Artifacts.Download
testcompClient := http.NewTestComposer(regio.APIBaseURL(), creds, testComposerTimeout)
webdriverClient := http.NewWebdriver(regio.WebDriverBaseURL(), creds, webdriverTimeout)
appsClient := *http.NewAppStore(regio.APIBaseURL(), creds.Username, creds.AccessKey, gFlags.appStoreTimeout)
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout, config.ArtifactDownload{})
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout)
insightsClient := http.NewInsightsService(regio.APIBaseURL(), creds, insightsTimeout)
iamClient := http.NewUserService(regio.APIBaseURL(), creds, iamTimeout)

vdcDownloader := downloader.NewArtifactDownloader(&restoClient, p.Artifacts.Download)

log.Info().Msg("Running Testcafe in Sauce Labs")
r := saucecloud.TestcafeRunner{
Project: p,
Expand All @@ -206,7 +208,7 @@ func runTestcafe(cmd *cobra.Command, tcFlags testcafeFlags, isCLIDriven bool) (i
VDCWriter: &testcompClient,
VDCStopper: &restoClient,
RDCStopper: &rdcClient,
VDCDownloader: &restoClient,
VDCDownloader: &vdcDownloader,
},
TunnelService: &restoClient,
MetadataService: &testcompClient,
Expand Down
10 changes: 6 additions & 4 deletions internal/cmd/run/xcuitest.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/region"
"github.com/saucelabs/saucectl/internal/saucecloud"
"github.com/saucelabs/saucectl/internal/saucecloud/downloader"
"github.com/saucelabs/saucectl/internal/saucecloud/retry"
"github.com/saucelabs/saucectl/internal/segment"
"github.com/saucelabs/saucectl/internal/usage"
Expand Down Expand Up @@ -138,14 +139,15 @@ func runXcuitestInCloud(p xcuitest.Project, regio region.Region) (int, error) {
creds := regio.Credentials()

restoClient := http.NewResto(regio.APIBaseURL(), creds.Username, creds.AccessKey, 0)
restoClient.ArtifactConfig = p.Artifacts.Download
testcompClient := http.NewTestComposer(regio.APIBaseURL(), creds, testComposerTimeout)
webdriverClient := http.NewWebdriver(regio.WebDriverBaseURL(), creds, webdriverTimeout)
appsClient := *http.NewAppStore(regio.APIBaseURL(), creds.Username, creds.AccessKey, gFlags.appStoreTimeout)
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout, p.Artifacts.Download)
rdcClient := http.NewRDCService(regio.APIBaseURL(), creds.Username, creds.AccessKey, rdcTimeout)
insightsClient := http.NewInsightsService(regio.APIBaseURL(), creds, insightsTimeout)
iamClient := http.NewUserService(regio.APIBaseURL(), creds, iamTimeout)

vdcDownloader := downloader.NewArtifactDownloader(&restoClient, p.Artifacts.Download)
rdcDownloader := downloader.NewArtifactDownloader(&rdcClient, p.Artifacts.Download)
r := saucecloud.XcuitestRunner{
Project: p,
CloudRunner: saucecloud.CloudRunner{
Expand All @@ -158,8 +160,8 @@ func runXcuitestInCloud(p xcuitest.Project, regio region.Region) (int, error) {
VDCWriter: &testcompClient,
VDCStopper: &restoClient,
RDCStopper: &rdcClient,
VDCDownloader: &restoClient,
RDCDownloader: &rdcClient,
VDCDownloader: &vdcDownloader,
RDCDownloader: &rdcDownloader,
},
TunnelService: &restoClient,
MetadataService: &testcompClient,
Expand Down
62 changes: 9 additions & 53 deletions internal/http/rdcservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,25 @@ import (
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"time"

"github.com/saucelabs/saucectl/internal/slice"

"github.com/hashicorp/go-retryablehttp"
"github.com/rs/zerolog/log"

"github.com/saucelabs/saucectl/internal/config"
"github.com/saucelabs/saucectl/internal/devices"
"github.com/saucelabs/saucectl/internal/espresso"
"github.com/saucelabs/saucectl/internal/fpath"
"github.com/saucelabs/saucectl/internal/job"
"github.com/saucelabs/saucectl/internal/xcuitest"
)

// RDCService http client.
type RDCService struct {
Client *retryablehttp.Client
URL string
Username string
AccessKey string
ArtifactConfig config.ArtifactDownload
Client *retryablehttp.Client
URL string
Username string
AccessKey string
}

type rdcJob struct {
Expand Down Expand Up @@ -87,13 +81,12 @@ type DeviceQuery struct {
}

// NewRDCService creates a new client.
func NewRDCService(url, username, accessKey string, timeout time.Duration, artifactConfig config.ArtifactDownload) RDCService {
func NewRDCService(url, username, accessKey string, timeout time.Duration) RDCService {
return RDCService{
Client: NewRetryableClient(timeout),
URL: url,
Username: username,
AccessKey: accessKey,
ArtifactConfig: artifactConfig,
Client: NewRetryableClient(timeout),
URL: url,
Username: username,
AccessKey: accessKey,
}
}

Expand Down Expand Up @@ -386,43 +379,6 @@ func (c *RDCService) GetJobAssetFileContent(ctx context.Context, jobID, fileName
return io.ReadAll(resp.Body)
}

// DownloadArtifact downloads artifacts and returns a list of downloaded files.
func (c *RDCService) DownloadArtifact(jobID, suiteName string, realDevice bool) []string {
targetDir, err := config.GetSuiteArtifactFolder(suiteName, c.ArtifactConfig)
if err != nil {
log.Error().Msgf("Unable to create artifacts folder (%v)", err)
return []string{}
}

files, err := c.GetJobAssetFileNames(context.Background(), jobID, realDevice)
if err != nil {
log.Error().Msgf("Unable to fetch artifacts list (%v)", err)
return []string{}
}

filepaths := fpath.MatchFiles(files, c.ArtifactConfig.Match)
var artifacts []string
for _, f := range filepaths {
targetFile, err := c.downloadArtifact(targetDir, jobID, f, realDevice)
if err != nil {
log.Err(err).Msg("Unable to download artifacts")
return artifacts
}
artifacts = append(artifacts, targetFile)
}

return artifacts
}

func (c *RDCService) downloadArtifact(targetDir, jobID, fileName string, realDevice bool) (string, error) {
content, err := c.GetJobAssetFileContent(context.Background(), jobID, fileName, realDevice)
if err != nil {
return "", err
}
targetFile := filepath.Join(targetDir, fileName)
return targetFile, os.WriteFile(targetFile, content, 0644)
}

// GetDevices returns the list of available devices using a specific operating system.
func (c *RDCService) GetDevices(ctx context.Context, OS string) ([]devices.Device, error) {
req, err := NewRetryableRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/v1/rdc/devices/filtered", c.URL), nil)
Expand Down
Loading

0 comments on commit 04e0196

Please sign in to comment.