feat(suite): Implement Suites (#1239)

* feat(suite): Implement Suites

Fixes #1230

* Update docs

* Fix variable alignment

* Prevent always-run endpoint from running if a context placeholder fails to resolve in the URL

* Return errors when a context placeholder path fails to resolve

* Add a couple of unit tests

* Add a couple of unit tests

* fix(ui): Update group count properly

Fixes #1233

* refactor: Pass down entire config instead of several sub-configs

* fix: Change default suite interval and timeout

* fix: Deprecate disable-monitoring-lock in favor of concurrency

* fix: Make sure there are no duplicate keys

* Refactor some code

* Update watchdog/watchdog.go

* Update web/app/src/components/StepDetailsModal.vue

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* chore: Remove useless log

* fix: Set default concurrency to 3 instead of 5

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
TwiN
2025-09-05 15:39:12 -04:00
committed by GitHub
co-authored by Copilot
parent 10cabb9dde
commit d668a14703
74 changed files with 7513 additions and 652 deletions
+19
View File
@@ -0,0 +1,19 @@
package key
import "strings"
// ConvertGroupAndNameToKey converts a group and a name to a key
func ConvertGroupAndNameToKey(groupName, name string) string {
return sanitize(groupName) + "_" + sanitize(name)
}
func sanitize(s string) string {
s = strings.TrimSpace(strings.ToLower(s))
s = strings.ReplaceAll(s, "/", "-")
s = strings.ReplaceAll(s, "_", "-")
s = strings.ReplaceAll(s, ".", "-")
s = strings.ReplaceAll(s, ",", "-")
s = strings.ReplaceAll(s, " ", "-")
s = strings.ReplaceAll(s, "#", "-")
return s
}
+11
View File
@@ -0,0 +1,11 @@
package key
import (
"testing"
)
func BenchmarkConvertGroupAndNameToKey(b *testing.B) {
for n := 0; n < b.N; n++ {
ConvertGroupAndNameToKey("group", "name")
}
}
+41
View File
@@ -0,0 +1,41 @@
package key
import "testing"
func TestConvertGroupAndNameToKey(t *testing.T) {
type Scenario struct {
GroupName string
Name string
ExpectedOutput string
}
scenarios := []Scenario{
{
GroupName: "Core",
Name: "Front End",
ExpectedOutput: "core_front-end",
},
{
GroupName: "Load balancers",
Name: "us-west-2",
ExpectedOutput: "load-balancers_us-west-2",
},
{
GroupName: "a/b test",
Name: "a",
ExpectedOutput: "a-b-test_a",
},
{
GroupName: "",
Name: "name",
ExpectedOutput: "_name",
},
}
for _, scenario := range scenarios {
t.Run(scenario.ExpectedOutput, func(t *testing.T) {
output := ConvertGroupAndNameToKey(scenario.GroupName, scenario.Name)
if output != scenario.ExpectedOutput {
t.Errorf("expected '%s', got '%s'", scenario.ExpectedOutput, output)
}
})
}
}