Skip to content

chore(iac): enable ri_exchange_reshape schedule in GCP and Azure staging and prod - #863

Merged
cristim merged 1 commit into
mainfrom
chore/enable-ri-exchange-gcp-azure-stg-prod
Oct 13, 2026
Merged

cristim merged 1 commit into
mainfrom
chore/enable-ri-exchange-gcp-azure-stg-prod

Conversation

@cristim

@cristim cristim commented Oct 13, 2026

Copy link
Copy Markdown
Member

Summary

Adds enable_ri_exchange_schedule = true to terraform/environments/{gcp,azure}/github-{staging,prod}.tfvars (one line each, fmt alignment kept). Mirrors #856, which did the same for the dev tfvars. Owner decision: enable in staging and prod as well as dev. Module defaults and AWS are untouched. The variable is already wired in gcp/compute.tf and azure/compute.tf.

What this changes at runtime

  1. The 6-hourly ri_exchange_reshape job is created in those environments. When it fires, it only does work where the global config has RIExchangeEnabled true. Where it is false, handleRIExchangeReshape returns early (internal/server/handler_ri_exchange.go:42, "RI exchange automation is disabled, skipping"). Creating the schedule does not turn automation on.
  2. Deploy path (from .github/workflows):
    • deploy-gcp.yml and deploy-azure.yml run on push to main with no environment input, which resolves to dev only.
    • Staging and prod are deployed only by workflow_dispatch (environment choice), or through deploy-all.yml, which is workflow_dispatch or a release created event; a release deploys prod to all selected clouds.
    • So merging this PR does not deploy staging or prod. The prod change takes effect on the next manual prod dispatch or the next release. Flag to the owner: the next release will carry this change into GCP and Azure prod.
  3. Nothing is applied by this PR beyond the normal merge-triggered dev workflows (which already have the dev value from chore(iac): enable ri_exchange_reshape schedule in GCP and Azure dev #856, so no dev diff from this PR).

Verification

  • terraform fmt -check clean in gcp and azure.
  • terraform init -backend=false and terraform validate succeed in both env dirs.
  • No plan, apply or cloud access.

🤖 Generated with Claude Code

…ing and prod

Mirrors #856, which did the same for dev.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

  • Run on-demand review

This review includes 4 billable files and costs up to $1.00.

  • Ask an admin to make reviews automatic

Open in CodeRabbit

Reviews can continue after your included limit without a manual trigger. An admin must approve usage-based billing.

Or wait 39 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available. Your 62 included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: LeanerCloud/cloud-commitments-platform/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 4a274794-1842-4176-b1a7-70c5e88023fc
📥 Commits

Reviewing files that changed from the base of the PR and between 2c91411 and 461f373.

📒 Files selected for processing: 4
  • terraform/environments/azure/github-prod.tfvars
  • terraform/environments/azure/github-staging.tfvars
  • terraform/environments/gcp/github-prod.tfvars
  • terraform/environments/gcp/github-staging.tfvars
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@cristim

cristim commented Oct 13, 2026

Copy link
Copy Markdown
Member Author

Gate verdict: APPROVE at 461f373

Independent adversarial review by the gate agent (not the author). Config-only change, no deploy dispatched.

Diff (4 files, +12/-8). Each file adds one line enable_ri_exchange_schedule = true. The only other change is a terraform fmt realignment of the two existing lines, and their values are unchanged:

  • before: enable_scheduled_tasks = true / recommendation_schedule = "0 2 * * *"
  • after: enable_scheduled_tasks = true / recommendation_schedule = "0 2 * * *" / enable_ri_exchange_schedule = true
  • This is identical in azure/github-{staging,prod}.tfvars and gcp/github-{staging,prod}.tfvars.

Wiring. terraform/environments/gcp/compute.tf:95-96 and azure/compute.tf:120-121 pass the variable through. Both env variables.tf files default ri_exchange_schedule to "0 */6 * * *". The GCP Cloud Scheduler job is at modules/compute/gcp/cloud-run/main.tf:393-409 and the Azure Logic App at modules/compute/azure/container-apps/scheduled-tasks.tf:297-306. Both POST /api/scheduled/ri_exchange_reshape, which internal/server/handler.go:84,194 routes to handleRIExchangeReshape.

What runs per tick in prod (every 6h), from internal/server/handler_ri_exchange.go and cloud-commitments-go/pkg/exchange/auto.go @ ad67030387e4:

  1. RIExchangeEnabled == false (the default): logs "disabled, skipping" and returns (handler_ri_exchange.go:42-45). Nothing else runs.
  2. RIExchangeEnabled == true and RIExchangeMode == "manual" (the default mode, internal/config/store_postgres.go:152): lists convertible AWS RIs and utilization, then gets read-only exchange quotes. It cancels stale standalone pending records (auto.go:178-189), saves pending records (auto.go:255-262, processManualExchange) and emails approval tokens. No exchange runs and no money moves until a human approves.
  3. RIExchangeEnabled == true and mode is anything other than "manual": processAutoExchange (auto.go:480+) executes real AWS RI exchanges unattended. The per-exchange cap (auto.go:333-341) and a daily cap reservation (auto.go:523) bound each exchange. Reaching this state requires an explicit config write gated by execute:ri-exchange (requireRIExchangeAutoModeGrant, internal/api/handler.go:612), and both write paths call it (handler_config.go:122, handler_ri_exchange.go:2150). Raising a cap while armed also needs that grant.

So the schedule alone moves no money. Money moves only where a holder of execute:ri-exchange has explicitly armed a non-manual mode in that environment's config.

Azure preconditions. The precondition requires scheduled_task_secret_name (scheduled-tasks.tf:53-58). It comes from module.secrets.scheduled_task_secret_name (azure/compute.tf:116), and create_scheduled_task_secret defaults to true (modules/secrets/azure/variables.tf:124-127), with no override in staging/prod. enable_scheduled_tasks = true was already set there, so the precondition was already met.

Deploy path (PR body claims confirmed). deploy-gcp.yml / deploy-azure.yml resolve a push to main with no input to dev (lines 99-105 / 107-113). Staging and prod are deployed only by workflow_dispatch, or by deploy-all.yml on release: created, which forces ENVIRONMENT=prod (deploy-all.yml:52-53, 92-93). The next release therefore applies this to GCP and Azure prod. Merging the PR deploys nothing beyond dev, and dev already has the value from #856.

Local verification (from git archive 461f3735, Terraform v1.14.7, no backend, no cloud): terraform fmt -check -recursive, init -backend=false and validate all pass in environments/gcp and environments/azure. I ran no plan or apply. Real-account verification gap: I could not check whether any staging/prod GCP or Azure DB already has an armed (enabled + non-manual) RI exchange config. If one does, it will start executing on the next release.

CI: all checks green and mergeStateStatus CLEAN at 461f373.

@cristim
cristim merged commit 1501254 into main Oct 13, 2026
25 checks passed
@cristim
cristim deleted the chore/enable-ri-exchange-gcp-azure-stg-prod branch October 16, 2026 14:12
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