Runtime Target Lifecycle #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Runtime Target Lifecycle | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| # QMT has no configured broker runtime. One weekday no-order validation is | |
| # sufficient for this daily strategy family and avoids pretending it has a | |
| # continuously running execution service. | |
| - cron: "17 22 * * 1-5" | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref_name }} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| publish: | |
| name: Publish disabled QMT target validation | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| env: | |
| EXECUTION_EVIDENCE_SYNC_URL: ${{ vars.EXECUTION_EVIDENCE_SYNC_URL }} | |
| QMT_DRY_RUN_ONLY: "true" | |
| QMT_MARKET_HISTORY_PATH: data/fixtures/market_history.sample.csv | |
| STRATEGY_PROFILE: cn_industry_etf_rotation | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| - name: Resolve QuantPlatformKit ref | |
| id: quant-platform-kit-ref | |
| run: | | |
| set -euo pipefail | |
| ref="$(grep -Eo 'QuantPlatformKit\.git@[0-9a-f]+' pyproject.toml | head -n1 | sed 's/.*@//')" | |
| echo "ref=${ref}" >> "$GITHUB_OUTPUT" | |
| - name: Resolve CnEquityStrategies ref | |
| id: cn-equity-strategies-ref | |
| run: | | |
| set -euo pipefail | |
| ref="$(grep -Eo 'CnEquityStrategies\.git@[0-9a-f]+' pyproject.toml | head -n1 | sed 's/.*@//')" | |
| echo "ref=${ref}" >> "$GITHUB_OUTPUT" | |
| - name: Checkout QuantPlatformKit | |
| uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| repository: QuantStrategyLab/QuantPlatformKit | |
| ref: ${{ steps.quant-platform-kit-ref.outputs.ref }} | |
| path: external/QuantPlatformKit | |
| - name: Checkout CnEquityStrategies | |
| uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6 | |
| with: | |
| repository: QuantStrategyLab/CnEquityStrategies | |
| ref: ${{ steps.cn-equity-strategies-ref.outputs.ref }} | |
| path: external/CnEquityStrategies | |
| - name: Set up Python | |
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install dry-run dependencies | |
| run: | | |
| set -euo pipefail | |
| python -m pip install --upgrade pip | |
| python -m pip install -e . | |
| python -m pip install --no-deps -e external/QuantPlatformKit -e external/CnEquityStrategies | |
| - name: Validate disabled dry-run target | |
| id: validation | |
| run: | | |
| set -euo pipefail | |
| python scripts/preflight_qmt_runtime.py | |
| # Exit 2 from this smoke means the cycle itself completed but the | |
| # deterministic risk gate kept target weights empty. That is an | |
| # expected no-order outcome for a disabled target, not a runtime | |
| # failure. Exit 1 still means the dry-run did not complete. | |
| set +e | |
| python scripts/smoke_cn_industry_etf_rotation_dry_run_e2e.py | |
| smoke_status="$?" | |
| set -e | |
| if [ "$smoke_status" -eq 0 ]; then | |
| exit 0 | |
| fi | |
| if [ "$smoke_status" -eq 2 ]; then | |
| echo "Dry-run completed with target weights safely blocked by the risk gate." | |
| exit 0 | |
| fi | |
| exit "$smoke_status" | |
| - name: Map validation to shared lifecycle checks | |
| if: ${{ always() }} | |
| id: monitoring | |
| env: | |
| VALIDATION_OUTCOME: ${{ steps.validation.outcome }} | |
| run: | | |
| set -euo pipefail | |
| if [ "$VALIDATION_OUTCOME" = "success" ]; then | |
| echo "runtime_guard=pass" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "runtime_guard=attention" >> "$GITHUB_OUTPUT" | |
| fi | |
| # This target is explicitly disabled. No process heartbeat or broker | |
| # execution exists, so the shared contract requires not_applicable. | |
| echo "execution_heartbeat=not_applicable" >> "$GITHUB_OUTPUT" | |
| - name: Publish target lifecycle snapshot | |
| if: ${{ always() }} | |
| uses: QuantStrategyLab/QuantRuntimeSettings/actions/publish-runtime-target-lifecycle@769616e9b0a21b9c9f40173b87d5f3e09bbdca9e | |
| with: | |
| source-id: qmt.runtime-target-lifecycle | |
| target-id: qmt.cn_industry_etf_rotation | |
| platform: qmt | |
| configured-state: disabled | |
| execution-mode: dry_run | |
| runtime-guard: ${{ steps.monitoring.outputs.runtime_guard }} | |
| execution-heartbeat: ${{ steps.monitoring.outputs.execution_heartbeat }} | |
| sync-url: ${{ env.EXECUTION_EVIDENCE_SYNC_URL }} | |
| env: | |
| EXECUTION_EVIDENCE_SYNC_TOKEN: ${{ secrets.EXECUTION_EVIDENCE_SYNC_TOKEN }} |