Skip to content

Add reminder configuration to opslevel_campaign resource#652

Open
jamescarr wants to merge 2 commits into
OpsLevel:mainfrom
jamescarr:jamescarr/campaign-reminders
Open

Add reminder configuration to opslevel_campaign resource#652
jamescarr wants to merge 2 commits into
OpsLevel:mainfrom
jamescarr:jamescarr/campaign-reminders

Conversation

@jamescarr

Copy link
Copy Markdown
Contributor

Summary

  • Adds a reminder single-nested attribute to the opslevel_campaign resource for configuring recurring Slack, email, and Microsoft Teams reminders on a schedule.
  • Schema validation: channel / frequency_unit / day-of-week enums, frequency >= 1, HH:MM time format, and channels non-empty. ValidateConfig enforces that days_of_week is required for a weekly cadence and rejected otherwise.
  • CRUD wiring: omit on create when absent, send an explicit null to clear on update when the block is removed, and normalize the # prefix on default_slack_channel to avoid perpetual diffs.
  • Exposes reminder as a computed attribute on the opslevel_campaign and opslevel_campaigns data sources.
  • Docs, example, and a changie entry.

Dependency

Depends on OpsLevel/opslevel-go#623. The go.mod replace directive and the submodules/opslevel-go pointer are temporary for development (matching the prior campaign PR workflow) and will be removed in favor of a released opslevel-go version bump before merge.

Test plan

  • go build ./..., go vet ./opslevel/
  • gofumpt clean, golangci-lint run ./opslevel/ (0 issues)
  • task test — terraform mock tests + Go unit tests (107 passed, 0 failed), including new reminder assertions on the opslevel_campaign resource
  • Remote acceptance tests (tests/remote/campaign.tftest.hcl) — added create-with-reminder, update-to-daily, and clear-reminder runs; require a live OPSLEVEL_API_TOKEN and valid owner_id

Made with Cursor

Add a `reminder` single-nested attribute to the opslevel_campaign resource for
configuring recurring Slack, email, and Microsoft Teams reminders on a schedule.
Includes schema validation (channel/frequency_unit/day enums, frequency >= 1,
HH:MM time format, weekly cadence requires days_of_week), create/read/update
wiring with clear-on-removal, and #-prefix normalization for the Slack channel
to avoid perpetual diffs. Also exposes the reminder as a computed attribute on
the opslevel_campaign and opslevel_campaigns data sources.

Depends on OpsLevel/opslevel-go#623. The go.mod replace directive and submodule
pointer are temporary for development and will be swapped for a released
opslevel-go version before merge.

Co-authored-by: Cursor <cursoragent@cursor.com>
@jamescarr

Copy link
Copy Markdown
Contributor Author

Usage examples

Weekly Slack + email reminder

resource "opslevel_campaign" "upgrade_rails" {
  name      = "Upgrade to Rails 7"
  owner_id  = data.opslevel_team.platform.id
  filter_id = data.opslevel_filter.tier_1.id

  start_date  = "2026-07-01"
  target_date = "2026-09-30"

  reminder = {
    channels       = ["slack", "email"]
    frequency      = 1
    frequency_unit = "week"
    days_of_week   = ["monday", "thursday"] # required for a weekly cadence
    time_of_day    = "09:30"
    timezone       = "America/Chicago"
    message        = "Friendly reminder to complete your Rails 7 upgrade checks."

    # Fallback channel used when a team has no default Slack contact.
    default_slack_channel = "#platform-eng"
  }
}

Every-2-days reminder (no days_of_week)

reminder = {
  channels       = ["slack"]
  frequency      = 2
  frequency_unit = "day" # daily/monthly cadences must omit days_of_week
  time_of_day    = "14:00"
  timezone       = "America/Chicago"
}

Microsoft Teams reminder

reminder = {
  channels                        = ["microsoft_teams"]
  frequency                       = 1
  frequency_unit                  = "month"
  time_of_day                     = "08:00"
  timezone                        = "Europe/London"
  default_microsoft_teams_channel = "Platform Eng"
}

No reminder / clearing one

Omit the reminder block entirely. Removing it from a campaign that previously had one sends an explicit null to clear it.

Reading it back

data "opslevel_campaign" "upgrade_rails" {
  identifier = opslevel_campaign.upgrade_rails.id
}

output "next_reminder" {
  value = data.opslevel_campaign.upgrade_rails.reminder.next_occurrence
}

Notes

  • days_of_week is required for frequency_unit = "week" and rejected for day / month.
  • The API prepends # to default_slack_channel; the provider normalizes this so "platform-eng" and "#platform-eng" don't perpetually diff.
  • next_occurrence is computed and stays null until the campaign is in_progress or delayed.

@codecov

codecov Bot commented Jun 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 51.98020% with 97 lines in your changes missing coverage. Please review.
✅ Project coverage is 2.09%. Comparing base (decd87c) to head (5a3d171).
⚠️ Report is 98 commits behind head on main.

Files with missing lines Patch % Lines
opslevel/resource_opslevel_campaign.go 52.60% 88 Missing and 3 partials ⚠️
opslevel/datasource_opslevel_campaign.go 40.00% 3 Missing ⚠️
opslevel/datasource_opslevel_campaigns_all.go 40.00% 3 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##            main    #652      +/-   ##
========================================
+ Coverage   0.22%   2.09%   +1.86%     
========================================
  Files         85     103      +18     
  Lines       9651   12469    +2818     
========================================
+ Hits          22     261     +239     
- Misses      9626   12186    +2560     
- Partials       3      22      +19     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Cover the reminder conversion, normalization, and data-source mapping helpers
with internal-package unit tests, and extract the reminder validation into a
testable validateReminderConfig helper. Addresses 0% patch coverage on the
reminder code paths.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant