diff --git a/.github/workflows/sync-cloud-run-env.yml b/.github/workflows/sync-cloud-run-env.yml index 13373e7..a497a3e 100644 --- a/.github/workflows/sync-cloud-run-env.yml +++ b/.github/workflows/sync-cloud-run-env.yml @@ -40,6 +40,14 @@ jobs: CRISIS_ALERT_EMAIL_SMTP_HOST: ${{ vars.CRISIS_ALERT_EMAIL_SMTP_HOST }} CRISIS_ALERT_EMAIL_SMTP_PORT: ${{ vars.CRISIS_ALERT_EMAIL_SMTP_PORT }} CRISIS_ALERT_EMAIL_SMTP_SECURITY: ${{ vars.CRISIS_ALERT_EMAIL_SMTP_SECURITY }} + CRISIS_ALERT_SMS_RECIPIENTS: ${{ vars.CRISIS_ALERT_SMS_RECIPIENTS }} + CRISIS_ALERT_SMS_PROVIDER: ${{ vars.CRISIS_ALERT_SMS_PROVIDER }} + CRISIS_ALERT_SMS_ACCOUNT_ID: ${{ vars.CRISIS_ALERT_SMS_ACCOUNT_ID }} + CRISIS_ALERT_SMS_AUTH_TOKEN_SECRET_NAME: ${{ vars.CRISIS_ALERT_SMS_AUTH_TOKEN_SECRET_NAME }} + CRISIS_ALERT_SMS_SENDER: ${{ vars.CRISIS_ALERT_SMS_SENDER }} + CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID: ${{ vars.CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID }} + CRISIS_ALERT_SMS_API_BASE_URL: ${{ vars.CRISIS_ALERT_SMS_API_BASE_URL }} + CRISIS_ALERT_SMS_BODY_MAX_CHARS: ${{ vars.CRISIS_ALERT_SMS_BODY_MAX_CHARS }} # 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 }} @@ -48,6 +56,7 @@ jobs: NOTIFY_LANG: ${{ vars.NOTIFY_LANG }} TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }} CRISIS_ALERT_EMAIL_SENDER_PASSWORD: ${{ secrets.CRISIS_ALERT_EMAIL_SENDER_PASSWORD }} + CRISIS_ALERT_SMS_AUTH_TOKEN: ${{ secrets.CRISIS_ALERT_SMS_AUTH_TOKEN }} steps: - name: Check whether env sync is enabled id: config @@ -312,6 +321,17 @@ jobs: remove_secret_vars+=("CRISIS_ALERT_EMAIL_SENDER_PASSWORD") fi + if [ -n "${CRISIS_ALERT_SMS_AUTH_TOKEN_SECRET_NAME:-}" ]; then + secret_pairs+=("CRISIS_ALERT_SMS_AUTH_TOKEN=${CRISIS_ALERT_SMS_AUTH_TOKEN_SECRET_NAME}:latest") + remove_env_vars+=("CRISIS_ALERT_SMS_AUTH_TOKEN") + elif [ -n "${CRISIS_ALERT_SMS_AUTH_TOKEN:-}" ]; then + env_pairs+=("CRISIS_ALERT_SMS_AUTH_TOKEN=${CRISIS_ALERT_SMS_AUTH_TOKEN}") + remove_secret_vars+=("CRISIS_ALERT_SMS_AUTH_TOKEN") + else + remove_env_vars+=("CRISIS_ALERT_SMS_AUTH_TOKEN") + remove_secret_vars+=("CRISIS_ALERT_SMS_AUTH_TOKEN") + fi + if [ -n "${IB_GATEWAY_ZONE:-}" ]; then env_pairs+=("IB_GATEWAY_ZONE=${IB_GATEWAY_ZONE}") else @@ -414,6 +434,48 @@ jobs: remove_env_vars+=("CRISIS_ALERT_EMAIL_SMTP_SECURITY") fi + if [ -n "${CRISIS_ALERT_SMS_RECIPIENTS:-}" ]; then + env_pairs+=("CRISIS_ALERT_SMS_RECIPIENTS=${CRISIS_ALERT_SMS_RECIPIENTS}") + else + remove_env_vars+=("CRISIS_ALERT_SMS_RECIPIENTS") + fi + + if [ -n "${CRISIS_ALERT_SMS_PROVIDER:-}" ]; then + env_pairs+=("CRISIS_ALERT_SMS_PROVIDER=${CRISIS_ALERT_SMS_PROVIDER}") + else + remove_env_vars+=("CRISIS_ALERT_SMS_PROVIDER") + fi + + if [ -n "${CRISIS_ALERT_SMS_ACCOUNT_ID:-}" ]; then + env_pairs+=("CRISIS_ALERT_SMS_ACCOUNT_ID=${CRISIS_ALERT_SMS_ACCOUNT_ID}") + else + remove_env_vars+=("CRISIS_ALERT_SMS_ACCOUNT_ID") + fi + + if [ -n "${CRISIS_ALERT_SMS_SENDER:-}" ]; then + env_pairs+=("CRISIS_ALERT_SMS_SENDER=${CRISIS_ALERT_SMS_SENDER}") + else + remove_env_vars+=("CRISIS_ALERT_SMS_SENDER") + fi + + if [ -n "${CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID:-}" ]; then + env_pairs+=("CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID=${CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID}") + else + remove_env_vars+=("CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID") + fi + + if [ -n "${CRISIS_ALERT_SMS_API_BASE_URL:-}" ]; then + env_pairs+=("CRISIS_ALERT_SMS_API_BASE_URL=${CRISIS_ALERT_SMS_API_BASE_URL}") + else + remove_env_vars+=("CRISIS_ALERT_SMS_API_BASE_URL") + fi + + if [ -n "${CRISIS_ALERT_SMS_BODY_MAX_CHARS:-}" ]; then + env_pairs+=("CRISIS_ALERT_SMS_BODY_MAX_CHARS=${CRISIS_ALERT_SMS_BODY_MAX_CHARS}") + else + remove_env_vars+=("CRISIS_ALERT_SMS_BODY_MAX_CHARS") + fi + if [ -n "${EXECUTION_REPORT_GCS_URI:-}" ]; then env_pairs+=("EXECUTION_REPORT_GCS_URI=${EXECUTION_REPORT_GCS_URI}") else diff --git a/main.py b/main.py index 0361546..3bba163 100644 --- a/main.py +++ b/main.py @@ -30,6 +30,10 @@ build_strategy_plugin_alert_context_label as build_email_alert_context_label, publish_strategy_plugin_email_alerts, ) +from quant_platform_kit.notifications.strategy_plugin_sms import ( + StrategyPluginSmsAlertMarkerStore, + publish_strategy_plugin_sms_alerts, +) from quant_platform_kit.common.runtime_assembly import build_runtime_assembly from quant_platform_kit.common.runtime_reports import ( append_runtime_report_error, @@ -485,6 +489,14 @@ def build_strategy_plugin_alert_store(): ) +def build_strategy_plugin_sms_alert_store(): + return StrategyPluginSmsAlertMarkerStore( + local_dir=os.getenv("STRATEGY_PLUGIN_ALERT_STATE_DIR") or "/tmp/quant_strategy_plugin_alerts", + gcs_prefix_uri=os.getenv("STRATEGY_PLUGIN_ALERT_STATE_GCS_URI") or os.getenv("EXECUTION_REPORT_GCS_URI"), + gcp_project_id=PROJECT_ID, + ) + + def build_strategy_plugin_alert_context_label() -> str: return build_email_alert_context_label( platform_id="ibkr", @@ -500,8 +512,13 @@ def attach_strategy_plugin_alert_email_result(report, result) -> None: report.setdefault("diagnostics", {}).update(result.to_report_fields()) +def attach_strategy_plugin_alert_sms_result(report, result) -> None: + report.setdefault("summary", {})["strategy_plugin_alert_sms_sent_count"] = result.sent_count + report.setdefault("diagnostics", {}).update(result.to_report_fields()) + + def publish_strategy_plugin_alerts(signals, *, report=None): - result = publish_strategy_plugin_email_alerts( + email_result = publish_strategy_plugin_email_alerts( signals, email_settings=RUNTIME_SETTINGS, translator=t, @@ -510,9 +527,19 @@ def publish_strategy_plugin_alerts(signals, *, report=None): alert_store=build_strategy_plugin_alert_store(), log_message=print, ) + sms_result = publish_strategy_plugin_sms_alerts( + signals, + sms_settings=RUNTIME_SETTINGS, + translator=t, + strategy_label=STRATEGY_PROFILE, + context_label=build_strategy_plugin_alert_context_label(), + alert_store=build_strategy_plugin_sms_alert_store(), + log_message=print, + ) if report is not None: - attach_strategy_plugin_alert_email_result(report, result) - return result + attach_strategy_plugin_alert_email_result(report, email_result) + attach_strategy_plugin_alert_sms_result(report, sms_result) + return email_result def build_account_notification_lines() -> tuple[str, ...]: diff --git a/requirements.txt b/requirements.txt index 0f2b30b..4236414 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ flask gunicorn -quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@3c8f52b16a8ebf98b9fdfa4af5e96be43e6144fe -us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@b84bebb784248bd2bb3d2c589db9ea0ab35ee95d +quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@d43800180aae1c7fe7051496a6af5d76f2c65879 +us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@9661d8bb74e33466fa0ec1efef168b1d1bae8875 pandas numpy requests diff --git a/runtime_config_support.py b/runtime_config_support.py index 518309a..332c9c2 100644 --- a/runtime_config_support.py +++ b/runtime_config_support.py @@ -78,6 +78,14 @@ class PlatformRuntimeSettings: crisis_alert_email_smtp_host: str | None = None crisis_alert_email_smtp_port: str | None = None crisis_alert_email_smtp_security: str | None = None + crisis_alert_sms_recipients: tuple[str, ...] = () + crisis_alert_sms_provider: str | None = None + crisis_alert_sms_account_id: str | None = None + crisis_alert_sms_auth_token: str | None = None + crisis_alert_sms_sender: str | None = None + crisis_alert_sms_messaging_service_id: str | None = None + crisis_alert_sms_api_base_url: str | None = None + crisis_alert_sms_body_max_chars: str | None = None runtime_target: RuntimeTarget | None = None @@ -204,6 +212,30 @@ def load_platform_runtime_settings( crisis_alert_email_smtp_security=first_non_empty( os.getenv("CRISIS_ALERT_EMAIL_SMTP_SECURITY") ), + crisis_alert_sms_recipients=split_env_list( + os.getenv("CRISIS_ALERT_SMS_RECIPIENTS") + ), + crisis_alert_sms_provider=first_non_empty( + os.getenv("CRISIS_ALERT_SMS_PROVIDER") + ), + crisis_alert_sms_account_id=first_non_empty( + os.getenv("CRISIS_ALERT_SMS_ACCOUNT_ID") + ), + crisis_alert_sms_auth_token=first_non_empty( + os.getenv("CRISIS_ALERT_SMS_AUTH_TOKEN") + ), + crisis_alert_sms_sender=first_non_empty( + os.getenv("CRISIS_ALERT_SMS_SENDER") + ), + crisis_alert_sms_messaging_service_id=first_non_empty( + os.getenv("CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID") + ), + crisis_alert_sms_api_base_url=first_non_empty( + os.getenv("CRISIS_ALERT_SMS_API_BASE_URL") + ), + crisis_alert_sms_body_max_chars=first_non_empty( + os.getenv("CRISIS_ALERT_SMS_BODY_MAX_CHARS") + ), runtime_target=runtime_target, ) diff --git a/tests/test_request_handling.py b/tests/test_request_handling.py index 611bfb2..82a965d 100644 --- a/tests/test_request_handling.py +++ b/tests/test_request_handling.py @@ -43,14 +43,14 @@ def test_handle_request_sends_escalated_strategy_plugin_alert(strategy_module, m would_trade_if_enabled=True, as_of="2026-05-24", ) - observed = {"alerts": []} + observed = {"email_alerts": [], "sms_alerts": []} monkeypatch.setattr(strategy_module, "is_market_open_today", lambda: True) monkeypatch.setattr(strategy_module, "load_strategy_plugin_signals", lambda: ((signal,), None)) monkeypatch.setattr(strategy_module, "attach_strategy_plugin_report", lambda *args, **kwargs: None) - def fake_publish(signals, **kwargs): - observed["alerts"].append((tuple(signals), kwargs)) + def fake_email_publish(signals, **kwargs): + observed["email_alerts"].append((tuple(signals), kwargs)) return types.SimpleNamespace( sent_count=1, to_report_fields=lambda: { @@ -62,7 +62,21 @@ def fake_publish(signals, **kwargs): }, ) - monkeypatch.setattr(strategy_module, "publish_strategy_plugin_email_alerts", fake_publish) + def fake_sms_publish(signals, **kwargs): + observed["sms_alerts"].append((tuple(signals), kwargs)) + return types.SimpleNamespace( + sent_count=1, + to_report_fields=lambda: { + "strategy_plugin_alert_sms_attempted_count": 1, + "strategy_plugin_alert_sms_sent_count": 1, + "strategy_plugin_alert_sms_skipped_count": 0, + "strategy_plugin_alert_sms_failed_count": 0, + "strategy_plugin_alert_sms_deliveries": [], + }, + ) + + monkeypatch.setattr(strategy_module, "publish_strategy_plugin_email_alerts", fake_email_publish) + monkeypatch.setattr(strategy_module, "publish_strategy_plugin_sms_alerts", fake_sms_publish) monkeypatch.setattr(strategy_module, "run_strategy_core", lambda **_kwargs: "OK - executed") with strategy_module.app.test_request_context("/", method="POST"): @@ -70,9 +84,12 @@ def fake_publish(signals, **kwargs): assert status == 200 assert body == "OK - executed" - assert len(observed["alerts"]) == 1 - assert observed["alerts"][0][0] == (signal,) - assert "ibkr" in observed["alerts"][0][1]["context_label"] + assert len(observed["email_alerts"]) == 1 + assert len(observed["sms_alerts"]) == 1 + assert observed["email_alerts"][0][0] == (signal,) + assert observed["sms_alerts"][0][0] == (signal,) + assert "ibkr" in observed["email_alerts"][0][1]["context_label"] + assert "ibkr" in observed["sms_alerts"][0][1]["context_label"] def test_handle_precheck_post_uses_dry_run_override(strategy_module, monkeypatch): diff --git a/tests/test_runtime_config_support.py b/tests/test_runtime_config_support.py index 245d87f..390a9a0 100644 --- a/tests/test_runtime_config_support.py +++ b/tests/test_runtime_config_support.py @@ -141,6 +141,14 @@ def test_load_platform_runtime_settings_uses_minimal_group_config(monkeypatch): assert settings.crisis_alert_email_smtp_host is None assert settings.crisis_alert_email_smtp_port is None assert settings.crisis_alert_email_smtp_security is None + assert settings.crisis_alert_sms_recipients == () + assert settings.crisis_alert_sms_provider is None + assert settings.crisis_alert_sms_account_id is None + assert settings.crisis_alert_sms_auth_token is None + assert settings.crisis_alert_sms_sender is None + assert settings.crisis_alert_sms_messaging_service_id is None + assert settings.crisis_alert_sms_api_base_url is None + assert settings.crisis_alert_sms_body_max_chars is None def test_load_platform_runtime_settings_prefers_runtime_target_json(monkeypatch): @@ -227,6 +235,31 @@ def test_load_platform_runtime_settings_reads_crisis_alert_email_config(monkeypa assert settings.crisis_alert_email_smtp_security == "starttls" +def test_load_platform_runtime_settings_reads_crisis_alert_sms_config(monkeypatch): + 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_SMS_RECIPIENTS", "+15165480265;(516) 548-0265") + monkeypatch.setenv("CRISIS_ALERT_SMS_PROVIDER", "twilio") + monkeypatch.setenv("CRISIS_ALERT_SMS_ACCOUNT_ID", "AC123") + monkeypatch.setenv("CRISIS_ALERT_SMS_AUTH_TOKEN", "secret") + monkeypatch.setenv("CRISIS_ALERT_SMS_SENDER", "+15551234567") + monkeypatch.setenv("CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID", "MG123") + monkeypatch.setenv("CRISIS_ALERT_SMS_API_BASE_URL", "https://twilio.example.test") + monkeypatch.setenv("CRISIS_ALERT_SMS_BODY_MAX_CHARS", "160") + + settings = load_platform_runtime_settings(project_id_resolver=lambda: "project-1") + + assert settings.crisis_alert_sms_recipients == ("+15165480265", "(516) 548-0265") + assert settings.crisis_alert_sms_provider == "twilio" + assert settings.crisis_alert_sms_account_id == "AC123" + assert settings.crisis_alert_sms_auth_token == "secret" + assert settings.crisis_alert_sms_sender == "+15551234567" + assert settings.crisis_alert_sms_messaging_service_id == "MG123" + assert settings.crisis_alert_sms_api_base_url == "https://twilio.example.test" + assert settings.crisis_alert_sms_body_max_chars == "160" + + def test_load_platform_runtime_settings_uses_whole_share_quantity_step(monkeypatch): monkeypatch.setenv("RUNTIME_TARGET_JSON", runtime_target_json(SAMPLE_STRATEGY_PROFILE)) monkeypatch.setenv("ACCOUNT_GROUP", "paper") diff --git a/tests/test_sync_cloud_run_env_workflow.sh b/tests/test_sync_cloud_run_env_workflow.sh index edd8bc5..3419d08 100644 --- a/tests/test_sync_cloud_run_env_workflow.sh +++ b/tests/test_sync_cloud_run_env_workflow.sh @@ -51,12 +51,21 @@ grep -Fq 'CRISIS_ALERT_EMAIL_SENDER_PASSWORD_SECRET_NAME: ${{ vars.CRISIS_ALERT_ grep -Fq 'CRISIS_ALERT_EMAIL_SMTP_HOST: ${{ vars.CRISIS_ALERT_EMAIL_SMTP_HOST }}' "$workflow_file" grep -Fq 'CRISIS_ALERT_EMAIL_SMTP_PORT: ${{ vars.CRISIS_ALERT_EMAIL_SMTP_PORT }}' "$workflow_file" grep -Fq 'CRISIS_ALERT_EMAIL_SMTP_SECURITY: ${{ vars.CRISIS_ALERT_EMAIL_SMTP_SECURITY }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_SMS_RECIPIENTS: ${{ vars.CRISIS_ALERT_SMS_RECIPIENTS }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_SMS_PROVIDER: ${{ vars.CRISIS_ALERT_SMS_PROVIDER }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_SMS_ACCOUNT_ID: ${{ vars.CRISIS_ALERT_SMS_ACCOUNT_ID }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_SMS_AUTH_TOKEN_SECRET_NAME: ${{ vars.CRISIS_ALERT_SMS_AUTH_TOKEN_SECRET_NAME }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_SMS_SENDER: ${{ vars.CRISIS_ALERT_SMS_SENDER }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID: ${{ vars.CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_SMS_API_BASE_URL: ${{ vars.CRISIS_ALERT_SMS_API_BASE_URL }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_SMS_BODY_MAX_CHARS: ${{ vars.CRISIS_ALERT_SMS_BODY_MAX_CHARS }}' "$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_EMAIL_SENDER_PASSWORD: ${{ secrets.CRISIS_ALERT_EMAIL_SENDER_PASSWORD }}' "$workflow_file" +grep -Fq 'CRISIS_ALERT_SMS_AUTH_TOKEN: ${{ secrets.CRISIS_ALERT_SMS_AUTH_TOKEN }}' "$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" @@ -100,6 +109,13 @@ grep -Fq 'env_pairs+=("CRISIS_ALERT_EMAIL_SENDER_PASSWORD=${CRISIS_ALERT_EMAIL_S grep -Fq 'env_pairs+=("CRISIS_ALERT_EMAIL_SMTP_HOST=${CRISIS_ALERT_EMAIL_SMTP_HOST}")' "$workflow_file" grep -Fq 'env_pairs+=("CRISIS_ALERT_EMAIL_SMTP_PORT=${CRISIS_ALERT_EMAIL_SMTP_PORT}")' "$workflow_file" grep -Fq 'env_pairs+=("CRISIS_ALERT_EMAIL_SMTP_SECURITY=${CRISIS_ALERT_EMAIL_SMTP_SECURITY}")' "$workflow_file" +grep -Fq 'env_pairs+=("CRISIS_ALERT_SMS_RECIPIENTS=${CRISIS_ALERT_SMS_RECIPIENTS}")' "$workflow_file" +grep -Fq 'env_pairs+=("CRISIS_ALERT_SMS_PROVIDER=${CRISIS_ALERT_SMS_PROVIDER}")' "$workflow_file" +grep -Fq 'env_pairs+=("CRISIS_ALERT_SMS_ACCOUNT_ID=${CRISIS_ALERT_SMS_ACCOUNT_ID}")' "$workflow_file" +grep -Fq 'env_pairs+=("CRISIS_ALERT_SMS_SENDER=${CRISIS_ALERT_SMS_SENDER}")' "$workflow_file" +grep -Fq 'env_pairs+=("CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID=${CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID}")' "$workflow_file" +grep -Fq 'env_pairs+=("CRISIS_ALERT_SMS_API_BASE_URL=${CRISIS_ALERT_SMS_API_BASE_URL}")' "$workflow_file" +grep -Fq 'env_pairs+=("CRISIS_ALERT_SMS_BODY_MAX_CHARS=${CRISIS_ALERT_SMS_BODY_MAX_CHARS}")' "$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" @@ -116,6 +132,14 @@ grep -Fq 'remove_env_vars+=("CRISIS_ALERT_EMAIL_SENDER_PASSWORD")' "$workflow_fi grep -Fq 'remove_env_vars+=("CRISIS_ALERT_EMAIL_SMTP_HOST")' "$workflow_file" grep -Fq 'remove_env_vars+=("CRISIS_ALERT_EMAIL_SMTP_PORT")' "$workflow_file" grep -Fq 'remove_env_vars+=("CRISIS_ALERT_EMAIL_SMTP_SECURITY")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_SMS_RECIPIENTS")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_SMS_PROVIDER")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_SMS_ACCOUNT_ID")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_SMS_AUTH_TOKEN")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_SMS_SENDER")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_SMS_MESSAGING_SERVICE_ID")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_SMS_API_BASE_URL")' "$workflow_file" +grep -Fq 'remove_env_vars+=("CRISIS_ALERT_SMS_BODY_MAX_CHARS")' "$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" @@ -129,6 +153,7 @@ grep -Fq '"CRISIS_ALERT_GOOGLE_VOICE_SMTP_SECURITY"' "$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_EMAIL_SENDER_PASSWORD=${CRISIS_ALERT_EMAIL_SENDER_PASSWORD_SECRET_NAME}:latest")' "$workflow_file" +grep -Fq 'secret_pairs+=("CRISIS_ALERT_SMS_AUTH_TOKEN=${CRISIS_ALERT_SMS_AUTH_TOKEN_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"