Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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 .changes/unreleased/Feature-20260916-090000.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
kind: Feature
body: Make `CampaignUpdateInput.Reminder` nullable so an existing campaign reminder
can be cleared by sending an explicit `null`
time: 2026-09-16T09:00:00.000000000-05:00
64 changes: 64 additions & 0 deletions campaign_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,70 @@ func TestUpdateCampaign(t *testing.T) {
autopilot.Equals(t, id2, campaign.Owner.Id)
}

func TestUpdateCampaignSetReminder(t *testing.T) {
// Arrange
testRequest := autopilot.NewTestRequest(
`{{ template "campaign_update_request" }}`,
`{{ template "campaign_update_reminder_request_vars" }}`,
`{{ template "campaign_update_reminder_response" }}`,
)
client := BestTestClient(t, "campaign/update_reminder", testRequest)

// Act
campaign, err := client.UpdateCampaign(ol.CampaignUpdateInput{
Id: id1,
Reminder: ol.NewNullableFrom(ol.CampaignReminderInput{
Channels: &[]ol.CampaignReminderChannelEnum{
ol.CampaignReminderChannelEnumSlack,
ol.CampaignReminderChannelEnumMicrosoftTeams,
},
DaysOfWeek: &[]ol.DayOfWeekEnum{ol.DayOfWeekEnumMonday},
DefaultSlackChannel: ol.RefOf("#engineering"),
Frequency: 1,
FrequencyUnit: ol.CampaignReminderFrequencyUnitEnumWeek,
Message: ol.RefOf("Please complete your campaign checks"),
TimeOfDay: "09:00",
Timezone: "America/Chicago",
}),
})

// Assert
autopilot.Ok(t, err)
autopilot.Equals(t, id1, campaign.Id)
autopilot.Equals(t, []ol.CampaignReminderChannelEnum{
ol.CampaignReminderChannelEnumSlack,
ol.CampaignReminderChannelEnumMicrosoftTeams,
}, campaign.Reminder.Channels)
autopilot.Equals(t, []ol.DayOfWeekEnum{ol.DayOfWeekEnumMonday}, campaign.Reminder.DaysOfWeek)
autopilot.Equals(t, "#engineering", campaign.Reminder.DefaultSlackChannel)
autopilot.Equals(t, 1, campaign.Reminder.Frequency)
autopilot.Equals(t, ol.CampaignReminderFrequencyUnitEnumWeek, campaign.Reminder.FrequencyUnit)
autopilot.Equals(t, "Please complete your campaign checks", campaign.Reminder.Message)
autopilot.Equals(t, "09:00", campaign.Reminder.TimeOfDay)
autopilot.Equals(t, "America/Chicago", campaign.Reminder.Timezone)
}

func TestUpdateCampaignClearReminder(t *testing.T) {
// Arrange
testRequest := autopilot.NewTestRequest(
`{{ template "campaign_update_request" }}`,
`{{ template "campaign_clear_reminder_request_vars" }}`,
`{{ template "campaign_update_response" }}`,
)
client := BestTestClient(t, "campaign/clear_reminder", testRequest)

// Act
campaign, err := client.UpdateCampaign(ol.CampaignUpdateInput{
Id: id1,
Reminder: ol.NewNullOf[ol.CampaignReminderInput](),
})

// Assert
autopilot.Ok(t, err)
autopilot.Equals(t, id1, campaign.Id)
autopilot.Equals(t, ol.CampaignReminder{}, campaign.Reminder)
}

func TestDeleteCampaign(t *testing.T) {
// Arrange
testRequest := autopilot.NewTestRequest(
Expand Down
12 changes: 6 additions & 6 deletions input.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,12 @@ type CampaignUnscheduleInput struct {

// CampaignUpdateInput Specifies the input fields used to update a campaign
type CampaignUpdateInput struct {
FilterId *Nullable[ID] `json:"filterId,omitempty" yaml:"filterId,omitempty" example:"Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"` // The ID of the filter applied to this campaign (Optional)
Id ID `json:"id" yaml:"id" example:"Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"` // The id of the campaign to be updated (Required)
Name *string `json:"name,omitempty" yaml:"name,omitempty" example:"example_value"` // The name of the campaign (Optional)
OwnerId *Nullable[ID] `json:"ownerId,omitempty" yaml:"ownerId,omitempty" example:"Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"` // The ID of the team that owns this campaign (Optional)
ProjectBrief *string `json:"projectBrief,omitempty" yaml:"projectBrief,omitempty" example:"example_value"` // The project brief of the campaign (Optional)
Reminder *CampaignReminderInput `json:"reminder,omitempty" yaml:"reminder,omitempty"` // Configuration of an optional campaign reminder (Optional)
FilterId *Nullable[ID] `json:"filterId,omitempty" yaml:"filterId,omitempty" example:"Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"` // The ID of the filter applied to this campaign (Optional)
Id ID `json:"id" yaml:"id" example:"Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"` // The id of the campaign to be updated (Required)
Name *string `json:"name,omitempty" yaml:"name,omitempty" example:"example_value"` // The name of the campaign (Optional)
OwnerId *Nullable[ID] `json:"ownerId,omitempty" yaml:"ownerId,omitempty" example:"Z2lkOi8vc2VydmljZS8xMjM0NTY3ODk"` // The ID of the team that owns this campaign (Optional)
ProjectBrief *string `json:"projectBrief,omitempty" yaml:"projectBrief,omitempty" example:"example_value"` // The project brief of the campaign (Optional)
Reminder *Nullable[CampaignReminderInput] `json:"reminder,omitempty" yaml:"reminder,omitempty"` // Configuration of an optional campaign reminder (Optional)
}

// CheckAlertSourceUsageCreateInput Specifies the input fields used to create an alert source usage check
Expand Down
1 change: 1 addition & 0 deletions templates/inputObjects.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
type {{ .Name }} struct { {{ range .Values }}
{{ title .Name.Name }} {{ if and (eq $.Name "AliasCreateInput") (eq .Name.Name "ownerId") }}ID
{{- else if and (eq $.Name "CheckPackageVersionUpdateInput") (eq .Name.Name "versionConstraintPredicate") }}*PredicateUpdateInput
{{- else if and (eq $.Name "CampaignUpdateInput") (eq .Name.Name "reminder") }}*Nullable[CampaignReminderInput]
{{- else if and (eq $.Name "ManualCheckFrequencyUpdateInput") (eq .Name.Name "frequencyValue") }}*Nullable[int]
{{- else if eq $.Name "IdentifierInput" }}
{{- if eq .Type.String "String" }}*string
Expand Down
34 changes: 34 additions & 0 deletions testdata/templates/campaigns.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,40 @@ mutation CampaignUpdate($input:CampaignUpdateInput!){campaignUpdate(input: $inpu
},"errors":[]}}
}{{ end }}

{{- define "campaign_update_reminder_request_vars" }}
{"input":{"id":"{{ template "id1_string" }}","reminder":{"channels":["slack","microsoft_teams"],"daysOfWeek":["monday"],"defaultSlackChannel":"#engineering","frequency":1,"frequencyUnit":"week","message":"Please complete your campaign checks","timeOfDay":"09:00","timezone":"America/Chicago"}}}
{{ end }}

{{- define "campaign_update_reminder_response" }}{
"data":{"campaignUpdate":{"campaign":{
{{ template "id1" }},
"name":"Updated Campaign",
"htmlUrl":"https://app.opslevel.com/campaigns/updated",
"status":"draft",
"checkStats":{"total":0,"totalSuccessful":0},
"serviceStats":{"total":0,"totalSuccessful":0},
"owner":{ {{ template "id2" }}, "alias":"staff" },
"projectBrief":"A test campaign",
"rawProjectBrief":"A test campaign",
"filter":null,
"reminder":{
"channels":["slack","microsoft_teams"],
"daysOfWeek":["monday"],
"defaultSlackChannel":"#engineering",
"frequency":1,
"frequencyUnit":"week",
"message":"Please complete your campaign checks",
"nextOccurrence":"2026-05-04T09:00:00Z",
"timeOfDay":"09:00",
"timezone":"America/Chicago"
}
},"errors":[]}}
}{{ end }}

{{- define "campaign_clear_reminder_request_vars" }}
{"input":{"id":"{{ template "id1_string" }}","reminder":null}}
{{ end }}

{{- define "campaign_delete_request" }}
mutation CampaignDelete($input:DeleteInput!){campaignDelete(input: $input){deletedId,errors{message,path}}}
{{ end }}
Expand Down