Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions .github/workflows/execution-report-heartbeat.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Execution Report Heartbeat

on:
workflow_dispatch:
inputs:
lookback_hours:
description: "Report lookback window in hours."
required: false
type: string
default: "36"
fail_workflow_on_alert:
description: "Fail this workflow when an alert is emitted."
required: false
type: choice
default: "true"
options:
- "true"
- "false"
schedule:
- cron: "10 23 * * 1-5"

env:
GCP_PROJECT_ID: firstradequant
GCP_WORKLOAD_IDENTITY_PROVIDER: projects/1088907247379/locations/global/workloadIdentityPools/github-actions/providers/github-main
GCP_WORKLOAD_IDENTITY_SERVICE_ACCOUNT: firstrade-platform-deploy@firstradequant.iam.gserviceaccount.com

jobs:
heartbeat:
name: Check execution report heartbeat
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
env:
RUNTIME_HEARTBEAT_NAME: FirstradePlatform
RUNTIME_HEARTBEAT_LOOKBACK_HOURS: ${{ inputs.lookback_hours || vars.RUNTIME_HEARTBEAT_LOOKBACK_HOURS || '36' }}
RUNTIME_HEARTBEAT_FAIL_WORKFLOW_ON_ALERT: ${{ inputs.fail_workflow_on_alert || vars.RUNTIME_HEARTBEAT_FAIL_WORKFLOW_ON_ALERT || 'true' }}
RUNTIME_HEARTBEAT_ACCEPT_STAGES: ${{ vars.RUNTIME_HEARTBEAT_ACCEPT_STAGES }}
RUNTIME_HEARTBEAT_REJECT_STAGES: ${{ vars.RUNTIME_HEARTBEAT_REJECT_STAGES }}
FIRSTRADE_GCS_STATE_BUCKET: ${{ vars.FIRSTRADE_GCS_STATE_BUCKET }}
FIRSTRADE_STATE_PREFIX: ${{ vars.FIRSTRADE_STATE_PREFIX }}
GLOBAL_TELEGRAM_CHAT_ID: ${{ vars.GLOBAL_TELEGRAM_CHAT_ID }}
CRISIS_ALERT_TELEGRAM_CHAT_IDS: ${{ vars.CRISIS_ALERT_TELEGRAM_CHAT_IDS }}
CRISIS_ALERT_TELEGRAM_API_BASE_URL: ${{ vars.CRISIS_ALERT_TELEGRAM_API_BASE_URL }}
TELEGRAM_TOKEN: ${{ secrets.TELEGRAM_TOKEN }}
CRISIS_ALERT_TELEGRAM_BOT_TOKEN: ${{ secrets.CRISIS_ALERT_TELEGRAM_BOT_TOKEN }}
steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v3
with:
workload_identity_provider: ${{ env.GCP_WORKLOAD_IDENTITY_PROVIDER }}
service_account: ${{ env.GCP_WORKLOAD_IDENTITY_SERVICE_ACCOUNT }}

- name: Set up gcloud
uses: google-github-actions/setup-gcloud@v3

- name: Check recent execution report
run: python scripts/execution_report_heartbeat.py
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,14 @@ set `RUNTIME_GUARD_REQUIRE_SUCCESS=true` and choose
Scheduler run. The default leaves that heartbeat check off to avoid false alerts
outside trading windows.

`Execution Report Heartbeat` (`.github/workflows/execution-report-heartbeat.yml`)
is the stricter completion check. It runs on weekdays after the expected US
window and verifies that a recent strategy-run JSON exists under
`FIRSTRADE_GCS_STATE_BUCKET` / `FIRSTRADE_STATE_PREFIX`. It reads the latest
report status/stage and alerts if no recent report exists or the latest reports
are error-like. The deploy service account needs object read/list access on the
state bucket.

## Cloud Run Shape

`main.py` exposes:
Expand Down Expand Up @@ -438,6 +446,12 @@ Run、OIDC/IAM/audience 配错、Cloud Run 返回 4xx/5xx,或容器启动/导
`RUNTIME_GUARD_REQUIRE_SUCCESS=true`,并把 `RUNTIME_GUARD_LOOKBACK_MINUTES` 设成覆盖
Firstrade 预期 Scheduler 运行时间的窗口。默认不强制心跳,避免非交易窗口误报。

更严格的完成检查是 `Execution Report Heartbeat`
(`.github/workflows/execution-report-heartbeat.yml`)。它会在工作日美股预期窗口后检查
`FIRSTRADE_GCS_STATE_BUCKET` / `FIRSTRADE_STATE_PREFIX` 下最近的 strategy-run JSON,
读取 `status/stage/errors`,如果没有近期 report 或 report 呈错误状态就发 Telegram。
GitHub deploy service account 需要对 state bucket 有对象读取/列举权限。

请不要把 Firstrade 登录凭据、MFA secret、cookie 文件提交到 Git。`.env`、
`.runtime/` 和 `ft_cookies*.json` 已经在 `.gitignore` 中。

Expand Down
Loading