Skip to content

Commit

Permalink
Merge pull request #73 from AlayaCare/slackintegration
Browse files Browse the repository at this point in the history
adding slack integration
  • Loading branch information
nzin-alayacare authored Oct 13, 2024
2 parents 6a3f3c1 + eaaf213 commit 38d19e8
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 14 deletions.
9 changes: 8 additions & 1 deletion cmd/goliac/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/Alayacare/goliac/internal"
"github.com/Alayacare/goliac/internal/config"
"github.com/Alayacare/goliac/internal/notification"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -170,7 +171,13 @@ any changes from the teams Git repository to Github.`,
if err != nil {
logrus.Fatalf("failed to create goliac: %s", err)
}
server := internal.NewGoliacServer(goliac)
notificationService := notification.NewNullNotificationService()
if config.Config.SlackToken != "" && config.Config.SlackChannel != "" {
slackService := notification.NewSlackNotificationService(config.Config.SlackToken, config.Config.SlackChannel)
notificationService = slackService
}

server := internal.NewGoliacServer(goliac, notificationService)
server.Serve()
},
}
Expand Down
2 changes: 2 additions & 0 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ You can run the goliac server as a service or a docker container. It needs sever
| GOLIAC_SERVER_PORT | 18000 | |
| GOLIAC_SERVER_GIT_BRANCH_PROTECTION_REQUIRED_CHECK | validate | ci check to enforce when evaluating a PR (used for CI mode) |
| GOLIAC_MAX_CHANGESETS_OVERRIDE | false | if you need to override the `max_changesets` setting in the `goliac.yaml` file. Useful in particular using the `goliac apply` CLI |
| GOLIAC_SLACK_TOKEN | | Slack token to send notification |
| GOLIAC_SLACK_CHANNEL | | Slack channel to send notification |

then you just need to start it with

Expand Down
2 changes: 1 addition & 1 deletion docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
This error is happening if a changeset (a team's PR) introduce more than X changesets. This is a safety mechanism to avoid applying a huge number of changesets at once.

If it is a legitimate change, you can
- either create a new PR to reduce the number of changesets in the original PR to stay below the limit, Goliac will automatically apply the cumulative changesets.
- either increase the `max_changesets` in the `goliac.yaml` file, but that's not the best approach.
- or you can use the CLI to force apply the changesets. To do so, you can run the following command:

```bash
Expand Down
4 changes: 4 additions & 0 deletions internal/config/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,8 @@ var Config = struct {
// UI path => localhost:18000/foo"
// API path => localhost:18000/foo/api/v1"
WebPrefix string `env:"GOLIAC_WEB_PREFIX" envDefault:""`

// to receive slack notifications on errors
SlackToken string `env:"GOLIAC_SLACK_TOKEN" envDefault:""`
SlackChannel string `env:"GOLIAC_SLACK_CHANNEL" envDefault:""`
}{}
31 changes: 19 additions & 12 deletions internal/goliac_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/Alayacare/goliac/internal/config"
"github.com/Alayacare/goliac/internal/entity"
"github.com/Alayacare/goliac/internal/notification"
"github.com/Alayacare/goliac/swagger_gen/models"
"github.com/Alayacare/goliac/swagger_gen/restapi"
"github.com/Alayacare/goliac/swagger_gen/restapi/operations"
Expand Down Expand Up @@ -44,21 +45,24 @@ type GoliacServer interface {
}

type GoliacServerImpl struct {
goliac Goliac
applyLobbyMutex sync.Mutex
applyLobbyCond *sync.Cond
applyCurrent bool
applyLobby bool
ready bool // when the server has finished to load the local configuration
lastSyncTime *time.Time
lastSyncError error
syncInterval int64 // in seconds time remaining between 2 sync
goliac Goliac
applyLobbyMutex sync.Mutex
applyLobbyCond *sync.Cond
applyCurrent bool
applyLobby bool
ready bool // when the server has finished to load the local configuration
lastSyncTime *time.Time
lastSyncError error
syncInterval int64 // in seconds time remaining between 2 sync
notificationService notification.NotificationService
}

func NewGoliacServer(goliac Goliac) GoliacServer {
func NewGoliacServer(goliac Goliac, notificationService notification.NotificationService) GoliacServer {

server := GoliacServerImpl{
goliac: goliac,
ready: false,
goliac: goliac,
ready: false,
notificationService: notificationService,
}
server.applyLobbyCond = sync.NewCond(&server.applyLobbyMutex)

Expand Down Expand Up @@ -507,6 +511,9 @@ func (g *GoliacServerImpl) Serve() {
// log the error only if it's a new one
if err != nil && (previousError == nil || err.Error() != previousError.Error()) {
logrus.Error(err)
if err := g.notificationService.SendNotification(fmt.Sprintf("Goliac error when syncing: %s", err)); err != nil {
logrus.Error(err)
}
}
g.syncInterval = config.Config.ServerApplyInterval
}
Expand Down
16 changes: 16 additions & 0 deletions internal/notification/notification.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package notification

type NotificationService interface {
SendNotification(message string) error
}

type NullNotificationService struct {
}

func NewNullNotificationService() NotificationService {
return &NullNotificationService{}
}

func (s *NullNotificationService) SendNotification(message string) error {
return nil
}
66 changes: 66 additions & 0 deletions internal/notification/slacknotifiction.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package notification

import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)

type SlackNotificationService struct {
SlackToken string
Channel string
}

func NewSlackNotificationService(slackToken string, channel string) NotificationService {
return &SlackNotificationService{
SlackToken: slackToken,
Channel: channel,
}
}

type SlackMessage struct {
Channel string `json:"channel"`
Text string `json:"text"`
}

func (s *SlackNotificationService) SendNotification(message string) error {
url := "https://slack.com/api/chat.postMessage"

// Prepare the message payload
msg := SlackMessage{
Channel: s.Channel,
Text: message,
}

// Convert the payload to JSON
jsonPayload, err := json.Marshal(msg)
if err != nil {
return fmt.Errorf("failed to marshal JSON: %v", err)
}

// Create a new HTTP POST request
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonPayload))
if err != nil {
return fmt.Errorf("failed to create new request: %v", err)
}

// Set the required headers
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+s.SlackToken)

// Make the HTTP request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return fmt.Errorf("failed to send request: %v", err)
}
defer resp.Body.Close()

// Check the response from Slack API
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("received non-200 response: %v", resp.Status)
}

return nil
}

0 comments on commit 38d19e8

Please sign in to comment.