Repository: prometheus/alertmanager (go)

Issue:
panic with amtool: invalid memory address or nil pointer dereference
running 

`amtool silence add --verbose '--start=2025-01-23T19:30:00Z' '--duration=90m' '--author=Ops Automation' '--comment=Scheduled silence: backups-vm-trv-prd-trv' '--alertmanager.url=http://alertmanager-operated.monitoring.svc.cluster.local:9093/' 'alertname=WindowsCpuUtilization' 'vmName=vm-trv-prd-trv'`

results into a panic:

```
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x9c1801]

goroutine 1 [running]:
github.com/prometheus/common/promslog.(*AllowedLevel).Set(0x0, {0xee4f9c, 0x5})
/go/pkg/mod/github.com/prometheus/common@v0.61.0/promslog/slog.go:117 +0x21
github.com/prometheus/alertmanager/cli.initMatchersCompat(0xc000005c08?)
/app/cli/root.go:55 +0x66
github.com/alecthomas/kingpin/v2.(*actionMixin).applyActions(...)
/go/pkg/mod/github.com/alecthomas/kingpin/v2@v2.4.0/actions.go:28
github.com/alecthomas/kingpin/v2.(*Application).applyActions(0xc000646700?, 0xc0000d66c0)
/go/pkg/mod/github.com/alecthomas/kingpin/v2@v2.4.0/app.go:562 +0x5a
github.com/alecthomas/kingpin/v2.(*Application).execute(0xc000646700, 0xc0000d66c0, {0xc0000bfac0, 0x2, 0x2})
/go/pkg/mod/github.com/alecthomas/kingpin/v2@v2.4.0/app.go:398 +0x65
github.com/alecthomas/kingpin/v2.(*Application).Parse(0xc000646700, {0xc00013e010?, 0xc00013e010?, 0xc0005617a0?})
/go/pkg/mod/github.com/alecthomas/kingpin/v2@v2.4.0/app.go:230 +0x14a
github.com/prometheus/alertmanager/cli.Execute()
/app/cli/root.go:183 +0x12dc
main.main()
/app/cmd/amtool/main.go:19 +0xf

```


Pull request:
amtool: fix panic if --verbose is in used.
fixes #4216 

I pattern to test a command which invokes os.exit comes from https://willsena.dev/golang-how-to-test-code-that-exits-or-crashes/

Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 860a3a30..d6c37510 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -21,10 +21,10 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        thread: [0, 1, 2]
+        thread: [ 0, 1, 2 ]
     steps:
       - uses: actions/checkout@3df4ab11eba7bda6032a0b82a6bb43b11571feac # v4.0.0
-      - uses: prometheus/promci@c3c93a50d581b928af720f0134b2b2dad32a6c41 # v0.4.6
+      - uses: prometheus/promci@3cb0c3871f223bd5ce1226995bd52ffb314798b6 # v0.1.0
       - uses: ./.github/promci/actions/build
         with:
           promu_opts: "-p linux/amd64 -p windows/amd64 -p linux/arm64 -p darwin/amd64 -p darwin/arm64 -p linux/386"
@@ -40,7 +40,7 @@ jobs:
       image: quay.io/prometheus/golang-builder:1.23-base
     steps:
       - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
-      - uses: prometheus/promci@c3c93a50d581b928af720f0134b2b2dad32a6c41 # v0.4.6
+      - uses: prometheus/promci@3cb0c3871f223bd5ce1226995bd52ffb314798b6 # v0.1.0
       - uses: ./.github/promci/actions/setup_environment
       - run: make
       - run: git diff --exit-code
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index db6ddfc6..d7ef97f1 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -14,11 +14,11 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        thread: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
+        thread: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]
     needs: ci
     steps:
       - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
-      - uses: prometheus/promci@c3c93a50d581b928af720f0134b2b2dad32a6c41 # v0.4.6
+      - uses: prometheus/promci@3cb0c3871f223bd5ce1226995bd52ffb314798b6 # v0.1.0
       - uses: ./.github/promci/actions/build
         with:
           parallelism: 12
@@ -29,7 +29,7 @@ jobs:
     needs: build
     steps:
       - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
-      - uses: prometheus/promci@c3c93a50d581b928af720f0134b2b2dad32a6c41 # v0.4.6
+      - uses: prometheus/promci@3cb0c3871f223bd5ce1226995bd52ffb314798b6 # v0.1.0
       - uses: ./.github/promci/actions/publish_main
         with:
           docker_hub_login: ${{ secrets.docker_hub_login }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 91da7d11..01f31883 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -14,11 +14,11 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        thread: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
+        thread: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ]
     needs: ci
     steps:
       - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
-      - uses: prometheus/promci@c3c93a50d581b928af720f0134b2b2dad32a6c41 # v0.4.6
+      - uses: prometheus/promci@3cb0c3871f223bd5ce1226995bd52ffb314798b6 # v0.1.0
       - uses: ./.github/promci/actions/build
         with:
           parallelism: 12
@@ -29,7 +29,7 @@ jobs:
     needs: build
     steps:
       - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
-      - uses: prometheus/promci@c3c93a50d581b928af720f0134b2b2dad32a6c41 # v0.4.6
+      - uses: prometheus/promci@3cb0c3871f223bd5ce1226995bd52ffb314798b6 # v0.1.0
       - uses: ./.github/promci/actions/publish_release
         with:
           docker_hub_login: ${{ secrets.docker_hub_login }}
diff --git a/cli/root.go b/cli/root.go
index a3ee33b8..d424275f 100644
--- a/cli/root.go
+++ b/cli/root.go
@@ -52,6 +52,7 @@ var (
 func initMatchersCompat(_ *kingpin.ParseContext) error {
 	promslogConfig := &promslog.Config{Writer: os.Stdout}
 	if verbose {
+		promslogConfig.Level = &promslog.AllowedLevel{}
 		_ = promslogConfig.Level.Set("debug")
 	}
 	logger := promslog.New(promslogConfig)
@@ -155,7 +156,7 @@ func Execute() {
 	app.Flag("timeout", "Timeout for the executed command").Default("30s").DurationVar(&timeout)
 	app.Flag("http.config.file", "HTTP client configuration file for amtool to connect to Alertmanager.").PlaceHolder("<filename>").ExistingFileVar(&httpConfigFile)
 	app.Flag("version-check", "Check alertmanager version. Use --no-version-check to disable.").Default("true").BoolVar(&versionCheck)
-	app.Flag("enable-feature", fmt.Sprintf("Experimental features to enable, comma separated. Valid options: %s", strings.Join(featurecontrol.AllowedFlags, ", "))).Default("").StringVar(&featureFlags)
+	app.Flag("enable-feature", fmt.Sprintf("Experimental features to enable. The flag can be repeated to enable multiple features. Valid options: %s", strings.Join(featurecontrol.AllowedFlags, ", "))).Default("").StringVar(&featureFlags)
 
 	app.Version(version.Print("amtool"))
 	app.GetFlag("help").Short('h')
diff --git a/cmd/alertmanager/main.go b/cmd/alertmanager/main.go
index 87cdab8a..30b02447 100644
--- a/cmd/alertmanager/main.go
+++ b/cmd/alertmanager/main.go
@@ -176,7 +176,7 @@ func run() int {
 		tlsConfigFile          = kingpin.Flag("cluster.tls-config", "[EXPERIMENTAL] Path to config yaml file that can enable mutual TLS within the gossip protocol.").Default("").String()
 		allowInsecureAdvertise = kingpin.Flag("cluster.allow-insecure-public-advertise-address-discovery", "[EXPERIMENTAL] Allow alertmanager to discover and listen on a public IP address.").Bool()
 		label                  = kingpin.Flag("cluster.label", "The cluster label is an optional string to include on each packet and stream. It uniquely identifies the cluster and prevents cross-communication issues when sending gossip messages.").Default("").String()
-		featureFlags           = kingpin.Flag("enable-feature", fmt.Sprintf("Comma-separated experimental features to enable. Valid options: %s", strings.Join(featurecontrol.AllowedFlags, ", "))).Default("").String()
+		featureFlags           = kingpin.Flag("enable-feature", fmt.Sprintf("Experimental features to enable. The flag can be repeated to enable multiple features. Valid options: %s", strings.Join(featurecontrol.AllowedFlags, ", "))).Default("").String()
 	)
 
 	promslogflag.AddFlags(kingpin.CommandLine, &promslogConfig)
diff --git a/config/config.go b/config/config.go
index 6f54c523..b8e48413 100644
--- a/config/config.go
+++ b/config/config.go
@@ -968,7 +968,11 @@ type InhibitRule struct {
 	TargetMatchers Matchers `yaml:"target_matchers,omitempty" json:"target_matchers,omitempty"`
 	// A set of labels that must be equal between the source and target alert
 	// for them to be a match.
-	Equal []string `yaml:"equal,omitempty" json:"equal,omitempty"`
+	Equal model.LabelNames `yaml:"-" json:"-"`
+	// EqualStr allows us to validate the label depending on whether UTF-8 is
+	// enabled or disabled. It should be removed when Alertmanager is updated
+	// to use the validation modes in recent versions of prometheus/common.
+	EqualStr []string `yaml:"equal,omitempty" json:"equal,omitempty"`
 }
 
 // UnmarshalYAML implements the yaml.Unmarshaler interface for InhibitRule.
@@ -990,11 +994,12 @@ func (r *InhibitRule) UnmarshalYAML(unmarshal func(interface{}) error) error {
 		}
 	}
 
-	for _, l := range r.Equal {
+	for _, l := range r.EqualStr {
 		labelName := model.LabelName(l)
 		if !compat.IsValidLabelName(labelName) {
 			return fmt.Errorf("invalid label name %q in equal list", l)
 		}
+		r.Equal = append(r.Equal, labelName)
 	}
 
 	return nil
diff --git a/docs/configuration.md b/docs/configuration.md
index 6a7c6b9c..01b16a88 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -719,7 +719,7 @@ pagerduty_configs:
   [ - <pagerduty_config>, ... ]
 pushover_configs:
   [ - <pushover_config>, ... ]
-rocketchat_configs:
+rocket_configs:
   [ - <rocketchat_config>, ... ]
 slack_configs:
   [ - <slack_config>, ... ]
@@ -1361,7 +1361,7 @@ The fields are documented in the [Rocketchat API api models](https://github.com/
 [ msg: <tmpl_string> ]
 ```
 
-#### `<slack_config>`
+### `<slack_config>`
 
 Slack notifications can be sent via [Incoming webhooks](https://api.slack.com/messaging/webhooks) or [Bot tokens](https://api.slack.com/authentication/token-types).
 
diff --git a/inhibit/inhibit.go b/inhibit/inhibit.go
index 3650186e..eb1f7752 100644
--- a/inhibit/inhibit.go
+++ b/inhibit/inhibit.go
@@ -214,7 +214,7 @@ func NewInhibitRule(cr config.InhibitRule) *InhibitRule {
 
 	equal := map[model.LabelName]struct{}{}
 	for _, ln := range cr.Equal {
-		equal[model.LabelName(ln)] = struct{}{}
+		equal[ln] = struct{}{}
 	}
 
 	return &InhibitRule{
@@ -230,11 +230,10 @@ func NewInhibitRule(cr config.InhibitRule) *InhibitRule {
 // is returned. If excludeTwoSidedMatch is true, alerts that match both the
 // source and the target side of the rule are disregarded.
 func (r *InhibitRule) hasEqual(lset model.LabelSet, excludeTwoSidedMatch bool) (model.Fingerprint, bool) {
-	now := time.Now()
 Outer:
 	for _, a := range r.scache.List() {
 		// The cache might be stale and contain resolved alerts.
-		if a.ResolvedAt(now) {
+		if a.Resolved() {
 			continue
 		}
 		for n := range r.Equal {
diff --git a/notify/jira/jira.go b/notify/jira/jira.go
index 259a5e62..02c75295 100644
--- a/notify/jira/jira.go
+++ b/notify/jira/jira.go
@@ -87,7 +87,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
 		method = http.MethodPost
 	)
 
-	existingIssue, shouldRetry, err := n.searchExistingIssue(ctx, logger, key.Hash(), alerts.HasFiring(), tmplTextFunc)
+	existingIssue, shouldRetry, err := n.searchExistingIssue(ctx, logger, key.Hash(), alerts.HasFiring())
 	if err != nil {
 		return shouldRetry, fmt.Errorf("failed to look up existing issues: %w", err)
 	}
@@ -194,7 +194,7 @@ func (n *Notifier) prepareIssueRequestBody(ctx context.Context, logger *slog.Log
 	return requestBody, nil
 }
 
-func (n *Notifier) searchExistingIssue(ctx context.Context, logger *slog.Logger, groupID string, firing bool, tmplTextFunc templateFunc) (*issue, bool, error) {
+func (n *Notifier) searchExistingIssue(ctx context.Context, logger *slog.Logger, groupID string, firing bool) (*issue, bool, error) {
 	jql := strings.Builder{}
 
 	if n.conf.WontFixResolution != "" {
@@ -214,11 +214,7 @@ func (n *Notifier) searchExistingIssue(ctx context.Context, logger *slog.Logger,
 	}
 
 	alertLabel := fmt.Sprintf("ALERT{%s}", groupID)
-	project, err := tmplTextFunc(n.conf.Project)
-	if err != nil {
-		return nil, false, fmt.Errorf("invalid project template or value: %w", err)
-	}
-	jql.WriteString(fmt.Sprintf(`project=%q and labels=%q order by status ASC,resolutiondate DESC`, project, alertLabel))
+	jql.WriteString(fmt.Sprintf(`project=%q and labels=%q order by status ASC,resolutiondate DESC`, n.conf.Project, alertLabel))
 
 	requestBody := issueSearch{
 		JQL:        jql.String(),
diff --git a/notify/msteamsv2/msteamsv2.go b/notify/msteamsv2/msteamsv2.go
index f013bc3b..84f5d926 100644
--- a/notify/msteamsv2/msteamsv2.go
+++ b/notify/msteamsv2/msteamsv2.go
@@ -61,7 +61,7 @@ type Content struct {
 type Body struct {
 	Type   string `json:"type"`
 	Text   string `json:"text"`
-	Weight string `json:"weight,omitempty"`
+	Weight string `json:"weigth,omitempty"`
 	Size   string `json:"size,omitempty"`
 	Wrap   bool   `json:"wrap,omitempty"`
 	Style  string `json:"style,omitempty"`
@@ -170,7 +170,6 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
 						{
 							Type: "TextBlock",
 							Text: text,
-							Wrap: true,
 						},
 					},
 					Msteams: Msteams{
diff --git a/notify/opsgenie/api_key_file b/notify/opsgenie/api_key_file
deleted file mode 100644
index 90d2bb3b..00000000
--- a/notify/opsgenie/api_key_file
+++ /dev/null
@@ -1,2 +0,0 @@
-my_secret_api_key
-
diff --git a/notify/opsgenie/opsgenie.go b/notify/opsgenie/opsgenie.go
index 54c0e245..75549846 100644
--- a/notify/opsgenie/opsgenie.go
+++ b/notify/opsgenie/opsgenie.go
@@ -282,7 +282,6 @@ func (n *Notifier) createRequests(ctx context.Context, as ...*types.Alert) ([]*h
 			return nil, false, fmt.Errorf("read key_file error: %w", err)
 		}
 		apiKey = tmpl(string(content))
-		apiKey = strings.TrimSpace(string(apiKey))
 	}
 
 	if err != nil {
diff --git a/notify/rocketchat/rocketchat.go b/notify/rocketchat/rocketchat.go
index ec225bd0..8f5b3ef8 100644
--- a/notify/rocketchat/rocketchat.go
+++ b/notify/rocketchat/rocketchat.go
@@ -202,7 +202,7 @@ func (n *Notifier) Notify(ctx context.Context, as ...*types.Alert) (bool, error)
 	}
 
 	body := &PostMessage{
-		Channel:     tmplText(n.conf.Channel),
+		Channel:     n.conf.Channel,
 		Emoji:       tmplText(n.conf.Emoji),
 		Avatar:      tmplText(n.conf.IconURL),
 		Attachments: []Attachment{*att},


Test patch:
diff --git a/config/config_test.go b/config/config_test.go
index 728d7670..99984827 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -1461,7 +1461,7 @@ func TestInhibitRuleEqual(t *testing.T) {
 	// The inhibition rule should have the expected equal labels.
 	require.Len(t, c.InhibitRules, 1)
 	r := c.InhibitRules[0]
-	require.Equal(t, []string{"qux", "corge"}, r.Equal)
+	require.Equal(t, model.LabelNames{"qux", "corge"}, r.Equal)
 
 	// Should not be able to load configuration with UTF-8 in equals list.
 	_, err = LoadFile("testdata/conf.inhibit-equal-utf8.yml")
@@ -1484,7 +1484,7 @@ func TestInhibitRuleEqual(t *testing.T) {
 	// The inhibition rule should have the expected equal labels.
 	require.Len(t, c.InhibitRules, 1)
 	r = c.InhibitRules[0]
-	require.Equal(t, []string{"qux", "corge"}, r.Equal)
+	require.Equal(t, model.LabelNames{"qux", "corge"}, r.Equal)
 
 	// Should also be able to load configuration with UTF-8 in equals list.
 	c, err = LoadFile("testdata/conf.inhibit-equal-utf8.yml")
@@ -1493,5 +1493,5 @@ func TestInhibitRuleEqual(t *testing.T) {
 	// The inhibition rule should have the expected equal labels.
 	require.Len(t, c.InhibitRules, 1)
 	r = c.InhibitRules[0]
-	require.Equal(t, []string{"qux🙂", "corge"}, r.Equal)
+	require.Equal(t, model.LabelNames{"qux🙂", "corge"}, r.Equal)
 }
diff --git a/inhibit/inhibit_test.go b/inhibit/inhibit_test.go
index 59ff52b1..1f6f4ef2 100644
--- a/inhibit/inhibit_test.go
+++ b/inhibit/inhibit_test.go
@@ -144,12 +144,12 @@ func TestInhibitRuleMatches(t *testing.T) {
 	rule1 := config.InhibitRule{
 		SourceMatch: map[string]string{"s1": "1"},
 		TargetMatch: map[string]string{"t1": "1"},
-		Equal:       []string{"e"},
+		Equal:       model.LabelNames{"e"},
 	}
 	rule2 := config.InhibitRule{
 		SourceMatch: map[string]string{"s2": "1"},
 		TargetMatch: map[string]string{"t2": "1"},
-		Equal:       []string{"e"},
+		Equal:       model.LabelNames{"e"},
 	}
 
 	m := types.NewMarker(prometheus.NewRegistry())
@@ -240,12 +240,12 @@ func TestInhibitRuleMatchers(t *testing.T) {
 	rule1 := config.InhibitRule{
 		SourceMatchers: config.Matchers{&labels.Matcher{Type: labels.MatchEqual, Name: "s1", Value: "1"}},
 		TargetMatchers: config.Matchers{&labels.Matcher{Type: labels.MatchNotEqual, Name: "t1", Value: "1"}},
-		Equal:          []string{"e"},
+		Equal:          model.LabelNames{"e"},
 	}
 	rule2 := config.InhibitRule{
 		SourceMatchers: config.Matchers{&labels.Matcher{Type: labels.MatchEqual, Name: "s2", Value: "1"}},
 		TargetMatchers: config.Matchers{&labels.Matcher{Type: labels.MatchEqual, Name: "t2", Value: "1"}},
-		Equal:          []string{"e"},
+		Equal:          model.LabelNames{"e"},
 	}
 
 	m := types.NewMarker(prometheus.NewRegistry())
@@ -374,7 +374,7 @@ func TestInhibit(t *testing.T) {
 		return config.InhibitRule{
 			SourceMatch: map[string]string{"s": "1"},
 			TargetMatch: map[string]string{"t": "1"},
-			Equal:       []string{"e"},
+			Equal:       model.LabelNames{"e"},
 		}
 	}
 	// alertOne is muted by alertTwo when it is active.
diff --git a/notify/jira/jira_test.go b/notify/jira/jira_test.go
index 9b5868aa..1c728b6c 100644
--- a/notify/jira/jira_test.go
+++ b/notify/jira/jira_test.go
@@ -62,104 +62,6 @@ func TestJiraRetry(t *testing.T) {
 	}
 }
 
-func TestSearchExistingIssue(t *testing.T) {
-	expectedJQL := ""
-	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
-		switch r.URL.Path {
-		case "/search":
-			body, err := io.ReadAll(r.Body)
-			if err != nil {
-				http.Error(w, "Error reading request body", http.StatusBadRequest)
-				return
-			}
-			defer r.Body.Close()
-
-			// Unmarshal the JSON data into the struct
-			var data issueSearch
-			err = json.Unmarshal(body, &data)
-			if err != nil {
-				http.Error(w, "Error unmarshaling JSON", http.StatusBadRequest)
-				return
-			}
-			require.Equal(t, expectedJQL, data.JQL)
-			w.Write([]byte(`{"total": 0, "issues": []}`))
-			return
-		default:
-			dec := json.NewDecoder(r.Body)
-			out := make(map[string]any)
-			err := dec.Decode(&out)
-			if err != nil {
-				panic(err)
-			}
-		}
-	}))
-
-	defer srv.Close()
-	u, _ := url.Parse(srv.URL)
-
-	for _, tc := range []struct {
-		title         string
-		cfg           *config.JiraConfig
-		groupKey      string
-		expectedJQL   string
-		expectedIssue *issue
-		expectedErr   bool
-		expectedRetry bool
-	}{
-		{
-			title: "search existing issue with project template",
-			cfg: &config.JiraConfig{
-				Summary:     `{{ template "jira.default.summary" . }}`,
-				Description: `{{ template "jira.default.description" . }}`,
-				Project:     `{{ .CommonLabels.project }}`,
-			},
-			groupKey:    "1",
-			expectedJQL: `statusCategory != Done and project="PROJ" and labels="ALERT{1}" order by status ASC,resolutiondate DESC`,
-		},
-	} {
-		tc := tc
-		t.Run(tc.title, func(t *testing.T) {
-			expectedJQL = tc.expectedJQL
-			tc.cfg.APIURL = &config.URL{URL: u}
-			tc.cfg.HTTPConfig = &commoncfg.HTTPClientConfig{}
-
-			as := []*types.Alert{
-				{
-					Alert: model.Alert{
-						Labels: model.LabelSet{
-							"project": "PROJ",
-						},
-						StartsAt: time.Now(),
-						EndsAt:   time.Now().Add(time.Hour),
-					},
-				},
-			}
-
-			pd, err := New(tc.cfg, test.CreateTmpl(t), promslog.NewNopLogger())
-			require.NoError(t, err)
-			logger := pd.logger.With("group_key", tc.groupKey)
-
-			ctx := notify.WithGroupKey(context.Background(), tc.groupKey)
-			data := notify.GetTemplateData(ctx, pd.tmpl, as, logger)
-
-			var tmplTextErr error
-			tmplText := notify.TmplText(pd.tmpl, data, &tmplTextErr)
-			tmplTextFunc := func(tmpl string) (string, error) {
-				return tmplText(tmpl), tmplTextErr
-			}
-
-			issue, retry, err := pd.searchExistingIssue(ctx, logger, tc.groupKey, true, tmplTextFunc)
-			if tc.expectedErr {
-				require.Error(t, err)
-			} else {
-				require.NoError(t, err)
-			}
-			require.EqualValues(t, tc.expectedIssue, issue)
-			require.Equal(t, tc.expectedRetry, retry)
-		})
-	}
-}
-
 func TestJiraTemplating(t *testing.T) {
 	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 		switch r.URL.Path {
diff --git a/notify/opsgenie/opsgenie_test.go b/notify/opsgenie/opsgenie_test.go
index c6d70047..9db635d1 100644
--- a/notify/opsgenie/opsgenie_test.go
+++ b/notify/opsgenie/opsgenie_test.go
@@ -321,25 +321,6 @@ func TestOpsGenieWithUpdate(t *testing.T) {
 `, body2)
 }
 
-func TestOpsGenieApiKeyFile(t *testing.T) {
-	u, err := url.Parse("https://test-opsgenie-url")
-	require.NoError(t, err)
-	tmpl := test.CreateTmpl(t)
-	ctx := context.Background()
-	ctx = notify.WithGroupKey(ctx, "1")
-	opsGenieConfigWithUpdate := config.OpsGenieConfig{
-		APIKeyFile: `./api_key_file`,
-		APIURL:     &config.URL{URL: u},
-		HTTPConfig: &commoncfg.HTTPClientConfig{},
-	}
-	notifierWithUpdate, err := New(&opsGenieConfigWithUpdate, tmpl, promslog.NewNopLogger())
-
-	require.NoError(t, err)
-	requests, _, err := notifierWithUpdate.createRequests(ctx)
-	require.NoError(t, err)
-	require.Equal(t, "GenieKey my_secret_api_key", requests[0].Header.Get("Authorization"))
-}
-
 func readBody(t *testing.T, r *http.Request) string {
 	t.Helper()
 	body, err := io.ReadAll(r.Body)