Context
PR #3733 added post-deploy cleanup for the App Engine (Flexible) v1 API: after each deploy it stops idle SERVING versions and deletes stopped versions beyond a retention window (cleanup_app_engine_versions.sh + the stop-staging-app-engine-version / cleanup-prod-app-engine-versions jobs in push.yml). It exists because App Engine Flex keeps an always-on VM for every non-stopped version, so idle versions cost money (~$212/mo each).
The v1 API is migrating to Cloud Run. When that cutover completes, this App Engine cleanup becomes obsolete and should be retired — but we still need an equivalent hygiene mechanism for Cloud Run.
Why Cloud Run differs (and what still needs doing)
Cloud Run scales to zero by default: an old revision with no traffic runs no instances and costs ~$0, and min-instances applies only to the revision(s) receiving traffic — it is not a per-revision floor. So the App Engine "idle version = always-on VM" cost problem does not carry over automatically.
However, on migration we will need to:
- Prune old revisions. Cloud Run has a per-service revision limit and revisions accumulate on every deploy (the
policyengine-api Cloud Run service already carries 20+ revisions). Add gcloud run revisions delete for revisions beyond a retention window, analogous to the App Engine version delete.
- Guard against stray
min-instances / reserved resources on superseded revisions or services. If an old revision or service is left with min-instances > 0 (or CPU-always-allocated), it keeps warm instances running and costs money. The cleanup should verify only the live revision carries a min-instance floor and de-resource anything else.
- Retire the App Engine machinery. Remove
cleanup_app_engine_versions.sh, stop_app_engine_version.sh, and the two App Engine cleanup jobs once App Engine is no longer deployed.
Suggested approach
Extend or replace cleanup_app_engine_versions.sh with a Cloud Run equivalent (e.g. cleanup_cloud_run_revisions.sh) wired into the Cloud Run deploy path in push.yml, keeping the same shape: keep the live + N recent revisions, delete older, and assert no superseded revision holds reserved instances. Reuse the stubbed-gcloud unit-test pattern in tests/unit/test_app_engine_cleanup_scripts.py.
Ref: #3733
Context
PR #3733 added post-deploy cleanup for the App Engine (Flexible) v1 API: after each deploy it stops idle
SERVINGversions and deletes stopped versions beyond a retention window (cleanup_app_engine_versions.sh+ thestop-staging-app-engine-version/cleanup-prod-app-engine-versionsjobs inpush.yml). It exists because App Engine Flex keeps an always-on VM for every non-stopped version, so idle versions cost money (~$212/mo each).The v1 API is migrating to Cloud Run. When that cutover completes, this App Engine cleanup becomes obsolete and should be retired — but we still need an equivalent hygiene mechanism for Cloud Run.
Why Cloud Run differs (and what still needs doing)
Cloud Run scales to zero by default: an old revision with no traffic runs no instances and costs ~$0, and
min-instancesapplies only to the revision(s) receiving traffic — it is not a per-revision floor. So the App Engine "idle version = always-on VM" cost problem does not carry over automatically.However, on migration we will need to:
policyengine-apiCloud Run service already carries 20+ revisions). Addgcloud run revisions deletefor revisions beyond a retention window, analogous to the App Engine version delete.min-instances/ reserved resources on superseded revisions or services. If an old revision or service is left withmin-instances > 0(or CPU-always-allocated), it keeps warm instances running and costs money. The cleanup should verify only the live revision carries a min-instance floor and de-resource anything else.cleanup_app_engine_versions.sh,stop_app_engine_version.sh, and the two App Engine cleanup jobs once App Engine is no longer deployed.Suggested approach
Extend or replace
cleanup_app_engine_versions.shwith a Cloud Run equivalent (e.g.cleanup_cloud_run_revisions.sh) wired into the Cloud Run deploy path inpush.yml, keeping the same shape: keep the live + N recent revisions, delete older, and assert no superseded revision holds reserved instances. Reuse the stubbed-gcloudunit-test pattern intests/unit/test_app_engine_cleanup_scripts.py.Ref: #3733