From a30ee21fd4ebae05eb65408f261f6f536a435bb4 Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Mon, 25 May 2026 17:31:11 +0800 Subject: [PATCH] Rename Google Voice config to recipients --- .github/workflows/sync-cloud-run-env.yml | 9 +++++---- README.md | 10 +++++----- requirements.txt | 4 ++-- runtime_config_support.py | 6 +++--- tests/conftest.py | 2 +- tests/test_runtime_config_support.py | 6 +++--- tests/test_sync_cloud_run_env_workflow.sh | 7 ++++--- 7 files changed, 23 insertions(+), 21 deletions(-) diff --git a/.github/workflows/sync-cloud-run-env.yml b/.github/workflows/sync-cloud-run-env.yml index a4e3b1f..1911af2 100644 --- a/.github/workflows/sync-cloud-run-env.yml +++ b/.github/workflows/sync-cloud-run-env.yml @@ -34,7 +34,7 @@ jobs: IBKR_MIN_RESERVED_CASH_USD: ${{ vars.IBKR_MIN_RESERVED_CASH_USD }} IBKR_RESERVED_CASH_RATIO: ${{ vars.IBKR_RESERVED_CASH_RATIO }} IBKR_SAFE_HAVEN_CASH_SUBSTITUTE_THRESHOLD_USD: ${{ vars.IBKR_SAFE_HAVEN_CASH_SUBSTITUTE_THRESHOLD_USD }} - CRISIS_ALERT_GOOGLE_VOICE_GATEWAY: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_GATEWAY }} + CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS }} CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER }} CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME }} # Strategy-owned defaults continue to come from UsEquityStrategies; this workflow only syncs platform/runtime inputs. @@ -268,6 +268,7 @@ jobs: "IB_GATEWAY_INSTANCE_NAME" "IB_GATEWAY_MODE" "CRISIS_ALERT_GOOGLE_VOICE_TO" + "CRISIS_ALERT_GOOGLE_VOICE_GATEWAY" "CRISIS_ALERT_SMTP_FROM" "CRISIS_ALERT_SMTP_HOST" "CRISIS_ALERT_SMTP_PORT" @@ -368,10 +369,10 @@ jobs: remove_env_vars+=("IBKR_RESERVED_CASH_RATIO") fi - if [ -n "${CRISIS_ALERT_GOOGLE_VOICE_GATEWAY:-}" ]; then - env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_GATEWAY=${CRISIS_ALERT_GOOGLE_VOICE_GATEWAY}") + if [ -n "${CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS:-}" ]; then + env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS=${CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS}") else - remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_GATEWAY") + remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS") fi if [ -n "${CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER:-}" ]; then diff --git a/README.md b/README.md index 5810606..0c58ece 100644 --- a/README.md +++ b/README.md @@ -112,9 +112,9 @@ For IBKR, keep `paper` as a single account-group entry. If you later add live ac | `TELEGRAM_TOKEN` | Yes | Telegram bot token. For Cloud Run, prefer a Secret Manager reference instead of a literal env var. | | `GLOBAL_TELEGRAM_CHAT_ID` | Yes | Telegram chat ID used by this service. | | `NOTIFY_LANG` | No | `en` (default) or `zh` | -| `CRISIS_ALERT_GOOGLE_VOICE_GATEWAY` | No | Comma/semicolon/newline-separated Google Voice SMS gateway recipients, usually ending in `@txt.voice.google.com`. | -| `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER` | No | Gmail address used to send Google Voice gateway alerts. | -| `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD` | No | Gmail App Password for Google Voice gateway alerts. For Cloud Run, prefer `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME` in env sync. | +| `CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS` | No | Comma/semicolon/newline-separated email-form recipients. Use a normal mailbox for email-only delivery, or a Google Voice mailbox/address to also trigger GV prompts. | +| `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER` | No | Gmail address used as the sender for Google Voice notification mail. | +| `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD` | No | Gmail App Password for the sender account. For Cloud Run, prefer `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME` in env sync. | The selected account-group entry must provide at least: @@ -358,9 +358,9 @@ IBKR 账户 | `TELEGRAM_TOKEN` | 是 | Telegram 机器人 Token。Cloud Run 上更推荐走 Secret Manager 引用,不要直接写成明文 env。 | | `GLOBAL_TELEGRAM_CHAT_ID` | 是 | 这个服务使用的 Telegram Chat ID。 | | `NOTIFY_LANG` | 否 | `en`(默认)或 `zh` | -| `CRISIS_ALERT_GOOGLE_VOICE_GATEWAY` | 否 | Google Voice 短信网关收件人,通常以 `@txt.voice.google.com` 结尾,支持逗号、分号或换行分隔。 | +| `CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS` | 否 | 通知收件邮箱。普通邮箱只收邮件;Google Voice 邮箱/地址会额外触发 GV 提醒。支持逗号、分号或换行分隔。 | | `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER` | 否 | Google Voice 通知使用的 Gmail 地址。 | -| `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD` | 否 | Google Voice 通知使用的 Gmail App Password。Cloud Run env sync 建议配置 `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME`。 | +| `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD` | 否 | 发送方 Gmail 账号的 App Password。Cloud Run env sync 建议配置 `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME`。 | 选中的账号组配置里,至少要有: diff --git a/requirements.txt b/requirements.txt index 927d54b..492b6c0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ flask gunicorn -quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@34a2c74deb7aafef0f6f4b278444d7b0efb76794 -us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@861eaedc1caecf1e33ff12f55bbe9af87a221df1 +quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@705667fbb88b743eb83e858b1cc42fe9ebc3a87a +us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@aca4e1449e9e87e0222b8a1a5e0dd84f822d516c pandas numpy requests diff --git a/runtime_config_support.py b/runtime_config_support.py index 0594ed3..b8c2721 100644 --- a/runtime_config_support.py +++ b/runtime_config_support.py @@ -72,7 +72,7 @@ class PlatformRuntimeSettings: tg_chat_id: str | None = None notify_lang: str = "en" strategy_plugin_mounts_json: str | None = None - crisis_alert_google_voice_gateway: tuple[str, ...] = () + crisis_alert_google_voice_recipients: tuple[str, ...] = () crisis_alert_google_voice_gmail_user: str | None = None crisis_alert_google_voice_gmail_app_password: str | None = None runtime_target: RuntimeTarget | None = None @@ -183,8 +183,8 @@ def load_platform_runtime_settings( os.getenv("IBKR_STRATEGY_PLUGIN_MOUNTS_JSON") or os.getenv("STRATEGY_PLUGIN_MOUNTS_JSON") ), - crisis_alert_google_voice_gateway=split_env_list( - os.getenv("CRISIS_ALERT_GOOGLE_VOICE_GATEWAY") + crisis_alert_google_voice_recipients=split_env_list( + os.getenv("CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS") ), crisis_alert_google_voice_gmail_user=first_non_empty( os.getenv("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER") diff --git a/tests/conftest.py b/tests/conftest.py index 0512f0b..f4d5692 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -30,7 +30,7 @@ def load_strategy_module(**env_overrides): ), "IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME": None, "GLOBAL_TELEGRAM_CHAT_ID": None, - "CRISIS_ALERT_GOOGLE_VOICE_GATEWAY": None, + "CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS": None, "CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER": None, "CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD": None, } diff --git a/tests/test_runtime_config_support.py b/tests/test_runtime_config_support.py index 0128bee..791f677 100644 --- a/tests/test_runtime_config_support.py +++ b/tests/test_runtime_config_support.py @@ -135,7 +135,7 @@ def test_load_platform_runtime_settings_uses_minimal_group_config(monkeypatch): assert settings.tg_token is None assert settings.tg_chat_id is None assert settings.strategy_plugin_mounts_json is None - assert settings.crisis_alert_google_voice_gateway == () + assert settings.crisis_alert_google_voice_recipients == () assert settings.crisis_alert_google_voice_gmail_user is None assert settings.crisis_alert_google_voice_gmail_app_password is None @@ -207,13 +207,13 @@ def test_load_platform_runtime_settings_reads_crisis_alert_google_voice_config(m monkeypatch.setenv("RUNTIME_TARGET_JSON", runtime_target_json(SAMPLE_STRATEGY_PROFILE)) monkeypatch.setenv("ACCOUNT_GROUP", "paper") monkeypatch.setenv("IB_ACCOUNT_GROUP_CONFIG_JSON", MINIMAL_GROUP_JSON) - monkeypatch.setenv("CRISIS_ALERT_GOOGLE_VOICE_GATEWAY", "gateway@txt.voice.google.com") + monkeypatch.setenv("CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS", "alerts@example.com; voice@example.com") monkeypatch.setenv("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER", "sender@gmail.com") monkeypatch.setenv("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD", "secret") settings = load_platform_runtime_settings(project_id_resolver=lambda: "project-1") - assert settings.crisis_alert_google_voice_gateway == ("gateway@txt.voice.google.com",) + assert settings.crisis_alert_google_voice_recipients == ("alerts@example.com", "voice@example.com") assert settings.crisis_alert_google_voice_gmail_user == "sender@gmail.com" assert settings.crisis_alert_google_voice_gmail_app_password == "secret" diff --git a/tests/test_sync_cloud_run_env_workflow.sh b/tests/test_sync_cloud_run_env_workflow.sh index 409282e..8b39f11 100644 --- a/tests/test_sync_cloud_run_env_workflow.sh +++ b/tests/test_sync_cloud_run_env_workflow.sh @@ -45,7 +45,7 @@ grep -Fq 'IBKR_PAPER_LIQUIDATE_ONLY: ${{ vars.IBKR_PAPER_LIQUIDATE_ONLY }}' "$wo grep -Fq 'IBKR_MIN_RESERVED_CASH_USD: ${{ vars.IBKR_MIN_RESERVED_CASH_USD }}' "$workflow_file" grep -Fq 'IBKR_RESERVED_CASH_RATIO: ${{ vars.IBKR_RESERVED_CASH_RATIO }}' "$workflow_file" grep -Fq 'IBKR_SAFE_HAVEN_CASH_SUBSTITUTE_THRESHOLD_USD: ${{ vars.IBKR_SAFE_HAVEN_CASH_SUBSTITUTE_THRESHOLD_USD }}' "$workflow_file" -grep -Fq 'CRISIS_ALERT_GOOGLE_VOICE_GATEWAY: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_GATEWAY }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS }}' "$workflow_file" grep -Fq 'CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER }}' "$workflow_file" grep -Fq 'CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME }}' "$workflow_file" grep -Fq 'IB_GATEWAY_ZONE: ${{ vars.IB_GATEWAY_ZONE }}' "$workflow_file" @@ -91,7 +91,7 @@ grep -Fq 'env_pairs+=("IBKR_PAPER_LIQUIDATE_ONLY=${IBKR_PAPER_LIQUIDATE_ONLY}")' grep -Fq 'env_pairs+=("IBKR_MIN_RESERVED_CASH_USD=${IBKR_MIN_RESERVED_CASH_USD}")' "$workflow_file" grep -Fq 'env_pairs+=("IBKR_RESERVED_CASH_RATIO=${IBKR_RESERVED_CASH_RATIO}")' "$workflow_file" grep -Fq 'env_pairs+=("IBKR_SAFE_HAVEN_CASH_SUBSTITUTE_THRESHOLD_USD=${IBKR_SAFE_HAVEN_CASH_SUBSTITUTE_THRESHOLD_USD}")' "$workflow_file" -grep -Fq 'env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_GATEWAY=${CRISIS_ALERT_GOOGLE_VOICE_GATEWAY}")' "$workflow_file" +grep -Fq 'env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS=${CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS}")' "$workflow_file" grep -Fq 'env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER=${CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER}")' "$workflow_file" grep -Fq 'env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD=${CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD}")' "$workflow_file" grep -Fq 'remove_env_vars+=("IBKR_FEATURE_SNAPSHOT_PATH")' "$workflow_file" @@ -104,10 +104,11 @@ grep -Fq 'remove_env_vars+=("IBKR_PAPER_LIQUIDATE_ONLY")' "$workflow_file" grep -Fq 'remove_env_vars+=("IBKR_MIN_RESERVED_CASH_USD")' "$workflow_file" grep -Fq 'remove_env_vars+=("IBKR_RESERVED_CASH_RATIO")' "$workflow_file" grep -Fq 'remove_env_vars+=("IBKR_SAFE_HAVEN_CASH_SUBSTITUTE_THRESHOLD_USD")' "$workflow_file" -grep -Fq 'remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_GATEWAY")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS")' "$workflow_file" grep -Fq 'remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER")' "$workflow_file" grep -Fq 'remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD")' "$workflow_file" grep -Fq '"CRISIS_ALERT_GOOGLE_VOICE_TO"' "$workflow_file" +grep -Fq '"CRISIS_ALERT_GOOGLE_VOICE_GATEWAY"' "$workflow_file" grep -Fq '"CRISIS_ALERT_SMTP_HOST"' "$workflow_file" grep -Fq 'secret_pairs+=("TELEGRAM_TOKEN=${TELEGRAM_TOKEN_SECRET_NAME}:latest")' "$workflow_file" grep -Fq 'secret_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD=${CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME}:latest")' "$workflow_file"