Skip to content

Commit 113f333

Browse files
Pigbibicursoragent
andauthored
Fix Invoke Cloud Run workflow for internal ingress probe/dry-run paths. (#135)
Recreate probe and precheck Cloud Scheduler jobs as annual invoke bridges so GitHub Actions can trigger /probe and /dry-run against internal Cloud Run, while scheduled checks remain owned by the monitor dispatcher. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 3c02b4d commit 113f333

4 files changed

Lines changed: 105 additions & 5 deletions

File tree

.github/workflows/invoke-cloud-run.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ env:
1818
GCP_PROJECT_ID: firstradequant
1919
GCP_WORKLOAD_IDENTITY_PROVIDER: projects/1088907247379/locations/global/workloadIdentityPools/github-actions/providers/github-main
2020
GCP_WORKLOAD_IDENTITY_SERVICE_ACCOUNT: firstrade-platform-deploy@firstradequant.iam.gserviceaccount.com
21+
GCP_SCHEDULER_SERVICE_ACCOUNT: firstrade-platform-scheduler@firstradequant.iam.gserviceaccount.com
2122

2223
concurrency:
2324
group: ${{ github.workflow }}-${{ github.ref_name }}
@@ -123,6 +124,45 @@ jobs:
123124
scheduler_job=""
124125
scheduler_location=""
125126
scheduler_expected_path=""
127+
ensure_invoke_bridge_job() {
128+
local bridge_job="$1"
129+
local bridge_uri="$2"
130+
local bridge_location="$3"
131+
if gcloud scheduler jobs describe "${bridge_job}" \
132+
--project="${GCP_PROJECT_ID}" \
133+
--location="${bridge_location}" >/dev/null 2>&1; then
134+
current_uri="$(
135+
gcloud scheduler jobs describe "${bridge_job}" \
136+
--project="${GCP_PROJECT_ID}" \
137+
--location="${bridge_location}" \
138+
--format='value(httpTarget.uri)' 2>/dev/null || true
139+
)"
140+
if [ -n "${current_uri}" ] && [ "${current_uri}" != "${bridge_uri}" ]; then
141+
echo "Updating invoke-bridge Cloud Scheduler job ${bridge_job} to ${bridge_uri}."
142+
gcloud scheduler jobs update http "${bridge_job}" \
143+
--project="${GCP_PROJECT_ID}" \
144+
--location="${bridge_location}" \
145+
--uri="${bridge_uri}" \
146+
--http-method=POST \
147+
--oidc-service-account-email="${GCP_SCHEDULER_SERVICE_ACCOUNT}" \
148+
--oidc-token-audience="${service_url}" \
149+
--quiet
150+
fi
151+
return 0
152+
fi
153+
echo "Creating invoke-bridge Cloud Scheduler job ${bridge_job} -> ${bridge_uri}."
154+
gcloud scheduler jobs create http "${bridge_job}" \
155+
--project="${GCP_PROJECT_ID}" \
156+
--location="${bridge_location}" \
157+
--uri="${bridge_uri}" \
158+
--http-method=POST \
159+
--oidc-service-account-email="${GCP_SCHEDULER_SERVICE_ACCOUNT}" \
160+
--oidc-token-audience="${service_url}" \
161+
--schedule="0 0 1 1 *" \
162+
--time-zone="UTC" \
163+
--attempt-deadline=600s \
164+
--quiet
165+
}
126166
if [ "${service_ingress}" = "internal" ]; then
127167
scheduler_location="${CLOUD_SCHEDULER_LOCATION:-${CLOUD_RUN_REGION}}"
128168
case "${raw_path}" in
@@ -133,10 +173,12 @@ jobs:
133173
/probe)
134174
scheduler_job="${CLOUD_RUN_SERVICE}-probe-scheduler"
135175
scheduler_expected_path="/probe"
176+
ensure_invoke_bridge_job "${scheduler_job}" "${service_url}/probe" "${scheduler_location}"
136177
;;
137178
/dry-run)
138179
scheduler_job="${CLOUD_RUN_SERVICE}-precheck-scheduler"
139180
scheduler_expected_path="/dry-run"
181+
ensure_invoke_bridge_job "${scheduler_job}" "${service_url}/dry-run" "${scheduler_location}"
140182
;;
141183
*)
142184
echo "Cloud Run service ${CLOUD_RUN_SERVICE} has internal ingress, so GitHub-hosted runners cannot curl ${raw_path} directly." >&2
@@ -147,6 +189,7 @@ jobs:
147189
148190
scheduler_uri="$(
149191
gcloud scheduler jobs describe "${scheduler_job}" \
192+
--project="${GCP_PROJECT_ID}" \
150193
--location="${scheduler_location}" \
151194
--format='value(httpTarget.uri)' 2>/dev/null || true
152195
)"

.github/workflows/sync-cloud-run-env.yml

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -861,23 +861,60 @@ jobs:
861861
--quiet
862862
fi
863863
864+
invoke_bridge_jobs=(
865+
"${CLOUD_RUN_SERVICE}-probe-scheduler|${service_url}/probe"
866+
"${CLOUD_RUN_SERVICE}-precheck-scheduler|${service_url}/dry-run"
867+
)
868+
if [[ "${CLOUD_RUN_SERVICE}" == *-service ]]; then
869+
invoke_bridge_jobs+=(
870+
"${CLOUD_RUN_SERVICE%-service}-probe-scheduler|${service_url}/probe"
871+
"${CLOUD_RUN_SERVICE%-service}-precheck-scheduler|${service_url}/dry-run"
872+
)
873+
fi
874+
for bridge_entry in "${invoke_bridge_jobs[@]}"; do
875+
bridge_job="${bridge_entry%%|*}"
876+
bridge_uri="${bridge_entry#*|}"
877+
if gcloud scheduler jobs describe "${bridge_job}" \
878+
--project="${GCP_PROJECT_ID}" \
879+
--location="${scheduler_location}" >/dev/null 2>&1; then
880+
echo "Updating invoke-bridge Cloud Scheduler job ${bridge_job} to ${bridge_uri}."
881+
gcloud scheduler jobs update http "${bridge_job}" \
882+
--project="${GCP_PROJECT_ID}" \
883+
--location="${scheduler_location}" \
884+
--uri="${bridge_uri}" \
885+
--http-method=POST \
886+
--oidc-service-account-email="${GCP_SCHEDULER_SERVICE_ACCOUNT}" \
887+
--oidc-token-audience="${service_url}" \
888+
--quiet
889+
else
890+
echo "Creating invoke-bridge Cloud Scheduler job ${bridge_job} at ${bridge_uri}."
891+
gcloud scheduler jobs create http "${bridge_job}" \
892+
--project="${GCP_PROJECT_ID}" \
893+
--location="${scheduler_location}" \
894+
--uri="${bridge_uri}" \
895+
--http-method=POST \
896+
--oidc-service-account-email="${GCP_SCHEDULER_SERVICE_ACCOUNT}" \
897+
--oidc-token-audience="${service_url}" \
898+
--schedule="0 0 1 1 *" \
899+
--time-zone="UTC" \
900+
--attempt-deadline=600s \
901+
--quiet
902+
fi
903+
done
904+
864905
legacy_jobs=(
865-
"${CLOUD_RUN_SERVICE}-probe-scheduler"
866-
"${CLOUD_RUN_SERVICE}-precheck-scheduler"
867906
"${CLOUD_RUN_SERVICE}-session-check-scheduler"
868907
)
869908
if [[ "${CLOUD_RUN_SERVICE}" == *-service ]]; then
870909
legacy_jobs+=(
871-
"${CLOUD_RUN_SERVICE%-service}-probe-scheduler"
872-
"${CLOUD_RUN_SERVICE%-service}-precheck-scheduler"
873910
"${CLOUD_RUN_SERVICE%-service}-session-check-scheduler"
874911
)
875912
fi
876913
for legacy_job in "${legacy_jobs[@]}"; do
877914
if gcloud scheduler jobs describe "${legacy_job}" \
878915
--project="${GCP_PROJECT_ID}" \
879916
--location="${scheduler_location}" >/dev/null 2>&1; then
880-
echo "Deleting legacy Cloud Scheduler job ${legacy_job}; monitor dispatcher now owns probe/precheck."
917+
echo "Deleting legacy Cloud Scheduler job ${legacy_job}; session checks are handled elsewhere."
881918
gcloud scheduler jobs delete "${legacy_job}" \
882919
--project="${GCP_PROJECT_ID}" \
883920
--location="${scheduler_location}" \
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from __future__ import annotations
2+
3+
from pathlib import Path
4+
5+
6+
def test_invoke_cloud_run_workflow_ensures_probe_and_dry_run_scheduler_bridges():
7+
workflow_path = Path(__file__).resolve().parents[1] / ".github/workflows/invoke-cloud-run.yml"
8+
workflow = workflow_path.read_text(encoding="utf-8")
9+
10+
assert "GCP_SCHEDULER_SERVICE_ACCOUNT: firstrade-platform-scheduler@firstradequant.iam.gserviceaccount.com" in workflow
11+
assert "ensure_invoke_bridge_job()" in workflow
12+
assert 'scheduler_job="${CLOUD_RUN_SERVICE}-probe-scheduler"' in workflow
13+
assert 'scheduler_job="${CLOUD_RUN_SERVICE}-precheck-scheduler"' in workflow
14+
assert 'ensure_invoke_bridge_job "${scheduler_job}" "${service_url}/probe"' in workflow
15+
assert 'ensure_invoke_bridge_job "${scheduler_job}" "${service_url}/dry-run"' in workflow
16+
assert '--schedule="0 0 1 1 *"' in workflow

tests/test_sync_cloud_run_env_workflow.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,10 @@ def test_sync_cloud_run_env_workflow_syncs_scheduler_from_runtime_target():
157157
assert 'gcloud scheduler jobs create http "${job_name}"' in workflow
158158
assert 'monitor_job_name="firstrade-monitor-dispatcher-scheduler"' in workflow
159159
assert 'monitor_uri="${service_url}/monitor-dispatch"' in workflow
160+
assert 'invoke_bridge_jobs=(' in workflow
161+
assert '"${CLOUD_RUN_SERVICE}-probe-scheduler|${service_url}/probe"' in workflow
162+
assert '"${CLOUD_RUN_SERVICE}-precheck-scheduler|${service_url}/dry-run"' in workflow
163+
assert 'Creating invoke-bridge Cloud Scheduler job ${bridge_job} at ${bridge_uri}.' in workflow
160164
assert '"${CLOUD_RUN_SERVICE}-session-check-scheduler"' in workflow
161165
assert 'gcloud scheduler jobs delete "${legacy_job}"' in workflow
162166
assert '--schedule="${desired_schedule}"' in workflow

0 commit comments

Comments
 (0)