From fde9414d98c63b741914df2ed1c4e6bcca578423 Mon Sep 17 00:00:00 2001 From: Tian Feng Date: Fri, 22 Mar 2024 13:57:20 -0700 Subject: [PATCH] feat: Support archive folders (#895) * feat: Support archive folders * refine JSON schema for SO * add validation * check absolute path * auto convert backslashes --- api/saucectl.schema.json | 59 +++++++++++++++++-- api/v1/subschema/artifacts.schema.json | 7 +++ api/v1alpha/framework/imagerunner.schema.json | 45 ++++++++++++-- api/v1alpha/subschema/artifacts.schema.json | 7 +++ internal/config/config.go | 24 +++++++- internal/cucumber/config.go | 3 + internal/cypress/v1/config.go | 3 + internal/playwright/config.go | 4 ++ internal/testcafe/config.go | 4 ++ 9 files changed, 144 insertions(+), 12 deletions(-) diff --git a/api/saucectl.schema.json b/api/saucectl.schema.json index 50fd87cd0..229859a9a 100644 --- a/api/saucectl.schema.json +++ b/api/saucectl.schema.json @@ -78,6 +78,13 @@ "directory" ], "additionalProperties": false + }, + "retain": { + "description": "Compress folders into zip files, which can then be downloaded as artifacts.", + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "additionalProperties": false @@ -567,6 +574,13 @@ "directory" ], "additionalProperties": false + }, + "retain": { + "description": "Compress folders into zip files, which can then be downloaded as artifacts.", + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "additionalProperties": false @@ -2651,11 +2665,6 @@ "title": "saucectl image runner configuration", "description": "Configuration file for running container images using saucectl", "type": "object", - "allOf": [ - { - "$ref": "#/allOf/0/then/allOf/0" - } - ], "definitions": { "sauce": { "description": "All settings related to how tests are run and identified in the Sauce Labs platform.", @@ -2878,6 +2887,46 @@ }, "additionalProperties": false } + }, + "artifacts": { + "description": "Manage test output, such as logs, videos, and screenshots.", + "type": "object", + "properties": { + "cleanup": { + "description": "Whether to remove all contents of artifacts directory", + "type": "boolean" + }, + "download": { + "description": "Settings related to downloading test artifacts from Sauce Labs.", + "type": "object", + "properties": { + "match": { + "description": "Specifies which artifacts to download based on whether they match the file pattern provided. Supports the wildcard character '*'.", + "type": "array" + }, + "when": { + "description": "Specifies when and under what circumstances to download artifacts.", + "enum": [ + "always", + "fail", + "never", + "pass" + ] + }, + "directory": { + "description": "Specifies the path to the folder in which to download artifacts. A separate subdirectory is generated in this location for each suite.", + "type": "string" + } + }, + "required": [ + "when", + "match", + "directory" + ], + "additionalProperties": false + }, + "additionalProperties": false + } } }, "properties": { diff --git a/api/v1/subschema/artifacts.schema.json b/api/v1/subschema/artifacts.schema.json index 9627a4f99..b3e4ad199 100644 --- a/api/v1/subschema/artifacts.schema.json +++ b/api/v1/subschema/artifacts.schema.json @@ -40,6 +40,13 @@ "directory" ], "additionalProperties": false + }, + "retain": { + "description": "Compress folders into zip files, which can then be downloaded as artifacts.", + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "additionalProperties": false diff --git a/api/v1alpha/framework/imagerunner.schema.json b/api/v1alpha/framework/imagerunner.schema.json index 5767cd5ed..d9a349260 100644 --- a/api/v1alpha/framework/imagerunner.schema.json +++ b/api/v1alpha/framework/imagerunner.schema.json @@ -3,11 +3,6 @@ "title": "saucectl image runner configuration", "description": "Configuration file for running container images using saucectl", "type": "object", - "allOf": [ - { - "$ref": "../subschema/artifacts.schema.json" - } - ], "definitions": { "sauce": { "description": "All settings related to how tests are run and identified in the Sauce Labs platform.", @@ -223,6 +218,46 @@ }, "additionalProperties": false } + }, + "artifacts": { + "description": "Manage test output, such as logs, videos, and screenshots.", + "type": "object", + "properties": { + "cleanup": { + "description": "Whether to remove all contents of artifacts directory", + "type": "boolean" + }, + "download": { + "description": "Settings related to downloading test artifacts from Sauce Labs.", + "type": "object", + "properties": { + "match": { + "description": "Specifies which artifacts to download based on whether they match the file pattern provided. Supports the wildcard character '*'.", + "type": "array" + }, + "when": { + "description": "Specifies when and under what circumstances to download artifacts.", + "enum": [ + "always", + "fail", + "never", + "pass" + ] + }, + "directory": { + "description": "Specifies the path to the folder in which to download artifacts. A separate subdirectory is generated in this location for each suite.", + "type": "string" + } + }, + "required": [ + "when", + "match", + "directory" + ], + "additionalProperties": false + }, + "additionalProperties": false + } } }, "properties": { diff --git a/api/v1alpha/subschema/artifacts.schema.json b/api/v1alpha/subschema/artifacts.schema.json index 9627a4f99..b3e4ad199 100644 --- a/api/v1alpha/subschema/artifacts.schema.json +++ b/api/v1alpha/subschema/artifacts.schema.json @@ -40,6 +40,13 @@ "directory" ], "additionalProperties": false + }, + "retain": { + "description": "Compress folders into zip files, which can then be downloaded as artifacts.", + "type": "object", + "additionalProperties": { + "type": "string" + } } }, "additionalProperties": false diff --git a/internal/config/config.go b/internal/config/config.go index 5a33b9ab3..542fecd9c 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -141,8 +141,9 @@ type Slack struct { // Artifacts represents the test artifacts configuration. type Artifacts struct { - Download ArtifactDownload `yaml:"download,omitempty" json:"download"` - Cleanup bool `yaml:"cleanup,omitempty" json:"cleanup"` + Retain map[string]string `yaml:"retain,omitempty" json:"retain"` + Download ArtifactDownload `yaml:"download,omitempty" json:"download"` + Cleanup bool `yaml:"cleanup,omitempty" json:"cleanup"` } // Reporters represents the reporter configuration. @@ -606,3 +607,22 @@ func ValidateRegistries(registries []Registry) error { } return nil } + +func ValidateArtifacts(artifacts Artifacts) error { + for source, dest := range artifacts.Retain { + if filepath.IsAbs(source) { + return fmt.Errorf("invalid source path %q: absolute path is not allowed", source) + } + if !strings.HasSuffix(dest, ".zip") { + return fmt.Errorf("invalid zip filename %q: only .zip file is permitted", dest) + } + + // Automatically convert the path to use slashes. + newSource := strings.ReplaceAll(source, "\\", "/") + if newSource != source { + artifacts.Retain[newSource] = dest + delete(artifacts.Retain, source) + } + } + return nil +} diff --git a/internal/cucumber/config.go b/internal/cucumber/config.go index 569b2b496..65f00016e 100644 --- a/internal/cucumber/config.go +++ b/internal/cucumber/config.go @@ -181,6 +181,9 @@ func Validate(p *Project) error { if err != nil { return err } + if err := config.ValidateArtifacts(p.Artifacts); err != nil { + return err + } p.Playwright.Version = config.StandardizeVersionFormat(p.Playwright.Version) if p.Playwright.Version == "" { diff --git a/internal/cypress/v1/config.go b/internal/cypress/v1/config.go index d3d0fa322..6fdcda7cb 100644 --- a/internal/cypress/v1/config.go +++ b/internal/cypress/v1/config.go @@ -215,6 +215,9 @@ func (p *Project) Validate() error { if err != nil { return err } + if err := config.ValidateArtifacts(p.Artifacts); err != nil { + return err + } if p.Sauce.LaunchOrder != "" && p.Sauce.LaunchOrder != config.LaunchOrderFailRate { return fmt.Errorf(msg.InvalidLaunchingOption, p.Sauce.LaunchOrder, string(config.LaunchOrderFailRate)) diff --git a/internal/playwright/config.go b/internal/playwright/config.go index 1a4aa2668..89d50b098 100644 --- a/internal/playwright/config.go +++ b/internal/playwright/config.go @@ -323,6 +323,10 @@ func Validate(p *Project) error { return err } + if err := config.ValidateArtifacts(p.Artifacts); err != nil { + return err + } + if p.Sauce.LaunchOrder != "" && p.Sauce.LaunchOrder != config.LaunchOrderFailRate { return fmt.Errorf(msg.InvalidLaunchingOption, p.Sauce.LaunchOrder, string(config.LaunchOrderFailRate)) } diff --git a/internal/testcafe/config.go b/internal/testcafe/config.go index ff3755f7d..d1dc03d67 100644 --- a/internal/testcafe/config.go +++ b/internal/testcafe/config.go @@ -257,6 +257,10 @@ func Validate(p *Project) error { return err } + if err := config.ValidateArtifacts(p.Artifacts); err != nil { + return err + } + p.Testcafe.Version = config.StandardizeVersionFormat(p.Testcafe.Version) if p.Testcafe.Version == "" { return errors.New(msg.MissingFrameworkVersionConfig)