Skip to content
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
47 changes: 26 additions & 21 deletions tools/testing/deployer/deployer.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,27 @@ func (d *CliDeployer) Deploy(ctx context.Context) error {
return err
}

var urlRegex = regexp.MustCompile(`will be available at:\s*.*?(https://[^\s]+)`)
var urlRegex = regexp.MustCompile(`DEPLOYMENT_COMPLETED\s*([^\s]+)`)
var internalURLRegex = regexp.MustCompile(`\.internal:\d+$`)

func findUrlsInOutput(output string) []string {
var urls []string
match := urlRegex.FindAllStringSubmatch(output, -1)
for _, m := range match {
if m[1] == "" {
continue
}
if internalURLRegex.MatchString(m[1]) {
log.Printf("Skipping internal URL %v", m[1])
continue
}
// Check if the URL starts with a scheme (http, https, etc.)
if strings.HasPrefix(m[1], "https://") {
urls = append(urls, m[1])
}
}
return urls
}

func (d *CliDeployer) RunDeployTest(ctx context.Context, t test.TestInfo) (*test.ItemResult, error) {
log := d.Logger
Expand Down Expand Up @@ -155,22 +175,6 @@ func (d *CliDeployer) RunDeployTest(ctx context.Context, t test.TestInfo) (*test
},
}

d.RunCommand(cmdCtx, func(cmd *exec.Cmd) {
if t.Stdout != nil {
cmd.Stdout = io.MultiWriter(&d.Stdout, t.Stdout, detector)
} else {
cmd.Stdout = io.MultiWriter(&d.Stdout, detector)
}
if t.Stderr != nil {
cmd.Stderr = io.MultiWriter(&d.Stderr, t.Stderr, detector)
} else {
cmd.Stderr = io.MultiWriter(&d.Stderr, detector)
}
cmd.Cancel = func() error {
return cmd.Process.Signal(os.Interrupt) // Use interrupt signal to stop the command when context is cancelled
}
}, "defang", "-C", "/tmp/", "compose", "down", "--detach")

d.HasDeployed = true
start := time.Now()
cmd, err := d.RunCommand(cmdCtx, func(cmd *exec.Cmd) {
Expand Down Expand Up @@ -204,10 +208,11 @@ func (d *CliDeployer) RunDeployTest(ctx context.Context, t test.TestInfo) (*test
result.DeploySucceeded = cmd.ProcessState.Success()
}

var urls []string
match := urlRegex.FindAllStringSubmatch(d.Stdout.String(), -1)
for _, m := range match {
urls = append(urls, m[1])
urls := findUrlsInOutput(d.Stdout.String())
if len(urls) == 0 {
result.Message = "No service URLs found in deployment output"
log.Printf(result.Message)
return result, fmt.Errorf(result.Message)
}

result.TotalServices = len(urls)
Expand Down
52 changes: 52 additions & 0 deletions tools/testing/deployer/deployer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package deployer

import (
"slices"
"testing"
)

func Test_findUrlsInOutput(t *testing.T) {
tests := []struct {
name string
out string
want []string
}{
{
name: "single url",
out: "some log\nDEPLOYMENT_COMPLETED\thttps://my-service.defang.io\nmore log",
want: []string{"https://my-service.defang.io"},
},
{
name: "multiple urls",
out: "log\nDEPLOYMENT_COMPLETED\thttps://service1.defang.io\nlog\nDEPLOYMENT_COMPLETED\thttps://service2.defang.io\nend",
want: []string{"https://service1.defang.io", "https://service2.defang.io"},
},
{
name: "no urls",
out: "just some logs without urls",
want: nil,
},
{
name: "internal url ignored",
out: "log\nDEPLOYMENT_COMPLETED\tservice.internal:8080\nend",
want: nil,
},
{
name: "url without scheme",
out: "log\nDEPLOYMENT_COMPLETED\tmy-service.defang.io\nend",
want: nil,
},
{
name: "some other string",
out: "log\nDEPLOYMENT_COMPLETED\tjust-a-string\nend",
want: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := findUrlsInOutput(tt.out); !slices.Equal(got, tt.want) {
t.Errorf("findUrlsInOutput() = %v, want %v", got, tt.want)
}
})
}
}