Repository: favonia/cloudflare-ddns (go)

Issue:
Add Cloudflare comments to updated records
Would be cool if we could add text to the Cloudflare comment field for the updated record.
Preferable if the comment can be personalised.

Pull request:
feat(api): make record comment configurable
(Fully) close #715.

BREAKING CHANGE: the record comment was always "Created by cloudflare-ddns", but now the default record comment is empty despite being configurable.

Patch:
diff --git a/README.markdown b/README.markdown
index b6af86f..a229a97 100644
--- a/README.markdown
+++ b/README.markdown
@@ -309,12 +309,13 @@ _(Click to expand the following items.)_
 <details>
 <summary>🐣 Parameters of new DNS records</summary>
 
-> 👉 The updater will preserve existing proxy and TTL settings until it has to create new DNS records (or recreate deleted ones). Only when it creates DNS records, the above settings will apply. To change existing proxy and TTL settings now, you can go to your [Cloudflare Dashboard](https://dash.cloudflare.com) and change them directly. If you think you have a use case where the updater should actively overwrite existing proxy and TTL settings in addition to IP addresses, please [let me know](https://github.com/favonia/cloudflare-ddns/issues/new). It is not hard to implement optional overwriting.
+> 👉 The updater will preserve existing proxy and TTL settings and other record parameters unless it has to create new DNS records (or recreate deleted ones). Only when it creates DNS records, the following settings will apply. To change existing record parameters now, you can go to your [Cloudflare Dashboard](https://dash.cloudflare.com) and change them directly. If you think you have a use case where the updater should actively overwrite existing record parameters in addition to IP addresses, please [let me know](https://github.com/favonia/cloudflare-ddns/issues/new).
 
-| Name      | Valid Values                                                                                                                                                                             | Meaning                                                 | Required? | Default Value                              |
-| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | --------- | ------------------------------------------ |
-| `PROXIED` | Boolean values, such as `true`, `false`, `0` and `1`. See [strconv.ParseBool](https://pkg.go.dev/strconv#ParseBool). 🧪 See below for experimental support of per-domain proxy settings. | Whether new DNS records should be proxied by Cloudflare | No        | `false`                                    |
-| `TTL`     | Time-to-live (TTL) values in seconds                                                                                                                                                     | The TTL values used to create new DNS records           | No        | `1` (This means “automatic” to Cloudflare) |
+| Name             | Valid Values                                                                                                                                                                             | Meaning                                                                                                                                    | Required? | Default Value                              |
+| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | --------- | ------------------------------------------ |
+| `PROXIED`        | Boolean values, such as `true`, `false`, `0` and `1`. See [strconv.ParseBool](https://pkg.go.dev/strconv#ParseBool). 🧪 See below for experimental support of per-domain proxy settings. | Whether new DNS records should be proxied by Cloudflare                                                                                    | No        | `false`                                    |
+| `TTL`            | Time-to-live (TTL) values in seconds                                                                                                                                                     | The TTL values used to create new DNS records                                                                                              | No        | `1` (This means “automatic” to Cloudflare) |
+| `RECORD_COMMENT` | Strings (that consist of only [Unicode graphic characters](https://en.wikipedia.org/wiki/Graphic_character))                                                                             | The [record comment](https://developers.cloudflare.com/dns/manage-dns-records/reference/record-attributes/) used to create new DNS records | No        | `""`                                       |
 
 > <details>
 > <summary>🧪 Experimental per-domain proxy settings (subject to changes):</summary>
diff --git a/internal/api/base.go b/internal/api/base.go
index 084889f..0d93f9e 100644
--- a/internal/api/base.go
+++ b/internal/api/base.go
@@ -26,7 +26,7 @@ type Handle interface {
 
 	// CreateRecord creates one DNS record.
 	CreateRecord(ctx context.Context, ppfmt pp.PP, domain domain.Domain, ipNet ipnet.Type,
-		ip netip.Addr, ttl TTL, proxied bool) (string, bool)
+		ip netip.Addr, ttl TTL, proxied bool, recordComment string) (string, bool)
 
 	// FlushCache flushes the API cache. Flushing should automatically happen when other operations encounter errors.
 	FlushCache()
diff --git a/internal/api/cloudflare.go b/internal/api/cloudflare.go
index 23e0e5a..871f094 100644
--- a/internal/api/cloudflare.go
+++ b/internal/api/cloudflare.go
@@ -272,7 +272,7 @@ func (h *CloudflareHandle) UpdateRecord(ctx context.Context, ppfmt pp.PP,
 
 // CreateRecord creates one DNS record.
 func (h *CloudflareHandle) CreateRecord(ctx context.Context, ppfmt pp.PP,
-	domain domain.Domain, ipNet ipnet.Type, ip netip.Addr, ttl TTL, proxied bool,
+	domain domain.Domain, ipNet ipnet.Type, ip netip.Addr, ttl TTL, proxied bool, recordComment string,
 ) (string, bool) {
 	zone, ok := h.ZoneOfDomain(ctx, ppfmt, domain)
 	if !ok {
@@ -286,7 +286,7 @@ func (h *CloudflareHandle) CreateRecord(ctx context.Context, ppfmt pp.PP,
 		Content: ip.String(),
 		TTL:     ttl.Int(),
 		Proxied: &proxied,
-		Comment: "Created by cloudflare-ddns",
+		Comment: recordComment,
 	}
 
 	res, err := h.cf.CreateDNSRecord(ctx, cloudflare.ZoneIdentifier(zone), params)
diff --git a/internal/config/config.go b/internal/config/config.go
index 0734dc8..757862f 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -27,6 +27,7 @@ type Config struct {
 	TTL              api.TTL
 	ProxiedTemplate  string
 	Proxied          map[domain.Domain]bool
+	RecordComment    string
 	DetectionTimeout time.Duration
 	UpdateTimeout    time.Duration
 	Monitors         []monitor.Monitor
@@ -53,6 +54,7 @@ func Default() *Config {
 		TTL:              api.TTLAuto,
 		ProxiedTemplate:  "false",
 		Proxied:          map[domain.Domain]bool{},
+		RecordComment:    "",
 		UpdateTimeout:    time.Second * 30, //nolint:mnd
 		DetectionTimeout: time.Second * 5,  //nolint:mnd
 		Monitors:         nil,
diff --git a/internal/config/config_print.go b/internal/config/config_print.go
index 4094790..f0805da 100644
--- a/internal/config/config_print.go
+++ b/internal/config/config_print.go
@@ -3,6 +3,7 @@ package config
 
 import (
 	"fmt"
+	"strconv"
 	"strings"
 	"time"
 
@@ -17,6 +18,13 @@ import (
 
 const itemTitleWidth = 24
 
+func describeComment(c string) string {
+	if c == "" {
+		return "(empty)"
+	}
+	return strconv.Quote(c)
+}
+
 func describeDomains(domains []domain.Domain) string {
 	if len(domains) == 0 {
 		return "(none)"
@@ -79,11 +87,12 @@ func (c *Config) Print(ppfmt pp.PP) {
 
 	section("New DNS records:")
 	item("TTL:", "%s", c.TTL.Describe())
-	if len(c.Proxied) > 0 {
+	{
 		_, inverseMap := getInverseMap(c.Proxied)
 		item("Proxied domains:", "%s", describeDomains(inverseMap[true]))
 		item("Unproxied domains:", "%s", describeDomains(inverseMap[false]))
 	}
+	item("Record comment:", "%s", describeComment(c.RecordComment))
 
 	section("Timeouts:")
 	item("IP detection:", "%v", c.DetectionTimeout)
diff --git a/internal/config/config_read.go b/internal/config/config_read.go
index bfd19e5..c78c26a 100644
--- a/internal/config/config_read.go
+++ b/internal/config/config_read.go
@@ -26,6 +26,7 @@ func (c *Config) ReadEnv(ppfmt pp.PP) bool {
 		!ReadNonnegDuration(ppfmt, "CACHE_EXPIRATION", &c.CacheExpiration) ||
 		!ReadTTL(ppfmt, "TTL", &c.TTL) ||
 		!ReadString(ppfmt, "PROXIED", &c.ProxiedTemplate) ||
+		!ReadString(ppfmt, "RECORD_COMMENT", &c.RecordComment) ||
 		!ReadNonnegDuration(ppfmt, "DETECTION_TIMEOUT", &c.DetectionTimeout) ||
 		!ReadNonnegDuration(ppfmt, "UPDATE_TIMEOUT", &c.UpdateTimeout) ||
 		!ReadAndAppendHealthchecksURL(ppfmt, "HEALTHCHECKS", &c.Monitors) ||
diff --git a/internal/mocks/mock_api.go b/internal/mocks/mock_api.go
index 5c90de5..ccb26f4 100644
--- a/internal/mocks/mock_api.go
+++ b/internal/mocks/mock_api.go
@@ -44,18 +44,18 @@ func (m *MockHandle) EXPECT() *MockHandleMockRecorder {
 }
 
 // CreateRecord mocks base method.
-func (m *MockHandle) CreateRecord(arg0 context.Context, arg1 pp.PP, arg2 domain.Domain, arg3 ipnet.Type, arg4 netip.Addr, arg5 api.TTL, arg6 bool) (string, bool) {
+func (m *MockHandle) CreateRecord(arg0 context.Context, arg1 pp.PP, arg2 domain.Domain, arg3 ipnet.Type, arg4 netip.Addr, arg5 api.TTL, arg6 bool, arg7 string) (string, bool) {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "CreateRecord", arg0, arg1, arg2, arg3, arg4, arg5, arg6)
+	ret := m.ctrl.Call(m, "CreateRecord", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
 	ret0, _ := ret[0].(string)
 	ret1, _ := ret[1].(bool)
 	return ret0, ret1
 }
 
 // CreateRecord indicates an expected call of CreateRecord.
-func (mr *MockHandleMockRecorder) CreateRecord(arg0, arg1, arg2, arg3, arg4, arg5, arg6 any) *HandleCreateRecordCall {
+func (mr *MockHandleMockRecorder) CreateRecord(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 any) *HandleCreateRecordCall {
 	mr.mock.ctrl.T.Helper()
-	call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateRecord", reflect.TypeOf((*MockHandle)(nil).CreateRecord), arg0, arg1, arg2, arg3, arg4, arg5, arg6)
+	call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateRecord", reflect.TypeOf((*MockHandle)(nil).CreateRecord), arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
 	return &HandleCreateRecordCall{Call: call}
 }
 
@@ -71,13 +71,13 @@ func (c *HandleCreateRecordCall) Return(arg0 string, arg1 bool) *HandleCreateRec
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *HandleCreateRecordCall) Do(f func(context.Context, pp.PP, domain.Domain, ipnet.Type, netip.Addr, api.TTL, bool) (string, bool)) *HandleCreateRecordCall {
+func (c *HandleCreateRecordCall) Do(f func(context.Context, pp.PP, domain.Domain, ipnet.Type, netip.Addr, api.TTL, bool, string) (string, bool)) *HandleCreateRecordCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *HandleCreateRecordCall) DoAndReturn(f func(context.Context, pp.PP, domain.Domain, ipnet.Type, netip.Addr, api.TTL, bool) (string, bool)) *HandleCreateRecordCall {
+func (c *HandleCreateRecordCall) DoAndReturn(f func(context.Context, pp.PP, domain.Domain, ipnet.Type, netip.Addr, api.TTL, bool, string) (string, bool)) *HandleCreateRecordCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
diff --git a/internal/mocks/mock_setter.go b/internal/mocks/mock_setter.go
index 2b21ad6..5b1995c 100644
--- a/internal/mocks/mock_setter.go
+++ b/internal/mocks/mock_setter.go
@@ -83,17 +83,17 @@ func (c *SetterDeleteCall) DoAndReturn(f func(context.Context, pp.PP, domain.Dom
 }
 
 // Set mocks base method.
-func (m *MockSetter) Set(arg0 context.Context, arg1 pp.PP, arg2 domain.Domain, arg3 ipnet.Type, arg4 netip.Addr, arg5 api.TTL, arg6 bool) setter.ResponseCode {
+func (m *MockSetter) Set(arg0 context.Context, arg1 pp.PP, arg2 domain.Domain, arg3 ipnet.Type, arg4 netip.Addr, arg5 api.TTL, arg6 bool, arg7 string) setter.ResponseCode {
 	m.ctrl.T.Helper()
-	ret := m.ctrl.Call(m, "Set", arg0, arg1, arg2, arg3, arg4, arg5, arg6)
+	ret := m.ctrl.Call(m, "Set", arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
 	ret0, _ := ret[0].(setter.ResponseCode)
 	return ret0
 }
 
 // Set indicates an expected call of Set.
-func (mr *MockSetterMockRecorder) Set(arg0, arg1, arg2, arg3, arg4, arg5, arg6 any) *SetterSetCall {
+func (mr *MockSetterMockRecorder) Set(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7 any) *SetterSetCall {
 	mr.mock.ctrl.T.Helper()
-	call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockSetter)(nil).Set), arg0, arg1, arg2, arg3, arg4, arg5, arg6)
+	call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Set", reflect.TypeOf((*MockSetter)(nil).Set), arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
 	return &SetterSetCall{Call: call}
 }
 
@@ -109,13 +109,13 @@ func (c *SetterSetCall) Return(arg0 setter.ResponseCode) *SetterSetCall {
 }
 
 // Do rewrite *gomock.Call.Do
-func (c *SetterSetCall) Do(f func(context.Context, pp.PP, domain.Domain, ipnet.Type, netip.Addr, api.TTL, bool) setter.ResponseCode) *SetterSetCall {
+func (c *SetterSetCall) Do(f func(context.Context, pp.PP, domain.Domain, ipnet.Type, netip.Addr, api.TTL, bool, string) setter.ResponseCode) *SetterSetCall {
 	c.Call = c.Call.Do(f)
 	return c
 }
 
 // DoAndReturn rewrite *gomock.Call.DoAndReturn
-func (c *SetterSetCall) DoAndReturn(f func(context.Context, pp.PP, domain.Domain, ipnet.Type, netip.Addr, api.TTL, bool) setter.ResponseCode) *SetterSetCall {
+func (c *SetterSetCall) DoAndReturn(f func(context.Context, pp.PP, domain.Domain, ipnet.Type, netip.Addr, api.TTL, bool, string) setter.ResponseCode) *SetterSetCall {
 	c.Call = c.Call.DoAndReturn(f)
 	return c
 }
diff --git a/internal/setter/base.go b/internal/setter/base.go
index 0d3e465..fd8c964 100644
--- a/internal/setter/base.go
+++ b/internal/setter/base.go
@@ -28,6 +28,7 @@ type Setter interface {
 		IP netip.Addr,
 		ttl api.TTL,
 		proxied bool,
+		recordComment string,
 	) ResponseCode
 
 	// Delete removes DNS records of a particular domain.
diff --git a/internal/setter/setter.go b/internal/setter/setter.go
index d14ad22..35ea1ab 100644
--- a/internal/setter/setter.go
+++ b/internal/setter/setter.go
@@ -47,7 +47,7 @@ func New(_ppfmt pp.PP, handle api.Handle) (Setter, bool) {
 //
 //nolint:funlen
 func (s *setter) Set(ctx context.Context, ppfmt pp.PP,
-	domain domain.Domain, ipnet ipnet.Type, ip netip.Addr, ttl api.TTL, proxied bool,
+	domain domain.Domain, ipnet ipnet.Type, ip netip.Addr, ttl api.TTL, proxied bool, recordComment string,
 ) ResponseCode {
 	recordType := ipnet.RecordType()
 	domainDescription := domain.Describe()
@@ -140,7 +140,7 @@ func (s *setter) Set(ctx context.Context, ppfmt pp.PP,
 	// any one of them. This leaves us no choices---we have to create a new record with the correct IP.
 	if !foundMatched {
 		if id, ok := s.Handle.CreateRecord(ctx, ppfmt,
-			domain, ipnet, ip, ttl, proxied); ok {
+			domain, ipnet, ip, ttl, proxied, recordComment); ok {
 			ppfmt.Noticef(pp.EmojiCreateRecord, "Added a new %s record of %q (ID: %q)", recordType, domainDescription, id)
 
 			// Now it's up to date! unprocessedMatched and unprocessedUnmatched must both be empty at this point
diff --git a/internal/updater/updater.go b/internal/updater/updater.go
index 31caabe..2313ab7 100644
--- a/internal/updater/updater.go
+++ b/internal/updater/updater.go
@@ -59,7 +59,7 @@ func setIP(ctx context.Context, ppfmt pp.PP,
 		ctx, cancel := context.WithTimeoutCause(ctx, c.UpdateTimeout, errSettingTimeout)
 		defer cancel()
 
-		resp := s.Set(ctx, ppfmt, domain, ipNet, ip, c.TTL, getProxied(ppfmt, c, domain))
+		resp := s.Set(ctx, ppfmt, domain, ipNet, ip, c.TTL, getProxied(ppfmt, c, domain), c.RecordComment)
 		resps.Register(resp, domain)
 		if resp == setter.ResponseFailed {
 			if ShouldDisplayHints["update-timeout"] && errors.Is(context.Cause(ctx), errSettingTimeout) {


Test patch:
diff --git a/internal/api/cloudflare_test.go b/internal/api/cloudflare_test.go
index 6c39042..9472e22 100644
--- a/internal/api/cloudflare_test.go
+++ b/internal/api/cloudflare_test.go
@@ -1128,7 +1128,7 @@ func TestCreateRecordValid(t *testing.T) {
 					!assert.Equal(t, "::1", record.Content) ||
 					!assert.Equal(t, 100, record.TTL) ||
 					!assert.False(t, *record.Proxied) ||
-					!assert.Equal(t, "Created by cloudflare-ddns", record.Comment) {
+					!assert.Equal(t, "hello", record.Comment) {
 					panic(http.ErrAbortHandler)
 				}
 				record.ID = "record1"
@@ -1144,14 +1144,14 @@ func TestCreateRecordValid(t *testing.T) {
 
 	createAccessCount = 1
 	mockPP := mocks.NewMockPP(mockCtrl)
-	actualID, ok := h.CreateRecord(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6, mustIP("::1"), 100, false) //nolint:lll
+	actualID, ok := h.CreateRecord(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6, mustIP("::1"), 100, false, "hello") //nolint:lll
 	require.True(t, ok)
 	require.Equal(t, "record1", actualID)
 
 	listAccessCount, createAccessCount = 1, 1
 	mockPP = mocks.NewMockPP(mockCtrl)
 	h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6)
-	h.CreateRecord(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6, mustIP("::1"), 100, false) //nolint:lll
+	h.CreateRecord(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6, mustIP("::1"), 100, false, "hello") //nolint:lll
 	rs, cached, ok := h.ListRecords(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6)
 	require.True(t, ok)
 	require.True(t, cached)
@@ -1173,7 +1173,7 @@ func TestCreateRecordInvalid(t *testing.T) {
 		"sub.test.org",
 		gomock.Any(),
 	)
-	actualID, ok := h.CreateRecord(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6, mustIP("::1"), 100, false) //nolint:lll
+	actualID, ok := h.CreateRecord(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6, mustIP("::1"), 100, false, "hello") //nolint:lll
 	require.False(t, ok)
 	require.Equal(t, "", actualID)
 }
@@ -1189,7 +1189,7 @@ func TestCreateRecordInvalidZone(t *testing.T) {
 		"sub.test.org",
 		gomock.Any(),
 	)
-	actualID, ok := h.CreateRecord(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6, mustIP("::1"), 100, false) //nolint:lll
+	actualID, ok := h.CreateRecord(context.Background(), mockPP, domain.FQDN("sub.test.org"), ipnet.IP6, mustIP("::1"), 100, false, "hello") //nolint:lll
 	require.False(t, ok)
 	require.Equal(t, "", actualID)
 }
diff --git a/internal/config/config_print_test.go b/internal/config/config_print_test.go
index 80169c6..c3cef99 100644
--- a/internal/config/config_print_test.go
+++ b/internal/config/config_print_test.go
@@ -44,6 +44,9 @@ func TestPrintDefault(t *testing.T) {
 		printItem(innerMockPP, "Cache expiration:", "6h0m0s"),
 		mockPP.EXPECT().Infof(pp.EmojiConfig, "New DNS records:"),
 		printItem(innerMockPP, "TTL:", "1 (auto)"),
+		printItem(innerMockPP, "Proxied domains:", "(none)"),
+		printItem(innerMockPP, "Unproxied domains:", "(none)"),
+		printItem(innerMockPP, "Record comment:", "(empty)"),
 		mockPP.EXPECT().Infof(pp.EmojiConfig, "Timeouts:"),
 		printItem(innerMockPP, "IP detection:", "5s"),
 		printItem(innerMockPP, "Record updating:", "30s"),
@@ -52,7 +55,7 @@ func TestPrintDefault(t *testing.T) {
 }
 
 //nolint:paralleltest // changing the environment variable TZ
-func TestPrintMaps(t *testing.T) {
+func TestPrintValues(t *testing.T) {
 	mockCtrl := gomock.NewController(t)
 
 	store(t, "TZ", "UTC")
@@ -79,6 +82,7 @@ func TestPrintMaps(t *testing.T) {
 		printItem(innerMockPP, "TTL:", "30000"),
 		printItem(innerMockPP, "Proxied domains:", "a, b"),
 		printItem(innerMockPP, "Unproxied domains:", "c, d"),
+		printItem(innerMockPP, "Record comment:", "\"Created by Cloudflare DDNS\""),
 		mockPP.EXPECT().Infof(pp.EmojiConfig, "Timeouts:"),
 		printItem(innerMockPP, "IP detection:", "5s"),
 		printItem(innerMockPP, "Record updating:", "30s"),
@@ -101,6 +105,8 @@ func TestPrintMaps(t *testing.T) {
 	c.Proxied[domain.FQDN("c")] = false
 	c.Proxied[domain.FQDN("d")] = false
 
+	c.RecordComment = "Created by Cloudflare DDNS"
+
 	m := mocks.NewMockMonitor(mockCtrl)
 	m.EXPECT().Describe(gomock.Any()).
 		DoAndReturn(func(f func(string, string)) {
@@ -140,6 +146,9 @@ func TestPrintEmpty(t *testing.T) {
 		printItem(innerMockPP, "Cache expiration:", "0s"),
 		mockPP.EXPECT().Infof(pp.EmojiConfig, "New DNS records:"),
 		printItem(innerMockPP, "TTL:", "0"),
+		printItem(innerMockPP, "Proxied domains:", "(none)"),
+		printItem(innerMockPP, "Unproxied domains:", "(none)"),
+		printItem(innerMockPP, "Record comment:", "(empty)"),
 		mockPP.EXPECT().Infof(pp.EmojiConfig, "Timeouts:"),
 		printItem(innerMockPP, "IP detection:", "0s"),
 		printItem(innerMockPP, "Record updating:", "0s"),
diff --git a/internal/config/config_read_test.go b/internal/config/config_read_test.go
index fb81047..5fb42a1 100644
--- a/internal/config/config_read_test.go
+++ b/internal/config/config_read_test.go
@@ -29,6 +29,7 @@ func unsetAll(t *testing.T) {
 		"CACHE_EXPIRATION",
 		"TTL",
 		"PROXIED",
+		"RECORD_COMMENT",
 		"DETECTION_TIMEOUT",
 		"UPDATE_TIMEOUT",
 		"HEALTHCHECKS",
@@ -59,6 +60,7 @@ func TestReadEnvWithOnlyToken(t *testing.T) {
 		innerMockPP.EXPECT().Infof(pp.EmojiBullet, "Use default %s=%v", "CACHE_EXPIRATION", time.Duration(0)),
 		innerMockPP.EXPECT().Infof(pp.EmojiBullet, "Use default %s=%d", "TTL", api.TTL(0)),
 		innerMockPP.EXPECT().Infof(pp.EmojiBullet, "Use default %s=%s", "PROXIED", ""),
+		innerMockPP.EXPECT().Infof(pp.EmojiBullet, "Use default %s=%s", "RECORD_COMMENT", ""),
 		innerMockPP.EXPECT().Infof(pp.EmojiBullet, "Use default %s=%v", "DETECTION_TIMEOUT", time.Duration(0)),
 		innerMockPP.EXPECT().Infof(pp.EmojiBullet, "Use default %s=%v", "UPDATE_TIMEOUT", time.Duration(0)),
 	)
diff --git a/internal/setter/setter_test.go b/internal/setter/setter_test.go
index 3b17941..e94bac3 100644
--- a/internal/setter/setter_test.go
+++ b/internal/setter/setter_test.go
@@ -35,31 +35,25 @@ func TestSet(t *testing.T) {
 	for name, tc := range map[string]struct {
 		ip                netip.Addr
 		resp              setter.ResponseCode
-		ttl               api.TTL
-		proxied           bool
 		prepareMockPP     func(m *mocks.MockPP)
 		prepareMockHandle func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle)
 	}{
-		"0/1-false": {
+		"0": {
 			ip1,
 			setter.ResponseUpdated,
-			1,
-			false,
 			func(m *mocks.MockPP) {
 				m.EXPECT().Noticef(pp.EmojiCreateRecord, "Added a new %s record of %q (ID: %q)", "AAAA", "sub.test.org", record1)
 			},
 			func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) {
 				gomock.InOrder(
 					m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{}, true, true),
-					m.EXPECT().CreateRecord(ctx, ppfmt, domain, ipNetwork, ip1, api.TTL(1), false).Return(record1, true),
+					m.EXPECT().CreateRecord(ctx, ppfmt, domain, ipNetwork, ip1, api.TTLAuto, false, "hello").Return(record1, true),
 				)
 			},
 		},
-		"1unmatched/300-false": {
+		"1unmatched": {
 			ip1,
 			setter.ResponseUpdated,
-			300,
-			false,
 			func(m *mocks.MockPP) {
 				m.EXPECT().Noticef(pp.EmojiUpdateRecord,
 					"Updated a stale %s record of %q (ID: %q)",
@@ -75,11 +69,9 @@ func TestSet(t *testing.T) {
 				)
 			},
 		},
-		"1unmatched-updatefail/300-false": {
+		"1unmatched-updatefail": {
 			ip1,
 			setter.ResponseUpdated,
-			300,
-			false,
 			func(m *mocks.MockPP) {
 				gomock.InOrder(
 					m.EXPECT().Noticef(pp.EmojiDeleteRecord, "Deleted a stale %s record of %q (ID: %q)", "AAAA", "sub.test.org", record1), //nolint:lll
@@ -91,15 +83,13 @@ func TestSet(t *testing.T) {
 					m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip2}, true, true),
 					m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record1, ip1).Return(false),
 					m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record1).Return(true),
-					m.EXPECT().CreateRecord(ctx, ppfmt, domain, ipNetwork, ip1, api.TTL(300), false).Return(record2, true),
+					m.EXPECT().CreateRecord(ctx, ppfmt, domain, ipNetwork, ip1, api.TTLAuto, false, "hello").Return(record2, true),
 				)
 			},
 		},
-		"1matched/300-false": {
+		"1matched": {
 			ip1,
 			setter.ResponseNoop,
-			300,
-			false,
 			func(m *mocks.MockPP) {
 				m.EXPECT().Infof(pp.EmojiAlreadyDone,
 					"The %s records of %q are already up to date (cached)", "AAAA", "sub.test.org")
@@ -108,11 +98,9 @@ func TestSet(t *testing.T) {
 				m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1}, true, true)
 			},
 		},
-		"1matched/300-false/not-cached": {
+		"1matched/not-cached": {
 			ip1,
 			setter.ResponseNoop,
-			300,
-			false,
 			func(m *mocks.MockPP) {
 				m.EXPECT().Infof(pp.EmojiAlreadyDone, "The %s records of %q are already up to date", "AAAA", "sub.test.org")
 			},
@@ -120,11 +108,9 @@ func TestSet(t *testing.T) {
 				m.EXPECT().ListRecords(ctx, ppfmt, domain, ipNetwork).Return(map[string]netip.Addr{record1: ip1}, false, true)
 			},
 		},
-		"2matched/300-false": {
+		"2matched": {
 			ip1,
 			setter.ResponseUpdated,
-			300,
-			false,
 			func(m *mocks.MockPP) {
 				m.EXPECT().Noticef(
 					pp.EmojiDeleteRecord,
@@ -141,11 +127,9 @@ func TestSet(t *testing.T) {
 				)
 			},
 		},
-		"2matched-deletefail/300-false": {
+		"2matched-deletefail": {
 			ip1,
 			setter.ResponseUpdated,
-			300,
-			false,
 			nil,
 			func(ctx context.Context, ppfmt pp.PP, m *mocks.MockHandle) {
 				gomock.InOrder(
@@ -154,11 +138,9 @@ func TestSet(t *testing.T) {
 				)
 			},
 		},
-		"2unmatched/300-false": {
+		"2unmatched": {
 			ip1,
 			setter.ResponseUpdated,
-			300,
-			false,
 			func(m *mocks.MockPP) {
 				gomock.InOrder(
 					m.EXPECT().Noticef(
@@ -183,11 +165,9 @@ func TestSet(t *testing.T) {
 				)
 			},
 		},
-		"2unmatched-updatefail/300-false": {
+		"2unmatched-updatefail": {
 			ip1,
 			setter.ResponseUpdated,
-			300,
-			false,
 			func(m *mocks.MockPP) {
 				gomock.InOrder(
 					m.EXPECT().Noticef(pp.EmojiDeleteRecord, "Deleted a stale %s record of %q (ID: %q)", "AAAA", "sub.test.org", record1), //nolint:lll
@@ -209,11 +189,9 @@ func TestSet(t *testing.T) {
 				)
 			},
 		},
-		"2unmatched-updatefailtwice/300-false": {
+		"2unmatched-updatefailtwice": {
 			ip1,
 			setter.ResponseUpdated,
-			300,
-			false,
 			func(m *mocks.MockPP) {
 				gomock.InOrder(
 					m.EXPECT().Noticef(pp.EmojiDeleteRecord, "Deleted a stale %s record of %q (ID: %q)", "AAAA", "sub.test.org", record1), //nolint:lll
@@ -228,16 +206,14 @@ func TestSet(t *testing.T) {
 					m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record1).Return(true),
 					m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record2, ip1).Return(false),
 					m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record2).Return(true),
-					m.EXPECT().CreateRecord(ctx, ppfmt, domain, ipNetwork, ip1, api.TTL(300), false).Return(record3, true),
+					m.EXPECT().CreateRecord(ctx, ppfmt, domain, ipNetwork, ip1, api.TTLAuto, false, "hello").Return(record3, true),
 				)
 			},
 		},
 		//nolint:dupl
-		"2unmatched-updatefail-deletefail-updatefail/300-false": {
+		"2unmatched-updatefail-deletefail-updatefail": {
 			ip1,
 			setter.ResponseFailed,
-			300,
-			false,
 			func(m *mocks.MockPP) {
 				gomock.InOrder(
 					m.EXPECT().Noticef(pp.EmojiDeleteRecord, "Deleted a stale %s record of %q (ID: %q)", "AAAA", "sub.test.org", record2),                 //nolint:lll
@@ -252,16 +228,14 @@ func TestSet(t *testing.T) {
 					m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record1).Return(false),
 					m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record2, ip1).Return(false),
 					m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record2).Return(true),
-					m.EXPECT().CreateRecord(ctx, ppfmt, domain, ipNetwork, ip1, api.TTL(300), false).Return(record3, true),
+					m.EXPECT().CreateRecord(ctx, ppfmt, domain, ipNetwork, ip1, api.TTLAuto, false, "hello").Return(record3, true),
 				)
 			},
 		},
 		//nolint:dupl
-		"2unmatched-updatefailtwice-createfail/300-false": {
+		"2unmatched-updatefailtwice-createfail": {
 			ip1,
 			setter.ResponseFailed,
-			300,
-			false,
 			func(m *mocks.MockPP) {
 				gomock.InOrder(
 					m.EXPECT().Noticef(pp.EmojiDeleteRecord, "Deleted a stale %s record of %q (ID: %q)", "AAAA", "sub.test.org", record1),                 //nolint:lll
@@ -276,15 +250,13 @@ func TestSet(t *testing.T) {
 					m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record1).Return(true),
 					m.EXPECT().UpdateRecord(ctx, ppfmt, domain, ipNetwork, record2, ip1).Return(false),
 					m.EXPECT().DeleteRecord(ctx, ppfmt, domain, ipNetwork, record2).Return(true),
-					m.EXPECT().CreateRecord(ctx, ppfmt, domain, ipNetwork, ip1, api.TTL(300), false).Return(record3, false),
+					m.EXPECT().CreateRecord(ctx, ppfmt, domain, ipNetwork, ip1, api.TTLAuto, false, "hello").Return(record3, false),
 				)
 			},
 		},
-		"listfail/300-false": {
+		"listfail": {
 			ip1,
 			setter.ResponseFailed,
-			300,
-			false,
 			func(m *mocks.MockPP) {
 				m.EXPECT().Errorf(pp.EmojiError, "Failed to retrieve the current %s records of %q", "AAAA", "sub.test.org")
 			},
@@ -311,7 +283,7 @@ func TestSet(t *testing.T) {
 			s, ok := setter.New(mockPP, mockHandle)
 			require.True(t, ok)
 
-			resp := s.Set(ctx, mockPP, domain, ipNetwork, tc.ip, tc.ttl, tc.proxied)
+			resp := s.Set(ctx, mockPP, domain, ipNetwork, tc.ip, api.TTLAuto, false, "hello")
 			require.Equal(t, tc.resp, resp)
 		})
 	}
diff --git a/internal/updater/updater_test.go b/internal/updater/updater_test.go
index e66d4e5..9df2cd8 100644
--- a/internal/updater/updater_test.go
+++ b/internal/updater/updater_test.go
@@ -20,6 +20,8 @@ import (
 	"github.com/favonia/cloudflare-ddns/internal/updater"
 )
 
+const RecordComment string = "hello"
+
 //nolint:funlen,paralleltest // updater.IPv6MessageDisplayed is a global variable
 func TestUpdateIPsMultiple(t *testing.T) {
 	domain4_1 := domain.FQDN("ip4.hello1")
@@ -55,13 +57,13 @@ func TestUpdateIPsMultiple(t *testing.T) {
 			mockproviders{ipnet.IP4: provider4},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
 				gomock.InOrder(
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello1"), ipnet.IP4, ip4, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello1"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseUpdated),
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello2"), ipnet.IP4, ip4, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello2"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseFailed),
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello3"), ipnet.IP4, ip4, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello3"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseNoop),
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello4"), ipnet.IP4, ip4, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello4"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseUpdated),
 				)
 			},
@@ -76,13 +78,13 @@ func TestUpdateIPsMultiple(t *testing.T) {
 			mockproviders{ipnet.IP4: provider4},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
 				gomock.InOrder(
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello1"), ipnet.IP4, ip4, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello1"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseUpdated),
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello2"), ipnet.IP4, ip4, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello2"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseNoop),
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello3"), ipnet.IP4, ip4, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello3"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseUpdated),
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello4"), ipnet.IP4, ip4, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello4"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseUpdated),
 				)
 			},
@@ -100,6 +102,7 @@ func TestUpdateIPsMultiple(t *testing.T) {
 				domain4_3: false,
 				domain4_4: false,
 			}
+			conf.RecordComment = RecordComment
 			conf.Use1001 = true
 			conf.UpdateTimeout = time.Second
 			mockPP := mocks.NewMockPP(mockCtrl)
@@ -198,6 +201,7 @@ func TestDeleteIPsMultiple(t *testing.T) {
 				domain4_3: false,
 				domain4_4: false,
 			}
+			conf.RecordComment = RecordComment
 			conf.Use1001 = true
 			conf.UpdateTimeout = time.Second
 			mockPP := mocks.NewMockPP(mockCtrl)
@@ -261,7 +265,7 @@ func TestUpdateIPsUninitializedProbied(t *testing.T) {
 			},
 			mockproviders{ipnet.IP4: provider4},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 					Return(setter.ResponseUpdated)
 			},
 		},
@@ -273,6 +277,7 @@ func TestUpdateIPsUninitializedProbied(t *testing.T) {
 			conf.Domains = domains
 			conf.TTL = api.TTLAuto
 			conf.Proxied = map[domain.Domain]bool{}
+			conf.RecordComment = RecordComment
 			conf.Use1001 = true
 			conf.UpdateTimeout = time.Second
 			mockPP := mocks.NewMockPP(mockCtrl)
@@ -348,7 +353,7 @@ func TestUpdateIPsHints(t *testing.T) {
 				},
 			},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 					Return(setter.ResponseNoop)
 			},
 		},
@@ -360,6 +365,7 @@ func TestUpdateIPsHints(t *testing.T) {
 			conf.Domains = domains
 			conf.TTL = api.TTLAuto
 			conf.Proxied = map[domain.Domain]bool{domain4: false, domain6: false}
+			conf.RecordComment = RecordComment
 			conf.Use1001 = true
 			conf.UpdateTimeout = time.Second
 			mockPP := mocks.NewMockPP(mockCtrl)
@@ -439,7 +445,7 @@ func TestUpdateIPs(t *testing.T) {
 			pp4only,
 			mockproviders{ipnet.IP4: provider4},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 					Return(setter.ResponseNoop)
 			},
 		},
@@ -450,7 +456,7 @@ func TestUpdateIPs(t *testing.T) {
 			pp4only,
 			mockproviders{ipnet.IP4: provider4},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 					Return(setter.ResponseFailed)
 			},
 		},
@@ -461,7 +467,7 @@ func TestUpdateIPs(t *testing.T) {
 			pp6only,
 			mockproviders{ipnet.IP6: provider6},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false).
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false, RecordComment).
 					Return(setter.ResponseUpdated)
 			},
 		},
@@ -472,7 +478,7 @@ func TestUpdateIPs(t *testing.T) {
 			pp6only,
 			mockproviders{ipnet.IP6: provider6},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false).
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false, RecordComment).
 					Return(setter.ResponseFailed)
 			},
 		},
@@ -484,9 +490,9 @@ func TestUpdateIPs(t *testing.T) {
 			mockproviders{ipnet.IP4: provider4, ipnet.IP6: provider6},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
 				gomock.InOrder(
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseNoop),
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseNoop),
 				)
 			},
@@ -499,9 +505,9 @@ func TestUpdateIPs(t *testing.T) {
 			mockproviders{ipnet.IP4: provider4, ipnet.IP6: provider6},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
 				gomock.InOrder(
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseFailed),
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseNoop),
 				)
 			},
@@ -514,9 +520,9 @@ func TestUpdateIPs(t *testing.T) {
 			mockproviders{ipnet.IP4: provider4, ipnet.IP6: provider6},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
 				gomock.InOrder(
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseNoop),
-					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false).
+					m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false, RecordComment).
 						Return(setter.ResponseFailed),
 				)
 			},
@@ -539,7 +545,7 @@ func TestUpdateIPs(t *testing.T) {
 				ipnet.IP6: provider6,
 			},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false).
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip6.hello"), ipnet.IP6, ip6, api.TTLAuto, false, RecordComment).
 					Return(setter.ResponseNoop)
 			},
 		},
@@ -563,7 +569,7 @@ func TestUpdateIPs(t *testing.T) {
 				},
 			},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 					Return(setter.ResponseNoop)
 			},
 		},
@@ -607,9 +613,9 @@ func TestUpdateIPs(t *testing.T) {
 				},
 			},
 			func(ppfmt pp.PP, m *mocks.MockSetter) {
-				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false).
+				m.EXPECT().Set(gomock.Any(), ppfmt, domain.FQDN("ip4.hello"), ipnet.IP4, ip4, api.TTLAuto, false, RecordComment).
 					DoAndReturn(
-						func(_ context.Context, _ pp.PP, _ domain.Domain, _ ipnet.Type, _ netip.Addr, _ api.TTL, _ bool) setter.ResponseCode { //nolint:lll
+						func(_ context.Context, _ pp.PP, _ domain.Domain, _ ipnet.Type, _ netip.Addr, _ api.TTL, _ bool, _ string) setter.ResponseCode { //nolint:lll
 							time.Sleep(2 * time.Second)
 							return setter.ResponseFailed
 						})
@@ -623,6 +629,7 @@ func TestUpdateIPs(t *testing.T) {
 			conf.Domains = domains
 			conf.TTL = api.TTLAuto
 			conf.Proxied = map[domain.Domain]bool{domain4: false, domain6: false}
+			conf.RecordComment = RecordComment
 			conf.Use1001 = true
 			conf.UpdateTimeout = time.Second
 			mockPP := mocks.NewMockPP(mockCtrl)
@@ -770,6 +777,7 @@ func TestDeleteIPs(t *testing.T) {
 			conf.Domains = domains
 			conf.TTL = api.TTLAuto
 			conf.Proxied = map[domain.Domain]bool{domain4: false, domain6: false}
+			conf.RecordComment = RecordComment
 			mockPP := mocks.NewMockPP(mockCtrl)
 			if tc.prepareMockPP != nil {
 				tc.prepareMockPP(mockPP)