Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit 2e66aec

Browse files
author
Noah Hanjun Lee
authored
Merge pull request #56 from gitploy-io/feat/repositoy-filter
feat: filter organizations when Gitploy sync
2 parents 6217ba9 + c055590 commit 2e66aec

File tree

10 files changed

+218
-2
lines changed

10 files changed

+218
-2
lines changed

cmd/server/config.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ type (
2424
ServerProxyProto string `default:"https" split_words:"true"`
2525
ServerProxyPort string `default:"8081" split_words:"true"`
2626

27-
AdminUsers []string `split_words:"true"`
27+
OrganizationEntries []string `split_words:"true"`
28+
AdminUsers []string `split_words:"true"`
2829

2930
License string `split_words:"true"`
3031
}

cmd/server/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ func NewInteractor(c *Config) server.Interactor {
118118
&interactor.InteractorConfig{
119119
ServerHost: c.ServerHost,
120120
ServerProto: c.ServerProto,
121+
OrgEntries: c.OrganizationEntries,
121122
AdminUsers: c.AdminUsers,
122123
LicenseKey: c.License,
123124
Store: newStore(c),
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# GITPLOY_ORGANIZATION_ENTRIES
2+
3+
Optional comma-separated list of accounts, used to limit which organization(or owner) are syncronized between your source control management system and Gitploy. *Note that this variable must be set before your first login. If you don't set this environment it synchronize with all repositories the user owns.
4+
5+
```
6+
GITPLOY_ORGANIZATION_ENTRIES=gitploy-io,octocat,facebook
7+
```

docs/references/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Reference
22

33
* [GITPLOY_SERVER_HOST](./GITPLOY_SERVER_HOST.md)
4+
* [GITPLOY_ORGANIZATION_ENTRIES](./GITPLOY_ORGANIZATION_ENTRIES.md)
45
* [GITPLOY_LICENSE](./GITPLOY_LICENSE.md)

internal/interactor/interactor.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ type (
1111
ServerHost string
1212
ServerProto string
1313

14+
orgEntries []string
1415
// Admin Users
1516
admins []string
1617

@@ -31,6 +32,7 @@ type (
3132
ServerHost string
3233
ServerProto string
3334

35+
OrgEntries []string
3436
AdminUsers []string
3537

3638
LicenseKey string
@@ -44,6 +46,7 @@ func NewInteractor(c *InteractorConfig) *Interactor {
4446
i := &Interactor{
4547
ServerHost: c.ServerHost,
4648
ServerProto: c.ServerProto,
49+
orgEntries: c.OrgEntries,
4750
admins: c.AdminUsers,
4851
licenseKey: c.LicenseKey,
4952
Store: c.Store,

internal/interactor/sync.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,20 @@ import (
88
"github.com/hanjunlee/gitploy/vo"
99
)
1010

11+
func (i *Interactor) IsEntryOrg(ctx context.Context, namespace string) bool {
12+
if i.orgEntries == nil {
13+
return true
14+
}
15+
16+
for _, r := range i.orgEntries {
17+
if namespace == r {
18+
return true
19+
}
20+
}
21+
22+
return false
23+
}
24+
1125
func (i *Interactor) SyncRemoteRepo(ctx context.Context, u *ent.User, re *vo.RemoteRepo) error {
1226
var (
1327
r *ent.Repo

internal/server/api/v1/sync/interface.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//go:generate mockgen -source ./interface.go -destination ./mock/interactor.go -package mock
2+
13
package sync
24

35
import (
@@ -11,6 +13,7 @@ import (
1113
type (
1214
Interactor interface {
1315
ListRemoteRepos(ctx context.Context, u *ent.User) ([]*vo.RemoteRepo, error)
16+
IsEntryOrg(ctx context.Context, namespace string) bool
1417
SyncRemoteRepo(ctx context.Context, u *ent.User, re *vo.RemoteRepo) error
1518
DeletePermsOfUserLessThanUpdatedAt(ctx context.Context, u *ent.User, t time.Time) (int, error)
1619
}

internal/server/api/v1/sync/mock/interactor.go

Lines changed: 96 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/server/api/v1/sync/syncher.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,20 @@ func (s *Syncher) Sync(c *gin.Context) {
4444
}
4545

4646
syncTime := time.Now()
47+
syncCnt := 0
4748
for _, re := range remotes {
49+
// Skip un-selected repositories.
50+
if !s.i.IsEntryOrg(ctx, re.Namespace) {
51+
continue
52+
}
53+
4854
if err := s.i.SyncRemoteRepo(ctx, u, re); err != nil {
4955
s.log.Error("It has failed to sync with the remote repository.", zap.Error(err), zap.String("repo_id", re.ID))
56+
continue
5057
}
58+
syncCnt = syncCnt + 1
5159
}
52-
s.log.Debug(fmt.Sprintf("Schronize with %d repositories.", len(remotes)), zap.String("user_id", u.ID))
60+
s.log.Debug(fmt.Sprintf("Processed to schronize with %d repositories.", syncCnt), zap.String("user_id", u.ID))
5361

5462
// Delete staled perms.
5563
var cnt int
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package sync
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
9+
"github.com/gin-gonic/gin"
10+
"github.com/golang/mock/gomock"
11+
"github.com/hanjunlee/gitploy/ent"
12+
"github.com/hanjunlee/gitploy/internal/server/api/v1/sync/mock"
13+
"github.com/hanjunlee/gitploy/internal/server/global"
14+
"github.com/hanjunlee/gitploy/vo"
15+
)
16+
17+
func TestSyncher_Sync(t *testing.T) {
18+
ctx := gomock.Any()
19+
20+
t.Run("Synchronize with remote repositories", func(t *testing.T) {
21+
ctrl := gomock.NewController(t)
22+
m := mock.NewMockInteractor(ctrl)
23+
24+
t.Log("List remote repositories")
25+
m.
26+
EXPECT().
27+
ListRemoteRepos(ctx, gomock.AssignableToTypeOf(&ent.User{})).
28+
Return([]*vo.RemoteRepo{
29+
{
30+
ID: "1",
31+
Namespace: "octocat",
32+
Name: "HelloWorld",
33+
},
34+
{
35+
ID: "1",
36+
Namespace: "cat",
37+
Name: "GoodBye",
38+
},
39+
}, nil)
40+
41+
t.Log("Only octocat is trusted namespace.")
42+
m.
43+
EXPECT().
44+
IsEntryOrg(ctx, gomock.Any()).
45+
DoAndReturn(func(ctx context.Context, namespace string) bool {
46+
return namespace == "octocat"
47+
}).
48+
AnyTimes()
49+
50+
t.Log("Sync with HelloWorld only.")
51+
m.
52+
EXPECT().
53+
SyncRemoteRepo(ctx, gomock.Any(), gomock.Eq(&vo.RemoteRepo{
54+
ID: "1",
55+
Namespace: "octocat",
56+
Name: "HelloWorld",
57+
})).
58+
Return(nil)
59+
60+
t.Log("Delete staled perms.")
61+
m.
62+
EXPECT().
63+
DeletePermsOfUserLessThanUpdatedAt(ctx, gomock.Any(), gomock.Any()).
64+
Return(0, nil)
65+
66+
gin.SetMode(gin.ReleaseMode)
67+
router := gin.New()
68+
69+
s := NewSyncher(m)
70+
router.POST("/sync", func(c *gin.Context) {
71+
c.Set(global.KeyUser, &ent.User{})
72+
}, s.Sync)
73+
74+
req, _ := http.NewRequest("POST", "/sync", nil)
75+
w := httptest.NewRecorder()
76+
77+
router.ServeHTTP(w, req)
78+
if w.Code != http.StatusOK {
79+
t.Fatalf("Sync = %v, wanted %v", w.Code, http.StatusOK)
80+
}
81+
})
82+
}

0 commit comments

Comments
 (0)