CI workflow (tradecatlabs/tradecat-public)
The CI workflow from tradecatlabs/tradecat-public, explained and optimized by Latchkey.
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.
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
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
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cache dependency installs on the setup step so they are served from cache.
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:
- Dependency installs
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.