Skip to content

Check each release calls its own environment's Simulation Entrypoint - #4003

Draft
anth-volk wants to merge 2 commits into
masterfrom
v2plan/1j-141-own-environment-check
Draft

anth-volk wants to merge 2 commits into
masterfrom
v2plan/1j-141-own-environment-check

Conversation

@anth-volk

Copy link
Copy Markdown
Collaborator

Fixes #4002

Merge order: merge only after the staging secret points at the staging Simulation Entrypoint

Do not merge this PR until an operator has done both of these:

  1. Confirmed that the staging Simulation Entrypoint's stable URL answers /health with an x-policyengine-simulation-revision: policyengine-simulation-entry-staging-<number>-<suffix> header.
  2. Set this repository's staging environment secret SIMULATION_ENTRYPOINT_URL to that URL, leaving the production secret unchanged.

Why: today both environment secrets resolve to https://simulation.api.policyengine.org, which the production service policyengine-simulation-entry serves. With this check in place, the staging alignment job would reject that URL. Every staging and production deploy job needs the alignment jobs, so every release would fail at its staging step until the secret is changed.

Rollback: set the staging secret back to https://simulation.api.policyengine.org and revert this PR.

Summary

  • New script .github/scripts/check_simulation_entrypoint_environment.sh:
    • It requests /health from the Simulation Entrypoint URL that SIM_ENTRYPOINT selects, using the existing simulation_entrypoint_env.sh helper.
    • It reads the Cloud Run revision from the x-policyengine-simulation-revision response header, and takes the service name by removing the revision's five-digit number and three-character suffix.
    • Staging must be served by policyengine-simulation-entry-staging, and production by policyengine-simulation-entry.
    • The check fails on:
      • a revision from the other environment's service;
      • a response with no revision header (for example Cloud Run's sample container);
      • a name that is not a Cloud Run revision name;
      • a missing URL;
      • a failed request (curl's exit code);
      • an unknown DEPLOYMENT_ENVIRONMENT (exit 2).
    • The shared old gateway (SIM_ENTRYPOINT=old_gateway_direct) reports no environment, so it is not checked.
  • push.yml:
    • ensure-staging-model-version-aligns-with-sim-api and ensure-production-model-version-aligns-with-sim-api now set DEPLOYMENT_ENVIRONMENT and run the check right after checkout, before the bundle compatibility check.
    • deploy-cloud-run-staging and deploy-cloud-run-candidate need these jobs, and read the same environment secret in the same run. A release whose environments are crossed therefore stops before it deploys.
  • What changes once this merges after the secret change: the staging candidate's live simulation tests ("Run live simulations against the staging candidate") run against the staging Simulation Entrypoint, and through it the staging Modal environment, instead of production.
  • Documentation: docs/migration/cloud-run-operations.md states which URL each environment's secret holds and describes the check.
  • Changelog: fragment changelog.d/simulation-entrypoint-environment-check.added.md.
  • Rules: this PR changes no rules (rules/, scripts/rules/, the quality-guard scripts or CODEOWNERS).

Environment variables and secrets

Both changed jobs are the release workflow's version-alignment jobs. They run with environment: staging or environment: production, and only on the Update PolicyEngine API release commit.

Value Read by Provider How it reaches the script Status
DEPLOYMENT_ENVIRONMENT the new check literal in push.yml (staging or production) job env: Verified in this diff; the staging deploy job already sets the same literal
SIM_ENTRYPOINT the new check (selects the URL variable) staging and production environment variables, currently cloud_run_simulation_entrypoint in both job env: as ${{ vars.SIM_ENTRYPOINT }} (unchanged) Verified on 2026-10-20
SIMULATION_ENTRYPOINT_URL the new check, and (unchanged) the bundle check and the deploy jobs staging and production environment secrets job env: as ${{ secrets.SIMULATION_ENTRYPOINT_URL }} (unchanged); the deploy jobs pass the same secret to Cloud Run through deploy_cloud_run_candidate.sh Exists in both environments. Both currently resolve to https://simulation.api.policyengine.org (production), checked on the running services on 2026-10-20. The staging value must change before merge (see above).
OLD_SIMULATION_GATEWAY_URL not read by the check (it exits before selecting a URL when SIM_ENTRYPOINT=old_gateway_direct) repository variable — Unchanged

No secret or variable is added, and nothing is passed to Docker builds or to Cloud Run that was not passed before.

Testing

All runs are local, on this branch, with uv run --frozen after uv sync --frozen --extra dev.

  • Commit 9d99e5704, script and script tests:
    • Failing run first: before the script existed, pytest tests/unit/test_simulation_entrypoint_environment_script.py gave 11 failed.
    • Passing run after: 11 passed.
    • Tests cover:
      • both environments accepted;
      • a trailing slash on the URL;
      • staging calling production, and production calling staging;
      • the sample container's response with no header;
      • a name with no revision suffix;
      • a failed request;
      • an unknown environment;
      • a missing URL;
      • the old gateway skipped.
    • Other checks:
      • ruff format and ruff check on the test file: clean;
      • python scripts/run_quality_guards.py (migration-contracts, rules-registry, ci-scripts): passed;
      • shellcheck --format=gcc .github/scripts/*.sh, the guard's invocation: 0 findings.
  • Commit 0ed5c11b2, workflow wiring:
    • Failing run first: the two new workflow tests failed with KeyError: 'DEPLOYMENT_ENVIRONMENT'.
    • Passing run after:
      • the test file: 13 passed;
      • with tests/unit/test_cloud_run_deploy_scripts.py, test_deploy_pipeline_scripts.py, test_ci_complete_gate.py and test_alembic_workflows.py: 174 passed;
      • the quality guards and ruff: clean again.
  • Not run in this PR: the release workflow itself. An earlier read-only run of the same check logic against the real services behaved as expected:
    • staging with https://simulation.api.policyengine.org failed, naming production revision policyengine-simulation-entry-00122-low;
    • production with the same URL passed;
    • the staging stable URL, still serving the sample container, failed with "did not name a Simulation Entrypoint revision".

🤖 Generated with Claude Code

anth-volk and others added 2 commits October 22, 2026 02:10
…service

The new script requests /health from the Simulation Entrypoint URL that
SIM_ENTRYPOINT selects, reads the Cloud Run revision from the
x-policyengine-simulation-revision header, and removes the revision's
number and suffix to get the service name. Staging must be served by
policyengine-simulation-entry-staging and production by
policyengine-simulation-entry; a missing header, a name that is not a
Cloud Run revision, a failed request or an unknown environment fails.
The shared old gateway reports no environment and is not checked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The staging and production model-version alignment jobs now set
DEPLOYMENT_ENVIRONMENT and run check_simulation_entrypoint_environment.sh
right after checkout, before the bundle compatibility check. Every staging
and production deploy job needs these jobs, so a release whose staging
SIMULATION_ENTRYPOINT_URL is served by the production Simulation
Entrypoint, or the reverse, stops before it deploys.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.86%. Comparing base (62de73a) to head (0ed5c11).
⚠️ Report is 84 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4003      +/-   ##
==========================================
+ Coverage   86.00%   87.86%   +1.86%     
==========================================
  Files         259      259              
  Lines       15777    16149     +372     
  Branches     2628     2630       +2     
==========================================
+ Hits        13569    14190     +621     
+ Misses       1456     1283     -173     
+ Partials      752      676      -76     

☔ 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.

This branch was successfully deployed

1 active deployment
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.

Releases do not check that each environment calls its own simulation service

1 participant