Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 30 additions & 10 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
name: tests
name: ci

on:
pull_request:
push:
branches: [main, refactor]
branches:
- main
pull_request:
workflow_dispatch:

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

jobs:
pytest:
test-python:
name: test python
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Checkout repository
uses: actions/checkout@v7

- name: Install pnpm
uses: pnpm/action-setup@v6
Expand All @@ -20,22 +28,34 @@ jobs:
node-version: 24
cache: pnpm

- name: Build frontend plugin
- name: Install frontend dependencies
run: pnpm install --frozen-lockfile

# NOTE(abraham): we must build the frontend assets otherwise tangram_minisky would fail
# with missing frontend assets.
# we should document this and potentially split up the action into repo-with-frontend
# just like tangram
- name: Check and build frontend plugin
run: |
pnpm install --frozen-lockfile
pnpm check
pnpm build

- name: Install uv
uses: astral-sh/setup-uv@v5
uses: astral-sh/setup-uv@v7
with:
enable-cache: true

- name: Install Python dependencies
run: uv sync --locked --all-packages
run: uv sync --all-groups --all-packages

- name: Check code quality
run: |
uv run ruff check packages
uv run ruff format packages --check
uv run pyright

- name: Run unit and integration tests
run: uv run pytest

- name: Run API smoke tests
run: uv run pytest -m api tests/test_api.py
run: uv run pytest -m api packages/minisky/tests/test_api.py
197 changes: 14 additions & 183 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,187 +1,18 @@

# Automatically generated directories and files
output
cache

# tangram frontend plugin builds (example_plugins/tangram/*)
# generated frontend artifacts
node_modules/
dist-frontend/
bluesky/resources/grib
bluesky/resources/netcdf

.vscode

# Byte-compiled / optimized / DLL files
# python
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# zensical documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# Ruff stuff:
.ruff_cache/

# PyPI configuration file
.pypirc
/.pytest_cache/
/.ruff_cache/
/.venv/
/dist/

# zensical
/.cache/
/site/

# misc
.vscode/
.DS_Store
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ minisky console # interactive console
```

The FastAPI app lives in `packages/minisky/minisky/server.py`; `minisky server` is the CLI entry point
(`MINISKY_HOST`/`MINISKY_PORT` env vars, default `0.0.0.0:8000`).
(default `0.0.0.0:8000`; configure `[server]` in TOML or override with `--host` and `--port`).

## Architecture

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ uv run minisky --help
| Command | Purpose |
| --- | --- |
| `minisky run --scenario FILE [--speed N] [--config FILE]` | Run a scenario file without interaction. |
| `minisky server [--host HOST] [--port PORT] [--reload] [--config FILE]` | Start the REST and WebSocket API server. |
| `minisky server [--host HOST] [--port PORT] [--reload] [--config FILE]` | Start the REST and WebSocket API server; CLI bind options override `[server]` config. |
| `minisky console [--server URL] [--port PORT]` | Open an interactive console against a running server. |
| `minisky stream [--url URL] [--raw]` | Print snapshots from the `/stream` WebSocket. |

Expand Down
30 changes: 21 additions & 9 deletions docs/guides/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,18 @@ Use [`@plugin.command`][minisky.plugin.plugin_decorators.command] on an instance
Use the `arguments` option when MiniSky's stack parser needs more information than the Python annotations provide:

```python
from minisky import Err, Ok, Result

@plugin_api.command(arguments="txt,[int]")
def passengers(self, callsign: str, count: int = -1) -> tuple[bool, str]:
def passengers(self, callsign: str, count: int = -1) -> Result[str, str]:
"""Set or get the passenger count for an aircraft."""
...
if count < 0:
return Ok("current passenger count")
if count > 500:
return Err("passenger count is too large")
return Ok("passenger count updated")
```

A command handler can return `(success, message)`. Returning `None` means the command completed successfully without a message.

## Add simulation hooks

Use [`@plugin.hook`][minisky.plugin.plugin_decorators.hook] for work tied to the simulation cycle:
Expand Down Expand Up @@ -138,17 +142,25 @@ async with MiniSky(config=config) as runtime:
To load only one installed plugin, call `load()` with its plugin ID:

```python
ok, message = await runtime.plugins.load("example")
print(message)
from minisky import Err, Ok

match await runtime.plugins.load("example"):
case Ok(message):
print(message)
case Err(error):
# ... handle the error
```

Plugin IDs are case-insensitive. `load()` returns a success flag and a message, so you can decide how your application should handle a missing, invalid, or already loaded plugin.
Plugin IDs are case-insensitive. `load()` returns [`Result[str, str]`][minisky.result.Result]`.

To inspect the plugins known to the runtime, use `listing()`:

```python
ok, text = runtime.plugins.listing()
print(text)
match runtime.plugins.listing():
case Ok(text):
print(text)
case Err(error):
# ... handle the error
```

While the simulator is running, you can manage plugins through the stack instead:
Expand Down
12 changes: 6 additions & 6 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ sync:
uv sync --all-packages

fmt:
uv run ruff check packages tests --fix
uv run ruff format packages tests
uv run ruff check packages --fix
uv run ruff format packages
pnpm lint:fix

check:
uv run ruff check packages tests
uv run ruff format packages tests --check
uv run ruff check packages
uv run ruff format packages --check
uv run pyright
pnpm check

Expand All @@ -20,11 +20,11 @@ test:

# Run fast unit tests.
test-unit:
uv run pytest tests/unit
uv run pytest packages/*/tests/unit

# Run opt-in REST API tests.
test-api:
uv run pytest -m api tests/test_api.py
uv run pytest -m api packages/minisky/tests/test_api.py

docs-serve:
uv run --group docs zensical serve
Expand Down
Loading