Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package
golang-github-prometheus-alertmanager for openSUSE:Factory checked in at
2026-06-10 17:37:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/golang-github-prometheus-alertmanager (Old)
and
/work/SRC/openSUSE:Factory/.golang-github-prometheus-alertmanager.new.2375 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "golang-github-prometheus-alertmanager"
Wed Jun 10 17:37:04 2026 rev:34 rq:1358570 version:0.32.2
Changes:
--------
---
/work/SRC/openSUSE:Factory/golang-github-prometheus-alertmanager/golang-github-prometheus-alertmanager.changes
2026-05-08 16:44:13.434309000 +0200
+++
/work/SRC/openSUSE:Factory/.golang-github-prometheus-alertmanager.new.2375/golang-github-prometheus-alertmanager.changes
2026-06-10 17:37:07.011140698 +0200
@@ -1,0 +2,7 @@
+Mon Jun 8 05:28:42 UTC 2026 - Johannes Kastl
<[email protected]>
+
+- update to 0.32.2:
+ * [BUGFIX] Fix dispatcher goroutine leaks on destroyed alertgroup
+ swap. #5241
+
+-------------------------------------------------------------------
Old:
----
alertmanager-0.32.1.tar.gz
ui-0.32.1.tar.gz
New:
----
alertmanager-0.32.2.tar.gz
ui-0.32.2.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ golang-github-prometheus-alertmanager.spec ++++++
--- /var/tmp/diff_new_pack.0pYgZO/_old 2026-06-10 17:37:08.671209478 +0200
+++ /var/tmp/diff_new_pack.0pYgZO/_new 2026-06-10 17:37:08.679209810 +0200
@@ -17,7 +17,7 @@
Name: golang-github-prometheus-alertmanager
-Version: 0.32.1
+Version: 0.32.2
Release: 0
Summary: Prometheus Alertmanager
License: Apache-2.0
++++++ PACKAGING_README.md ++++++
--- /var/tmp/diff_new_pack.0pYgZO/_old 2026-06-10 17:37:08.747212627 +0200
+++ /var/tmp/diff_new_pack.0pYgZO/_new 2026-06-10 17:37:08.751212793 +0200
@@ -6,7 +6,7 @@
locally. For the OBS workflow you also need `obs-service-go_modules` as well
as
`obs-service-download_files`.
-1. Change the version in the `_service` file
+1. Change the version in the `spec` file
2. Run `make`
3. Create a changelog entry
4. Commit the changes as usual
++++++ alertmanager-0.32.1.tar.gz -> alertmanager-0.32.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/alertmanager-0.32.1/CHANGELOG.md
new/alertmanager-0.32.2/CHANGELOG.md
--- old/alertmanager-0.32.1/CHANGELOG.md 2026-04-29 19:28:46.000000000
+0200
+++ new/alertmanager-0.32.2/CHANGELOG.md 2026-06-05 17:49:12.000000000
+0200
@@ -4,6 +4,10 @@
* [FEATURE] ...
* [ENHANCEMENT] ...
+## 0.32.2 / 2026-05-25
+
+* [BUGFIX] Fix dispatcher goroutine leaks on destroyed alertgroup swap. #5241
+
## 0.32.1 / 2026-04-29
* [BUGFIX] dispatcher: Fix issue with dispatching to a contended route. #5179
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/alertmanager-0.32.1/VERSION
new/alertmanager-0.32.2/VERSION
--- old/alertmanager-0.32.1/VERSION 2026-04-29 19:28:46.000000000 +0200
+++ new/alertmanager-0.32.2/VERSION 2026-06-05 17:49:12.000000000 +0200
@@ -1 +1 @@
-0.32.1
+0.32.2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/alertmanager-0.32.1/dispatch/dispatch.go
new/alertmanager-0.32.2/dispatch/dispatch.go
--- old/alertmanager-0.32.1/dispatch/dispatch.go 2026-04-29
19:28:46.000000000 +0200
+++ new/alertmanager-0.32.2/dispatch/dispatch.go 2026-06-05
17:49:12.000000000 +0200
@@ -317,9 +317,14 @@
ag := el.(*aggrGroup)
if ag.destroyed() {
ag.stop()
- d.marker.DeleteByGroupKey(ag.routeID,
ag.GroupKey())
deleted :=
d.routeGroupsSlice[i].groups.CompareAndDelete(ag.fingerprint(), ag)
if deleted {
+ // TODO(ultrotter, siavash):
+ // Deletion from the marker should only
happen if we really deleted the group.
+ // Fully fixing the case where a new
group with the same fingerprint is created between
+ // CompareAndDelete and
DeleteByGroupKey would require changes to the marker interface,
+ // so we leave it as a fix for after
landing the pending marker changes.
+ d.marker.DeleteByGroupKey(ag.routeID,
ag.GroupKey())
d.routeGroupsSlice[i].groupsLen.Add(-1)
d.aggrGroupsNum.Add(-1)
d.metrics.aggrGroups.Set(float64(d.aggrGroupsNum.Load()))
@@ -516,6 +521,9 @@
// Try to store the new group in the map. If another
goroutine has already created the same group, use the existing one.
swapped :=
d.routeGroupsSlice[route.Idx].groups.CompareAndSwap(fp, el, ag)
if swapped {
+ // Since we swapped the new group in, we need
to cancel the old one,
+ // as doMaintenance will not be able to find it
in the map anymore.
+ el.(*aggrGroup).cancel()
// We swapped the new group in, we can break
and start it.
break
}
@@ -735,6 +743,11 @@
cancel()
+ // If destroyed, exit: this particular alert group
won't be used anymore.
+ if ag.destroyed() {
+ return
+ }
+
case <-ag.ctx.Done():
return
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/alertmanager-0.32.1/dispatch/dispatch_test.go
new/alertmanager-0.32.2/dispatch/dispatch_test.go
--- old/alertmanager-0.32.1/dispatch/dispatch_test.go 2026-04-29
19:28:46.000000000 +0200
+++ new/alertmanager-0.32.2/dispatch/dispatch_test.go 2026-06-05
17:49:12.000000000 +0200
@@ -899,6 +899,66 @@
require.Positive(t,
testutil.ToFloat64(metrics.aggrGroupCreationRetries), "contended CAS path was
not exercised in %d rounds — scheduler is unusually serial", rounds)
}
+// TestGroupAlert_DisplacedAggrGroupGoroutineExits is a regression test for a
+// goroutine leak: when groupAlert CAS-replaces a destroyed aggrGroup in the
+// map, the displaced group's run goroutine must be torn down. Otherwise it
+// stays parked in its select forever (doMaintenance can no longer find it
+// because it's been removed from the map), accumulating one stuck goroutine
+// per replacement for the lifetime of the process.
+func TestGroupAlert_DisplacedAggrGroupGoroutineExits(t *testing.T) {
+ logger := promslog.NewNopLogger()
+ reg := prometheus.NewRegistry()
+ marker := types.NewMarker(reg)
+ alerts, err := mem.NewAlerts(context.Background(), marker, time.Hour,
0, nil, logger, reg, nil)
+ require.NoError(t, err)
+ defer alerts.Close()
+
+ route := &Route{
+ RouteOpts: RouteOpts{
+ Receiver: "test",
+ GroupBy:
map[model.LabelName]struct{}{"alertname": {}},
+ GroupWait: time.Hour, // never auto-flush during
the test
+ GroupInterval: time.Hour,
+ RepeatInterval: time.Hour,
+ },
+ Idx: 0,
+ }
+ timeout := func(d time.Duration) time.Duration { return d }
+ recorder := &recordStage{alerts:
make(map[string]map[model.Fingerprint]*types.Alert)}
+ dispatcher := NewDispatcher(alerts, route, recorder, marker, timeout,
testMaintenanceInterval, nil, logger, NewDispatcherMetrics(false, reg))
+ dispatcher.routeGroupsSlice = []routeAggrGroups{{route: route}}
+ // WaitingToStart so groupAlert won't auto-start the new ag — keeps the
+ // test focused on the displaced group.
+ dispatcher.state.Store(DispatcherStateWaitingToStart)
+
+ groupLabels := model.LabelSet{"alertname": "displaced"}
+ displaced := newAggrGroup(context.Background(), groupLabels, route,
timeout, marker, logger)
+ // Mark destroyed so groupAlert can't insert into it and is forced down
+ // the CAS-replace path.
+ require.NoError(t,
displaced.alerts.DeleteIfNotModified(types.AlertSlice{}, true))
+ require.True(t, displaced.destroyed())
+ dispatcher.routeGroupsSlice[0].groups.Store(displaced.fingerprint(),
displaced)
+
+ // Start the run goroutine on the displaced group — this is the orphan
+ // candidate. Without the fix it would never exit.
+ go displaced.run(func(context.Context, ...*types.Alert) bool { return
true })
+
+ // Trigger the CAS replacement.
+ dispatcher.groupAlert(context.Background(), newAlert(groupLabels),
route)
+
+ // The displaced group should have been swapped out for a fresh one.
+ el, ok :=
dispatcher.routeGroupsSlice[0].groups.Load(displaced.fingerprint())
+ require.True(t, ok)
+ require.NotSame(t, displaced, el.(*aggrGroup), "destroyed group must
have been replaced")
+
+ // And its run goroutine must have exited.
+ select {
+ case <-displaced.done:
+ case <-time.After(2 * time.Second):
+ t.Fatal("displaced aggrGroup.run goroutine did not exit after
CAS replacement")
+ }
+}
+
func TestDispatcher_DeleteResolvedAlertsFromMarker(t *testing.T) {
t.Run("successful flush deletes markers for resolved alerts", func(t
*testing.T) {
ctx := context.Background()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/alertmanager-0.32.1/notify/email/email_test.go
new/alertmanager-0.32.2/notify/email/email_test.go
--- old/alertmanager-0.32.1/notify/email/email_test.go 2026-04-29
19:28:46.000000000 +0200
+++ new/alertmanager-0.32.2/notify/email/email_test.go 2026-06-05
17:49:12.000000000 +0200
@@ -575,7 +575,7 @@
cfg.Hello = "invalid hello string"
},
- errMsg: "501 Error",
+ errMsg: "501",
retry: true,
},
} {
@@ -733,7 +733,8 @@
// Send the alert to mock SMTP server.
retry, err := e.Notify(context.Background(), firingAlert)
- require.ErrorContains(t, err, "501 5.5.4 Rejected!")
+ require.ErrorContains(t, err, "501")
+ require.ErrorContains(t, err, "5.5.4")
require.True(t, retry)
require.NoError(t, srv.Shutdown(ctx))
++++++ ui-0.32.1.tar.gz -> ui-0.32.2.tar.gz ++++++
++++++ vendor.tar.gz ++++++