Files
atlantis/server/events/webhooks/http.go
Piotr Pawluk 46e181e725 feat: add http webhook (#5233)
Signed-off-by: Piotr Pawluk <piotr.pawluk@zendesk.com>
Co-authored-by: PePe Amengual <2208324+jamengual@users.noreply.github.com>
2025-01-22 19:39:20 -08:00

66 lines
1.6 KiB
Go

package webhooks
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"regexp"
"github.com/pkg/errors"
"github.com/runatlantis/atlantis/server/logging"
)
// HttpWebhook sends webhooks to any HTTP destination.
type HttpWebhook struct {
Client *HttpClient
WorkspaceRegex *regexp.Regexp
BranchRegex *regexp.Regexp
URL string
}
// Send sends the webhook to URL if workspace and branch matches their respective regex.
func (h *HttpWebhook) Send(_ logging.SimpleLogging, applyResult ApplyResult) error {
if !h.WorkspaceRegex.MatchString(applyResult.Workspace) || !h.BranchRegex.MatchString(applyResult.Pull.BaseBranch) {
return nil
}
if err := h.doSend(applyResult); err != nil {
return errors.Wrap(err, fmt.Sprintf("sending webhook to %q", h.URL))
}
return nil
}
func (h *HttpWebhook) doSend(applyResult ApplyResult) error {
body, err := json.Marshal(applyResult)
if err != nil {
return err
}
req, err := http.NewRequest("POST", h.URL, bytes.NewBuffer(body))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
for header, values := range h.Client.Headers {
for _, value := range values {
req.Header.Add(header, value)
}
}
resp, err := h.Client.Client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
respBody, _ := io.ReadAll(resp.Body)
return fmt.Errorf("returned status code %d with response %q", resp.StatusCode, respBody)
}
return nil
}
// HttpClient wraps http.Client allowing to add arbitrary Headers to a request.
type HttpClient struct {
Client *http.Client
Headers map[string][]string
}