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
2 changes: 1 addition & 1 deletion projects/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ layout.

Current projects:

- `middleware-kit`: `mkit` CLI that creates and updates version-matched
- `openshell-middleware-kit`: `omkit` CLI that creates and updates version-matched
Python and Rust OpenShell supervisor middleware projects.
- `python-project-template`: Minimal, production-ready Python project scaffold
managed with uv.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Read `README.md` and `pyproject.toml` before changing this project.

## Safety rules

- `mkit create` must never write into, follow, or replace an existing output
- `omkit create` must never write into, follow, or replace an existing output
path, including a symlink.
- Build and check the project in a temporary directory next to its destination.
Move it into place only after every check passes.
Expand All @@ -27,7 +27,7 @@ Read `README.md` and `pyproject.toml` before changing this project.

## Templates

- Templates in `src/middleware_kit/templates/` must produce working standalone
- Templates in `src/openshell_middleware_kit/templates/` must produce working standalone
projects.
- Write template markers as `__UPPER_SNAKE_CASE__`. Add each marker to
`TemplateContext.replacements` and test its rendered value.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# OpenShell Middleware Kit

`middleware-kit` creates and updates Python or Rust services for OpenShell
`openshell-middleware-kit` creates and updates Python or Rust services for OpenShell
supervisor middleware. Each new project starts as a working pass-through gRPC
service. It includes the protocol file for one OpenShell release, tests,
dependency locks, and instructions for registering the service.
Expand All @@ -16,35 +16,35 @@ The CLI does not install or change OpenShell.

## Install the CLI

Install `mkit` from GitHub with `uv`:
Install `omkit` from GitHub with `uv`:

```sh
uv tool install \
"middleware-kit @ git+https://github.com/NVIDIA/OpenShell-Research.git#subdirectory=projects/middleware-kit"
"openshell-middleware-kit @ git+https://github.com/NVIDIA/OpenShell-Research.git#subdirectory=projects/openshell-middleware-kit"
```

If you already have this repository checked out, install from its local path
instead:

```sh
uv tool install /path/to/OpenShell-Research/projects/middleware-kit
uv tool install /path/to/OpenShell-Research/projects/openshell-middleware-kit
```

Both commands install `mkit` for use outside this repository.
Both commands install `omkit` for use outside this repository.

To work on the CLI itself, use the locked project environment:

```sh
uv sync --locked
uv run mkit --help
uv run omkit --help
```

## Quick start

Generate and run a Python starter with the installed command:

```sh
mkit create audit-headers \
omkit create audit-headers \
--language python \
--openshell-version v0.0.86 \
--output /tmp/audit-headers
Expand All @@ -57,7 +57,7 @@ uv run audit-headers
Or generate and run a Rust starter:

```sh
mkit create audit-headers \
omkit create audit-headers \
--language rust \
--openshell-version v0.0.86 \
--output /tmp/audit-headers-rust
Expand All @@ -70,29 +70,29 @@ cargo run --locked -- 127.0.0.1:50051
The output path must not exist. Pin an OpenShell tag when you need repeatable
builds. Use `--openshell-version latest` when you want the newest release.

Run `mkit --help` for all options. By default, `mkit` derives the Python package
Run `omkit --help` for all options. By default, `omkit` derives the Python package
name from the project name. Use `--package-name` to set it yourself.

## Update a project

Run this inside a generated project to use the latest OpenShell release:

```sh
mkit update
omkit update
```

To choose a release or update a project in another directory:

```sh
mkit update /path/to/audit-headers \
omkit update /path/to/audit-headers \
--openshell-version v0.0.90
```

`mkit update` reads `middleware-dev-manifest.json` to find the project language
`omkit update` reads `middleware-dev-manifest.json` to find the project language
and Python package. It downloads the selected `supervisor_middleware.proto`,
regenerates Python protobuf and gRPC bindings when needed, updates `uv.lock` or
`Cargo.lock`, and writes the version and protocol checksum to the manifest.
The manifest must name `middleware-kit` as its generator.
The manifest must name `openshell-middleware-kit` as its generator.

## What you get

Expand All @@ -111,29 +111,29 @@ Start by implementing policy behavior in the generated `validate_config` and
`evaluate_http_request` functions. The generated README explains how to run the
service and register it with OpenShell.

## How `mkit` protects your files
## How `omkit` protects your files

`mkit create` builds and checks the project in a temporary directory next to
`omkit create` builds and checks the project in a temporary directory next to
the output path. It moves the finished project into place only after every
check passes. If the output path already exists, including as a symlink, the
command stops without changing it.

`mkit update` works on a temporary copy of the project. It changes only the
`omkit update` works on a temporary copy of the project. It changes only the
protocol, generated bindings or Rust build files, lockfile, and manifest. It
runs the project checks before replacing those files. Your implementation files
stay unchanged. If a file replacement fails, `mkit` restores the files it
stay unchanged. If a file replacement fails, `omkit` restores the files it
already replaced.

A lock prevents two `mkit` processes from changing the same path at once.
A lock prevents two `omkit` processes from changing the same path at once.
Normal failures remove the lock and temporary files. If an update and its
rollback both fail, `mkit` keeps the recovery files and prints their locations.
rollback both fail, `omkit` keeps the recovery files and prints their locations.

If the process is killed, it may leave a `.<output>.middleware-kit.lock`
If the process is killed, it may leave a `.<output>.openshell-middleware-kit.lock`
directory and a temporary project directory. Clean them up as follows:

1. Open `metadata.json` in the lock directory.
2. On the host listed in that file, check that the listed PID is no longer an
`mkit` process.
`omkit` process.
3. For `create`, also check that the requested output path does not exist.
Never remove the project directory after an interrupted `update`.
4. Inspect the temporary directory listed in `metadata.json`, then remove only
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[project]
name = "middleware-kit"
name = "openshell-middleware-kit"
version = "0.1.0"
description = "Create and update version-matched OpenShell middleware projects."
readme = "README.md"
Expand All @@ -13,7 +13,7 @@ dependencies = [
]

[project.scripts]
mkit = "middleware_kit.cli:main"
omkit = "openshell_middleware_kit.cli:main"

[project.urls]
Repository = "https://github.com/NVIDIA/OpenShell-Research"
Expand All @@ -34,7 +34,7 @@ build-backend = "uv_build"
addopts = [
"--strict-config",
"--strict-markers",
"--cov=middleware_kit",
"--cov=openshell_middleware_kit",
"--cov-report=term-missing",
"--cov-fail-under=95",
]
Expand All @@ -43,14 +43,14 @@ testpaths = ["tests"]
[tool.ruff]
line-length = 100
target-version = "py310"
extend-exclude = ["src/middleware_kit/templates"]
extend-exclude = ["src/openshell_middleware_kit/templates"]

[tool.ruff.lint]
select = ["B", "E", "F", "I", "RUF", "SIM", "UP"]

[tool.ty.src]
include = ["src", "tests"]
exclude = ["src/middleware_kit/templates"]
exclude = ["src/openshell_middleware_kit/templates"]

[tool.uv]
required-version = ">=0.11.0"
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import typer

from middleware_kit.generator import (
from openshell_middleware_kit.generator import (
ProjectError,
create_project,
update_project,
Expand Down Expand Up @@ -113,7 +113,7 @@ def update(


def _report_error(error: ProjectError) -> None:
typer.echo(f"mkit: error: {error}", err=True)
typer.echo(f"omkit: error: {error}", err=True)
raise typer.Exit(code=1) from error


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from importlib.resources import files
from pathlib import Path

from middleware_kit import __version__
from openshell_middleware_kit import __version__

_REPOSITORY_URL = "https://github.com/NVIDIA/OpenShell"
_RAW_URL = "https://raw.githubusercontent.com/NVIDIA/OpenShell"
Expand All @@ -36,7 +36,7 @@
_PYTHON_PACKAGE_PATTERN = re.compile(r"^[a-z][a-z0-9_]*$")
_PROJECT_NAME_PATTERN = re.compile(r"^[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$")
_NETWORK_ATTEMPTS = 4
_TOOL_NAME = "middleware-kit"
_TOOL_NAME = "openshell-middleware-kit"
_STAGING_IGNORED_ROOT_ENTRIES = {
".coverage",
".git",
Expand Down Expand Up @@ -512,7 +512,7 @@ def _read_project_metadata(project_dir: Path) -> ProjectMetadata:
generator = manifest.get("generator")
generator_name = generator.get("name") if isinstance(generator, dict) else None
if generator_name != _TOOL_NAME:
raise ProjectError("project manifest generator must be middleware-kit")
raise ProjectError("project manifest generator must be openshell-middleware-kit")
languages = manifest.get("languages")
if languages not in (["python"], ["rust"]):
raise ProjectError("project manifest must identify exactly one supported language")
Expand Down Expand Up @@ -989,7 +989,7 @@ def _publish_generated_artifacts(


def _render_project(destination: Path, language: str, context: TemplateContext) -> None:
template_root = files("middleware_kit").joinpath("templates").joinpath(language)
template_root = files("openshell_middleware_kit").joinpath("templates").joinpath(language)
template_paths = {
"python": (
".gitignore",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ for the policy syntax supported by your pinned OpenShell release.
Commit these files. Refresh all version-matched artifacts together with:

```sh
mkit update --openshell-version latest
omkit update --openshell-version latest
```

Use a release tag instead of `latest` for a reproducible update.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ for the policy syntax supported by your pinned OpenShell release.
Commit these files. Refresh all version-matched artifacts together with:

```sh
mkit update --openshell-version latest
omkit update --openshell-version latest
```

Use a release tag instead of `latest` for a reproducible update.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

from typer.testing import CliRunner

from middleware_kit import cli
from middleware_kit.generator import ProjectError, ProjectResult
from openshell_middleware_kit import cli
from openshell_middleware_kit.generator import ProjectError, ProjectResult

runner = CliRunner()

Expand Down Expand Up @@ -79,7 +79,7 @@ def fake_create_project(**options):
)

assert result.exit_code == 1
assert "error: output exists" in result.stderr
assert "omkit: error: output exists" in result.stderr


def test_cli_reports_update_success(monkeypatch, tmp_path: Path) -> None:
Expand Down Expand Up @@ -124,4 +124,4 @@ def fake_update_project(**options):
result = runner.invoke(cli.app, ["update", str(tmp_path)])

assert result.exit_code == 1
assert "error: not generated" in result.stderr
assert "omkit: error: not generated" in result.stderr
Loading