Skip to content

chore: publish ArmaraOS CLI v0.8.4 for Intel macs (x86_64-apple-darwin) #656

chore: publish ArmaraOS CLI v0.8.4 for Intel macs (x86_64-apple-darwin)

chore: publish ArmaraOS CLI v0.8.4 for Intel macs (x86_64-apple-darwin) #656

Workflow file for this run

name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
schedule:
- cron: "0 3 * * *"
workflow_dispatch:
jobs:
docs-contract:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: Run docs contract check (PR diff-aware)
if: github.event_name == 'pull_request'
run: |
python scripts/check_docs_contracts.py --scope changed --base-ref "origin/${{ github.base_ref }}"
- name: Run docs contract check (full)
if: github.event_name != 'pull_request'
run: |
python scripts/check_docs_contracts.py --scope all
core-pr:
if: github.event_name != 'schedule'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.10", "3.11"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: Run core profile
run: python scripts/run_test_profiles.py --profile core
# Named gate: a2a unit tests + local threaded HTTPServer integration (skips bind in strict sandboxes).
- name: A2A adapter (tests.test_a2a_adapter + tests.test_a2a_adapter_integration)
run: python -m pytest -q tests/test_a2a_adapter.py tests/test_a2a_adapter_integration.py
# Explicit gate: compile → RuntimeEngine → SolanaAdapter (includes dry-run mutating verbs).
# Core profile already runs this file; this step names the contract in CI logs.
- name: Solana prediction-market E2E (dry-run runtime)
run: python -m pytest -q tests/test_solana_prediction_market_e2e.py
- name: Verify adapter manifest consistency
run: python -m pytest -q tests/test_adapter_manifest.py
- name: Verify artifact profile consistency
run: |
python scripts/check_all_strict.py
python scripts/check_all_nonstrict.py
python -m pytest -q tests/test_artifact_profiles.py
parser-compat:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: Validate S+cron schedule lines (IR services.path)
run: python scripts/validate_s_cron_schedules.py
- name: Run parser compatibility gate
run: |
python -m pytest -q \
tests/test_compiler_patch_a_guardrails.py \
tests/test_sanity_fixes.py \
tests/test_ir_canonical.py \
tests/test_emits_artifacts.py \
tests/test_conformance.py::test_minimal_api_emit_openapi_has_path
- name: Wishlist examples strict + no-network smoke (01, 05b)
run: |
set -euo pipefail
python -m pytest -q tests/test_wishlist_examples_strict.py
python -m cli.main run examples/wishlist/01_cache_and_memory.ainl --json \
--frame-json '{"session_key":"ci","note":"hello"}' 2>/dev/null \
| python -c "import sys,json; d=json.load(sys.stdin); assert d.get('ok') is True, d"
python -m cli.main run examples/wishlist/05b_unified_llm_offline_config.ainl --json \
--config examples/wishlist/fixtures/llm_offline.yaml \
--frame-json '{"user_query":"ci rust smoke"}' 2>/dev/null \
| python -c "import sys,json; d=json.load(sys.stdin); assert d.get('ok') is True, d; assert 'OFFLINE_LLM' in str(d.get('result')), d"
# No outbound network required: a2a unit tests only (integration may skip in stricter sandboxes; core-pr also runs both).
a2a-adapter-unit:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: A2A adapter unit tests only
run: python -m pytest -q tests/test_a2a_adapter.py
conformance-matrix:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: Run conformance matrix
run: make conformance
openapi-compat:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: Run OpenAPI compatibility gate
run: |
python -m pytest -q \
tests/test_compiler_patch_c_openapi_types.py \
tests/test_conformance.py::test_minimal_api_emit_openapi_has_path \
tests/test_lossless.py::test_openapi_array_inner_type_ref_for_model \
tests/test_lossless.py::test_openapi_json_type_maps_to_object_schema \
tests/test_lossless.py::test_openapi_response_data_allows_array_or_object
apollo-promoter:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: Apollo promoter safety net (strict + gateway tests)
run: make check-apollo-promoter
compiler-compat-required:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
needs: [parser-compat, openapi-compat]
steps:
- name: Compatibility gates passed
run: echo "parser-compat and openapi-compat both passed"
integration-nightly:
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install deps
run: |
python -m pip install --upgrade pip
pip install .[dev]
- name: Run full profile
run: python scripts/run_test_profiles.py --profile full
# Benchmarks + JSON regression gate: prefers committed CI baselines (tooling/benchmark_*_ci.json)
# when present on the base SHA; otherwise falls back to full reports (benchmark_size.json,
# benchmark_runtime_results.json).
benchmark-regression:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
env:
BENCH_THRESHOLD: "0.10"
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-bench-${{ hashFiles('pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-bench-
- name: Install deps (dev + benchmark)
run: |
python -m pip install --upgrade pip
pip install .[dev,benchmark]
- name: Resolve baseline SHA
id: baseline
run: |
git fetch origin main --depth=1 2>/dev/null || true
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "sha=${{ github.event.pull_request.base.sha }}" >> "$GITHUB_OUTPUT"
elif [ "${{ github.event_name }}" = "push" ] \
&& [ -n "${{ github.event.before }}" ] \
&& [ "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]; then
echo "sha=${{ github.event.before }}" >> "$GITHUB_OUTPUT"
else
echo "sha=$(git rev-parse origin/main 2>/dev/null || echo "")" >> "$GITHUB_OUTPUT"
fi
- name: Extract baseline JSON (from git)
id: baselines
run: |
set -euo pipefail
SHA="${{ steps.baseline.outputs.sha }}"
mkdir -p /tmp/bench-baseline
if [ -z "$SHA" ]; then
echo "size_ci=missing" >> "$GITHUB_OUTPUT"
echo "size=missing" >> "$GITHUB_OUTPUT"
echo "runtime_ci=missing" >> "$GITHUB_OUTPUT"
echo "runtime=missing" >> "$GITHUB_OUTPUT"
exit 0
fi
if git cat-file -e "${SHA}:tooling/benchmark_size_ci.json" 2>/dev/null; then
git show "${SHA}:tooling/benchmark_size_ci.json" > /tmp/bench-baseline/benchmark_size_ci.json
echo "size_ci=present" >> "$GITHUB_OUTPUT"
else
echo "size_ci=missing" >> "$GITHUB_OUTPUT"
fi
if git cat-file -e "${SHA}:tooling/benchmark_size.json" 2>/dev/null; then
git show "${SHA}:tooling/benchmark_size.json" > /tmp/bench-baseline/benchmark_size.json
echo "size=present" >> "$GITHUB_OUTPUT"
else
echo "size=missing" >> "$GITHUB_OUTPUT"
fi
if git cat-file -e "${SHA}:tooling/benchmark_runtime_ci.json" 2>/dev/null; then
git show "${SHA}:tooling/benchmark_runtime_ci.json" > /tmp/bench-baseline/benchmark_runtime_ci.json
echo "runtime_ci=present" >> "$GITHUB_OUTPUT"
else
echo "runtime_ci=missing" >> "$GITHUB_OUTPUT"
fi
if git cat-file -e "${SHA}:tooling/benchmark_runtime_results.json" 2>/dev/null; then
git show "${SHA}:tooling/benchmark_runtime_results.json" > /tmp/bench-baseline/benchmark_runtime_results.json
echo "runtime=present" >> "$GITHUB_OUTPUT"
else
echo "runtime=missing" >> "$GITHUB_OUTPUT"
fi
- name: Run size benchmark (CI slice)
run: |
python scripts/benchmark_size.py \
--mode minimal_emit \
--profile-name canonical_strict_valid \
--compare-baselines \
--cost-model gpt-4o \
--json-out tooling/benchmark_size_ci.json \
--skip-markdown-inject
- name: Run runtime benchmark
run: |
python scripts/benchmark_runtime.py \
--profile-name canonical_strict_valid \
--compare-baselines \
--reliability-runs 10 \
--cost-model gpt-4o \
--json-out tooling/benchmark_runtime_ci.json \
--skip-markdown-inject
- name: Upload benchmark JSON (pre-regression)
uses: actions/upload-artifact@v4
with:
name: benchmark-json-precheck-${{ github.run_id }}
if-no-files-found: warn
path: |
tooling/benchmark_size_ci.json
tooling/benchmark_runtime_ci.json
- name: Regression check (size)
if: steps.baselines.outputs.size_ci == 'present' || steps.baselines.outputs.size == 'present'
run: |
set -euo pipefail
if [ "${{ steps.baselines.outputs.size_ci }}" = "present" ]; then
OLD_JSON=/tmp/bench-baseline/benchmark_size_ci.json
else
OLD_JSON=/tmp/bench-baseline/benchmark_size.json
fi
python scripts/compare_benchmark_json.py \
--old-json "$OLD_JSON" \
--new-json tooling/benchmark_size_ci.json \
--threshold "$BENCH_THRESHOLD"
- name: Regression check (size baseline missing)
if: steps.baselines.outputs.size_ci != 'present' && steps.baselines.outputs.size != 'present'
run: |
echo "::notice::No tooling/benchmark_size_ci.json or benchmark_size.json at baseline SHA; skipping size regression compare."
- name: Regression check (runtime)
id: runtime_regression
if: (steps.baselines.outputs.runtime_ci == 'present' || steps.baselines.outputs.runtime == 'present') && github.event_name != 'pull_request'
continue-on-error: true
run: |
set -euo pipefail
if [ "${{ steps.baselines.outputs.runtime_ci }}" = "present" ]; then
OLD_JSON=/tmp/bench-baseline/benchmark_runtime_ci.json
else
OLD_JSON=/tmp/bench-baseline/benchmark_runtime_results.json
fi
python scripts/compare_benchmark_json.py \
--old-json "$OLD_JSON" \
--new-json tooling/benchmark_runtime_ci.json \
--threshold "$BENCH_THRESHOLD"
- name: Runtime benchmark compare (PR informational)
if: (steps.baselines.outputs.runtime_ci == 'present' || steps.baselines.outputs.runtime == 'present') && github.event_name == 'pull_request'
run: |
set -euo pipefail
if [ "${{ steps.baselines.outputs.runtime_ci }}" = "present" ]; then
OLD_JSON=/tmp/bench-baseline/benchmark_runtime_ci.json
else
OLD_JSON=/tmp/bench-baseline/benchmark_runtime_results.json
fi
python scripts/compare_benchmark_json.py \
--old-json "$OLD_JSON" \
--new-json tooling/benchmark_runtime_ci.json \
--threshold "$BENCH_THRESHOLD" || true
- name: Runtime baseline missing (informational)
if: steps.baselines.outputs.runtime_ci != 'present' && steps.baselines.outputs.runtime != 'present'
run: |
echo "::notice::No tooling/benchmark_runtime_ci.json or benchmark_runtime_results.json at baseline SHA; commit those files on main to enable runtime regression checks."
- name: Upload benchmark JSON artifacts
uses: actions/upload-artifact@v4
with:
name: benchmark-json-${{ github.run_id }}
if-no-files-found: warn
path: |
tooling/benchmark_size_ci.json
tooling/benchmark_runtime_ci.json
install-smoke:
if: github.event_name != 'schedule'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Normal install smoke (venv)
shell: bash
run: |
set -euo pipefail
python -m venv .venv-smoke
. .venv-smoke/bin/activate
python -m pip install --upgrade pip
python -m pip install ".[mcp]"
python -m pip check
ainl --help >/dev/null
ainl-mcp --help >/dev/null
- name: User install smoke (no sudo)
shell: bash
run: |
set -euo pipefail
export PYTHONUSERBASE="${RUNNER_TEMP}/ainl-userbase"
mkdir -p "${PYTHONUSERBASE}"
python -m pip install --upgrade pip
python -m pip install --user --constraint constraints/py313-mcp.txt ".[mcp]"
python -m pip check
"${PYTHONUSERBASE}/bin/ainl" --help >/dev/null
"${PYTHONUSERBASE}/bin/ainl-mcp" --help >/dev/null
- name: Break-system-packages install smoke
shell: bash
run: |
set -euo pipefail
python -m pip install --upgrade pip
python -m pip install --break-system-packages --constraint constraints/py313-mcp.txt ".[mcp]"
python -m pip check
SCRIPT_DIR="$(python -c 'import sysconfig; print(sysconfig.get_path("scripts"))')"
"${SCRIPT_DIR}/ainl" --help >/dev/null
"${SCRIPT_DIR}/ainl-mcp" --help >/dev/null
wheel-integrity:
if: github.event_name != 'schedule'
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Build wheel
shell: bash
run: |
set -euo pipefail
python -m pip install --upgrade pip build
python -m build
- name: Wheel install integrity + imports
shell: bash
run: |
set -euo pipefail
python -m venv .venv-wheel
. .venv-wheel/bin/activate
python -m pip install --upgrade pip
WHEEL="$(ls dist/*.whl | head -n 1)"
python -m pip install --force-reinstall --constraint constraints/py313-mcp.txt "${WHEEL}[mcp]"
python -m pip check
python -c "import runtime.compat, adapters, cli.main"
ainl --help >/dev/null
ainl-mcp --help >/dev/null
container-install-smoke:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
image: ["python:3.10-slim", "python:3.11-slim", "python:3.12-slim", "python:3.13-slim"]
container:
image: ${{ matrix.image }}
steps:
- uses: actions/checkout@v4
- name: Non-root container install smoke
shell: bash
run: |
set -euo pipefail
useradd -m -u 1000 ainl 2>/dev/null || true
chown -R 1000:1000 "$GITHUB_WORKSPACE"
su -s /bin/bash ainl -c '
cd "$GITHUB_WORKSPACE" && \
python -m venv .venv-container && \
. .venv-container/bin/activate && \
python -m pip install --upgrade pip && \
python -m pip install --constraint constraints/py313-mcp.txt ".[mcp]" && \
python -m pip check && \
ainl --help >/dev/null && \
ainl-mcp --help >/dev/null
'