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

Separate the community edition from the enterprise edition #184

Merged
merged 8 commits into from
Oct 27, 2021
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
2 changes: 1 addition & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
docs/
README.md
.env
falcon9.db
sqlite3.db

# ui
ui/node_modules
Expand Down
4 changes: 4 additions & 0 deletions BUILDING
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
1. Clone the repository
2. Build the Docker image:

docker build -t gitploy .
4 changes: 4 additions & 0 deletions BUILDING_OSS
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
1. Clone the repository
2. Build the Docker image:

docker build -t gitploy --build-arg "OSS=true" .
17 changes: 13 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
# Build the server binary file.
FROM golang:1.15 AS server
ARG OSS=false

WORKDIR /server

COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN go install ./cmd/server
RUN if [ "${OSS}" = "false" ]; then \
echo "Build the enterprise edition"; \
go build -o gitploy-server ./cmd/server; \
else \
echo "Build the community edition"; \
go build -o gitploy-server -tags "oss" ./cmd/server; \
fi

# Build UI.
FROM node:14.17.0 AS ui
ARG OSS=false

WORKDIR /ui

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

COPY ./ui ./
ENV REACT_APP_GITPLOY_OSS="${OSS}"
RUN npm run build

# Copy to the final image.
Expand All @@ -30,10 +39,10 @@ WORKDIR /app
# Create DB
RUN mkdir /data

COPY --from=server --chown=root:root /server/LICENSE /server/NOTICE .
COPY --from=server --chown=root:root /go/bin/server /go/bin/server
COPY --from=server --chown=root:root /server/LICENSE /server/NOTICE ./
COPY --from=server --chown=root:root /server/gitploy-server /go/bin/gitploy-server

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

ENTRYPOINT [ "/go/bin/server" ]
ENTRYPOINT [ "/go/bin/gitploy-server" ]
12 changes: 10 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
Copyright 2021 Gitploy.IO, Inc.

The Gitploy Community Edition is licensed under the Apache License,
Version 2.0 (the "Apache License").

http://www.apache.org/licenses/LICENSE-2.0

The source files in this repository are under the Apache License
basically, but some files are under the Gitploy Non-Commercial License.
The header of files indicating which license they are under.

The Gitploy Enterprise Edition is licensed under the Gitploy
Non-Commercial License (the "Non-Commercial License"). A copy of
the Non-Commercial License is provided below.
Expand All @@ -20,8 +29,7 @@ software that would otherwise infringe either the contributor's
copyright in it.

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

Expand Down
6 changes: 6 additions & 0 deletions cmd/server/db.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
// Copyright 2021 Gitploy.IO Inc. All rights reserved.
// Use of this source code is governed by the Gitploy Non-Commercial License
// that can be found in the LICENSE file.

// +build !oss

package main

import (
Expand Down
18 changes: 18 additions & 0 deletions cmd/server/db_oss.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// +build oss

package main

import (
"fmt"

"entgo.io/ent/dialect"
"github.com/gitploy-io/gitploy/ent"
)

func OpenDB(driver string, dsn string) (*ent.Client, error) {
if driver != dialect.SQLite {
return nil, fmt.Errorf("The community edition support sqlite only.")
}

return ent.Open(driver, dsn)
}
6 changes: 6 additions & 0 deletions internal/server/api/v1/repos/approval.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
// Copyright 2021 Gitploy.IO Inc. All rights reserved.
// Use of this source code is governed by the Gitploy Non-Commercial License
// that can be found in the LICENSE file.

// +build !oss

package repos

import (
Expand Down
36 changes: 36 additions & 0 deletions internal/server/api/v1/repos/approval_oss.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// +build oss

package repos

import (
"net/http"

"github.com/gin-gonic/gin"

"github.com/gitploy-io/gitploy/ent"
gb "github.com/gitploy-io/gitploy/internal/server/global"
)

func (r *Repo) ListApprovals(c *gin.Context) {
gb.Response(c, http.StatusOK, make([]*ent.Approval, 0))
}

func (r *Repo) GetApproval(c *gin.Context) {
gb.Response(c, http.StatusNotFound, nil)
}

func (r *Repo) GetMyApproval(c *gin.Context) {
gb.Response(c, http.StatusNotFound, nil)
}

func (r *Repo) CreateApproval(c *gin.Context) {
gb.ErrorResponse(c, http.StatusPaymentRequired, "It is limited to the community edition.")
}

func (r *Repo) UpdateMyApproval(c *gin.Context) {
gb.ErrorResponse(c, http.StatusPaymentRequired, "It is limited to the community edition.")
}

func (r *Repo) DeleteApproval(c *gin.Context) {
gb.ErrorResponse(c, http.StatusPaymentRequired, "It is limited to the community edition.")
}
6 changes: 6 additions & 0 deletions internal/server/api/v1/repos/lock.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
// Copyright 2021 Gitploy.IO Inc. All rights reserved.
// Use of this source code is governed by the Gitploy Non-Commercial License
// that can be found in the LICENSE file.

// +build !oss

package repos

import (
Expand Down
28 changes: 28 additions & 0 deletions internal/server/api/v1/repos/lock_oss.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// +build oss

package repos

import (
"net/http"

"github.com/gin-gonic/gin"

"github.com/gitploy-io/gitploy/ent"
gb "github.com/gitploy-io/gitploy/internal/server/global"
)

func (r *Repo) ListLocks(c *gin.Context) {
gb.Response(c, http.StatusOK, make([]*ent.Lock, 0))
}

func (r *Repo) CreateLock(c *gin.Context) {
gb.ErrorResponse(c, http.StatusPaymentRequired, "It is limited to the community edition.")
}

func (r *Repo) UpdateLock(c *gin.Context) {
gb.ErrorResponse(c, http.StatusPaymentRequired, "It is limited to the community edition.")
}

func (r *Repo) DeleteLock(c *gin.Context) {
gb.ErrorResponse(c, http.StatusPaymentRequired, "It is limited to the community edition.")
}
144 changes: 144 additions & 0 deletions internal/server/api/v1/stream/events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright 2021 Gitploy.IO Inc. All rights reserved.
// Use of this source code is governed by the Gitploy Non-Commercial License
// that can be found in the LICENSE file.

// +build !oss

package stream

import (
"context"
"fmt"
"math/rand"
"net/http"
"time"

"github.com/gin-contrib/sse"
"github.com/gin-gonic/gin"
"go.uber.org/zap"

"github.com/gitploy-io/gitploy/ent"
"github.com/gitploy-io/gitploy/ent/event"
gb "github.com/gitploy-io/gitploy/internal/server/global"
)

// GetEvents streams events of deployment, or approval.
func (s *Stream) GetEvents(c *gin.Context) {
ctx := c.Request.Context()

v, _ := c.Get(gb.KeyUser)
u, _ := v.(*ent.User)

debugID := randstr()

events := make(chan *ent.Event, 10)

// Subscribe events
// it'll unsubscribe after the connection is closed.
sub := func(e *ent.Event) {

// Deleted type is always propagated to all.
if e.Type == event.TypeDeleted {
events <- e
return
}

if ok, err := s.hasPermForEvent(ctx, u, e); !ok {
s.log.Debug("Skip the event. The user has not the perm.")
return
} else if err != nil {
s.log.Error("It has failed to check the perm.", zap.Error(err))
return
}

events <- e
}
if err := s.i.SubscribeEvent(sub); err != nil {
s.log.Error("failed to subscribe notification events", zap.Error(err))
gb.ErrorResponse(c, http.StatusInternalServerError, "It has failed to connect.")
return
}

defer func() {
if err := s.i.UnsubscribeEvent(sub); err != nil {
s.log.Error("failed to unsubscribe notification events.")
}

close(events)
}()

w := c.Writer

L:
for {
select {
case <-w.CloseNotify():
break L
case <-time.After(time.Hour):
break L
case <-time.After(time.Second * 30):
c.Render(-1, sse.Event{
Event: "ping",
Data: "ping",
})
w.Flush()
case e := <-events:
c.Render(-1, sse.Event{
Event: "event",
Data: e,
})
w.Flush()
s.log.Debug("server sent event.", zap.Int("event_id", e.ID), zap.String("debug_id", debugID))
}
}
}

// hasPermForEvent checks the user has permission for the event.
func (s *Stream) hasPermForEvent(ctx context.Context, u *ent.User, e *ent.Event) (bool, error) {
if e.Kind == event.KindDeployment {
d, err := s.i.FindDeploymentByID(ctx, e.DeploymentID)
if err != nil {
return false, err
}

if _, err = s.i.FindPermOfRepo(ctx, d.Edges.Repo, u); ent.IsNotFound(err) {
return false, nil
} else if err != nil {
return false, err
}

return true, nil
}

if e.Kind == event.KindApproval {
a, err := s.i.FindApprovalByID(ctx, e.ApprovalID)
if err != nil {
return false, err
}

d, err := s.i.FindDeploymentByID(ctx, a.DeploymentID)
if err != nil {
return false, err
}

if _, err = s.i.FindPermOfRepo(ctx, d.Edges.Repo, u); ent.IsNotFound(err) {
return false, nil
} else if err != nil {
return false, err
}

return true, nil
}

return false, fmt.Errorf("The type of event is not \"deployment\" or \"approval\".")
}

func randstr() string {
var letterRunes = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

b := make([]rune, 4)
for i := range b {
b[i] = letterRunes[rand.Intn(len(letterRunes))]
}
return string(b)
}
23 changes: 23 additions & 0 deletions internal/server/api/v1/stream/events_oss.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// +build oss

package stream

import (
"time"

"github.com/gin-gonic/gin"
)

func (s *Stream) GetEvents(c *gin.Context) {
w := c.Writer

L:
for {
select {
case <-w.CloseNotify():
break L
case <-time.After(time.Minute):
break L
}
}
}
Loading