Skip to content
Latchkey

CI workflow (tradecatlabs/tradecat-public)

The CI workflow from tradecatlabs/tradecat-public, explained and optimized by Latchkey.

A

CI health: A - excellent

Point runs-on at Latchkey and get caching, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: tradecatlabs/tradecat-public.github/workflows/ci.ymlLicense MITView source

What it does

This is the CI workflow from the tradecatlabs/tradecat-public repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: CI

on:
  push:
  pull_request:
  workflow_dispatch:
  schedule:
    - cron: "17 2 * * *"

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"

jobs:
  verify:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.12", "3.13"]
    steps:
      - uses: actions/checkout@v5
        with:
          fetch-depth: 0
          persist-credentials: false
      - uses: actions/setup-python@v6
        with:
          python-version: ${{ matrix.python-version }}
      - name: Skill strict
        run: bash scripts/validate-skill.sh --strict
      - name: Secret scan
        shell: bash
        run: |
          set -euo pipefail
          if [[ "${{ github.event_name }}" == "pull_request" ]]; then
            git fetch origin "${{ github.base_ref }}" --depth=1
            log_opts="origin/${{ github.base_ref }}..HEAD"
          elif [[ "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]]; then
            log_opts="${{ github.event.before }}..${{ github.sha }}"
          else
            log_opts="HEAD~1..HEAD"
          fi
          bash scripts/security-scan.sh --history "$log_opts"
      - name: Install
        run: python -m pip install -c constraints.txt -e ".[dev]"
      - name: Guard public boundary
        run: bash scripts/guard_public_local_files.sh
      - name: Dependency policy
        run: python scripts/validate_dependency_policy.py
      - name: Testing/CI contract
        run: python scripts/validate_testing_ci_contract.py
      - name: Lint
        run: ruff check src tests
      - name: Format
        run: ruff format --check src tests scripts
      - name: Test
        run: PYTHONPATH=src pytest -q
      - name: Data contracts
        run: |
          PYTHONPATH=src python scripts/validate_data_contract.py --remote --timeout 10
          PYTHONPATH=src python scripts/validate_dataset_consumption_contract.py
          PYTHONPATH=src python scripts/validate_agent_market_context_resources.py
      - name: Supply-chain audit
        run: bash scripts/supply-chain-audit.sh
      - name: Dependency evidence
        run: |
          python -m pip freeze --all >"${RUNNER_TEMP}/tradecat-dependency-freeze.txt"
          cp constraints.txt "${RUNNER_TEMP}/tradecat-constraints.txt"
      - name: Upload dependency evidence
        uses: actions/upload-artifact@v7
        with:
          name: dependency-evidence-${{ matrix.python-version }}
          path: |
            ${{ runner.temp }}/tradecat-dependency-freeze.txt
            ${{ runner.temp }}/tradecat-constraints.txt
      - name: Shell syntax
        run: |
          bash -n scripts/validate-skill.sh scripts/verify.sh scripts/run-tradecat.sh scripts/agent-smoke.sh
          bash -n scripts/security-scan.sh scripts/bootstrap-dev.sh scripts/supply-chain-audit.sh scripts/install-security-tools.sh
          bash -n scripts/clean-local-runtime.sh scripts/start-auto-paper.sh scripts/monitor-auto-paper.sh scripts/verify-project.sh scripts/guard_public_local_files.sh
      - name: Python script syntax
        run: |
          python -m py_compile \
            scripts/request.py \
            scripts/ops-audit.py \
            scripts/serve-auto-paper-monitor.py \
            scripts/validate_dependency_policy.py \
            scripts/validate_testing_ci_contract.py \
            scripts/validate_data_contract.py \
            scripts/validate_dataset_consumption_contract.py \
            scripts/validate_agent_market_context_resources.py
      - name: Wheel package data
        shell: bash
        run: |
          python -m pip wheel . --no-deps -w /tmp/tradecat-wheel
          python - <<'PY'
          from pathlib import Path
          import zipfile

          wheel = next(Path("/tmp/tradecat-wheel").glob("*.whl"))
          with zipfile.ZipFile(wheel) as zf:
              names = set(zf.namelist())
          required = {
              "tradecat_sources/dataset_consumption_contract.json",
              "tradecat_sources/dataset_registry.json",
              "tradecat_sources/dataset_contract.py",
              "tradecat_sources/registry.py",
              "tradecat_sources/sheets.py",
              "tradecat_auto/agent_market_context.py",
              "tradecat_auto/agent_trade_thesis.py",
              "tradecat_auto/cli.py",
              "tradecat_auto/paper_ledger.py",
              "tradecat_auto/pipeline.py",
              "tradecat_auto/production_control.py",
              "tradecat_auto/safety_boundary.py",
              "tradecat_auto/service.py",
          }
          missing = sorted(required - names)
          if missing:
              raise SystemExit(f"missing package data: {missing}")
          PY

  agent-readiness:
    runs-on: ubuntu-24.04
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v5
        with:
          persist-credentials: false
      - uses: actions/setup-python@v6
        with:
          python-version: "3.12"
      - name: Install package
        run: python -m pip install -c constraints.txt -e ".[dev]"
      - name: Agent readiness smoke
        run: bash scripts/agent-smoke.sh
      - name: Upload agent smoke evidence
        uses: actions/upload-artifact@v7
        if: always()
        with:
          name: agent-readiness-${{ github.run_id }}
          path: |
            skills/tradecat-public/agents/manifest.json
            skills/tradecat-public/references/agent-contract.md

The same workflow, on Latchkey

Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.

name: CI
 
on:
  push:
  pull_request:
  workflow_dispatch:
  schedule:
    - cron: "17 2 * * *"
 
permissions:
  contents: read
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
env:
  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
 
jobs:
  verify:
    runs-on: latchkey-small
    timeout-minutes: 30
    strategy:
      fail-fast: false
      matrix:
        python-version: ["3.12", "3.13"]
    steps:
      - uses: actions/checkout@v5
        with:
          fetch-depth: 0
          persist-credentials: false
      - uses: actions/setup-python@v6
        with:
          cache: 'pip'
          python-version: ${{ matrix.python-version }}
      - name: Skill strict
        run: bash scripts/validate-skill.sh --strict
      - name: Secret scan
        shell: bash
        run: |
          set -euo pipefail
          if [[ "${{ github.event_name }}" == "pull_request" ]]; then
            git fetch origin "${{ github.base_ref }}" --depth=1
            log_opts="origin/${{ github.base_ref }}..HEAD"
          elif [[ "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]]; then
            log_opts="${{ github.event.before }}..${{ github.sha }}"
          else
            log_opts="HEAD~1..HEAD"
          fi
          bash scripts/security-scan.sh --history "$log_opts"
      - name: Install
        run: python -m pip install -c constraints.txt -e ".[dev]"
      - name: Guard public boundary
        run: bash scripts/guard_public_local_files.sh
      - name: Dependency policy
        run: python scripts/validate_dependency_policy.py
      - name: Testing/CI contract
        run: python scripts/validate_testing_ci_contract.py
      - name: Lint
        run: ruff check src tests
      - name: Format
        run: ruff format --check src tests scripts
      - name: Test
        run: PYTHONPATH=src pytest -q
      - name: Data contracts
        run: |
          PYTHONPATH=src python scripts/validate_data_contract.py --remote --timeout 10
          PYTHONPATH=src python scripts/validate_dataset_consumption_contract.py
          PYTHONPATH=src python scripts/validate_agent_market_context_resources.py
      - name: Supply-chain audit
        run: bash scripts/supply-chain-audit.sh
      - name: Dependency evidence
        run: |
          python -m pip freeze --all >"${RUNNER_TEMP}/tradecat-dependency-freeze.txt"
          cp constraints.txt "${RUNNER_TEMP}/tradecat-constraints.txt"
      - name: Upload dependency evidence
        uses: actions/upload-artifact@v7
        with:
          name: dependency-evidence-${{ matrix.python-version }}
          path: |
            ${{ runner.temp }}/tradecat-dependency-freeze.txt
            ${{ runner.temp }}/tradecat-constraints.txt
      - name: Shell syntax
        run: |
          bash -n scripts/validate-skill.sh scripts/verify.sh scripts/run-tradecat.sh scripts/agent-smoke.sh
          bash -n scripts/security-scan.sh scripts/bootstrap-dev.sh scripts/supply-chain-audit.sh scripts/install-security-tools.sh
          bash -n scripts/clean-local-runtime.sh scripts/start-auto-paper.sh scripts/monitor-auto-paper.sh scripts/verify-project.sh scripts/guard_public_local_files.sh
      - name: Python script syntax
        run: |
          python -m py_compile \
            scripts/request.py \
            scripts/ops-audit.py \
            scripts/serve-auto-paper-monitor.py \
            scripts/validate_dependency_policy.py \
            scripts/validate_testing_ci_contract.py \
            scripts/validate_data_contract.py \
            scripts/validate_dataset_consumption_contract.py \
            scripts/validate_agent_market_context_resources.py
      - name: Wheel package data
        shell: bash
        run: |
          python -m pip wheel . --no-deps -w /tmp/tradecat-wheel
          python - <<'PY'
          from pathlib import Path
          import zipfile
 
          wheel = next(Path("/tmp/tradecat-wheel").glob("*.whl"))
          with zipfile.ZipFile(wheel) as zf:
              names = set(zf.namelist())
          required = {
              "tradecat_sources/dataset_consumption_contract.json",
              "tradecat_sources/dataset_registry.json",
              "tradecat_sources/dataset_contract.py",
              "tradecat_sources/registry.py",
              "tradecat_sources/sheets.py",
              "tradecat_auto/agent_market_context.py",
              "tradecat_auto/agent_trade_thesis.py",
              "tradecat_auto/cli.py",
              "tradecat_auto/paper_ledger.py",
              "tradecat_auto/pipeline.py",
              "tradecat_auto/production_control.py",
              "tradecat_auto/safety_boundary.py",
              "tradecat_auto/service.py",
          }
          missing = sorted(required - names)
          if missing:
              raise SystemExit(f"missing package data: {missing}")
          PY
 
  agent-readiness:
    runs-on: latchkey-small
    timeout-minutes: 10
    steps:
      - uses: actions/checkout@v5
        with:
          persist-credentials: false
      - uses: actions/setup-python@v6
        with:
          cache: 'pip'
          python-version: "3.12"
      - name: Install package
        run: python -m pip install -c constraints.txt -e ".[dev]"
      - name: Agent readiness smoke
        run: bash scripts/agent-smoke.sh
      - name: Upload agent smoke evidence
        uses: actions/upload-artifact@v7
        if: always()
        with:
          name: agent-readiness-${{ github.run_id }}
          path: |
            skills/tradecat-public/agents/manifest.json
            skills/tradecat-public/references/agent-contract.md
 

What changed

What Latchkey heals here

This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:

This workflow runs 2 jobs (3 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow