diff --git a/.github/workflows/sync-cloud-run-env.yml b/.github/workflows/sync-cloud-run-env.yml index 1911af2..f475aba 100644 --- a/.github/workflows/sync-cloud-run-env.yml +++ b/.github/workflows/sync-cloud-run-env.yml @@ -35,8 +35,11 @@ jobs: 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_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 }} + CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL }} + CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD_SECRET_NAME: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD_SECRET_NAME }} + CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST }} + CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT }} + CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY }} # Strategy-owned defaults continue to come from UsEquityStrategies; this workflow only syncs platform/runtime inputs. EXECUTION_REPORT_GCS_URI: ${{ vars.EXECUTION_REPORT_GCS_URI }} IB_GATEWAY_ZONE: ${{ vars.IB_GATEWAY_ZONE }} @@ -44,7 +47,7 @@ jobs: GLOBAL_TELEGRAM_CHAT_ID: ${{ vars.GLOBAL_TELEGRAM_CHAT_ID }} NOTIFY_LANG: ${{ vars.NOTIFY_LANG }} TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }} - CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD: ${{ secrets.CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD }} + CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD: ${{ secrets.CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD }} steps: - name: Check whether env sync is enabled id: config @@ -269,6 +272,8 @@ jobs: "IB_GATEWAY_MODE" "CRISIS_ALERT_GOOGLE_VOICE_TO" "CRISIS_ALERT_GOOGLE_VOICE_GATEWAY" + "CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER" + "CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD" "CRISIS_ALERT_SMTP_FROM" "CRISIS_ALERT_SMTP_HOST" "CRISIS_ALERT_SMTP_PORT" @@ -277,7 +282,7 @@ jobs: "CRISIS_ALERT_SMTP_STARTTLS" "CRISIS_ALERT_SMTP_SSL" ) - remove_secret_vars=("CRISIS_ALERT_SMTP_PASSWORD") + remove_secret_vars=("CRISIS_ALERT_SMTP_PASSWORD" "CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD") if [ -n "${TELEGRAM_TOKEN_SECRET_NAME:-}" ]; then secret_pairs+=("TELEGRAM_TOKEN=${TELEGRAM_TOKEN_SECRET_NAME}:latest") @@ -286,15 +291,15 @@ jobs: remove_secret_vars+=("TELEGRAM_TOKEN") fi - if [ -n "${CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME:-}" ]; then - secret_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD=${CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME}:latest") - remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD") - elif [ -n "${CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD:-}" ]; then - env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD=${CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD}") - remove_secret_vars+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD") + if [ -n "${CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD_SECRET_NAME:-}" ]; then + secret_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD=${CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD_SECRET_NAME}:latest") + remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD") + elif [ -n "${CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD:-}" ]; then + env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD=${CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD}") + remove_secret_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD") else - remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD") - remove_secret_vars+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD") + remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD") + remove_secret_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD") fi if [ -n "${IB_GATEWAY_ZONE:-}" ]; then @@ -375,10 +380,28 @@ jobs: remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS") fi - if [ -n "${CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER:-}" ]; then - env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER=${CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER}") + if [ -n "${CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL:-}" ]; then + env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL=${CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL}") else - remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER") + remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL") + fi + + if [ -n "${CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST:-}" ]; then + env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST=${CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST}") + else + remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST") + fi + + if [ -n "${CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT:-}" ]; then + env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT=${CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT}") + else + remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT") + fi + + if [ -n "${CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY:-}" ]; then + env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY=${CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY}") + else + remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY") fi if [ -n "${EXECUTION_REPORT_GCS_URI:-}" ]; then diff --git a/README.md b/README.md index 0c58ece..31524e7 100644 --- a/README.md +++ b/README.md @@ -113,8 +113,11 @@ For IBKR, keep `paper` as a single account-group entry. If you later add live ac | `GLOBAL_TELEGRAM_CHAT_ID` | Yes | Telegram chat ID used by this service. | | `NOTIFY_LANG` | No | `en` (default) or `zh` | | `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. | +| `CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL` | No | Sender email address used for Google Voice notification mail. Gmail is the default transport, but the sender naming is provider-neutral. | +| `CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD` | No | Sender SMTP password or app password. For Cloud Run, prefer `CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD_SECRET_NAME` in env sync. | +| `CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST` | No | Optional SMTP host override. Defaults to Gmail SMTP when unset. | +| `CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT` | No | Optional SMTP port override. Defaults to `465` when unset. | +| `CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY` | No | Optional SMTP security override: `ssl`, `starttls`, or `none`. Defaults to `ssl` when unset. | The selected account-group entry must provide at least: @@ -232,7 +235,7 @@ Recommended setup: - `NOTIFY_LANG` - **Repository Secrets** - `TELEGRAM_TOKEN` (fallback only when `TELEGRAM_TOKEN_SECRET_NAME` is not set) - - `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD` (fallback only when `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME` is not set) + - `CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD` (fallback only when `CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD_SECRET_NAME` is not set) - **Optional transition Variables** - `IB_GATEWAY_ZONE` - `IB_GATEWAY_IP_MODE` @@ -359,8 +362,11 @@ IBKR 账户 | `GLOBAL_TELEGRAM_CHAT_ID` | 是 | 这个服务使用的 Telegram Chat ID。 | | `NOTIFY_LANG` | 否 | `en`(默认)或 `zh` | | `CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS` | 否 | 通知收件邮箱。普通邮箱只收邮件;Google Voice 邮箱/地址会额外触发 GV 提醒。支持逗号、分号或换行分隔。 | -| `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER` | 否 | Google Voice 通知使用的 Gmail 地址。 | -| `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD` | 否 | 发送方 Gmail 账号的 App Password。Cloud Run env sync 建议配置 `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME`。 | +| `CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL` | 否 | Google Voice 通知邮件的发送方邮箱。默认传输走 Gmail SMTP,但命名不绑定 Gmail。 | +| `CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD` | 否 | 发送方 SMTP 密码或 app password。Cloud Run env sync 建议配置 `CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD_SECRET_NAME`。 | +| `CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST` | 否 | 可选 SMTP host 覆盖。不设置时默认 Gmail SMTP。 | +| `CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT` | 否 | 可选 SMTP port 覆盖。不设置时默认 `465`。 | +| `CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY` | 否 | 可选 SMTP 加密方式:`ssl`、`starttls` 或 `none`。不设置时默认 `ssl`。 | 选中的账号组配置里,至少要有: @@ -444,7 +450,7 @@ Google Voice 告警结果会写入 runtime report。重复发送抑制使用稳 - `NOTIFY_LANG` - **仓库级 Secrets** - `TELEGRAM_TOKEN`(仅在没设置 `TELEGRAM_TOKEN_SECRET_NAME` 时作为 fallback) - - `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD`(仅在没设置 `CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD_SECRET_NAME` 时作为 fallback) + - `CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD`(仅在没设置 `CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD_SECRET_NAME` 时作为 fallback) - **可选过渡 Variables** - `IB_GATEWAY_ZONE` - `IB_GATEWAY_IP_MODE` diff --git a/requirements.txt b/requirements.txt index 492b6c0..920d439 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ flask gunicorn -quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@705667fbb88b743eb83e858b1cc42fe9ebc3a87a -us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@aca4e1449e9e87e0222b8a1a5e0dd84f822d516c +quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@43b2ecb9dc7b1a70e52fe038ce321d79f5f7987a +us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@a3f1899079d8d6c11601dddc40cb6f3020b6fc82 pandas numpy requests diff --git a/runtime_config_support.py b/runtime_config_support.py index b8c2721..ac09abb 100644 --- a/runtime_config_support.py +++ b/runtime_config_support.py @@ -73,8 +73,11 @@ class PlatformRuntimeSettings: notify_lang: str = "en" strategy_plugin_mounts_json: str | None = None 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 + crisis_alert_google_voice_sender_email: str | None = None + crisis_alert_google_voice_sender_password: str | None = None + crisis_alert_google_voice_smtp_host: str | None = None + crisis_alert_google_voice_smtp_port: str | None = None + crisis_alert_google_voice_smtp_security: str | None = None runtime_target: RuntimeTarget | None = None @@ -186,11 +189,20 @@ def load_platform_runtime_settings( 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") + crisis_alert_google_voice_sender_email=first_non_empty( + os.getenv("CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL") ), - crisis_alert_google_voice_gmail_app_password=first_non_empty( - os.getenv("CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD") + crisis_alert_google_voice_sender_password=first_non_empty( + os.getenv("CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD") + ), + crisis_alert_google_voice_smtp_host=first_non_empty( + os.getenv("CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST") + ), + crisis_alert_google_voice_smtp_port=first_non_empty( + os.getenv("CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT") + ), + crisis_alert_google_voice_smtp_security=first_non_empty( + os.getenv("CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY") ), runtime_target=runtime_target, ) diff --git a/tests/conftest.py b/tests/conftest.py index f4d5692..2a7f72a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -31,8 +31,11 @@ def load_strategy_module(**env_overrides): "IB_ACCOUNT_GROUP_CONFIG_SECRET_NAME": None, "GLOBAL_TELEGRAM_CHAT_ID": None, "CRISIS_ALERT_GOOGLE_VOICE_RECIPIENTS": None, - "CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER": None, - "CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD": None, + "CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL": None, + "CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD": None, + "CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST": None, + "CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT": None, + "CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY": None, } defaults.update(env_overrides) if "RUNTIME_TARGET_JSON" not in defaults: diff --git a/tests/test_runtime_config_support.py b/tests/test_runtime_config_support.py index 791f677..8ae8e21 100644 --- a/tests/test_runtime_config_support.py +++ b/tests/test_runtime_config_support.py @@ -136,8 +136,11 @@ def test_load_platform_runtime_settings_uses_minimal_group_config(monkeypatch): assert settings.tg_chat_id is None assert settings.strategy_plugin_mounts_json is None 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 + assert settings.crisis_alert_google_voice_sender_email is None + assert settings.crisis_alert_google_voice_sender_password is None + assert settings.crisis_alert_google_voice_smtp_host is None + assert settings.crisis_alert_google_voice_smtp_port is None + assert settings.crisis_alert_google_voice_smtp_security is None def test_load_platform_runtime_settings_prefers_runtime_target_json(monkeypatch): @@ -208,14 +211,20 @@ def test_load_platform_runtime_settings_reads_crisis_alert_google_voice_config(m monkeypatch.setenv("ACCOUNT_GROUP", "paper") monkeypatch.setenv("IB_ACCOUNT_GROUP_CONFIG_JSON", MINIMAL_GROUP_JSON) 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") + monkeypatch.setenv("CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL", "sender@example.com") + monkeypatch.setenv("CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD", "secret") + monkeypatch.setenv("CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST", "smtp.example.com") + monkeypatch.setenv("CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT", "587") + monkeypatch.setenv("CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY", "starttls") settings = load_platform_runtime_settings(project_id_resolver=lambda: "project-1") 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" + assert settings.crisis_alert_google_voice_sender_email == "sender@example.com" + assert settings.crisis_alert_google_voice_sender_password == "secret" + assert settings.crisis_alert_google_voice_smtp_host == "smtp.example.com" + assert settings.crisis_alert_google_voice_smtp_port == "587" + assert settings.crisis_alert_google_voice_smtp_security == "starttls" def test_load_platform_runtime_settings_uses_whole_share_quantity_step(monkeypatch): diff --git a/tests/test_sync_cloud_run_env_workflow.sh b/tests/test_sync_cloud_run_env_workflow.sh index 8b39f11..93396ce 100644 --- a/tests/test_sync_cloud_run_env_workflow.sh +++ b/tests/test_sync_cloud_run_env_workflow.sh @@ -46,14 +46,17 @@ grep -Fq 'IBKR_MIN_RESERVED_CASH_USD: ${{ vars.IBKR_MIN_RESERVED_CASH_USD }}' "$ 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_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 'CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD_SECRET_NAME: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD_SECRET_NAME }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY: ${{ vars.CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY }}' "$workflow_file" grep -Fq 'IB_GATEWAY_ZONE: ${{ vars.IB_GATEWAY_ZONE }}' "$workflow_file" grep -Fq 'IB_GATEWAY_IP_MODE: ${{ vars.IB_GATEWAY_IP_MODE }}' "$workflow_file" grep -Fq 'GLOBAL_TELEGRAM_CHAT_ID: ${{ vars.GLOBAL_TELEGRAM_CHAT_ID }}' "$workflow_file" grep -Fq 'NOTIFY_LANG: ${{ vars.NOTIFY_LANG }}' "$workflow_file" grep -Fq 'TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}' "$workflow_file" -grep -Fq 'CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD: ${{ secrets.CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD: ${{ secrets.CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD }}' "$workflow_file" grep -Fq "Skipping Cloud Run env sync because ENABLE_GITHUB_ENV_SYNC is not set to true." "$workflow_file" grep -Fq "Cloud Run env sync is enabled, but these values are missing:" "$workflow_file" grep -Fq 'TELEGRAM_TOKEN_SECRET_NAME or TELEGRAM_TOKEN' "$workflow_file" @@ -92,8 +95,11 @@ grep -Fq 'env_pairs+=("IBKR_MIN_RESERVED_CASH_USD=${IBKR_MIN_RESERVED_CASH_USD}" 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_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 'env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL=${CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL}")' "$workflow_file" +grep -Fq 'env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD=${CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD}")' "$workflow_file" +grep -Fq 'env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST=${CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST}")' "$workflow_file" +grep -Fq 'env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT=${CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT}")' "$workflow_file" +grep -Fq 'env_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY=${CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY}")' "$workflow_file" grep -Fq 'remove_env_vars+=("IBKR_FEATURE_SNAPSHOT_PATH")' "$workflow_file" grep -Fq 'remove_env_vars+=("IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH")' "$workflow_file" grep -Fq 'remove_env_vars+=("IBKR_STRATEGY_CONFIG_PATH")' "$workflow_file" @@ -105,13 +111,18 @@ 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_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 'remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_EMAIL")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SMTP_HOST")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SMTP_PORT")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY")' "$workflow_file" grep -Fq '"CRISIS_ALERT_GOOGLE_VOICE_TO"' "$workflow_file" grep -Fq '"CRISIS_ALERT_GOOGLE_VOICE_GATEWAY"' "$workflow_file" +grep -Fq '"CRISIS_ALERT_GOOGLE_VOICE_GMAIL_USER"' "$workflow_file" +grep -Fq '"CRISIS_ALERT_GOOGLE_VOICE_GMAIL_APP_PASSWORD"' "$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" +grep -Fq 'secret_pairs+=("CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD=${CRISIS_ALERT_GOOGLE_VOICE_SENDER_PASSWORD_SECRET_NAME}:latest")' "$workflow_file" grep -Fq 'env_pairs+=("TELEGRAM_TOKEN=${TELEGRAM_TOKEN}")' "$workflow_file" grep -Fq 'remove_env_vars+=("IB_GATEWAY_ZONE")' "$workflow_file" grep -Fq 'remove_env_vars+=("IB_GATEWAY_IP_MODE")' "$workflow_file"