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

Commit 6df41aa

Browse files
author
Noah Hanjun Lee
authored
Add lock/unlock slash commands (#89)
1 parent 37e5595 commit 6df41aa

File tree

5 files changed

+175
-6
lines changed

5 files changed

+175
-6
lines changed

internal/server/slack/deploy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func (s *Slack) handleDeployCmd(c *gin.Context) {
5454
ctx := c.Request.Context()
5555

5656
// SlashCommandParse hvae to be success because
57-
// it was called in the Cmd method.
57+
// it has parsed in the Cmd method.
5858
cmd, _ := slack.SlashCommandParse(c.Request)
5959

6060
cu, err := s.i.FindChatUserByID(ctx, cmd.UserID)

internal/server/slack/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type (
2222
FindPermOfRepo(ctx context.Context, r *ent.Repo, u *ent.User) (*ent.Perm, error)
2323

2424
FindRepoOfUserByNamespaceName(ctx context.Context, u *ent.User, namespace, name string) (*ent.Repo, error)
25+
UpdateRepo(ctx context.Context, r *ent.Repo) (*ent.Repo, error)
2526

2627
CreateCallback(ctx context.Context, cb *ent.Callback) (*ent.Callback, error)
2728
FindCallbackByHash(ctx context.Context, hash string) (*ent.Callback, error)

internal/server/slack/lock.go

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
package slack
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"strings"
7+
8+
"github.com/gin-gonic/gin"
9+
"github.com/slack-go/slack"
10+
"go.uber.org/zap"
11+
12+
"github.com/gitploy-io/gitploy/ent"
13+
"github.com/gitploy-io/gitploy/ent/perm"
14+
)
15+
16+
func (s *Slack) handleLockCmd(c *gin.Context) {
17+
ctx := c.Request.Context()
18+
19+
// SlashCommandParse hvae to be success because
20+
// it has parsed in the Cmd method.
21+
cmd, _ := slack.SlashCommandParse(c.Request)
22+
23+
cu, err := s.i.FindChatUserByID(ctx, cmd.UserID)
24+
if ent.IsNotFound(err) {
25+
postResponseMessage(cmd.ChannelID, cmd.ResponseURL, "Slack is not connected with Gitploy.")
26+
c.Status(http.StatusOK)
27+
return
28+
} else if err != nil {
29+
s.log.Error("It has failed to get chat user.", zap.Error(err))
30+
c.Status(http.StatusInternalServerError)
31+
return
32+
}
33+
34+
args := strings.Split(cmd.Text, " ")
35+
36+
ns, n, err := parseFullName(args[1])
37+
if err != nil {
38+
postResponseMessage(cmd.ChannelID, cmd.ResponseURL, fmt.Sprintf("`%s` is invalid repository format.", args[1]))
39+
c.Status(http.StatusOK)
40+
return
41+
}
42+
43+
r, err := s.i.FindRepoOfUserByNamespaceName(ctx, cu.Edges.User, ns, n)
44+
if ent.IsNotFound(err) {
45+
postResponseMessage(cmd.ChannelID, cmd.ResponseURL, fmt.Sprintf("The `%s` repository is not found.", args[1]))
46+
c.Status(http.StatusOK)
47+
return
48+
} else if err != nil {
49+
s.log.Error("It has failed to get the repo.", zap.Error(err))
50+
c.Status(http.StatusInternalServerError)
51+
return
52+
}
53+
54+
p, err := s.i.FindPermOfRepo(ctx, r, cu.Edges.User)
55+
if ent.IsNotFound(err) {
56+
postResponseMessage(cmd.ChannelID, cmd.ResponseURL, fmt.Sprintf("The `%s` repository is not found.", args[1]))
57+
c.Status(http.StatusOK)
58+
return
59+
} else if err != nil {
60+
s.log.Error("It has failed to get the perm.", zap.Error(err))
61+
c.Status(http.StatusInternalServerError)
62+
return
63+
}
64+
65+
if p.RepoPerm != perm.RepoPermAdmin {
66+
postResponseMessage(cmd.ChannelID, cmd.ResponseURL, "Only admin can lock the repository.")
67+
c.Status(http.StatusOK)
68+
return
69+
}
70+
71+
r.Locked = true
72+
if r, err = s.i.UpdateRepo(ctx, r); err != nil {
73+
s.log.Error("It has failed to update the repo.", zap.Error(err))
74+
c.Status(http.StatusInternalServerError)
75+
return
76+
}
77+
78+
s.log.Debug("Lock the repository successfully.", zap.Bool("locked", r.Locked))
79+
postResponseMessage(cmd.ChannelID, cmd.ResponseURL, fmt.Sprintf("Lock the `%s` repository successfully.", args[1]))
80+
c.Status(http.StatusOK)
81+
}
82+
83+
func (s *Slack) handleUnlockCmd(c *gin.Context) {
84+
ctx := c.Request.Context()
85+
86+
// SlashCommandParse hvae to be success because
87+
// it has parsed in the Cmd method.
88+
cmd, _ := slack.SlashCommandParse(c.Request)
89+
90+
cu, err := s.i.FindChatUserByID(ctx, cmd.UserID)
91+
if ent.IsNotFound(err) {
92+
postResponseMessage(cmd.ChannelID, cmd.ResponseURL, "Slack is not connected with Gitploy.")
93+
c.Status(http.StatusOK)
94+
return
95+
} else if err != nil {
96+
s.log.Error("It has failed to get chat user.", zap.Error(err))
97+
c.Status(http.StatusInternalServerError)
98+
return
99+
}
100+
101+
args := strings.Split(cmd.Text, " ")
102+
103+
ns, n, err := parseFullName(args[1])
104+
if err != nil {
105+
postResponseMessage(cmd.ChannelID, cmd.ResponseURL, fmt.Sprintf("`%s` is invalid repository format.", args[1]))
106+
c.Status(http.StatusOK)
107+
return
108+
}
109+
110+
r, err := s.i.FindRepoOfUserByNamespaceName(ctx, cu.Edges.User, ns, n)
111+
if ent.IsNotFound(err) {
112+
postResponseMessage(cmd.ChannelID, cmd.ResponseURL, fmt.Sprintf("The `%s` repository is not found.", args[1]))
113+
c.Status(http.StatusOK)
114+
return
115+
} else if err != nil {
116+
s.log.Error("It has failed to get the repo.", zap.Error(err))
117+
c.Status(http.StatusInternalServerError)
118+
return
119+
}
120+
121+
p, err := s.i.FindPermOfRepo(ctx, r, cu.Edges.User)
122+
if ent.IsNotFound(err) {
123+
postResponseMessage(cmd.ChannelID, cmd.ResponseURL, fmt.Sprintf("The `%s` repository is not found.", args[1]))
124+
c.Status(http.StatusOK)
125+
return
126+
} else if err != nil {
127+
s.log.Error("It has failed to get the perm.", zap.Error(err))
128+
c.Status(http.StatusInternalServerError)
129+
return
130+
}
131+
132+
if p.RepoPerm != perm.RepoPermAdmin {
133+
postResponseMessage(cmd.ChannelID, cmd.ResponseURL, "Only admin can unlock the repository.")
134+
c.Status(http.StatusOK)
135+
return
136+
}
137+
138+
r.Locked = false
139+
if r, err = s.i.UpdateRepo(ctx, r); err != nil {
140+
s.log.Error("It has failed to update the repo.", zap.Error(err))
141+
c.Status(http.StatusInternalServerError)
142+
return
143+
}
144+
145+
s.log.Debug("Unlock the repository successfully.", zap.Bool("locked", r.Locked))
146+
postResponseMessage(cmd.ChannelID, cmd.ResponseURL, fmt.Sprintf("Unlock the `%s` repository successfully.", args[1]))
147+
c.Status(http.StatusOK)
148+
}

internal/server/slack/mock/interactor.go

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

internal/server/slack/slack.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,25 @@ func (s *Slack) Cmd(c *gin.Context) {
6565
s.handleDeployCmd(c)
6666
} else if args[0] == "rollback" && len(args) == 2 {
6767
s.handleRollbackCmd(c)
68+
} else if args[0] == "lock" && len(args) == 2 {
69+
s.handleLockCmd(c)
70+
} else if args[0] == "unlock" && len(args) == 2 {
71+
s.handleUnlockCmd(c)
6872
} else {
6973
s.handleHelpCmd(cmd.ChannelID, cmd.ResponseURL)
7074
}
7175
}
7276

7377
func (s *Slack) handleHelpCmd(channelID, responseURL string) {
7478
msg := strings.Join([]string{
75-
"Below are the commands you can use:",
76-
"",
79+
"Below are the commands you can use:\n",
7780
"*Deploy*",
78-
"`/gitploy deploy OWNER/REPO` - Create a new deployment for OWNER/REPO.",
79-
"",
81+
"`/gitploy deploy OWNER/REPO` - Create a new deployment for OWNER/REPO.\n",
8082
"*Rollback*",
81-
"`/gitploy rollback OWNER/REPO` - Rollback by the deployment for OWNER/REPO.",
83+
"`/gitploy rollback OWNER/REPO` - Rollback by the deployment for OWNER/REPO.\n",
84+
"*Lock/Unlock*",
85+
"`/gitploy lock OWNER/REPO` - Lock the repository to disable deploying.",
86+
"`/gitploy unlock OWNER/REPO` - Unlock the repository to enable deploying.\n",
8287
}, "\n")
8388

8489
postResponseMessage(channelID, responseURL, msg)

0 commit comments

Comments
 (0)