mirror of
https://github.com/whekin/household-bot.git
synced 2026-03-31 10:24:02 +00:00
feat(infra): add reminder scheduler jobs
This commit is contained in:
@@ -7,7 +7,7 @@ This directory contains baseline IaC for deploying the household bot platform on
|
||||
- Artifact Registry Docker repository
|
||||
- Cloud Run service: bot API (public webhook endpoint)
|
||||
- Cloud Run service: mini app (public web UI)
|
||||
- Cloud Scheduler job for reminder triggers
|
||||
- Cloud Scheduler jobs for reminder triggers
|
||||
- Runtime and scheduler service accounts with least-privilege bindings
|
||||
- Secret Manager secrets (IDs only, secret values are added separately)
|
||||
- Optional GitHub OIDC Workload Identity setup for deploy automation
|
||||
@@ -16,7 +16,7 @@ This directory contains baseline IaC for deploying the household bot platform on
|
||||
|
||||
- `bot-api`: Telegram webhook + app API endpoints
|
||||
- `mini-app`: front-end delivery
|
||||
- `scheduler`: triggers `bot-api` internal reminder endpoint using OIDC token
|
||||
- `scheduler`: triggers `bot-api` reminder endpoints using OIDC tokens
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -84,5 +84,5 @@ CI runs:
|
||||
|
||||
## Notes
|
||||
|
||||
- Scheduler job defaults to `paused = true` to prevent accidental sends before app logic is ready.
|
||||
- Scheduler jobs default to `paused = true` and `dry_run = true` to prevent accidental sends before live reminder delivery is ready.
|
||||
- Bot API is public to accept Telegram webhooks; scheduler endpoint should still verify app-level auth.
|
||||
|
||||
@@ -12,6 +12,21 @@ locals {
|
||||
|
||||
artifact_location = coalesce(var.artifact_repository_location, var.region)
|
||||
|
||||
reminder_jobs = {
|
||||
utilities = {
|
||||
schedule = var.scheduler_utilities_cron
|
||||
path = "/jobs/reminder/utilities"
|
||||
}
|
||||
rent-warning = {
|
||||
schedule = var.scheduler_rent_warning_cron
|
||||
path = "/jobs/reminder/rent-warning"
|
||||
}
|
||||
rent-due = {
|
||||
schedule = var.scheduler_rent_due_cron
|
||||
path = "/jobs/reminder/rent-due"
|
||||
}
|
||||
}
|
||||
|
||||
runtime_secret_ids = toset(compact([
|
||||
var.telegram_webhook_secret_id,
|
||||
var.scheduler_shared_secret_id,
|
||||
|
||||
@@ -92,6 +92,9 @@ module "bot_api_service" {
|
||||
},
|
||||
var.bot_parser_model == null ? {} : {
|
||||
PARSER_MODEL = var.bot_parser_model
|
||||
},
|
||||
{
|
||||
SCHEDULER_OIDC_ALLOWED_EMAILS = google_service_account.scheduler_invoker.email
|
||||
}
|
||||
)
|
||||
|
||||
@@ -158,22 +161,27 @@ resource "google_service_account_iam_member" "scheduler_token_creator" {
|
||||
}
|
||||
|
||||
resource "google_cloud_scheduler_job" "reminders" {
|
||||
for_each = local.reminder_jobs
|
||||
|
||||
project = var.project_id
|
||||
region = var.region
|
||||
name = "${local.name_prefix}-reminders"
|
||||
schedule = var.scheduler_cron
|
||||
name = "${local.name_prefix}-${each.key}"
|
||||
schedule = each.value.schedule
|
||||
time_zone = var.scheduler_timezone
|
||||
paused = var.scheduler_paused
|
||||
|
||||
http_target {
|
||||
uri = "${module.bot_api_service.uri}${var.scheduler_path}"
|
||||
http_method = var.scheduler_http_method
|
||||
uri = "${module.bot_api_service.uri}${each.value.path}"
|
||||
http_method = "POST"
|
||||
|
||||
headers = {
|
||||
"Content-Type" = "application/json"
|
||||
}
|
||||
|
||||
body = base64encode(var.scheduler_body_json)
|
||||
body = base64encode(jsonencode({
|
||||
dryRun = var.scheduler_dry_run
|
||||
jobId = "${local.name_prefix}-${each.key}"
|
||||
}))
|
||||
|
||||
oidc_token {
|
||||
service_account_email = google_service_account.scheduler_invoker.email
|
||||
|
||||
@@ -23,9 +23,9 @@ output "mini_app_service_url" {
|
||||
value = module.mini_app_service.uri
|
||||
}
|
||||
|
||||
output "scheduler_job_name" {
|
||||
description = "Cloud Scheduler job for reminders"
|
||||
value = google_cloud_scheduler_job.reminders.name
|
||||
output "scheduler_job_names" {
|
||||
description = "Cloud Scheduler jobs for reminders"
|
||||
value = { for name, job in google_cloud_scheduler_job.reminders : name => job.name }
|
||||
}
|
||||
|
||||
output "runtime_secret_ids" {
|
||||
|
||||
@@ -13,9 +13,12 @@ bot_household_chat_id = "-1001234567890"
|
||||
bot_purchase_topic_id = 777
|
||||
bot_parser_model = "gpt-4.1-mini"
|
||||
|
||||
scheduler_cron = "0 9 * * *"
|
||||
scheduler_timezone = "Asia/Tbilisi"
|
||||
scheduler_paused = true
|
||||
scheduler_utilities_cron = "0 9 4 * *"
|
||||
scheduler_rent_warning_cron = "0 9 17 * *"
|
||||
scheduler_rent_due_cron = "0 9 20 * *"
|
||||
scheduler_timezone = "Asia/Tbilisi"
|
||||
scheduler_paused = true
|
||||
scheduler_dry_run = true
|
||||
|
||||
create_workload_identity = true
|
||||
github_repository = "whekin/household-bot"
|
||||
|
||||
@@ -118,35 +118,34 @@ variable "openai_api_key_secret_id" {
|
||||
nullable = true
|
||||
}
|
||||
|
||||
|
||||
variable "scheduler_path" {
|
||||
description = "Reminder endpoint path on bot API"
|
||||
type = string
|
||||
default = "/internal/scheduler/reminders"
|
||||
}
|
||||
|
||||
variable "scheduler_http_method" {
|
||||
description = "Scheduler HTTP method"
|
||||
type = string
|
||||
default = "POST"
|
||||
}
|
||||
|
||||
variable "scheduler_cron" {
|
||||
description = "Cron expression for reminder scheduler"
|
||||
type = string
|
||||
default = "0 9 * * *"
|
||||
}
|
||||
|
||||
variable "scheduler_timezone" {
|
||||
description = "Scheduler timezone"
|
||||
type = string
|
||||
default = "Asia/Tbilisi"
|
||||
}
|
||||
|
||||
variable "scheduler_body_json" {
|
||||
description = "JSON payload for scheduler requests"
|
||||
variable "scheduler_utilities_cron" {
|
||||
description = "Cron expression for the utilities reminder scheduler job"
|
||||
type = string
|
||||
default = "{\"kind\":\"monthly-reminder\"}"
|
||||
default = "0 9 4 * *"
|
||||
}
|
||||
|
||||
variable "scheduler_rent_warning_cron" {
|
||||
description = "Cron expression for the rent warning scheduler job"
|
||||
type = string
|
||||
default = "0 9 17 * *"
|
||||
}
|
||||
|
||||
variable "scheduler_rent_due_cron" {
|
||||
description = "Cron expression for the rent due scheduler job"
|
||||
type = string
|
||||
default = "0 9 20 * *"
|
||||
}
|
||||
|
||||
variable "scheduler_dry_run" {
|
||||
description = "Whether scheduler jobs should invoke the bot in dry-run mode"
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
|
||||
variable "scheduler_paused" {
|
||||
|
||||
Reference in New Issue
Block a user