diff --git a/pkg/services/ngalert/store/alert_rule.go b/pkg/services/ngalert/store/alert_rule.go index 4a50990c5c1..77d432ddc78 100644 --- a/pkg/services/ngalert/store/alert_rule.go +++ b/pkg/services/ngalert/store/alert_rule.go @@ -329,7 +329,13 @@ func (st DBstore) UpdateAlertRules(ctx context.Context, user *ngmodels.UserUID, v := alertRuleToAlertRuleVersion(converted) v.Version++ v.ParentVersion = r.Existing.Version - ruleVersions = append(ruleVersions, v) + + // check if there is diff between existing and new, and if no, skip saving version. + existingConverted, err := alertRuleFromModelsAlertRule(*r.Existing) + if err != nil || !alertRuleToAlertRuleVersion(existingConverted).EqualSpec(v) { + ruleVersions = append(ruleVersions, v) + } + keys = append(keys, ngmodels.AlertRuleKey{OrgID: r.New.OrgID, UID: r.New.UID}) } if len(ruleVersions) > 0 { diff --git a/pkg/services/ngalert/store/alert_rule_test.go b/pkg/services/ngalert/store/alert_rule_test.go index 0eba646ab46..e5d5e77f483 100644 --- a/pkg/services/ngalert/store/alert_rule_test.go +++ b/pkg/services/ngalert/store/alert_rule_test.go @@ -73,6 +73,16 @@ func TestIntegrationUpdateAlertRules(t *testing.T) { require.NoError(t, err) require.Equal(t, rule.Version+1, dbrule.Version) + + t.Run("should create version record", func(t *testing.T) { + var count int64 + err = sqlStore.WithDbSession(context.Background(), func(sess *db.Session) error { + count, err = sess.Table(alertRuleVersion{}).Where("rule_uid = ?", rule.UID).Count() + return err + }) + require.NoError(t, err) + require.EqualValues(t, 1, count) // only the current version, insert did not create version. + }) }) t.Run("updating record field should increase version", func(t *testing.T) { @@ -191,6 +201,32 @@ func TestIntegrationUpdateAlertRules(t *testing.T) { assert.Nil(t, dbrule.UpdatedBy) }) }) + + t.Run("should save noop update", func(t *testing.T) { + rule := createRule(t, store, gen) + newRule := models.CopyRule(rule) + err := store.UpdateAlertRules(context.Background(), &usr, []models.UpdateRule{{ + Existing: rule, + New: *newRule, + }, + }) + require.NoError(t, err) + + newRule, err = store.GetAlertRuleByUID(context.Background(), &models.GetAlertRuleByUIDQuery{UID: rule.UID}) + require.NoError(t, err) + + assert.Equal(t, rule.Version+1, newRule.Version) + + t.Run("should not create version record", func(t *testing.T) { + var count int64 + err = sqlStore.WithDbSession(context.Background(), func(sess *db.Session) error { + count, err = sess.Table(alertRuleVersion{}).Where("rule_uid = ?", rule.UID).Count() + return err + }) + require.NoError(t, err) + require.EqualValues(t, 1, count) // only the current version + }) + }) } func TestIntegrationUpdateAlertRulesWithUniqueConstraintViolation(t *testing.T) {