Add background jobs for group and project secret rotation reminders

What does this MR do and why?

Adds separate background workers and services for processing project and group secret rotation reminders, as part of #577344 (closed).

With GroupSecretRotationInfo records now being created and surfaced through the services in !225562 (merged) and !225935 (merged), this MR wires up the notification side so that group secret owners receive rotation reminder emails when secrets are due — mirroring the existing project secret rotation reminder job.

Rather than extending the existing SecretRotationBatchReminderService to process both types in a single pass (which would break the worker's loop-exit logic since a full project batch would mask pending group records), this MR introduces separate workers and services for each resource type so they run independently and can be scaled or tuned separately.

Implementation details

Services:

  • BaseSecretRotationBatchReminderService — new abstract base class (renamed from SecretRotationBatchReminderService) holding all shared batch processing logic: pending_reminders query, orphan detection via polymorphic #resource on each rotation info model, and logging; notification dispatch is delegated to subclasses via the abstract send_rotation_reminder method
  • ProjectSecretRotationBatchReminderService — thin subclass defining rotation_info_class = ProjectSecretRotationInfo and send_rotation_reminder calling notification_service.secret_rotation_reminder_for_project
  • GroupSecretRotationBatchReminderService — thin subclass defining rotation_info_class = GroupSecretRotationInfo and send_rotation_reminder calling notification_service.secret_rotation_reminder_for_group
  • SecretRotationBatchReminderService — deprecated no-op (replaced by the above two; removed from cron, kept for safe in-flight job handling per GitLab worker deprecation guidelines)

Models — adds #resource to each rotation info model so the base service needs no is_a? checks:

  • ProjectSecretRotationInfo#resource — returns project
  • GroupSecretRotationInfo#resource — returns group

Workers:

  • BaseSecretRotationReminderBatchWorker — new abstract base worker with shared perform loop logic (runtime limiter, batch counting, metadata logging); loop exits when processed_count + skipped_count < BATCH_SIZE; subclasses define service_class
  • ProjectSecretRotationReminderBatchWorker — thin subclass
  • GroupSecretRotationReminderBatchWorker — thin subclass
  • SecretRotationReminderBatchWorker — deprecated no-op per GitLab worker deprecation guidelines; removed from cron schedule

Notifications:

  • Renamed NotificationService#secret_rotation_remindersecret_rotation_reminder_for_project (project-specific, no type dispatch)
  • Added NotificationService#secret_rotation_reminder_for_group — sends rotation reminder emails to group owners
  • Renamed secret_rotation_reminder_email mailer method → project_secret_rotation_reminder_email for naming symmetry
  • Added group_secret_rotation_reminder_email mailer method with HTML/text templates
  • Added preview methods for both in notify_preview.rb

Cron schedule (1_settings.rb):

  • Removed secret_rotation_reminder_batch_worker (no-op worker no longer needs scheduling)
  • Added project_secret_rotation_reminder_batch_worker (* * * * *)
  • Added group_secret_rotation_reminder_batch_worker (* * * * *)

Worker deprecation (per GitLab guidelines):

  • M (this MR): SecretRotationReminderBatchWorker#perform replaced with no-op; removed from cron; new workers added
  • M+1: migration using sidekiq_remove_jobs to drain any in-flight jobs
  • M+2: delete the worker class file

Specs:

  • secret_rotation_batch_reminder_service_examples.rb — shared examples ('a batch reminder service processing secrets') covering: no secrets needing reminders, batch size limiting, eligible secrets processing, version-mismatch orphan cleanup, and general orphaned record cleanup; both project and group specs are now thin wrappers around this shared example
  • project_secret_rotation_batch_reminder_service_spec.rb — thin spec using shared examples
  • group_secret_rotation_batch_reminder_service_spec.rb — thin spec using shared examples
  • secret_rotation_reminder_batch_worker_examples.rb — shared examples ('a secret rotation reminder batch worker') covering: loop/batch/runtime unit tests + idempotent worker integration test
  • project_secret_rotation_reminder_batch_worker_spec.rb — thin spec using shared examples
  • group_secret_rotation_reminder_batch_worker_spec.rb — thin spec using shared examples
  • secret_rotation_reminder_batch_worker_spec.rb — reduced to no-op test

Series overview

Part of a series for #577344 (closed):

# MR Description
1 !225247 (merged) DB migration + GroupSecretRotationInfo model + BaseSecretRotationInfo base class
2 !225338 (merged) Rename SecretRotationInfoProjectSecretRotationInfo for naming consistency
3 !225562 (merged) CreateService + UpdateService + GraphQL mutations (add rotation_interval_days param)
4 !225935 (merged) List/Read services + GroupSecretType GraphQL type (add rotation info loading/field)
5 👉 You are here Background jobs for group and project secret rotation reminders

References

MR acceptance checklist

Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Erick Bajao

Merge request reports

Loading