Skip to content

Commit

Permalink
imple for issue #9
Browse files Browse the repository at this point in the history
  • Loading branch information
ShotaKitazawa committed Oct 8, 2022
1 parent 60ffd3c commit 640ce2f
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 28 deletions.
13 changes: 9 additions & 4 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ func LoadConf(filename string) (*Config, error) {
}

type Config struct {
Debug bool `json:"debug"`
Slack SlackConfig `json:"slack" validate:"required"`
GitHub GitHubConfig `json:"github" validate:"required"`
Release ReleaseConfig `json:"release" validate:"required"`
Debug bool `json:"debug"`
Slack SlackConfig `json:"slack" validate:"required"`
GitHub GitHubConfig `json:"github" validate:"required"`
Release ReleaseConfig `json:"release" validate:"required"`
Broadcast BroadcastConfig `json:"broadcast"`
}

// for each external service
Expand All @@ -63,3 +64,7 @@ type ReleaseTarget struct {
Url string `json:"url" validate:"required"`
BaseBranch string `json:"baseBranch" default:"main"`
}

type BroadcastConfig struct {
EndpointUrl string `json:"endpointUrl"`
}
8 changes: 8 additions & 0 deletions docs/broadcast.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# broadcast コマンド

## Summary

`broadcast` コマンドは、 Slack から [cloudnativedaysjp/cnd-operation-server](https://github.com/cloudnativedaysjp/cnd-operation-server) を叩くためのコマンドです。

cnd-operation-server の詳細は [cloudnativedaysjp/cnd-operation-server - README.md](https://github.com/cloudnativedaysjp/cnd-operation-server#readme) を確認してください。

6 changes: 3 additions & 3 deletions docs/release.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# release サブコマンド
# release コマンド

## 概要
## Summary

`release` サブコマンドを呼び出すと、リポジトリとリリースレベルをそれぞれ選択することになります。これらを選択すると `release/major` などのラベルの付与された PR を自動生成するのがこのコマンドの責務です。
`release` コマンドを呼び出すと、リポジトリとリリースレベルをそれぞれ選択することになります。これらを選択すると `release/major` などのラベルの付与された PR を自動生成するのがこのコマンドの責務です。

注意点として、当コマンドの責務は上述した PR の作成のみです。以下は別途 GitHub Actions を利用して実現する必要があります。

Expand Down
2 changes: 2 additions & 0 deletions example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ release:
targets:
- url: https://github.com/ShotaKitazawa/kube-portal
baseBranch: master
broadcast:
endpointUrl: localhost:20080
27 changes: 27 additions & 0 deletions seaman/api/broadcast.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,33 @@
package api

import (
"fmt"
"strconv"
"strings"
)

const (
// Action IDs
ActIdBroadcast_SceneNext = "broadcast_scenenext"
)

type Track struct {
Id int32
Name string
}

func NewTrack(str string) (Track, error) {
s := strings.Split(str, "__")
if len(s) != 2 {
return Track{}, fmt.Errorf("callbackValue (%s) is not expected", str)
}
trackId, err := strconv.Atoi(s[0])
if err != nil {
return Track{}, fmt.Errorf("callbackValue (%s) is not expected", str)
}
return Track{int32(trackId), s[1]}, nil
}

func (m Track) String() string {
return fmt.Sprintf("%d__%s", m.Id, m.Name)
}
54 changes: 48 additions & 6 deletions seaman/controller/broadcast.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

pb "github.com/cloudnativedaysjp/cnd-operation-server/pkg/ws-proxy/schema"

"github.com/cloudnativedaysjp/seaman/seaman/api"
infra_cnd "github.com/cloudnativedaysjp/seaman/seaman/infra/cnd-operation-server"
infra_slack "github.com/cloudnativedaysjp/seaman/seaman/infra/slack"
"github.com/cloudnativedaysjp/seaman/seaman/utils"
Expand All @@ -21,15 +22,15 @@ import (

type BroadcastController struct {
slackFactory infra_slack.SlackClientFactory
cndSceneClient pb.TrackServiceClient
cndSceneClient pb.SceneServiceClient
cndTrackClient pb.TrackServiceClient
log logr.Logger
}

func NewBroadcastController(
logger logr.Logger,
slackFactory infra_slack.SlackClientFactory,
cndClient infra_cnd.CndWrapper,
cndClient *infra_cnd.CndWrapper,
) *BroadcastController {
return &BroadcastController{slackFactory, cndClient, cndClient, logger}
}
Expand Down Expand Up @@ -69,14 +70,14 @@ func (c *BroadcastController) ListTrack(evt *socketmode.Event, client *socketmod
}
}

func (c *BroadcastController) DisableAutomation(evt *socketmode.Event, client *socketmode.Client) {
func (c *BroadcastController) EnableAutomation(evt *socketmode.Event, client *socketmode.Client) {
client.Ack(*evt.Request)
c.switchAutomation(evt, client, false)
c.switchAutomation(evt, client, true)
}

func (c *BroadcastController) EnableAutomation(evt *socketmode.Event, client *socketmode.Client) {
func (c *BroadcastController) DisableAutomation(evt *socketmode.Event, client *socketmode.Client) {
client.Ack(*evt.Request)
c.switchAutomation(evt, client, true)
c.switchAutomation(evt, client, false)
}

func (c *BroadcastController) switchAutomation(evt *socketmode.Event, client *socketmode.Client, enabled bool) {
Expand Down Expand Up @@ -140,3 +141,44 @@ func (c *BroadcastController) switchAutomation(evt *socketmode.Event, client *so
return
}
}

func (c *BroadcastController) UpdateSceneToNext(evt *socketmode.Event, client *socketmode.Client) {
client.Ack(*evt.Request)

interaction, err := getInteractionCallback(evt)
if err != nil {
c.log.Error(err, "failed to get InteractionCallback")
return
}
channelId := interaction.Container.ChannelID
messageTs := interaction.Container.MessageTs
callbackValue := interaction.ActionCallback.BlockActions[0].SelectedOption.Value
// init logger & context
logger := c.log.WithValues("messageTs", messageTs)
ctx := utils.IntoContext(context.Background(), logger)
// new client from factory
sc, err := c.slackFactory.New(client.Client)
if err != nil {
logger.Error(xerrors.Errorf("message: %w", err), "failed to initialize Slack client")
}

track, err := api.NewTrack(callbackValue)
if err != nil {
_ = sc.PostMessage(ctx, channelId, view.InvalidArguments(messageTs,
"callbackValue (trackId) must be integer"))
return
}

if _, err := c.cndSceneClient.MoveSceneToNext(ctx,
&pb.MoveSceneToNextRequest{TrackId: track.Id}); err != nil {
_ = sc.PostMessage(ctx, channelId, view.SomethingIsWrong(messageTs))
return
}

if err := sc.UpdateMessage(ctx, channelId, messageTs,
view.BroadcastMovedToNextScene(track)); err != nil {
logger.Error(xerrors.Errorf("message: %w", err), "failed to post message: %v", err)
_ = sc.UpdateMessage(ctx, channelId, messageTs, view.SomethingIsWrong(messageTs))
return
}
}
2 changes: 2 additions & 0 deletions seaman/controller/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func (c *ReleaseController) SelectRepository(evt *socketmode.Event, client *sock
); err != nil {
logger.Error(xerrors.Errorf("message: %w", err), "failed to post message")
_ = sc.PostMessage(ctx, channelId, view.SomethingIsWrong(messageTs))
return
}
}

Expand All @@ -90,6 +91,7 @@ func (c *ReleaseController) SelectReleaseLevel(evt *socketmode.Event, client *so
sc, err := c.slackFactory.New(client.Client)
if err != nil {
logger.Error(xerrors.Errorf("message: %w", err), "failed to initialize Slack client")
return
}

orgRepo, err := api.NewOrgRepo(callbackValue)
Expand Down
59 changes: 44 additions & 15 deletions seaman/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ import (
"github.com/slack-go/slack/slackevents"
"github.com/slack-go/slack/socketmode"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"

pb "github.com/cloudnativedaysjp/cnd-operation-server/pkg/ws-proxy/schema"

"github.com/cloudnativedaysjp/seaman/config"
"github.com/cloudnativedaysjp/seaman/seaman/api"
"github.com/cloudnativedaysjp/seaman/seaman/controller"
cndoperationserver "github.com/cloudnativedaysjp/seaman/seaman/infra/cnd-operation-server"
"github.com/cloudnativedaysjp/seaman/seaman/infra/gitcommand"
"github.com/cloudnativedaysjp/seaman/seaman/infra/githubapi"
infra_slack "github.com/cloudnativedaysjp/seaman/seaman/infra/slack"
Expand Down Expand Up @@ -53,21 +58,33 @@ func Run(conf *config.Config) error {
logger := zapr.NewLogger(zapLogger)

// setup some instances
slackClientFactory := infra_slack.NewSlackClientFactory()
slackFactory := infra_slack.NewSlackClientFactory()
githubApiClient := githubapi.NewGitHubApiClientImpl(conf.GitHub.AccessToken)
gitCommandClient := gitcommand.NewGitCommandClientImpl(conf.GitHub.Username, conf.GitHub.AccessToken)
var cndClient *cndoperationserver.CndWrapper
if conf.Broadcast.EndpointUrl != "" {
func() {
conn, err := grpc.Dial(conf.Broadcast.EndpointUrl,
grpc.WithTransportCredentials(insecure.NewCredentials()), // TODO (cloudnativedaysjp/cnd-operation-server#7)
)
if err != nil {
return
}
cndClient = cndoperationserver.NewCndWrapper(
pb.NewSceneServiceClient(conn), pb.NewTrackServiceClient(conn),
)
}()
}

{ // release
var targets []controller.Target
for _, target := range conf.Release.Targets {
targets = append(targets, controller.Target(target))
}
c := controller.NewReleaseController(logger,
slackClientFactory, gitCommandClient, githubApiClient, targets)

slackFactory, gitCommandClient, githubApiClient, targets)
socketmodeHandler.HandleEvents(
slackevents.AppMention, middleware.MiddlewareSet(
c.SelectRepository,
slackevents.AppMention, middleware.MiddlewareSet(c.SelectRepository,
middleware.RegisterCommand("release").
WithURL("https://github.com/cloudnativedaysjp/seaman/blob/main/docs/release.md"),
))
Expand All @@ -82,23 +99,35 @@ func Run(conf *config.Config) error {
socketmodeHandler.HandleInteractionBlockAction(
api.ActIdRelease_OK, c.CreatePullRequestForRelease)
}
{ // broadcast
// TODO
if cndClient != nil { // broadcast
c := controller.NewBroadcastController(logger, slackFactory, cndClient)
socketmodeHandler.HandleEvents(
slackevents.AppMention, middleware.MiddlewareSet(c.ListTrack,
middleware.RegisterCommand("broadcast", "list-track").
WithURL("https://github.com/cloudnativedaysjp/seaman/blob/main/docs/broadcast.md"),
))
socketmodeHandler.HandleEvents(
slackevents.AppMention, middleware.MiddlewareSet(c.EnableAutomation,
middleware.RegisterCommand("broadcast", "enable-track").
WithURL("https://github.com/cloudnativedaysjp/seaman/blob/main/docs/broadcast.md"),
))
socketmodeHandler.HandleEvents(
slackevents.AppMention, middleware.MiddlewareSet(c.DisableAutomation,
middleware.RegisterCommand("broadcast", "disable-track").
WithURL("https://github.com/cloudnativedaysjp/seaman/blob/main/docs/broadcast.md"),
))
socketmodeHandler.HandleInteractionBlockAction(
api.ActIdBroadcast_SceneNext, c.UpdateSceneToNext)
}
{ // common
c := controller.NewCommonController(logger,
slackClientFactory, middleware.Subcommands.List())

slackFactory, middleware.Subcommands.List())
socketmodeHandler.HandleEvents(
slackevents.AppMention, middleware.MiddlewareSet(
c.ShowCommands,
middleware.RegisterCommand("help"),
))
c.ShowCommands, middleware.RegisterCommand("help")))
socketmodeHandler.HandleEvents(
slackevents.AppMention, middleware.MiddlewareSet(
c.ShowVersion,
middleware.RegisterCommand("version"),
))
c.ShowVersion, middleware.RegisterCommand("version")))
socketmodeHandler.HandleInteractionBlockAction(
api.ActIdCommon_Cancel, c.InteractionCancel)
}
Expand Down
22 changes: 22 additions & 0 deletions seaman/view/broadcast.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"sigs.k8s.io/yaml"

pb "github.com/cloudnativedaysjp/cnd-operation-server/pkg/ws-proxy/schema"
"github.com/cloudnativedaysjp/seaman/seaman/api"
)

func BroadcastListTrack(track []*pb.Track) slack.Msg {
Expand Down Expand Up @@ -88,3 +89,24 @@ func broadcastEnabled(trackName string) (slack.Msg, error) {
}
`, trackName))
}

func BroadcastMovedToNextScene(track api.Track) slack.Msg {
result, _ := broadcastMovedToNextScene(track)
return result
}

func broadcastMovedToNextScene(track api.Track) (slack.Msg, error) {
return castFromStringToMsg(fmt.Sprintf(`
{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "Track %s の自動切り替えを有効化しました"
}
}
]
}
`, track.Name))
}

0 comments on commit 640ce2f

Please sign in to comment.