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
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,13 @@ For a temporary rule-and-file suppression, run `codedecorum --unlocking-with-exp

## How to write a plugin

Each immediate non-private `.py` file in a configured plugin directory exports one `RULE`. Plugin directories are non-recursive. Plugins are trusted Python and execute inside the Codedecorum process.
Store repository-specific plugins in a tracked directory and register it in the repository's `.codedecorum.toml`:

```toml
plugin-dirs = ["codedecorum-rules"]
```

Relative plugin directories resolve from the configuration file's directory. Each immediate non-private `.py` file in the directory exports one `RULE`. Plugin directories are non-recursive. Plugins are trusted Python and execute inside the Codedecorum process.

### Scopes and rule units

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "codedecorum"
version = "0.1.2"
version = "0.1.3"
description = "Run code-backed policy rules across Git repository changes"
readme = "README.md"
license = "MIT"
Expand Down
9 changes: 8 additions & 1 deletion src/codedecorum/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,14 @@

def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(
prog="codedecorum", description="Lint a repository against code-backed policy rules."
prog="codedecorum",
description="Lint a repository against code-backed policy rules.",
epilog=(
"Full README:\n"
" curl -fsSL "
"https://raw.githubusercontent.com/mwrshah/codedecorum/main/README.md"
),
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument("paths", nargs="*", type=Path)
parser.add_argument("--config", type=Path, metavar="PATH")
Expand Down
7 changes: 5 additions & 2 deletions tests/test_contracts.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import subprocess
from collections.abc import Iterable, Mapping
from datetime import UTC, datetime, timedelta
from importlib.metadata import metadata
from pathlib import Path, PurePosixPath

import pytest
Expand Down Expand Up @@ -274,7 +273,7 @@ def test_parameterized_guidance_contract() -> None:
def test_plugin_help_prints_packaged_readme_section(
capsys: pytest.CaptureFixture[str],
) -> None:
readme = metadata("codedecorum").get_payload()
readme = (Path(__file__).parents[1] / "README.md").read_text(encoding="utf-8")
expected = readme[readme.index("## How to write a plugin") :].split("\n## ", 1)[0].rstrip()

assert main(["--plugin-help"]) == 0
Expand All @@ -289,6 +288,10 @@ def test_plugin_help_prints_packaged_readme_section(
assert "--plugin-help" in help_output
assert "show the complete plugin setup and rule-authoring" in help_output
assert "guide, then exit" in help_output
assert (
"curl -fsSL https://raw.githubusercontent.com/mwrshah/codedecorum/main/README.md"
in help_output
)


def test_complete_plugin_pipeline(tmp_path: Path, capsys: pytest.CaptureFixture[str]) -> None:
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading