Skip to content

Improve Betfair Decimal parsing #3059

Improve Betfair Decimal parsing

Improve Betfair Decimal parsing #3059

Workflow file for this run

name: build-v2
# Build & publish wheels for the *v2* Python package living under the
# `python/` directory. These wheels are uploaded to the dedicated
# v2 package index at:
# https://packages.nautechsystems.io/v2/simple/nautilus-trader/
permissions:
# Principle of least privilege
contents: read
actions: read
on:
push:
branches:
- test-ci
- test-ci-v2
- develop
- nightly
env:
PACKAGE_DIR: python
jobs:
plan:
runs-on: ubuntu-latest
outputs:
run-tests: ${{ steps.plan.outputs.run_tests }}
run-rust-tests: ${{ steps.plan.outputs.run_rust_tests }}
steps:
# https://github.com/step-security/harden-runner
- uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1
with:
egress-policy: ${{ vars.STEP_SECURITY_EGRESS_POLICY || 'block' }}
allowed-endpoints: >-
${{ vars.COMMON_ALLOWED_ENDPOINTS }}
${{ vars.CI_ALLOWED_ENDPOINTS }}
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
persist-credentials: false
- name: Plan
id: plan
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
BEFORE_SHA: ${{ github.event.before }}
run: bash scripts/ci/plan.sh
pre-commit:
# Fork PRs stay on GitHub-hosted runners.
runs-on: >-
${{ github.event.pull_request.head.repo.fork
&& 'ubuntu-22.04'
|| fromJson('["self-hosted", "Linux", "X64", "build-v2"]') }}
env:
# Self-hosted keeps Rust artifacts outside the workspace.
CARGO_TARGET_DIR: >-
${{ github.event.pull_request.head.repo.fork
&& format('{0}/target', github.workspace)
|| '/home/runner/.cache/cargo-target/pre-commit' }}
CARGO_CI_PROFILE: >-
${{ github.event.pull_request.head.repo.fork && 'ci-pr' || 'nextest' }}
# Scopes incremental clippy/doc checks; empty for non-PR/push events.
CHANGED_BASE_SHA: >-
${{ github.event.pull_request.base.sha || github.event.before }}
steps:
- uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1
with:
egress-policy: ${{ vars.STEP_SECURITY_EGRESS_POLICY || 'block' }}
allowed-endpoints: >-
${{ vars.COMMON_ALLOWED_ENDPOINTS }}
${{ vars.CI_ALLOWED_ENDPOINTS }}
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
# Full history so changed-file scripts can resolve CHANGED_BASE_SHA.
fetch-depth: 0
# Temporary: fail fast on rare runner worktree corruption while we isolate the root cause
- name: Verify immutable CI inputs (post-checkout)
run: bash scripts/ci/verify-ci-inputs.sh post-checkout
- name: Common setup
uses: ./.github/actions/common-setup
with:
python-version: "3.13"
# free-disk-space auto-skips on the nautilus-ci-runner-* pool.
free-disk-space: "true"
build-type: "pre-commit"
rust-cache-enabled: ${{ github.event.pull_request.head.repo.fork && 'true' || 'false' }}
- name: Limit Cargo build jobs on fork PR runners
if: github.event.pull_request.head.repo.fork
run: echo "CARGO_BUILD_JOBS=2" >> "$GITHUB_ENV"
- name: Run pre-commit
run: prek run --all-files
build:
if: needs.plan.outputs.run-tests == 'true'
needs:
- plan
- pre-commit
strategy:
fail-fast: false
matrix:
python-version:
- "3.12"
- "3.13"
- "3.14"
runs-on: [self-hosted, Linux, X64, build-v2]
defaults:
run:
shell: bash
env:
BUILD_MODE: release
CARGO_CI_PROFILE: nextest
RUST_BACKTRACE: 1
# Outside the workspace so it survives actions/checkout's git clean -ffdx,
# giving us persistent on-disk Rust artifact reuse between runs.
CARGO_TARGET_DIR: /home/runner/.cache/cargo-target/py${{ matrix.python-version }}
# yamllint disable rule:line-length
services:
redis:
image: public.ecr.aws/docker/library/redis:7.4.5-alpine3.21@sha256:bb186d083732f669da90be8b0f975a37812b15e913465bb14d845db72a4e3e08
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
postgres:
image: public.ecr.aws/docker/library/postgres:16.4-alpine@sha256:5660c2cbfea50c7a9127d17dc4e48543eedd3d7a41a595a2dfa572471e37e64c
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: pass
POSTGRES_DB: nautilus
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres -d nautilus"
--health-interval 10s
--health-timeout 5s
--health-retries 5
# yamllint enable rule:line-length
steps:
- uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1
with:
egress-policy: ${{ vars.STEP_SECURITY_EGRESS_POLICY || 'block' }}
allowed-endpoints: >-
${{ vars.COMMON_ALLOWED_ENDPOINTS }}
${{ vars.CI_ALLOWED_ENDPOINTS }}
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
# Temporary: fail fast on rare runner worktree corruption while we isolate the root cause
- name: Verify immutable CI inputs (post-checkout)
run: bash scripts/ci/verify-ci-inputs.sh post-checkout
- name: Common setup
uses: ./.github/actions/common-setup
with:
python-version: ${{ matrix.python-version }}
# free-disk-space auto-skips on the nautilus-ci-runner-* pool.
free-disk-space: "true"
# Persistent CARGO_TARGET_DIR replaces Swatinem/rust-cache here.
rust-cache-enabled: "false"
- name: Install Nautilus CLI
if: needs.plan.outputs.run-rust-tests == 'true'
env:
NAUTILUS_CLI_FORCE_SOURCE: ${{ github.ref == 'refs/heads/nightly' && '1' || '0' }}
run: bash scripts/ci/install-nautilus-cli.sh
- name: Init postgres schema
if: needs.plan.outputs.run-rust-tests == 'true'
run: nautilus database init --schema ${{ github.workspace }}/schema/sql
env:
POSTGRES_HOST: localhost
POSTGRES_PORT: 5432
POSTGRES_USERNAME: postgres
POSTGRES_PASSWORD: pass
POSTGRES_DATABASE: nautilus
- name: Cached test data
if: needs.plan.outputs.run-rust-tests == 'true'
uses: ./.github/actions/common-test-data
- name: Run Rust tests (core)
if: needs.plan.outputs.run-rust-tests == 'true'
run: make cargo-test-core HYPERSYNC=true NEXTEST_PROFILE=ci
- name: Run Rust tests (adapters)
if: needs.plan.outputs.run-rust-tests == 'true'
run: make cargo-test-adapters HYPERSYNC=true NEXTEST_PROFILE=ci
- name: Clean Rust test artifacts
if: needs.plan.outputs.run-rust-tests == 'true'
run: |
rm -rf "${CARGO_TARGET_DIR}/nextest"
rm -rf "${CARGO_TARGET_DIR}/${CARGO_CI_PROFILE:-nextest}"
df -h .
# Update version for dev/nightly branches
- name: Update version in pyproject.toml
if: ${{ github.ref != 'refs/heads/master' }}
working-directory: ${{ env.PACKAGE_DIR }}
run: |
bash ../scripts/ci/update-pyproject-version.sh
# Temporary: fail fast on rare runner worktree corruption while we isolate the root cause
- name: Verify immutable CI inputs (pre-wheel build)
run: bash scripts/ci/verify-ci-inputs.sh pre-wheel-build
# Build the wheel for v2 under python/ using maturin
- name: Build wheel (v2)
working-directory: ${{ env.PACKAGE_DIR }}
run: |
MATURIN_VERSION="$(bash ../scripts/tool-version.sh maturin)"
uv run --no-project --no-build --with "maturin==${MATURIN_VERSION}" -- \
maturin build --release --out ../dist
- name: Run v2 Python tests
working-directory: ${{ env.PACKAGE_DIR }}
run: |
uv sync --group test --no-install-package nautilus-trader
uv pip install "../dist/"*.whl
cd /tmp && uv run --project "$GITHUB_WORKSPACE/${{ env.PACKAGE_DIR }}" --no-sync pytest \
--import-mode=importlib \
--rootdir="$GITHUB_WORKSPACE/${{ env.PACKAGE_DIR }}" \
"$GITHUB_WORKSPACE/${{ env.PACKAGE_DIR }}/tests/" -v
# Temporary: show whether v2 stub or docstring generation dirtied tracked files while we isolate CI drift
- name: Report generated v2 file drift
if: always()
run: |
targets=(
python/generate_docstrings.py
python/generate_stubs.py
crates/pyo3
':(glob)python/nautilus_trader/**/*.pyi'
':(glob)crates/**/src/python/**/*.rs'
)
changes="$(git status --short --untracked-files=all -- "${targets[@]}")"
if [ -z "$changes" ]; then
echo "No generated v2 file drift detected"
exit 0
fi
echo "::warning::Tracked or untracked v2 build files changed during the job"
printf '%s\n' "$changes"
echo
git diff --stat HEAD -- "${targets[@]}" || true
- name: Upload wheel artifact
uses: ./.github/actions/upload-artifact-wheel
publish:
needs:
- build
runs-on: ubuntu-latest
# Only publish from mainline branches, never from test branches
if: >
github.ref_name == 'develop' ||
github.ref_name == 'nightly' ||
github.ref_name == 'master'
environment: r2-${{ github.ref_name }}
permissions:
actions: write # Required for deleting artifacts
contents: read
id-token: write # Required for attestations
attestations: write # Required for attestations
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
CLOUDFLARE_R2_URL: ${{ secrets.CLOUDFLARE_R2_URL }}
CLOUDFLARE_R2_REGION: "auto"
CLOUDFLARE_R2_BUCKET_NAME: "packages"
CLOUDFLARE_R2_PREFIX: "v2/simple/nautilus-trader"
steps:
- uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1
with:
egress-policy: ${{ vars.STEP_SECURITY_EGRESS_POLICY || 'block' }}
allowed-endpoints: >-
${{ vars.COMMON_ALLOWED_ENDPOINTS }}
${{ vars.CI_ALLOWED_ENDPOINTS }}
# Sigstore TUF trust root (for gh attestation verify)
tuf-repo-cdn.sigstore.dev:443
${{ secrets.CLOUDFLARE_R2_ALLOWED_HOST }}:443
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Block develop publish after failed security audit
if: github.ref_name == 'develop'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: bash scripts/ci/check-security-audit-result.sh
- name: Download built wheels
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
path: dist
pattern: "*.whl"
merge-multiple: true
# https://github.com/actions/attest-build-provenance
- name: Attest wheel provenance
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
with:
subject-path: "dist/*.whl"
- name: Verify wheel attestations
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
IDENTITY: ${{ github.server_url }}/${{ github.workflow_ref }}
ISSUER: https://token.actions.githubusercontent.com
run: |
set -e
for whl in dist/*.whl; do
gh attestation verify "$whl" \
--repo "$GITHUB_REPOSITORY" \
--cert-identity "$IDENTITY" \
--cert-oidc-issuer "$ISSUER"
done
- name: Publish wheels to Cloudflare R2 (v2 bucket)
uses: ./.github/actions/publish-wheels
- name: Fetch and delete artifacts for current run
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |-
bash ./scripts/ci/publish-wheels-delete-artifacts.sh