diff --git a/AGENTS.md b/AGENTS.md index 75c871b..c7d663e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,6 +23,7 @@ uv run ruff check src/ tests/ # lint uv run ruff format --check src/ tests/ # format check uv run mypy src/ # type check uv run pytest tests/unit/ # unit tests +uv run codespell src/ tests/ # spell check ``` Never use `pip install`. All dependency management goes through `uv` and `pyproject.toml`. @@ -56,6 +57,12 @@ examples/ # Example project layout (artifacts.yaml, spread.yaml, concierge. 4. **Avoid `Any`.** Prefer specific types; `mypy --strict` must pass. Legacy `Any` in YAML-handling helpers is tolerated but should not spread. 5. **CLI consistency: `run` / `expand` pairs.** Commands that execute a subprocess (`run`) and commands that print the equivalent command (`expand`) must be aligned in arguments, flags, and semantics. If `opcli foo run --bar baz` executes something, then `opcli foo expand --bar baz` must print the equivalent command with the same flags accepted. This applies to `spread`, `pytest`, and any future command groups with this pattern. 6. **Stepdown rule.** Within each module, order functions so callers appear before callees. Public API at the top, then private helpers below in call-order. Read top-to-bottom like a narrative. +7. **License headers required.** Every new `.py` file must begin with: + ```python + # Copyright Canonical Ltd. + # See LICENSE file for licensing details. + ``` + CI enforces this via `skywalking-eyes` and `.licenserc.yaml`. YAML, TOML, Markdown, and other non-Python files are excluded — see `.licenserc.yaml` for the full exclusion list. --- @@ -67,7 +74,7 @@ examples/ # Example project layout (artifacts.yaml, spread.yaml, concierge. | Packaging | `uv` | | CLI | `Typer` | | Data models | `Pydantic V2` | -| Lint/format | `Ruff` (rules: `E F W I UP B SIM PL RUF`; ignores: `B008` globally, `E501` in `spread.py`) | +| Lint/format | `Ruff` (see `pyproject.toml [tool.ruff.lint]` for full config — selected rule groups include `A B C D E F I N PL RUF S SIM TC UP W`) | | YAML (user files) | `ruamel.yaml` (preserves comments) | | Templating | `Jinja2` (pytest invocation templates) | | Testing | `pytest` + `pytest-mock` | @@ -112,7 +119,7 @@ The virtual backend in `spread.yaml` accepts opcli-only keys that are stripped d | Key | Values | Default | Effect | |---|---|---|---| -| `type` | `integration-test`, `tutorial` | (required) | Selects the backend template | +| `type` | `integration-test` | (required) | Selects the backend template | | `runner` | JSON array of labels | — | CI runner labels for GitHub Actions matrix | | `cpu`, `memory`, `disk` | integer | 4, 8, 20 | Local LXD VM resource allocation | @@ -229,6 +236,9 @@ The table below distinguishes *mechanically enforced* rules from *advisory* ones | Type safety (`mypy --strict`) | ✅ CI blocks | `ci.yml` step | | Unit tests pass | ✅ CI blocks | `ci.yml` step | | Coverage ≥ 85% | ✅ CI blocks | `pytest --cov-fail-under=85` | +| Spell check (`codespell`) | ✅ CI blocks | `ci.yml` lint step | +| License headers | ✅ CI blocks | `.licenserc.yaml` via `skywalking-eyes` | +| Shell scripts (`shellcheck`) | ✅ CI blocks | `ci.yml` shellcheck step | | No push to main | ⚠️ Advisory | Branch protection (enable on canonical/charm-ci) | | CI green before merge | ⚠️ Advisory | Branch protection (enable on canonical/charm-ci) | | Docs updated with code | ⚠️ Advisory | PR review discipline | diff --git a/README.md b/README.md index afdfd79..5cdcdf2 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,20 @@ A **local-first CLI tool** for Canonical operator developers to build charms, ro `opcli` replaces the monolithic [`operator-workflows`](https://github.com/canonical/operator-workflows) approach with a modular pipeline based on explicit build plans (`artifacts.yaml`), stable build output (`artifacts.build.yaml`), and [spread](https://github.com/canonical/spread)-based test execution. +## Contents + +- [Documentation](#documentation) +- [Installation](#installation) +- [Quick start](#quick-start) +- [Commands](#commands) +- [`artifacts.yaml` schema](#artifactsyaml-schema) +- [`spread.yaml` virtual backends](#spreadyaml-virtual-backends) +- [`integration-suites` in `spread.yaml`](#integration-suites-in-spreadyaml) +- [CI vs local](#ci-vs-local) +- [GitHub Actions reusable workflows](#github-actions-reusable-workflows) +- [Secrets for integration tests](#secrets-for-integration-tests) +- [Development](#development) + ## Documentation | Document | Purpose | @@ -14,13 +28,6 @@ A **local-first CLI tool** for Canonical operator developers to build charms, ro ## Installation -```bash -sudo snap install astral-uv --classic -uv tool install git+https://github.com/canonical/charm-ci.git -export PATH="$HOME/.local/bin:$PATH" # or: uv tool update-shell && exec $SHELL -opcli --help -``` - ### Prerequisites - Python 3.12+ @@ -28,9 +35,18 @@ opcli --help - [charmcraft](https://charmcraft.io/) (`sudo snap install charmcraft --classic`) - [rockcraft](https://rockcraft.io/) (`sudo snap install rockcraft --classic`) — if building rocks - [LXD](https://canonical.com/lxd) (`sudo lxd init --auto && sudo usermod -aG lxd $USER`) -- [spread](https://github.com/canonical/spread) (installed via `opcli install spread`) — for spread workflow +- [spread](https://github.com/canonical/spread) — installed via `opcli install spread` after opcli is set up - [concierge](https://github.com/canonical/concierge/) (`sudo snap install concierge --classic`) — for env provisioning +### Install opcli + +```bash +sudo snap install astral-uv --classic +uv tool install git+https://github.com/canonical/charm-ci.git +export PATH="$HOME/.local/bin:$PATH" # or: uv tool update-shell && exec $SHELL +opcli --help +``` + ## Quick start ### Local testing with spread @@ -150,12 +166,6 @@ opcli pytest expand --suite machine-charm/tests/integration/ When a single `integration-suites` entry exists, `--suite` is auto-detected. With multiple suites, it's required. -### `opcli tutorial` - -| Command | Description | -|---|---| -| `expand ` | Extract shell commands from a tutorial (`.md`/`.rst`) and print as a shell script for `eval`. | - ## `artifacts.yaml` schema ```yaml @@ -187,7 +197,7 @@ Key fields: ## `spread.yaml` virtual backends -opcli recognises virtual backend types (`integration-test`, `tutorial`) and expands them into concrete spread backends at runtime: +opcli recognises the `integration-test` virtual backend type and expands it into a concrete spread backend at runtime: ```yaml backends: