diff --git a/test/tests/components/ws-manager/multi_repo_test.go b/test/tests/components/ws-manager/multi_repo_test.go new file mode 100644 index 00000000000000..f3ec21435487bc --- /dev/null +++ b/test/tests/components/ws-manager/multi_repo_test.go @@ -0,0 +1,179 @@ +// Copyright (c) 2022 Gitpod GmbH. All rights reserved. +// Licensed under the GNU Affero General Public License (AGPL). +// See License-AGPL.txt in the project root for license information. + +package wsmanager + +import ( + "context" + "net/rpc" + "path/filepath" + "strings" + "testing" + "time" + + "sigs.k8s.io/e2e-framework/pkg/envconf" + "sigs.k8s.io/e2e-framework/pkg/features" + + csapi "github.com/gitpod-io/gitpod/content-service/api" + agent "github.com/gitpod-io/gitpod/test/pkg/agent/workspace/api" + "github.com/gitpod-io/gitpod/test/pkg/integration" + "github.com/gitpod-io/gitpod/test/pkg/integration/common" + wsmanapi "github.com/gitpod-io/gitpod/ws-manager/api" +) + +var repos = []struct { + RemoteUri string + CloneTarget string + CheckoutLocation string +}{ + { + RemoteUri: "https://github.com/gitpod-io/gitpod", + CloneTarget: "main", + CheckoutLocation: "gitpod", + }, + { + RemoteUri: "https://github.com/gitpod-io/website", + CloneTarget: "main", + CheckoutLocation: "website", + }, + { + RemoteUri: "https://github.com/gitpod-io/dazzle", + CloneTarget: "main", + CheckoutLocation: "dazzle", + }, + { + RemoteUri: "https://github.com/gitpod-io/leeway", + CloneTarget: "main", + CheckoutLocation: "leeway", + }, + { + RemoteUri: "https://github.com/gitpod-io/ws-manager-integration-test", + CloneTarget: "master", + CheckoutLocation: "ws-manager-integration-test", + }, +} + +func TestMultiRepoWorkspaceSuccess(t *testing.T) { + f := features.New("multi-repo").WithLabel("component", "ws-manager").Assess("can create multi repo workspace", func(_ context.Context, t *testing.T, cfg *envconf.Config) context.Context { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + defer cancel() + + api := integration.NewComponentAPI(ctx, cfg.Namespace(), kubeconfig, cfg.Client()) + t.Cleanup(func() { + api.Done(t) + }) + + multiRepoInit := func(swr *wsmanapi.StartWorkspaceRequest) error { + composite := &csapi.CompositeInitializer{} + initializers := []*csapi.WorkspaceInitializer{} + + for _, repo := range repos { + init := &csapi.WorkspaceInitializer{ + Spec: &csapi.WorkspaceInitializer_Git{ + Git: &csapi.GitInitializer{ + RemoteUri: repo.RemoteUri, + TargetMode: csapi.CloneTargetMode_REMOTE_BRANCH, + CloneTaget: repo.CloneTarget, + CheckoutLocation: repo.CheckoutLocation, + Config: &csapi.GitConfig{}, + }, + }, + } + + initializers = append(initializers, init) + } + + composite.Initializer = initializers + swr.Spec.Initializer = &csapi.WorkspaceInitializer{ + Spec: &csapi.WorkspaceInitializer_Composite{ + Composite: &csapi.CompositeInitializer{ + Initializer: initializers, + }, + }, + } + swr.Spec.WorkspaceLocation = "gitpod" + return nil + } + + ws, stopWs, err := integration.LaunchWorkspaceDirectly(ctx, api, integration.WithRequestModifier(multiRepoInit)) + if err != nil { + t.Fatal(err) + } + + defer func() { + err = stopWs(true) + if err != nil { + t.Errorf("cannot stop workspace: %q", err) + } + }() + + rsa, closer, err := integration.Instrument(integration.ComponentWorkspace, "workspace", cfg.Namespace(), kubeconfig, cfg.Client(), + integration.WithInstanceID(ws.Req.Id), + integration.WithContainer("workspace"), + integration.WithWorkspacekitLift(true), + ) + + integration.DeferCloser(t, closer) + defer rsa.Close() + + assertRepositories(t, rsa) + + return ctx + }).Feature() + + testEnv.Test(t, f) +} + +func assertRepositories(t *testing.T, rsa *rpc.Client) { + var ls agent.ListDirResponse + err := rsa.Call("WorkspaceAgent.ListDir", &agent.ListDirRequest{ + Dir: "/workspace", + }, &ls) + + if err != nil { + t.Fatal(err) + } + + expected := make(map[string]*struct { + Cloned bool + Branch string + }) + for _, r := range repos { + expected[r.CheckoutLocation] = &struct { + Cloned bool + Branch string + }{ + Cloned: false, + Branch: r.CloneTarget, + } + } + + for _, dir := range ls.Files { + if strings.HasPrefix(dir, ".") { + continue + } + if _, ok := expected[dir]; ok { + expected[dir].Cloned = true + } else { + t.Fatalf("unexpected repository %s", dir) + } + } + + git := common.Git(rsa) + + for k, v := range expected { + if !v.Cloned { + t.Fatalf("repository %s has not been cloned", k) + } + + branch, err := git.GetBranch(filepath.Join("/workspace", k)) + if err != nil { + t.Fatal(err) + } + + if branch != v.Branch { + t.Fatalf("expected branch %s, but got %s", v.Branch, branch) + } + } +}