Skip to content

Commit 2d4f946

Browse files
authored
[ws-manager-mk2] Fix git status (#17097)
* [ws-manager-mk2] Fix git status * Remove unused var
1 parent 7050e28 commit 2d4f946

File tree

4 files changed

+152
-74
lines changed

4 files changed

+152
-74
lines changed

components/ws-daemon/pkg/controller/workspace_operations.go

Lines changed: 0 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,17 @@ import (
1717
"github.com/gitpod-io/gitpod/common-go/tracing"
1818
csapi "github.com/gitpod-io/gitpod/content-service/api"
1919
"github.com/gitpod-io/gitpod/content-service/pkg/archive"
20-
"github.com/gitpod-io/gitpod/content-service/pkg/git"
2120
wsinit "github.com/gitpod-io/gitpod/content-service/pkg/initializer"
2221
"github.com/gitpod-io/gitpod/content-service/pkg/logs"
2322
"github.com/gitpod-io/gitpod/content-service/pkg/storage"
2423
"github.com/gitpod-io/gitpod/ws-daemon/pkg/content"
2524
"github.com/gitpod-io/gitpod/ws-daemon/pkg/internal/session"
26-
workspacev1 "github.com/gitpod-io/gitpod/ws-manager/api/crd/v1"
2725
"github.com/opentracing/opentracing-go"
2826
"github.com/prometheus/client_golang/prometheus"
2927
"github.com/sirupsen/logrus"
3028
"golang.org/x/xerrors"
3129
)
3230

33-
const (
34-
// maxPendingChanges is the limit beyond which we no longer report pending changes.
35-
// For example, if a workspace has then 150 untracked files, we'll report the first
36-
// 100 followed by "... and 50 more".
37-
//
38-
// We do this to keep the load on our infrastructure light and because beyond this number
39-
// the changes are irrelevant anyways.
40-
maxPendingChanges = 100
41-
)
42-
4331
type WorkspaceOperations interface {
4432
// InitWorkspace initializes the workspace content
4533
InitWorkspace(ctx context.Context, options InitOptions) (string, error)
@@ -478,68 +466,6 @@ func (wso *DefaultWorkspaceOperations) uploadWorkspaceContent(ctx context.Contex
478466
return nil
479467
}
480468

481-
// UpdateGitStatus attempts to update the LastGitStatus from the workspace's local working copy.
482-
func (wsc *WorkspaceController) UpdateGitStatus(ctx context.Context, ws *workspacev1.Workspace, s *session.Workspace) (res *csapi.GitStatus, err error) {
483-
var loc string
484-
loc = s.Location
485-
if loc == "" {
486-
// FWB workspaces don't have `Location` set, but rather ServiceLocDaemon and ServiceLocNode.
487-
// We'd can't easily produce the Git status, because in this context `mark` isn't mounted, and `upper`
488-
// only contains the full git working copy if the content was just initialised.
489-
// Something like
490-
// loc = filepath.Join(s.ServiceLocDaemon, "mark", "workspace")
491-
// does not work.
492-
//
493-
// TODO(cw): figure out a way to get ahold of the Git status.
494-
glog.WithField("loc", loc).WithFields(s.OWI()).Debug("not updating Git status of FWB workspace")
495-
return
496-
}
497-
498-
loc = filepath.Join(loc, s.CheckoutLocation)
499-
if !git.IsWorkingCopy(loc) {
500-
glog.WithField("loc", loc).WithField("checkout location", s.CheckoutLocation).WithFields(s.OWI()).Debug("did not find a Git working copy - not updating Git status")
501-
return nil, nil
502-
}
503-
504-
c := git.Client{Location: loc}
505-
506-
stat, err := c.Status(ctx)
507-
if err != nil {
508-
return nil, err
509-
}
510-
511-
lastGitStatus := toGitStatus(stat)
512-
513-
err = s.Persist()
514-
if err != nil {
515-
glog.WithError(err).Warn("cannot persist latest Git status")
516-
err = nil
517-
}
518-
519-
return lastGitStatus, err
520-
}
521-
522-
func toGitStatus(s *git.Status) *csapi.GitStatus {
523-
limit := func(entries []string) []string {
524-
if len(entries) > maxPendingChanges {
525-
return append(entries[0:maxPendingChanges], fmt.Sprintf("... and %d more", len(entries)-maxPendingChanges))
526-
}
527-
528-
return entries
529-
}
530-
531-
return &csapi.GitStatus{
532-
Branch: s.BranchHead,
533-
LatestCommit: s.LatestCommit,
534-
UncommitedFiles: limit(s.UncommitedFiles),
535-
TotalUncommitedFiles: int64(len(s.UncommitedFiles)),
536-
UntrackedFiles: limit(s.UntrackedFiles),
537-
TotalUntrackedFiles: int64(len(s.UntrackedFiles)),
538-
UnpushedCommits: limit(s.UnpushedCommits),
539-
TotalUnpushedCommits: int64(len(s.UnpushedCommits)),
540-
}
541-
}
542-
543469
func retryIfErr(ctx context.Context, attempts int, log *logrus.Entry, op func(ctx context.Context) error) (err error) {
544470
//nolint:ineffassign
545471
span, ctx := opentracing.StartSpanFromContext(ctx, "retryIfErr")

components/ws-manager-mk2/service/manager.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,7 @@ func (wsm *WorkspaceManagerServer) extractWorkspaceStatus(ws *workspacev1.Worksp
10241024
Admission: admissionLevel,
10251025
OwnerToken: ws.Status.OwnerToken,
10261026
},
1027+
Repo: convertGitStatus(ws.Status.GitStatus),
10271028
}
10281029

10291030
return res
@@ -1038,6 +1039,22 @@ func getConditionMessageIfTrue(conds []metav1.Condition, tpe string) string {
10381039
return ""
10391040
}
10401041

1042+
func convertGitStatus(gs *workspacev1.GitStatus) *csapi.GitStatus {
1043+
if gs == nil {
1044+
return nil
1045+
}
1046+
return &csapi.GitStatus{
1047+
Branch: gs.Branch,
1048+
LatestCommit: gs.LatestCommit,
1049+
UncommitedFiles: gs.UncommitedFiles,
1050+
TotalUncommitedFiles: gs.TotalUncommitedFiles,
1051+
UntrackedFiles: gs.UntrackedFiles,
1052+
TotalUntrackedFiles: gs.TotalUntrackedFiles,
1053+
UnpushedCommits: gs.UnpushedCommits,
1054+
TotalUnpushedCommits: gs.TotalUnpushedCommits,
1055+
}
1056+
}
1057+
10411058
func convertCondition(conds []metav1.Condition, tpe string) wsmanapi.WorkspaceConditionBool {
10421059
res := wsk8s.GetCondition(conds, tpe)
10431060
if res == nil {

test/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ If you want to run an entire test suite, the easiest is to use `./test/run.sh`:
6767
If you're iterating on a single test, the easiest is to use `go test` directly.
6868
If your integration tests depends on having having a user token available, then you'll have to set `USER_TOKEN` manually (see `test/run.sh` on how to fetch the credentials that are used during our build)
6969

70+
If you want to run the workspace tests against `ws-manager-mk2`, set the `WS_MANAGER_MK2=true` env var when running the tests.
71+
7072
```console
7173
cd test
7274
go test -v ./... \
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.
2+
// Licensed under the GNU Affero General Public License (AGPL).
3+
// See License.AGPL.txt in the project root for license information.
4+
5+
package wsmanager
6+
7+
import (
8+
"context"
9+
"fmt"
10+
"testing"
11+
"time"
12+
13+
"google.golang.org/protobuf/proto"
14+
"sigs.k8s.io/e2e-framework/pkg/envconf"
15+
"sigs.k8s.io/e2e-framework/pkg/features"
16+
17+
csapi "github.com/gitpod-io/gitpod/content-service/api"
18+
agent "github.com/gitpod-io/gitpod/test/pkg/agent/workspace/api"
19+
"github.com/gitpod-io/gitpod/test/pkg/integration"
20+
wsmanapi "github.com/gitpod-io/gitpod/ws-manager/api"
21+
)
22+
23+
// TestGitStatus tests that the git status is reported after a workspace is stopped.
24+
func TestGitStatus(t *testing.T) {
25+
f := features.New("git-status").
26+
WithLabel("component", "ws-manager").
27+
Assess("it should report the git status of a workspace when it stops", func(ctx context.Context, t *testing.T, cfg *envconf.Config) context.Context {
28+
tests := []struct {
29+
Name string
30+
ContextURL string
31+
WorkspaceRoot string
32+
CheckoutLocation string
33+
}{
34+
{
35+
Name: "classic",
36+
ContextURL: "https://github.com/gitpod-io/empty",
37+
WorkspaceRoot: "/workspace/empty",
38+
CheckoutLocation: "empty",
39+
},
40+
}
41+
for _, test := range tests {
42+
test := test
43+
t.Run(test.Name, func(t *testing.T) {
44+
t.Parallel()
45+
46+
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(10*len(tests))*time.Minute)
47+
defer cancel()
48+
49+
api := integration.NewComponentAPI(ctx, cfg.Namespace(), kubeconfig, cfg.Client())
50+
t.Cleanup(func() {
51+
api.Done(t)
52+
})
53+
54+
// TODO: change to use server API to launch the workspace, so we could run the integration test as the user code flow
55+
// which is client -> server -> ws-manager rather than client -> ws-manager directly
56+
ws1, stopWs, err := integration.LaunchWorkspaceDirectly(t, ctx, api, integration.WithRequestModifier(func(w *wsmanapi.StartWorkspaceRequest) error {
57+
w.Spec.Initializer = &csapi.WorkspaceInitializer{
58+
Spec: &csapi.WorkspaceInitializer_Git{
59+
Git: &csapi.GitInitializer{
60+
RemoteUri: test.ContextURL,
61+
CheckoutLocation: test.CheckoutLocation,
62+
Config: &csapi.GitConfig{},
63+
},
64+
},
65+
}
66+
w.Spec.WorkspaceLocation = test.CheckoutLocation
67+
return nil
68+
}))
69+
if err != nil {
70+
t.Fatal(err)
71+
}
72+
t.Cleanup(func() {
73+
if err != nil {
74+
sctx, scancel := context.WithTimeout(context.Background(), 5*time.Minute)
75+
defer scancel()
76+
77+
sapi := integration.NewComponentAPI(sctx, cfg.Namespace(), kubeconfig, cfg.Client())
78+
defer sapi.Done(t)
79+
80+
_, err = stopWs(true, sapi)
81+
if err != nil {
82+
t.Fatal(err)
83+
}
84+
}
85+
})
86+
87+
rsa, closer, err := integration.Instrument(integration.ComponentWorkspace, "workspace", cfg.Namespace(), kubeconfig, cfg.Client(),
88+
integration.WithInstanceID(ws1.Req.Id),
89+
integration.WithContainer("workspace"),
90+
integration.WithWorkspacekitLift(true),
91+
)
92+
if err != nil {
93+
t.Fatal(err)
94+
}
95+
integration.DeferCloser(t, closer)
96+
97+
var resp agent.WriteFileResponse
98+
err = rsa.Call("WorkspaceAgent.WriteFile", &agent.WriteFileRequest{
99+
Path: fmt.Sprintf("%s/foobar.txt", test.WorkspaceRoot),
100+
Content: []byte("hello world"),
101+
Mode: 0644,
102+
}, &resp)
103+
rsa.Close()
104+
if err != nil {
105+
if _, serr := stopWs(true, api); serr != nil {
106+
t.Errorf("cannot stop workspace: %q", serr)
107+
}
108+
t.Fatal(err)
109+
}
110+
111+
lastStatus, err := stopWs(true, api)
112+
if err != nil {
113+
t.Fatal(err)
114+
}
115+
116+
t.Logf("last status: %v", lastStatus)
117+
expected := &csapi.GitStatus{
118+
Branch: "main",
119+
UntrackedFiles: []string{"foobar.txt"},
120+
TotalUntrackedFiles: 1,
121+
}
122+
if !proto.Equal(lastStatus.Repo, expected) {
123+
t.Fatalf("unexpected git status: expected \"%+q\", got \"%+q\"", expected, lastStatus.Repo)
124+
}
125+
})
126+
}
127+
return ctx
128+
}).
129+
Feature()
130+
131+
testEnv.Test(t, f)
132+
133+
}

0 commit comments

Comments
 (0)