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

Commit 1b01105

Browse files
author
Noah Hanjun Lee
authored
Separate the community edition from the enterprise edition (#184)
* Add oss tag to the 'db.go' file * Add lock of OSS version * Fix to handle 402 error differently for OSS version * Add approval file of OSS version * Add event file of OSS version * Add slack package of OSS version * Fix Dockerfile to support community edition * Fix the license for OSS edition
1 parent dbb783c commit 1b01105

21 files changed

+390
-183
lines changed

.dockerignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
docs/
55
README.md
66
.env
7-
falcon9.db
7+
sqlite3.db
88

99
# ui
1010
ui/node_modules

BUILDING

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
1. Clone the repository
2+
2. Build the Docker image:
3+
4+
docker build -t gitploy .

BUILDING_OSS

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
1. Clone the repository
2+
2. Build the Docker image:
3+
4+
docker build -t gitploy --build-arg "OSS=true" .

Dockerfile

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
# Build the server binary file.
22
FROM golang:1.15 AS server
3+
ARG OSS=false
34

45
WORKDIR /server
56

67
COPY go.mod go.sum ./
78
RUN go mod download
89

910
COPY . .
10-
RUN go install ./cmd/server
11+
RUN if [ "${OSS}" = "false" ]; then \
12+
echo "Build the enterprise edition"; \
13+
go build -o gitploy-server ./cmd/server; \
14+
else \
15+
echo "Build the community edition"; \
16+
go build -o gitploy-server -tags "oss" ./cmd/server; \
17+
fi
1118

1219
# Build UI.
1320
FROM node:14.17.0 AS ui
21+
ARG OSS=false
1422

1523
WORKDIR /ui
1624

@@ -20,6 +28,7 @@ COPY ./ui/package.json ./ui/package-lock.json ./
2028
RUN npm install --silent
2129

2230
COPY ./ui ./
31+
ENV REACT_APP_GITPLOY_OSS="${OSS}"
2332
RUN npm run build
2433

2534
# Copy to the final image.
@@ -30,10 +39,10 @@ WORKDIR /app
3039
# Create DB
3140
RUN mkdir /data
3241

33-
COPY --from=server --chown=root:root /server/LICENSE /server/NOTICE .
34-
COPY --from=server --chown=root:root /go/bin/server /go/bin/server
42+
COPY --from=server --chown=root:root /server/LICENSE /server/NOTICE ./
43+
COPY --from=server --chown=root:root /server/gitploy-server /go/bin/gitploy-server
3544

3645
# Copy UI output into the assets directory.
3746
COPY --from=ui --chown=root:root /ui/build/ /app/
3847

39-
ENTRYPOINT [ "/go/bin/server" ]
48+
ENTRYPOINT [ "/go/bin/gitploy-server" ]

LICENSE

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
Copyright 2021 Gitploy.IO, Inc.
22

3+
The Gitploy Community Edition is licensed under the Apache License,
4+
Version 2.0 (the "Apache License").
5+
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
8+
The source files in this repository are under the Apache License
9+
basically, but some files are under the Gitploy Non-Commercial License.
10+
The header of files indicating which license they are under.
11+
312
The Gitploy Enterprise Edition is licensed under the Gitploy
413
Non-Commercial License (the "Non-Commercial License"). A copy of
514
the Non-Commercial License is provided below.
@@ -20,8 +29,7 @@ software that would otherwise infringe either the contributor's
2029
copyright in it.
2130

2231
1. You must limit use of this software in any manner primarily
23-
intended for commercial advantage or private monetary compensation
24-
to the count of user limit.
32+
intended for commercial advantage or private monetary compensation.
2533
This limit does not apply to use in developing feedback or extensions
2634
that you contribute back to those giving this license.
2735

cmd/server/db.go

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
// Copyright 2021 Gitploy.IO Inc. All rights reserved.
2+
// Use of this source code is governed by the Gitploy Non-Commercial License
3+
// that can be found in the LICENSE file.
4+
5+
// +build !oss
6+
17
package main
28

39
import (

cmd/server/db_oss.go

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// +build oss
2+
3+
package main
4+
5+
import (
6+
"fmt"
7+
8+
"entgo.io/ent/dialect"
9+
"github.com/gitploy-io/gitploy/ent"
10+
)
11+
12+
func OpenDB(driver string, dsn string) (*ent.Client, error) {
13+
if driver != dialect.SQLite {
14+
return nil, fmt.Errorf("The community edition support sqlite only.")
15+
}
16+
17+
return ent.Open(driver, dsn)
18+
}

internal/server/api/v1/repos/approval.go

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
// Copyright 2021 Gitploy.IO Inc. All rights reserved.
2+
// Use of this source code is governed by the Gitploy Non-Commercial License
3+
// that can be found in the LICENSE file.
4+
5+
// +build !oss
6+
17
package repos
28

39
import (
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// +build oss
2+
3+
package repos
4+
5+
import (
6+
"net/http"
7+
8+
"github.com/gin-gonic/gin"
9+
10+
"github.com/gitploy-io/gitploy/ent"
11+
gb "github.com/gitploy-io/gitploy/internal/server/global"
12+
)
13+
14+
func (r *Repo) ListApprovals(c *gin.Context) {
15+
gb.Response(c, http.StatusOK, make([]*ent.Approval, 0))
16+
}
17+
18+
func (r *Repo) GetApproval(c *gin.Context) {
19+
gb.Response(c, http.StatusNotFound, nil)
20+
}
21+
22+
func (r *Repo) GetMyApproval(c *gin.Context) {
23+
gb.Response(c, http.StatusNotFound, nil)
24+
}
25+
26+
func (r *Repo) CreateApproval(c *gin.Context) {
27+
gb.ErrorResponse(c, http.StatusPaymentRequired, "It is limited to the community edition.")
28+
}
29+
30+
func (r *Repo) UpdateMyApproval(c *gin.Context) {
31+
gb.ErrorResponse(c, http.StatusPaymentRequired, "It is limited to the community edition.")
32+
}
33+
34+
func (r *Repo) DeleteApproval(c *gin.Context) {
35+
gb.ErrorResponse(c, http.StatusPaymentRequired, "It is limited to the community edition.")
36+
}

internal/server/api/v1/repos/lock.go

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
// Copyright 2021 Gitploy.IO Inc. All rights reserved.
2+
// Use of this source code is governed by the Gitploy Non-Commercial License
3+
// that can be found in the LICENSE file.
4+
5+
// +build !oss
6+
17
package repos
28

39
import (
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// +build oss
2+
3+
package repos
4+
5+
import (
6+
"net/http"
7+
8+
"github.com/gin-gonic/gin"
9+
10+
"github.com/gitploy-io/gitploy/ent"
11+
gb "github.com/gitploy-io/gitploy/internal/server/global"
12+
)
13+
14+
func (r *Repo) ListLocks(c *gin.Context) {
15+
gb.Response(c, http.StatusOK, make([]*ent.Lock, 0))
16+
}
17+
18+
func (r *Repo) CreateLock(c *gin.Context) {
19+
gb.ErrorResponse(c, http.StatusPaymentRequired, "It is limited to the community edition.")
20+
}
21+
22+
func (r *Repo) UpdateLock(c *gin.Context) {
23+
gb.ErrorResponse(c, http.StatusPaymentRequired, "It is limited to the community edition.")
24+
}
25+
26+
func (r *Repo) DeleteLock(c *gin.Context) {
27+
gb.ErrorResponse(c, http.StatusPaymentRequired, "It is limited to the community edition.")
28+
}
+144
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Copyright 2021 Gitploy.IO Inc. All rights reserved.
2+
// Use of this source code is governed by the Gitploy Non-Commercial License
3+
// that can be found in the LICENSE file.
4+
5+
// +build !oss
6+
7+
package stream
8+
9+
import (
10+
"context"
11+
"fmt"
12+
"math/rand"
13+
"net/http"
14+
"time"
15+
16+
"github.com/gin-contrib/sse"
17+
"github.com/gin-gonic/gin"
18+
"go.uber.org/zap"
19+
20+
"github.com/gitploy-io/gitploy/ent"
21+
"github.com/gitploy-io/gitploy/ent/event"
22+
gb "github.com/gitploy-io/gitploy/internal/server/global"
23+
)
24+
25+
// GetEvents streams events of deployment, or approval.
26+
func (s *Stream) GetEvents(c *gin.Context) {
27+
ctx := c.Request.Context()
28+
29+
v, _ := c.Get(gb.KeyUser)
30+
u, _ := v.(*ent.User)
31+
32+
debugID := randstr()
33+
34+
events := make(chan *ent.Event, 10)
35+
36+
// Subscribe events
37+
// it'll unsubscribe after the connection is closed.
38+
sub := func(e *ent.Event) {
39+
40+
// Deleted type is always propagated to all.
41+
if e.Type == event.TypeDeleted {
42+
events <- e
43+
return
44+
}
45+
46+
if ok, err := s.hasPermForEvent(ctx, u, e); !ok {
47+
s.log.Debug("Skip the event. The user has not the perm.")
48+
return
49+
} else if err != nil {
50+
s.log.Error("It has failed to check the perm.", zap.Error(err))
51+
return
52+
}
53+
54+
events <- e
55+
}
56+
if err := s.i.SubscribeEvent(sub); err != nil {
57+
s.log.Error("failed to subscribe notification events", zap.Error(err))
58+
gb.ErrorResponse(c, http.StatusInternalServerError, "It has failed to connect.")
59+
return
60+
}
61+
62+
defer func() {
63+
if err := s.i.UnsubscribeEvent(sub); err != nil {
64+
s.log.Error("failed to unsubscribe notification events.")
65+
}
66+
67+
close(events)
68+
}()
69+
70+
w := c.Writer
71+
72+
L:
73+
for {
74+
select {
75+
case <-w.CloseNotify():
76+
break L
77+
case <-time.After(time.Hour):
78+
break L
79+
case <-time.After(time.Second * 30):
80+
c.Render(-1, sse.Event{
81+
Event: "ping",
82+
Data: "ping",
83+
})
84+
w.Flush()
85+
case e := <-events:
86+
c.Render(-1, sse.Event{
87+
Event: "event",
88+
Data: e,
89+
})
90+
w.Flush()
91+
s.log.Debug("server sent event.", zap.Int("event_id", e.ID), zap.String("debug_id", debugID))
92+
}
93+
}
94+
}
95+
96+
// hasPermForEvent checks the user has permission for the event.
97+
func (s *Stream) hasPermForEvent(ctx context.Context, u *ent.User, e *ent.Event) (bool, error) {
98+
if e.Kind == event.KindDeployment {
99+
d, err := s.i.FindDeploymentByID(ctx, e.DeploymentID)
100+
if err != nil {
101+
return false, err
102+
}
103+
104+
if _, err = s.i.FindPermOfRepo(ctx, d.Edges.Repo, u); ent.IsNotFound(err) {
105+
return false, nil
106+
} else if err != nil {
107+
return false, err
108+
}
109+
110+
return true, nil
111+
}
112+
113+
if e.Kind == event.KindApproval {
114+
a, err := s.i.FindApprovalByID(ctx, e.ApprovalID)
115+
if err != nil {
116+
return false, err
117+
}
118+
119+
d, err := s.i.FindDeploymentByID(ctx, a.DeploymentID)
120+
if err != nil {
121+
return false, err
122+
}
123+
124+
if _, err = s.i.FindPermOfRepo(ctx, d.Edges.Repo, u); ent.IsNotFound(err) {
125+
return false, nil
126+
} else if err != nil {
127+
return false, err
128+
}
129+
130+
return true, nil
131+
}
132+
133+
return false, fmt.Errorf("The type of event is not \"deployment\" or \"approval\".")
134+
}
135+
136+
func randstr() string {
137+
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
138+
139+
b := make([]rune, 4)
140+
for i := range b {
141+
b[i] = letterRunes[rand.Intn(len(letterRunes))]
142+
}
143+
return string(b)
144+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// +build oss
2+
3+
package stream
4+
5+
import (
6+
"time"
7+
8+
"github.com/gin-gonic/gin"
9+
)
10+
11+
func (s *Stream) GetEvents(c *gin.Context) {
12+
w := c.Writer
13+
14+
L:
15+
for {
16+
select {
17+
case <-w.CloseNotify():
18+
break L
19+
case <-time.After(time.Minute):
20+
break L
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)