Skip to content

deps(libraries): add upper bound specifiers and sync package versions (fixes #693) #1269

deps(libraries): add upper bound specifiers and sync package versions (fixes #693)

deps(libraries): add upper bound specifiers and sync package versions (fixes #693) #1269

Workflow file for this run

# Main CI workflow: runs on every push and pull request targeting main or develop.
# Job order: lint -> (test + test-ui) in parallel -> build
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
lint:
name: Lint
runs-on: ubuntu-latest
steps:
# Check out the full repository so subsequent steps can access all files.
- uses: actions/checkout@v6
- name: Check workflow security invariants
run: python .github/scripts/check_opencode_workflow.py
# Install uv (fast Python package/project manager) with dependency caching enabled
# so repeated runs reuse cached packages and finish faster.
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
enable-cache: true
# Pin to Python 3.12 for lint checks; consistent with the test matrix default.
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.12'
# Install ruff and mypy via uv for linting, formatting, and type checking.
- name: Install lint tools
run: |
uv lock --check
uv pip install --system ruff mypy
# Run Ruff linter across both Python packages.
# --output-format=github annotates pull requests with inline lint errors.
- name: Run Ruff
run: ruff check packages/ --output-format=github
# Verify code is formatted according to Ruff's formatter rules.
# --check exits with a non-zero code if any file would be reformatted,
# failing the job without actually writing changes.
- name: Check Ruff formatting
run: ruff format --check packages/
# Run mypy type checking across both source trees.
# mypy is configured via pyproject.toml at the repo root.
# continue-on-error: pre-existing type errors exist across the codebase;
# mypy runs for visibility but does not block CI until they are resolved.
- name: Run mypy
continue-on-error: true
run: mypy packages/core/src packages/libraries/src
test:
# Matrix strategy tests every supported Python version on every supported OS,
# giving early signal on platform-specific or version-specific regressions.
name: Test (Python ${{ matrix.python-version }}, ${{ matrix.os }})
runs-on: ${{ matrix.os }}
# Lint must pass before spending runner time on tests.
needs: lint
strategy:
# Keep running remaining matrix legs even if one fails, so we get a full
# picture of failures across all platforms in a single CI run.
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ["3.10", "3.11", "3.12"]
exclude:
# Python 3.10 on macOS is excluded because the macOS-latest runner
# ships with an arm64 (M1) image where 3.10 builds are not available.
- os: macos-latest
python-version: "3.10"
steps:
# Full checkout required for test discovery and package builds.
- uses: actions/checkout@v6
# uv replaces pip + virtualenv with a single, faster tool.
# Caching is enabled so dependencies don't re-download on every run.
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
enable-cache: true
# Install the exact Python version specified by the matrix cell.
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
# Install all test dependencies plus both packages in editable mode (-e)
# so import paths resolve to the source tree.
# pytest-asyncio is required for async test cases in core.
# pytest-cov enables coverage collection.
- name: Install dependencies
run: |
uv lock --check
uv venv
uv pip install -r requirements-dev.txt
uv pip install -e packages/core
uv pip install -e packages/libraries
uv pip install pytest pytest-asyncio pytest-cov
# Run pytest for core package with coverage.
# --tb=short keeps failure output concise.
# --cov=packages/core/src generates a per-package coverage report.
- name: Run core tests
run: uv run --no-project python -m pytest packages/core/tests -v --tb=short --cov=packages/core/src --cov-report=xml --cov-report=term-missing
# Run pytest for libraries package with coverage appended to the same report.
- name: Run libraries tests
run: uv run --no-project python -m pytest packages/libraries/tests -v --tb=short --cov=packages/libraries/src --cov-report=xml --cov-append
# Upload the XML coverage report to Codecov.
# Restricted to one matrix leg (ubuntu + 3.11) to avoid duplicate uploads
# that would skew the coverage percentage.
# fail_ci_if_error=false prevents a Codecov outage from breaking the build.
- name: Upload coverage
uses: codecov/codecov-action@v7
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11'
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./coverage.xml
fail_ci_if_error: false
test-ui:
name: Test Studio UI
runs-on: ubuntu-latest
# Lint must pass before spending runner time on UI tests.
needs: lint
steps:
# Full checkout needed to access packages/studio source.
- uses: actions/checkout@v6
# The Studio package targets Node 22 LTS; using setup-node ensures the correct
# version is available regardless of what the runner ships with.
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: "22"
# pnpm is the package manager for the monorepo workspace. Version 11 is
# pinned because pnpm-workspace.yaml's `overrides`/`allowBuilds`/
# `onlyBuiltDependencies` keys are only understood by pnpm >=10.
- name: Install pnpm
uses: pnpm/action-setup@v6
with:
version: 11
# Install all JS/TS dependencies declared in packages/studio/package.json
# and the workspace root.
- name: Install dependencies
working-directory: packages/studio
run: pnpm install --frozen-lockfile
- name: Run Studio ESLint
working-directory: packages/studio
run: pnpm lint
# Run the Vitest/Jest suite for the React frontend.
- name: Run tests
working-directory: packages/studio
run: pnpm test
# TypeScript compiler check with --noEmit: validates types without producing
# output files. Catches type errors that unit tests alone may miss.
- name: Type check
working-directory: packages/studio
run: pnpm exec tsc --noEmit
build-electron:
name: Build Electron Installer (Windows)
runs-on: windows-latest
needs: [test, test-ui]
steps:
- uses: actions/checkout@v6
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: "22"
- name: Install pnpm
uses: pnpm/action-setup@v6
with:
version: 11
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.11"
- name: Install engine build tools
run: |
python -m pip install --upgrade pip
pip install pyinstaller
pip install ./packages/core
pip install "./packages/libraries[desktop,web,excel,database,keystore,dataframes]"
- name: Install dependencies
working-directory: packages/studio
run: pnpm install --frozen-lockfile
- name: Build Python bridge
working-directory: packages/studio
run: pnpm build:bridge
- name: Build Electron app
working-directory: packages/studio
run: pnpm build
- name: Run packaged Electron E2E smoke suite
working-directory: packages/studio
run: pnpm test:e2e
- name: Upload Electron E2E artifacts on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: electron-e2e-failure-artifacts
path: |
packages/studio/test-results
packages/studio/playwright-report
- name: Upload installer artifact
uses: actions/upload-artifact@v4
with:
name: windows-installer
path: packages/studio/dist-electron/*.exe
build:
name: Build Packages
runs-on: ubuntu-latest
# Both test jobs must succeed before attempting a build to avoid wasting
# runner time packaging broken code.
needs: [test, test-ui]
steps:
# Full checkout required so python -m build can locate pyproject.toml.
- uses: actions/checkout@v6
- name: Install uv
uses: astral-sh/setup-uv@v8.1.0
with:
enable-cache: true
# Use a stable, non-EOL Python for the build step.
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.11'
- name: Verify Python lockfile
run: uv lock --check
# Install the PEP 517 build frontend; no other runtime deps needed here.
- name: Install build tools
run: uv venv && uv pip install build
# Build source distribution and wheel for the root project.
# Artifacts land in dist/ for the upload step.
- name: Build packages
run: uv run --no-project python -m build
# Persist the built distributions as a downloadable workflow artifact.
# Other workflows (e.g. release.yml) or manual inspection can use these
# without re-running the build.
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: dist
path: dist/