diff --git a/gitlab.go b/gitlab.go new file mode 100644 index 0000000..5ca8dd0 --- /dev/null +++ b/gitlab.go @@ -0,0 +1,81 @@ +package main + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "strconv" + "strings" + "time" + + "github.com/go-kit/kit/log" + "github.com/go-kit/kit/log/level" +) + +// GitlabSender has the URL, ProjectID and Token to create GitLab issues. +type GitlabSender struct { + Hostname string + APIToken string + ProjectID int + Labels string + logger log.Logger +} + +type gitlabPayload struct { + Title string `json:"title"` + Description string `json:"description"` + Labels string `json:"labels"` +} + +// Send a notification with a formatted message build from the repository. +func (g *GitlabSender) Send(repository Repository) error { + payload := gitlabPayload{ + Title: fmt.Sprintf( + ":arrow_up: New version of %s released: %s", + repository.Name, + repository.Release.Name, + ), + Description: fmt.Sprintf( + "More info: %s", + repository.Release.URL.String(), + ), + Labels: g.Labels, + } + + payloadData, err := json.Marshal(payload) + if err != nil { + return err + } + + client := &http.Client{} + url := strings.Join([]string{"https:/", g.Hostname, "api/v4/projects", strconv.Itoa(g.ProjectID), "issues"}, "/") + level.Debug(g.logger).Log( + "msg", "attempting to post issue", + "url", url, + ) + req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(payloadData)) + if err != nil { + return err + } + req.Header.Set("PRIVATE-TOKEN", g.APIToken) + req.Header.Set("Content-Type", "application/json") + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + req = req.WithContext(ctx) + defer cancel() + + resp, err := client.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusCreated { + body, _ := ioutil.ReadAll(resp.Body) + return fmt.Errorf("request didn't respond with 201 Created: %s, %s", resp.Status, body) + } + + return nil +} diff --git a/main.go b/main.go index 0feec38..8ce392e 100644 --- a/main.go +++ b/main.go @@ -17,6 +17,10 @@ import ( // Config of env and args type Config struct { GithubToken string `arg:"env:GITHUB_TOKEN"` + GitlabAPIToken string `arg:"env:GITLAB_API_TOKEN"` + GitlabHostname string `arg:"env:GITLAB_HOSTNAME"` + GitlabProjectID int `arg:"env:GITLAB_PROJECT_ID"` + GitlabLabels string `arg:"env:GITLAB_LABELS"` Interval time.Duration `arg:"env:INTERVAL"` LogLevel string `arg:"env:LOG_LEVEL"` Repositories []string `arg:"-r,separate"` @@ -73,6 +77,13 @@ func main() { go checker.Run(c.Interval, c.Repositories, releases) slack := SlackSender{Hook: c.SlackHook} + gitlab := GitlabSender{ + Hostname: c.GitlabHostname, + APIToken: c.GitlabAPIToken, + ProjectID: c.GitlabProjectID, + Labels: c.GitlabLabels, + logger: logger, + } level.Info(logger).Log("msg", "waiting for new releases") for repository := range releases { @@ -80,12 +91,23 @@ func main() { level.Debug(logger).Log("msg", "not notifying about non-stable version", "version", repository.Release.Name) continue } - if err := slack.Send(repository); err != nil { - level.Warn(logger).Log( - "msg", "failed to send release to messenger", - "err", err, - ) - continue + if c.SlackHook != "" { + if err := slack.Send(repository); err != nil { + level.Warn(logger).Log( + "msg", "failed to send release to messenger", + "err", err, + ) + continue + } + } + if c.GitlabAPIToken != "" && c.GitlabHostname != "" && c.GitlabProjectID > 0 { + if err := gitlab.Send(repository); err != nil { + level.Warn(logger).Log( + "msg", "failed to send release to messenger", + "err", err, + ) + continue + } } } }