mirror of
https://github.com/TwiN/gatus.git
synced 2024-12-14 11:58:04 +00:00
feat(alerting): implement Gitea alerting provider (#842)
* feat: implement Gitea alerting provider integration - Add TypeGitea for the gitea alerting provider - Introduce a new file for the gitea alerting provider implementation - Implement the AlertProvider struct with necessary fields for gitea integration - Add validation logic for the AlertProvider configuration - Create tests for the AlertProvider's validation and sending functionality - Update go.mod to include the gitea SDK as a dependency - Modify the alerting configuration validation to recognize TypeGitea Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> * chore: integrate Gitea alerting provider configuration - Add Gitea alerting provider import to the configuration file - Update the comment for the RepositoryURL field to reflect Gitea instead of GitHub Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> * feat: add Assignees support to AlertProvider functionality - Add a field for Assignees to the AlertProvider struct - Update the Send function to include Assignees in the alert payload Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> * feat: implement Gitea alerting configuration and documentation - Add a new image asset for Gitea alerts - Update the README to include configuration details for Gitea alerts - Introduce parameters for Gitea alerting, including repository URL and personal access token - Document the behavior of the Gitea alerting provider regarding issue creation and resolution - Include an example YAML configuration for Gitea alerts Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> * Update README.md Co-authored-by: TwiN <twin@linux.com> * Update README.md Co-authored-by: TwiN <twin@linux.com> * Update README.md Co-authored-by: TwiN <twin@linux.com> * feat: refactor AlertProvider for improved client configuration - Add import for the Gatus client library - Remove the SkipVerify field from the AlertProvider struct - Introduce ClientConfig field in the AlertProvider struct for client configuration - Update validation logic to check for ClientConfig instead of SkipVerify Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> * Update README.md Co-authored-by: TwiN <twin@linux.com> * chore: update configuration for Gitea integration - Change references from GitHub to Gitea in the configuration section - Update alerting provider descriptions to reflect the correct platform - Swap the order of GitHub and Gitea configurations - Replace Gitea alert image with GitHub alert image - Adjust the type field from gitea to github in the relevant sections Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> * fix: ensure ClientConfig is validated and defaults set - Add a check for nil ClientConfig in the IsValid function - Set ClientConfig to a default configuration if it is nil Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> --------- Signed-off-by: Bo-Yi Wu <appleboy.tw@gmail.com> Co-authored-by: TwiN <twin@linux.com>
This commit is contained in:
parent
dd435a8eaf
commit
7de5a1fe48
10 changed files with 398 additions and 2 deletions
BIN
.github/assets/gitea-alerts.png
vendored
Normal file
BIN
.github/assets/gitea-alerts.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 638 KiB |
41
README.md
41
README.md
|
@ -7,7 +7,6 @@
|
|||
[![Docker pulls](https://img.shields.io/docker/pulls/twinproduction/gatus.svg)](https://cloud.docker.com/repository/docker/twinproduction/gatus)
|
||||
[![Follow TwiN](https://img.shields.io/github/followers/TwiN?label=Follow&style=social)](https://github.com/TwiN)
|
||||
|
||||
|
||||
Gatus is a developer-oriented health dashboard that gives you the ability to monitor your services using HTTP, ICMP, TCP, and even DNS
|
||||
queries as well as evaluate the result of said queries by using a list of conditions on values like the status code,
|
||||
the response time, the certificate expiration, the body and many others. The icing on top is that each of these health
|
||||
|
@ -54,6 +53,7 @@ Have any feedback or questions? [Create a discussion](https://github.com/TwiN/ga
|
|||
- [Alerting](#alerting)
|
||||
- [Configuring Discord alerts](#configuring-discord-alerts)
|
||||
- [Configuring Email alerts](#configuring-email-alerts)
|
||||
- [Configuring Gitea alerts](#configuring-gitea-alerts)
|
||||
- [Configuring GitHub alerts](#configuring-github-alerts)
|
||||
- [Configuring GitLab alerts](#configuring-gitlab-alerts)
|
||||
- [Configuring Google Chat alerts](#configuring-google-chat-alerts)
|
||||
|
@ -109,6 +109,7 @@ Have any feedback or questions? [Create a discussion](https://github.com/TwiN/ga
|
|||
- [Configuring a startup delay](#configuring-a-startup-delay)
|
||||
- [Keeping your configuration small](#keeping-your-configuration-small)
|
||||
- [Proxy client configuration](#proxy-client-configuration)
|
||||
- [How to fix 431 Request Header Fields Too Large error](#how-to-fix-431-request-header-fields-too-large-error)
|
||||
- [Badges](#badges)
|
||||
- [Uptime](#uptime)
|
||||
- [Health](#health)
|
||||
|
@ -660,8 +661,45 @@ endpoints:
|
|||
|
||||
> ⚠ Some mail servers are painfully slow.
|
||||
|
||||
#### Configuring Gitea alerts
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|:---------------------------------|:-----------------------------------------------------------------------------------------------------------|:--------------|
|
||||
| `alerting.gitea` | Configuration for alerts of type `gitea` | `{}` |
|
||||
| `alerting.gitea.repository-url` | Gitea repository URL (e.g. `https://gitea.com/TwiN/example`) | Required `""` |
|
||||
| `alerting.gitea.token` | Personal access token to use for authentication. <br />Must have at least RW on issues and RO on metadata. | Required `""` |
|
||||
| `alerting.github.default-alert` | Default alert configuration. <br />See [Setting a default alert](#setting-a-default-alert). | N/A |
|
||||
|
||||
The Gitea alerting provider creates an issue prefixed with `alert(gatus):` and suffixed with the endpoint's display
|
||||
name for each alert. If `send-on-resolved` is set to `true` on the endpoint alert, the issue will be automatically
|
||||
closed when the alert is resolved.
|
||||
|
||||
```yaml
|
||||
alerting:
|
||||
gitea:
|
||||
repository-url: "https://gitea.com/TwiN/test"
|
||||
token: "349d63f16......"
|
||||
|
||||
endpoints:
|
||||
- name: example
|
||||
url: "https://twin.sh/health"
|
||||
interval: 5m
|
||||
conditions:
|
||||
- "[STATUS] == 200"
|
||||
- "[BODY].status == UP"
|
||||
- "[RESPONSE_TIME] < 75"
|
||||
alerts:
|
||||
- type: gitea
|
||||
failure-threshold: 2
|
||||
success-threshold: 3
|
||||
send-on-resolved: true
|
||||
description: "Everything's burning AAAAAHHHHHHHHHHHHHHH"
|
||||
```
|
||||
|
||||
![Gitea alert](.github/assets/gitea-alerts.png)
|
||||
|
||||
#### Configuring GitHub alerts
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|:---------------------------------|:-----------------------------------------------------------------------------------------------------------|:--------------|
|
||||
| `alerting.github` | Configuration for alerts of type `github` | `{}` |
|
||||
|
@ -697,7 +735,6 @@ endpoints:
|
|||
|
||||
![GitHub alert](.github/assets/github-alerts.png)
|
||||
|
||||
|
||||
#### Configuring GitLab alerts
|
||||
| Parameter | Description | Default |
|
||||
|:------------------------------------|:--------------------------------------------------------------------------------------------------------------------|:--------------|
|
||||
|
|
|
@ -23,6 +23,9 @@ const (
|
|||
// TypeGitLab is the Type for the gitlab alerting provider
|
||||
TypeGitLab Type = "gitlab"
|
||||
|
||||
// TypeGitea is the Type for the gitea alerting provider
|
||||
TypeGitea Type = "gitea"
|
||||
|
||||
// TypeGoogleChat is the Type for the googlechat alerting provider
|
||||
TypeGoogleChat Type = "googlechat"
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/TwiN/gatus/v5/alerting/provider/custom"
|
||||
"github.com/TwiN/gatus/v5/alerting/provider/discord"
|
||||
"github.com/TwiN/gatus/v5/alerting/provider/email"
|
||||
"github.com/TwiN/gatus/v5/alerting/provider/gitea"
|
||||
"github.com/TwiN/gatus/v5/alerting/provider/github"
|
||||
"github.com/TwiN/gatus/v5/alerting/provider/gitlab"
|
||||
"github.com/TwiN/gatus/v5/alerting/provider/googlechat"
|
||||
|
@ -49,6 +50,9 @@ type Config struct {
|
|||
// GitLab is the configuration for the gitlab alerting provider
|
||||
GitLab *gitlab.AlertProvider `yaml:"gitlab,omitempty"`
|
||||
|
||||
// Gitea is the configuration for the gitea alerting provider
|
||||
Gitea *gitea.AlertProvider `yaml:"gitea,omitempty"`
|
||||
|
||||
// GoogleChat is the configuration for the googlechat alerting provider
|
||||
GoogleChat *googlechat.AlertProvider `yaml:"googlechat,omitempty"`
|
||||
|
||||
|
|
167
alerting/provider/gitea/gitea.go
Normal file
167
alerting/provider/gitea/gitea.go
Normal file
|
@ -0,0 +1,167 @@
|
|||
package gitea
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/TwiN/gatus/v5/alerting/alert"
|
||||
"github.com/TwiN/gatus/v5/client"
|
||||
"github.com/TwiN/gatus/v5/config/endpoint"
|
||||
)
|
||||
|
||||
// AlertProvider is the configuration necessary for sending an alert using Discord
|
||||
type AlertProvider struct {
|
||||
RepositoryURL string `yaml:"repository-url"` // The URL of the Gitea repository to create issues in
|
||||
Token string `yaml:"token"` // Token requires at least RW on issues and RO on metadata
|
||||
|
||||
// DefaultAlert is the default alert configuration to use for endpoints with an alert of the appropriate type
|
||||
DefaultAlert *alert.Alert `yaml:"default-alert,omitempty"`
|
||||
|
||||
// ClientConfig is the configuration of the client used to communicate with the provider's target
|
||||
ClientConfig *client.Config `yaml:"client,omitempty"`
|
||||
|
||||
// Assignees is a list of users to assign the issue to
|
||||
Assignees []string `yaml:"assignees,omitempty"`
|
||||
|
||||
username string
|
||||
repositoryOwner string
|
||||
repositoryName string
|
||||
giteaClient *gitea.Client
|
||||
}
|
||||
|
||||
// IsValid returns whether the provider's configuration is valid
|
||||
func (provider *AlertProvider) IsValid() bool {
|
||||
if provider.ClientConfig == nil {
|
||||
provider.ClientConfig = client.GetDefaultConfig()
|
||||
}
|
||||
|
||||
if len(provider.Token) == 0 || len(provider.RepositoryURL) == 0 {
|
||||
return false
|
||||
}
|
||||
// Validate format of the repository URL
|
||||
repositoryURL, err := url.Parse(provider.RepositoryURL)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
baseURL := repositoryURL.Scheme + "://" + repositoryURL.Host
|
||||
pathParts := strings.Split(repositoryURL.Path, "/")
|
||||
if len(pathParts) != 3 {
|
||||
return false
|
||||
}
|
||||
provider.repositoryOwner = pathParts[1]
|
||||
provider.repositoryName = pathParts[2]
|
||||
|
||||
opts := []gitea.ClientOption{
|
||||
gitea.SetToken(provider.Token),
|
||||
}
|
||||
|
||||
if provider.ClientConfig != nil && provider.ClientConfig.Insecure {
|
||||
// add new http client for skip verify
|
||||
httpClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
opts = append(opts, gitea.SetHTTPClient(httpClient))
|
||||
}
|
||||
|
||||
provider.giteaClient, err = gitea.NewClient(baseURL, opts...)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
user, _, err := provider.giteaClient.GetMyUserInfo()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
provider.username = user.UserName
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Send creates an issue in the designed RepositoryURL if the resolved parameter passed is false,
|
||||
// or closes the relevant issue(s) if the resolved parameter passed is true.
|
||||
func (provider *AlertProvider) Send(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result, resolved bool) error {
|
||||
title := "alert(gatus): " + ep.DisplayName()
|
||||
if !resolved {
|
||||
_, _, err := provider.giteaClient.CreateIssue(
|
||||
provider.repositoryOwner,
|
||||
provider.repositoryName,
|
||||
gitea.CreateIssueOption{
|
||||
Title: title,
|
||||
Body: provider.buildIssueBody(ep, alert, result),
|
||||
Assignees: provider.Assignees,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create issue: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
issues, _, err := provider.giteaClient.ListRepoIssues(
|
||||
provider.repositoryOwner,
|
||||
provider.repositoryName,
|
||||
gitea.ListIssueOption{
|
||||
State: gitea.StateOpen,
|
||||
CreatedBy: provider.username,
|
||||
ListOptions: gitea.ListOptions{
|
||||
Page: 100,
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list issues: %w", err)
|
||||
}
|
||||
|
||||
for _, issue := range issues {
|
||||
if issue.Title == title {
|
||||
stateClosed := gitea.StateClosed
|
||||
_, _, err = provider.giteaClient.EditIssue(
|
||||
provider.repositoryOwner,
|
||||
provider.repositoryName,
|
||||
issue.ID,
|
||||
gitea.EditIssueOption{
|
||||
State: &stateClosed,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to close issue: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// buildIssueBody builds the body of the issue
|
||||
func (provider *AlertProvider) buildIssueBody(ep *endpoint.Endpoint, alert *alert.Alert, result *endpoint.Result) string {
|
||||
var formattedConditionResults string
|
||||
if len(result.ConditionResults) > 0 {
|
||||
formattedConditionResults = "\n\n## Condition results\n"
|
||||
for _, conditionResult := range result.ConditionResults {
|
||||
var prefix string
|
||||
if conditionResult.Success {
|
||||
prefix = ":white_check_mark:"
|
||||
} else {
|
||||
prefix = ":x:"
|
||||
}
|
||||
formattedConditionResults += fmt.Sprintf("- %s - `%s`\n", prefix, conditionResult.Condition)
|
||||
}
|
||||
}
|
||||
var description string
|
||||
if alertDescription := alert.GetDescription(); len(alertDescription) > 0 {
|
||||
description = ":\n> " + alertDescription
|
||||
}
|
||||
message := fmt.Sprintf("An alert for **%s** has been triggered due to having failed %d time(s) in a row", ep.DisplayName(), alert.FailureThreshold)
|
||||
return message + description + formattedConditionResults
|
||||
}
|
||||
|
||||
// GetDefaultAlert returns the provider's default alert configuration
|
||||
func (provider *AlertProvider) GetDefaultAlert() *alert.Alert {
|
||||
return provider.DefaultAlert
|
||||
}
|
169
alerting/provider/gitea/gitea_test.go
Normal file
169
alerting/provider/gitea/gitea_test.go
Normal file
|
@ -0,0 +1,169 @@
|
|||
package gitea
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
"github.com/TwiN/gatus/v5/alerting/alert"
|
||||
"github.com/TwiN/gatus/v5/client"
|
||||
"github.com/TwiN/gatus/v5/config/endpoint"
|
||||
"github.com/TwiN/gatus/v5/test"
|
||||
)
|
||||
|
||||
func TestAlertDefaultProvider_IsValid(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
Name string
|
||||
Provider AlertProvider
|
||||
Expected bool
|
||||
}{
|
||||
{
|
||||
Name: "invalid",
|
||||
Provider: AlertProvider{RepositoryURL: "", Token: ""},
|
||||
Expected: false,
|
||||
},
|
||||
{
|
||||
Name: "invalid-token",
|
||||
Provider: AlertProvider{RepositoryURL: "https://gitea.com/TwiN/test", Token: "12345"},
|
||||
Expected: false,
|
||||
},
|
||||
{
|
||||
Name: "missing-repository-name",
|
||||
Provider: AlertProvider{RepositoryURL: "https://gitea.com/TwiN", Token: "12345"},
|
||||
Expected: false,
|
||||
},
|
||||
{
|
||||
Name: "enterprise-client",
|
||||
Provider: AlertProvider{RepositoryURL: "https://gitea.example.com/TwiN/test", Token: "12345"},
|
||||
Expected: false,
|
||||
},
|
||||
{
|
||||
Name: "invalid-url",
|
||||
Provider: AlertProvider{RepositoryURL: "gitea.com/TwiN/test", Token: "12345"},
|
||||
Expected: false,
|
||||
},
|
||||
}
|
||||
for _, scenario := range scenarios {
|
||||
t.Run(scenario.Name, func(t *testing.T) {
|
||||
if scenario.Provider.IsValid() != scenario.Expected {
|
||||
t.Errorf("expected %t, got %t", scenario.Expected, scenario.Provider.IsValid())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAlertProvider_Send(t *testing.T) {
|
||||
defer client.InjectHTTPClient(nil)
|
||||
firstDescription := "description-1"
|
||||
secondDescription := "description-2"
|
||||
scenarios := []struct {
|
||||
Name string
|
||||
Provider AlertProvider
|
||||
Alert alert.Alert
|
||||
Resolved bool
|
||||
MockRoundTripper test.MockRoundTripper
|
||||
ExpectedError bool
|
||||
}{
|
||||
{
|
||||
Name: "triggered-error",
|
||||
Provider: AlertProvider{RepositoryURL: "https://gitea.com/TwiN/test", Token: "12345"},
|
||||
Alert: alert.Alert{Description: &firstDescription, SuccessThreshold: 5, FailureThreshold: 3},
|
||||
Resolved: false,
|
||||
ExpectedError: true,
|
||||
},
|
||||
{
|
||||
Name: "resolved-error",
|
||||
Provider: AlertProvider{RepositoryURL: "https://gitea.com/TwiN/test", Token: "12345"},
|
||||
Alert: alert.Alert{Description: &secondDescription, SuccessThreshold: 5, FailureThreshold: 3},
|
||||
Resolved: true,
|
||||
ExpectedError: true,
|
||||
},
|
||||
}
|
||||
for _, scenario := range scenarios {
|
||||
t.Run(scenario.Name, func(t *testing.T) {
|
||||
scenario.Provider.giteaClient, _ = gitea.NewClient("https://gitea.com")
|
||||
client.InjectHTTPClient(&http.Client{Transport: scenario.MockRoundTripper})
|
||||
err := scenario.Provider.Send(
|
||||
&endpoint.Endpoint{Name: "endpoint-name", Group: "endpoint-group"},
|
||||
&scenario.Alert,
|
||||
&endpoint.Result{
|
||||
ConditionResults: []*endpoint.ConditionResult{
|
||||
{Condition: "[CONNECTED] == true", Success: scenario.Resolved},
|
||||
{Condition: "[STATUS] == 200", Success: scenario.Resolved},
|
||||
},
|
||||
},
|
||||
scenario.Resolved,
|
||||
)
|
||||
if scenario.ExpectedError && err == nil {
|
||||
t.Error("expected error, got none")
|
||||
}
|
||||
if !scenario.ExpectedError && err != nil {
|
||||
t.Error("expected no error, got", err.Error())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAlertProvider_buildRequestBody(t *testing.T) {
|
||||
firstDescription := "description-1"
|
||||
scenarios := []struct {
|
||||
Name string
|
||||
Endpoint endpoint.Endpoint
|
||||
Provider AlertProvider
|
||||
Alert alert.Alert
|
||||
NoConditions bool
|
||||
ExpectedBody string
|
||||
}{
|
||||
{
|
||||
Name: "triggered",
|
||||
Endpoint: endpoint.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
|
||||
Provider: AlertProvider{},
|
||||
Alert: alert.Alert{Description: &firstDescription, FailureThreshold: 3},
|
||||
ExpectedBody: "An alert for **endpoint-name** has been triggered due to having failed 3 time(s) in a row:\n> description-1\n\n## Condition results\n- :white_check_mark: - `[CONNECTED] == true`\n- :x: - `[STATUS] == 200`",
|
||||
},
|
||||
{
|
||||
Name: "triggered-with-no-description",
|
||||
Endpoint: endpoint.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
|
||||
Provider: AlertProvider{},
|
||||
Alert: alert.Alert{FailureThreshold: 10},
|
||||
ExpectedBody: "An alert for **endpoint-name** has been triggered due to having failed 10 time(s) in a row\n\n## Condition results\n- :white_check_mark: - `[CONNECTED] == true`\n- :x: - `[STATUS] == 200`",
|
||||
},
|
||||
{
|
||||
Name: "triggered-with-no-conditions",
|
||||
NoConditions: true,
|
||||
Endpoint: endpoint.Endpoint{Name: "endpoint-name", URL: "https://example.org"},
|
||||
Provider: AlertProvider{},
|
||||
Alert: alert.Alert{Description: &firstDescription, FailureThreshold: 10},
|
||||
ExpectedBody: "An alert for **endpoint-name** has been triggered due to having failed 10 time(s) in a row:\n> description-1",
|
||||
},
|
||||
}
|
||||
for _, scenario := range scenarios {
|
||||
t.Run(scenario.Name, func(t *testing.T) {
|
||||
var conditionResults []*endpoint.ConditionResult
|
||||
if !scenario.NoConditions {
|
||||
conditionResults = []*endpoint.ConditionResult{
|
||||
{Condition: "[CONNECTED] == true", Success: true},
|
||||
{Condition: "[STATUS] == 200", Success: false},
|
||||
}
|
||||
}
|
||||
body := scenario.Provider.buildIssueBody(
|
||||
&scenario.Endpoint,
|
||||
&scenario.Alert,
|
||||
&endpoint.Result{ConditionResults: conditionResults},
|
||||
)
|
||||
if strings.TrimSpace(body) != strings.TrimSpace(scenario.ExpectedBody) {
|
||||
t.Errorf("expected:\n%s\ngot:\n%s", scenario.ExpectedBody, body)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAlertProvider_GetDefaultAlert(t *testing.T) {
|
||||
if (&AlertProvider{DefaultAlert: &alert.Alert{}}).GetDefaultAlert() == nil {
|
||||
t.Error("expected default alert to be not nil")
|
||||
}
|
||||
if (&AlertProvider{DefaultAlert: nil}).GetDefaultAlert() != nil {
|
||||
t.Error("expected default alert to be nil")
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/TwiN/gatus/v5/alerting/provider/custom"
|
||||
"github.com/TwiN/gatus/v5/alerting/provider/discord"
|
||||
"github.com/TwiN/gatus/v5/alerting/provider/email"
|
||||
"github.com/TwiN/gatus/v5/alerting/provider/gitea"
|
||||
"github.com/TwiN/gatus/v5/alerting/provider/github"
|
||||
"github.com/TwiN/gatus/v5/alerting/provider/gitlab"
|
||||
"github.com/TwiN/gatus/v5/alerting/provider/googlechat"
|
||||
|
@ -66,6 +67,7 @@ var (
|
|||
_ AlertProvider = (*email.AlertProvider)(nil)
|
||||
_ AlertProvider = (*github.AlertProvider)(nil)
|
||||
_ AlertProvider = (*gitlab.AlertProvider)(nil)
|
||||
_ AlertProvider = (*gitea.AlertProvider)(nil)
|
||||
_ AlertProvider = (*googlechat.AlertProvider)(nil)
|
||||
_ AlertProvider = (*jetbrainsspace.AlertProvider)(nil)
|
||||
_ AlertProvider = (*matrix.AlertProvider)(nil)
|
||||
|
|
|
@ -400,6 +400,7 @@ func validateAlertingConfig(alertingConfig *alerting.Config, endpoints []*endpoi
|
|||
alert.TypeEmail,
|
||||
alert.TypeGitHub,
|
||||
alert.TypeGitLab,
|
||||
alert.TypeGitea,
|
||||
alert.TypeGoogleChat,
|
||||
alert.TypeGotify,
|
||||
alert.TypeJetBrainsSpace,
|
||||
|
|
4
go.mod
4
go.mod
|
@ -3,6 +3,7 @@ module github.com/TwiN/gatus/v5
|
|||
go 1.22.2
|
||||
|
||||
require (
|
||||
code.gitea.io/sdk/gitea v0.19.0
|
||||
github.com/TwiN/deepmerge v0.2.1
|
||||
github.com/TwiN/g8/v2 v2.0.0
|
||||
github.com/TwiN/gocache/v2 v2.2.2
|
||||
|
@ -38,8 +39,10 @@ require (
|
|||
github.com/blend/go-sdk v1.20220411.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-fed/httpsig v1.1.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
|
@ -49,6 +52,7 @@ require (
|
|||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/klauspost/compress v1.17.8 // indirect
|
||||
|
|
9
go.sum
9
go.sum
|
@ -5,6 +5,8 @@ cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKF
|
|||
cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q=
|
||||
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
|
||||
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
code.gitea.io/sdk/gitea v0.19.0 h1:8I6s1s4RHgzxiPHhOQdgim1RWIRcr0LVMbHBjBFXq4Y=
|
||||
code.gitea.io/sdk/gitea v0.19.0/go.mod h1:IG9xZJoltDNeDSW0qiF2Vqx5orMWa7OhVWrjvrd5NpI=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/TwiN/deepmerge v0.2.1 h1:GowJr9O4THTVW4awX63x1BVg1hgr4q+35XKKCYbwsSs=
|
||||
github.com/TwiN/deepmerge v0.2.1/go.mod h1:LVBmCEBQvibYSF8Gyl/NqhHXH7yIiT7Ozqf9dHxGPW0=
|
||||
|
@ -35,6 +37,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
|
||||
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
|
@ -43,6 +47,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
|||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
|
||||
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||
github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk=
|
||||
github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
|
@ -94,6 +100,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfF
|
|||
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
|
||||
github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg=
|
||||
github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI=
|
||||
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/ishidawataru/sctp v0.0.0-20230406120618-7ff4192f6ff2 h1:i2fYnDurfLlJH8AyyMOnkLHnHeP8Ff/DDpuZA/D3bPo=
|
||||
|
@ -172,6 +180,7 @@ go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5
|
|||
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
|
|
Loading…
Reference in a new issue