Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d0fc65e
feat: add `github.pullRequestComment.commentTag` to upsert github com…
bmbferreira Mar 23, 2025
434dfbb
fix: instantiate the http.Transport for conn limits
afzal442 May 6, 2025
5ab9a11
transfer to *Options struct
afzal442 May 6, 2025
b846f3a
modift the transport layer for svcs
afzal442 May 7, 2025
e624448
refactor the transport connection into the svc
afzal442 May 9, 2025
152958e
minor typo fix
afzal442 Jul 6, 2025
431990a
parse the idleConnTimeout
afzal442 Jul 6, 2025
a0be76f
modify to use `IdleConnTimeout` as a string
afzal442 Jul 9, 2025
8768c0b
parse the conn timeouts if not empty
afzal442 Jul 10, 2025
dfb043c
add err var to ret type error
afzal442 Jul 14, 2025
3cc39fc
add the info about the new params to docs
afzal442 Jul 14, 2025
8e963fb
add extra error field
afzal442 Jul 14, 2025
37f618f
rmvs the err extra field
afzal442 Jul 15, 2025
c5827a1
update the err field
afzal442 Jul 15, 2025
f707dc9
fix the linting issue
afzal442 Jul 15, 2025
b3675e3
docs: Adding info about template for Grafana service (#386)
lrochette Jul 10, 2025
b90ac7f
chore: bump golanglint-ci (#383)
blakepettersson Jul 10, 2025
2f4b8fc
chore: more lint (#387)
blakepettersson Jul 14, 2025
6335765
added a module to refactor the method
afzal442 Aug 29, 2025
45d45ac
refactor services to use newService HttpClient
afzal442 Oct 27, 2025
e514a9b
Merge branch 'master' into fix-ncspawns-22800
afzal442 Oct 27, 2025
5b32611
Merge branch 'master' into fix-ncspawns-22800
afzal442 Oct 29, 2025
22ebd3c
restructure into tpOptions
afzal442 Oct 29, 2025
0cc1347
refactor: simplify HTTP client initialization by using TransportOptio…
afzal442 Nov 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/services/alertmanager.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ The notification service is used to push events to [Alertmanager](https://github
* `basicAuth` - optional, server auth
* `bearerToken` - optional, server auth
* `timeout` - optional, the timeout in seconds used when sending alerts, default is "3 seconds"
* `maxIdleConns` - optional, maximum number of idle (keep-alive) connections across all hosts.
* `maxIdleConnsPerHost` - optional, maximum number of idle (keep-alive) connections per host.
* `maxConnsPerHost` - optional, maximum total connections per host.
* `idleConnTimeout` - optional, maximum amount of time an idle (keep-alive) connection will remain open before closing.

`basicAuth` or `bearerToken` is used for authentication, you can choose one. If the two are set at the same time, `basicAuth` takes precedence over `bearerToken`.

Expand Down
4 changes: 4 additions & 0 deletions docs/services/github.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ The GitHub notification service changes commit status using [GitHub Apps](https:
- `installationID` - the app installation id
- `privateKey` - the app private key
- `enterpriseBaseURL` - optional URL, e.g. https://git.example.com/api/v3
- `maxIdleConns` - optional, maximum number of idle (keep-alive) connections across all hosts.
- `maxIdleConnsPerHost` - optional, maximum number of idle (keep-alive) connections per host.
- `maxConnsPerHost` - optional, maximum total connections per host.
- `idleConnTimeout` - optional, maximum amount of time an idle (keep-alive) connection will remain open before closing.

> ⚠️ _NOTE:_ Specifying `/api/v3` in the `enterpriseBaseURL` is required until [argoproj/notifications-engine#205](https://github.com/argoproj/notifications-engine/issues/205) is resolved.

Expand Down
4 changes: 4 additions & 0 deletions docs/services/grafana.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ Available parameters :
* `apiURL` - the server url, e.g. https://grafana.example.com
* `apiKey` - the API key for the serviceaccount
* `insecureSkipVerify` - optional bool, true or false
* `maxIdleConns` - optional, maximum number of idle (keep-alive) connections across all hosts.
* `maxIdleConnsPerHost` - optional, maximum number of idle (keep-alive) connections per host.
* `maxConnsPerHost` - optional, maximum total connections per host.
* `idleConnTimeout` - optional, maximum amount of time an idle (keep-alive) connection will remain open before closing.

1. Login to your Grafana instance as `admin`
2. On the left menu, go to Configuration / API Keys
Expand Down
4 changes: 4 additions & 0 deletions docs/services/mattermost.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
* `apiURL` - the server url, e.g. https://mattermost.example.com
* `token` - the bot token
* `insecureSkipVerify` - optional bool, true or false
* `maxIdleConns` - optional, maximum number of idle (keep-alive) connections across all hosts.
* `maxIdleConnsPerHost` - optional, maximum number of idle (keep-alive) connections per host.
* `maxConnsPerHost` - optional, maximum total connections per host.
* `idleConnTimeout` - optional, maximum amount of time an idle (keep-alive) connection will remain open before closing, e.g. '90s'.

## Configuration

Expand Down
4 changes: 4 additions & 0 deletions docs/services/newrelic.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

* `apiURL` - the api server url, e.g. https://api.newrelic.com
* `apiKey` - a [NewRelic ApiKey](https://docs.newrelic.com/docs/apis/rest-api-v2/get-started/introduction-new-relic-rest-api-v2/#api_key)
* `maxIdleConns` - optional, maximum number of idle (keep-alive) connections across all hosts.
* `maxIdleConnsPerHost` - optional, maximum number of idle (keep-alive) connections per host.
* `maxConnsPerHost` - optional, maximum total connections per host.
* `idleConnTimeout` - optional, maximum amount of time an idle (keep-alive) connection will remain open before closing, e.g. '90s'.

## Configuration

Expand Down
5 changes: 5 additions & 0 deletions docs/services/slack.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ The Slack notification service configuration includes following settings:
| `token` | **True** | `string` | The app's OAuth access token. | `xoxb-1234567890-1234567890123-5n38u5ed63fgzqlvuyxvxcx6` |
| `username` | False | `string` | The app username. | `argocd` |
| `disableUnfurl` | False | `bool` | Disable slack unfurling links in messages | `true` |
| `maxIdleConns` | False | `int` | Maximum number of idle (keep-alive) connections across all hosts. | — |
| `maxIdleConnsPerHost` | False | `int` | Maximum number of idle (keep-alive) connections per host. | — |
| `maxConnsPerHost` | False | `int` | Maximum total connections per host. | — |
| `idleConnTimeout` | False | `string` | Maximum amount of time an idle (keep-alive) connection will remain open before closing (e.g., `90s`). | — |


## Configuration

Expand Down
4 changes: 4 additions & 0 deletions docs/services/webhook.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ The Webhook notification service configuration includes following settings:
- `retryWaitMin` - Optional, the minimum wait time between retries. Default value: 1s.
- `retryWaitMax` - Optional, the maximum wait time between retries. Default value: 5s.
- `retryMax` - Optional, the maximum number of retries. Default value: 3.
- `maxIdleConns` - optional, maximum number of idle (keep-alive) connections across all hosts.
- `maxIdleConnsPerHost` - optional, maximum number of idle (keep-alive) connections per host.
- `maxConnsPerHost` - optional, maximum total connections per host.
- `idleConnTimeout` - optional, maximum amount of time an idle (keep-alive) connection will remain open before closing, e.g. '90s'.

## Retry Behavior

Expand Down
12 changes: 6 additions & 6 deletions pkg/services/alertmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ type AlertmanagerOptions struct {
APIPath string `json:"apiPath"`
BasicAuth *BasicAuth `json:"basicAuth"`
BearerToken string `json:"bearerToken"`
InsecureSkipVerify bool `json:"insecureSkipVerify"`
Timeout int `json:"timeout"`
InsecureSkipVerify bool `json:"insecureSkipVerify"`
httputil.TransportOptions
}

// NewAlertmanagerService new service
Expand Down Expand Up @@ -204,14 +205,13 @@ func (s alertmanagerService) Send(notification Notification, dest Destination) e
return nil
}

func (s alertmanagerService) sendOneTarget(ctx context.Context, target string, rawBody []byte) error {
func (s alertmanagerService) sendOneTarget(ctx context.Context, target string, rawBody []byte) (err error) {
rawURL := fmt.Sprintf("%v://%v%v", s.opts.Scheme, target, s.opts.APIPath)

transport := httputil.NewTransport(rawURL, s.opts.InsecureSkipVerify)
client := &http.Client{
Transport: httputil.NewLoggingRoundTripper(transport, s.entry),
client, err := httputil.NewServiceHTTPClient(s.opts.TransportOptions, s.opts.InsecureSkipVerify, rawURL, "alertmanager")
if err != nil {
return err
}

req, err := http.NewRequestWithContext(ctx, http.MethodPost, rawURL, bytes.NewReader(rawBody))
if err != nil {
return err
Expand Down
27 changes: 15 additions & 12 deletions pkg/services/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/bradleyfalzon/ghinstallation/v2"
giturls "github.com/chainguard-dev/git-urls"
"github.com/google/go-github/v69/github"
log "github.com/sirupsen/logrus"
"github.com/spf13/cast"

httputil "github.com/argoproj/notifications-engine/pkg/util/http"
Expand All @@ -26,10 +25,12 @@ var (
)

type GitHubOptions struct {
AppID interface{} `json:"appID"`
InstallationID interface{} `json:"installationID"`
PrivateKey string `json:"privateKey"`
EnterpriseBaseURL string `json:"enterpriseBaseURL"`
AppID interface{} `json:"appID"`
InstallationID interface{} `json:"installationID"`
PrivateKey string `json:"privateKey"`
EnterpriseBaseURL string `json:"enterpriseBaseURL"`
InsecureSkipVerify bool `json:"insecureSkipVerify"`
httputil.TransportOptions
}

type GitHubNotification struct {
Expand Down Expand Up @@ -395,26 +396,28 @@ func NewGitHubService(opts GitHubOptions) (*gitHubService, error) {
return nil, err
}

tr := httputil.NewLoggingRoundTripper(
httputil.NewTransport(url, false), log.WithField("service", "github"))
itr, err := ghinstallation.New(tr, appID, installationID, []byte(opts.PrivateKey))
client, err := httputil.NewServiceHTTPClient(opts.TransportOptions, opts.InsecureSkipVerify, url, "github")
if err != nil {
return nil, err
}
itr, err := ghinstallation.New(client.Transport, appID, installationID, []byte(opts.PrivateKey))
if err != nil {
return nil, err
}

var client *github.Client
var ghclient *github.Client
if opts.EnterpriseBaseURL == "" {
client = github.NewClient(&http.Client{Transport: itr})
ghclient = github.NewClient(&http.Client{Transport: itr})
} else {
itr.BaseURL = opts.EnterpriseBaseURL
client, err = github.NewClient(&http.Client{Transport: itr}).WithEnterpriseURLs(opts.EnterpriseBaseURL, "")
ghclient, err = github.NewClient(&http.Client{Transport: itr}).WithEnterpriseURLs(opts.EnterpriseBaseURL, "")
if err != nil {
return nil, err
}
}

return &gitHubService{
client: &githubClientAdapter{client: client},
client: &githubClientAdapter{client: ghclient},
}, nil
}

Expand Down
14 changes: 8 additions & 6 deletions pkg/services/googlechat.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (

"github.com/google/uuid"

log "github.com/sirupsen/logrus"
"sigs.k8s.io/yaml"

"google.golang.org/api/chat/v1"
Expand Down Expand Up @@ -80,7 +79,9 @@ func (n *GoogleChatNotification) GetTemplater(name string, f texttemplate.FuncMa
}

type GoogleChatOptions struct {
WebhookUrls map[string]string `json:"webhooks"`
WebhookUrls map[string]string `json:"webhooks"`
InsecureSkipVerify bool `json:"insecureSkipVerify"`
httputil.TransportOptions
}

type googleChatService struct {
Expand All @@ -101,14 +102,15 @@ type webhookError struct {
Status string `json:"status"`
}

func (s googleChatService) getClient(recipient string) (*googlechatClient, error) {
func (s googleChatService) getClient(recipient string) (googlechatclient *googlechatClient, err error) {
webhookUrl, ok := s.opts.WebhookUrls[recipient]
if !ok {
return nil, fmt.Errorf("no Google chat webhook configured for recipient %s", recipient)
}
transport := httputil.NewTransport(webhookUrl, false)
client := &http.Client{
Transport: httputil.NewLoggingRoundTripper(transport, log.WithField("service", "googlechat")),

client, err := httputil.NewServiceHTTPClient(s.opts.TransportOptions, s.opts.InsecureSkipVerify, webhookUrl, "googlechat")
if err != nil {
return nil, err
}
return &googlechatClient{httpClient: client, url: webhookUrl}, nil
}
Expand Down
9 changes: 5 additions & 4 deletions pkg/services/grafana.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type GrafanaOptions struct {
ApiUrl string `json:"apiUrl"`
ApiKey string `json:"apiKey"`
InsecureSkipVerify bool `json:"insecureSkipVerify"`
httputil.TransportOptions
}

type grafanaService struct {
Expand All @@ -37,7 +38,7 @@ type GrafanaAnnotation struct {
Text string `json:"text"`
}

func (s *grafanaService) Send(notification Notification, dest Destination) error {
func (s *grafanaService) Send(notification Notification, dest Destination) (err error) {
ga := GrafanaAnnotation{
Time: time.Now().Unix() * 1000, // unix ts in ms
IsRegion: false,
Expand All @@ -49,9 +50,9 @@ func (s *grafanaService) Send(notification Notification, dest Destination) error
log.Warnf("Message is an empty string or not provided in the notifications template")
}

client := &http.Client{
Transport: httputil.NewLoggingRoundTripper(
httputil.NewTransport(s.opts.ApiUrl, s.opts.InsecureSkipVerify), log.WithField("service", "grafana")),
client, err := httputil.NewServiceHTTPClient(s.opts.TransportOptions, s.opts.InsecureSkipVerify, s.opts.ApiUrl, "grafana")
if err != nil {
return err
}

jsonValue, _ := json.Marshal(ga)
Expand Down
5 changes: 3 additions & 2 deletions pkg/services/grafana_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@ func TestGrafana_UnSuccessfullySendsNotification(t *testing.T) {
defer server.Close()

service := NewGrafanaService(GrafanaOptions{
ApiUrl: server.URL,
ApiKey: "something-secret-but-not-relevant-in-this-test",
ApiUrl: server.URL,
ApiKey: "something-secret-but-not-relevant-in-this-test",

InsecureSkipVerify: true,
})
err := service.Send(
Expand Down
11 changes: 5 additions & 6 deletions pkg/services/mattermost.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import (
"net/http"
texttemplate "text/template"

log "github.com/sirupsen/logrus"

httputil "github.com/argoproj/notifications-engine/pkg/util/http"
)

Expand Down Expand Up @@ -40,6 +38,7 @@ type MattermostOptions struct {
ApiURL string `json:"apiURL"`
Token string `json:"token"`
InsecureSkipVerify bool `json:"insecureSkipVerify"`
httputil.TransportOptions
}

type mattermostService struct {
Expand All @@ -50,10 +49,10 @@ func NewMattermostService(opts MattermostOptions) NotificationService {
return &mattermostService{opts: opts}
}

func (m *mattermostService) Send(notification Notification, dest Destination) error {
transport := httputil.NewTransport(m.opts.ApiURL, m.opts.InsecureSkipVerify)
client := &http.Client{
Transport: httputil.NewLoggingRoundTripper(transport, log.WithField("service", "mattermost")),
func (m *mattermostService) Send(notification Notification, dest Destination) (err error) {
client, err := httputil.NewServiceHTTPClient(m.opts.TransportOptions, m.opts.InsecureSkipVerify, m.opts.ApiURL, "mattermost")
if err != nil {
return err
}

attachments := []interface{}{}
Expand Down
14 changes: 8 additions & 6 deletions pkg/services/newrelic.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ import (
)

type NewrelicOptions struct {
ApiKey string `json:"apiKey"`
ApiURL string `json:"apiURL"`
ApiKey string `json:"apiKey"`
ApiURL string `json:"apiURL"`
InsecureSkipVerify bool `json:"insecureSkipVerify"`
httputil.TransportOptions
}

type NewrelicNotification struct {
Expand Down Expand Up @@ -110,7 +112,7 @@ type newrelicDeploymentMarkerRequest struct {
Deployment NewrelicNotification `json:"deployment"`
}

func (s newrelicService) Send(notification Notification, dest Destination) error {
func (s newrelicService) Send(notification Notification, dest Destination) (err error) {
if s.opts.ApiKey == "" {
return ErrMissingApiKey
}
Expand All @@ -132,9 +134,9 @@ func (s newrelicService) Send(notification Notification, dest Destination) error
},
}

client := &http.Client{
Transport: httputil.NewLoggingRoundTripper(
httputil.NewTransport(s.opts.ApiURL, false), log.WithField("service", dest.Service)),
client, err := httputil.NewServiceHTTPClient(s.opts.TransportOptions, s.opts.InsecureSkipVerify, s.opts.ApiURL, "newrelic")
if err != nil {
return err
}

jsonValue, err := json.Marshal(deploymentMarker)
Expand Down
22 changes: 12 additions & 10 deletions pkg/services/opsgenie.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ import (
"bytes"
"context"
"fmt"
"net/http"
texttemplate "text/template"

"github.com/opsgenie/opsgenie-go-sdk-v2/alert"
"github.com/opsgenie/opsgenie-go-sdk-v2/client"
log "github.com/sirupsen/logrus"

httputil "github.com/argoproj/notifications-engine/pkg/util/http"
)

type OpsgenieOptions struct {
ApiUrl string `json:"apiUrl"`
ApiKeys map[string]string `json:"apiKeys"`
ApiUrl string `json:"apiUrl"`
ApiKeys map[string]string `json:"apiKeys"`
InsecureSkipVerify bool `json:"insecureSkipVerify"`
httputil.TransportOptions
}

type OpsgenieNotification struct {
Expand Down Expand Up @@ -244,18 +244,20 @@ func NewOpsgenieService(opts OpsgenieOptions) NotificationService {
return &opsgenieService{opts: opts}
}

func (s *opsgenieService) Send(notification Notification, dest Destination) error {
func (s *opsgenieService) Send(notification Notification, dest Destination) (err error) {
apiKey, ok := s.opts.ApiKeys[dest.Recipient]
if !ok {
return fmt.Errorf("no API key configured for recipient %s", dest.Recipient)
}

opsclient, err := httputil.NewServiceHTTPClient(s.opts.TransportOptions, s.opts.InsecureSkipVerify, s.opts.ApiUrl, "opsgenie")
if err != nil {
return err
}
alertClient, _ := alert.NewClient(&client.Config{
ApiKey: apiKey,
OpsGenieAPIURL: client.ApiUrl(s.opts.ApiUrl),
HttpClient: &http.Client{
Transport: httputil.NewLoggingRoundTripper(
httputil.NewTransport(s.opts.ApiUrl, false), log.WithField("service", "opsgenie")),
},
HttpClient: opsclient,
})

var description, alias, note, entity, user string
Expand Down Expand Up @@ -308,7 +310,7 @@ func (s *opsgenieService) Send(notification Notification, dest Destination) erro
}
}

_, err := alertClient.Create(context.TODO(), &alert.CreateAlertRequest{
_, err = alertClient.Create(context.TODO(), &alert.CreateAlertRequest{
Message: notification.Message,
Description: description,
Priority: priority,
Expand Down
Loading