|
| 1 | + |
| 2 | +# LLM Context Guide for `infrahub-sync` |
| 3 | + |
| 4 | +`infrahub-sync` synchronizes data between infra sources and destinations (Infrahub, NetBox, Nautobot, etc.). It uses Poetry for packaging, a Typer CLI, and Invoke tasks for linting and docs. Examples live in `examples/`. |
| 5 | + |
| 6 | +## Agent Operating Principles |
| 7 | + |
| 8 | +1. **Plan → Ask → Act → Verify → Record** |
| 9 | + Plan briefly, ask for missing context, act with the smallest change, verify locally, then record with a concise commit or PR note. |
| 10 | + |
| 11 | +2. **Default to read-only and dry runs** |
| 12 | + Prefer `list`, `diff`, and `generate` before `sync`. Write/apply only with explicit instruction and human approval. |
| 13 | + |
| 14 | +3. **Be specific and reversible** |
| 15 | + Use small, scoped commits. Do not mix large refactors with behavior changes in the same PR. |
| 16 | + |
| 17 | +4. **Match existing patterns** |
| 18 | + Keep CLI, adapters, examples, and directory structure consistent with the codebase. |
| 19 | + |
| 20 | +5. **Idempotency and safety** |
| 21 | + Favor operations that are safe to re-run. Use dry runs. Never print or guess secrets. Handle timeouts, auth, and network errors explicitly. |
| 22 | + |
| 23 | +## Required Development Workflow |
| 24 | + |
| 25 | +Run these in order before committing. |
| 26 | + |
| 27 | +```bash |
| 28 | +poetry install |
| 29 | +poetry run invoke format |
| 30 | +poetry run invoke lint |
| 31 | +poetry run mypy infrahub_sync/ --ignore-missing-imports |
| 32 | +``` |
| 33 | + |
| 34 | +**Policy:** |
| 35 | + |
| 36 | +- New or changed code is Ruff-clean and typed where touched (docstrings, specific exceptions). |
| 37 | +- Do not increase existing mypy debt. If needed, use targeted `# type: ignore[<code>]` with a short TODO. |
| 38 | +- If you add tests, run `poetry run pytest -q`. |
| 39 | + |
| 40 | +**CLI sanity after changes:** |
| 41 | + |
| 42 | +```bash |
| 43 | +poetry run infrahub-sync --help |
| 44 | +poetry run infrahub-sync list --directory examples/ |
| 45 | +poetry run infrahub-sync generate --name from-netbox --directory examples/ |
| 46 | +``` |
| 47 | + |
| 48 | +**Docs:** (only if user-facing changes) |
| 49 | + |
| 50 | +```bash |
| 51 | +poetry run invoke docs.generate |
| 52 | +poetry run invoke docs.docusaurus |
| 53 | +``` |
| 54 | + |
| 55 | +## Repository Structure |
| 56 | + |
| 57 | +```text |
| 58 | +infrahub-sync/ |
| 59 | +├─ infrahub_sync/ # Source |
| 60 | +│ ├─ cli.py # Typer entrypoint |
| 61 | +│ ├─ __init__.py # Public API |
| 62 | +│ ├─ utils.py # Utilities |
| 63 | +│ ├─ potenda/ # Core sync engine |
| 64 | +│ └─ adapters/ # NetBox/Nautobot/Infrahub adapters |
| 65 | +├─ examples/ # Example sync configs |
| 66 | +├─ tasks/ # Invoke task definitions |
| 67 | +├─ docs/ # Docusaurus (npm project) |
| 68 | +├─ tests/ # Scaffolding (no tests yet) |
| 69 | +├─ pyproject.toml # Poetry + tool configs |
| 70 | +└─ .github/workflows/ # CI |
| 71 | +``` |
| 72 | + |
| 73 | +## Core Surfaces |
| 74 | + |
| 75 | +- **Adapters** (`infrahub_sync/adapters/`): per-system connectors. Use existing ones as patterns. |
| 76 | +- **Engine** (`infrahub_sync/potenda/`): orchestrates `list`, `diff`, `generate`, and `sync`. |
| 77 | +- **Examples** (`examples/`): runnable configs and templates. |
| 78 | + |
| 79 | +**CLI commands:** |
| 80 | + |
| 81 | +- `infrahub-sync list` — show available sync projects. |
| 82 | +- `infrahub-sync diff` — compute differences (safe). |
| 83 | +- `infrahub-sync generate` — generate Python from YAML config (servers required). |
| 84 | +- `infrahub-sync sync` — perform synchronization (servers and approval required). |
| 85 | + |
| 86 | +## Configuration and Examples |
| 87 | + |
| 88 | +- YAML config keys: `name`, `source`, `destination`, `order`. |
| 89 | +- `source` and `destination` specify adapter names and connection settings. |
| 90 | +- `order` defines the sync sequence of object types. |
| 91 | +- Defaults often target `localhost`; adjust for real deployments. |
| 92 | +- Credentials must come from environment or a secret manager. Never commit secrets. |
| 93 | + |
| 94 | +## Code Standards |
| 95 | + |
| 96 | +### Python (3.10–3.12) |
| 97 | + |
| 98 | +- Prefer explicit types on new or changed code. |
| 99 | +- Ruff: formatted and lint-clean. Honor `pyproject.toml`. |
| 100 | +- Pylint: fix actionable issues in touched code; some warnings are expected. |
| 101 | +- Mypy: run with `--ignore-missing-imports`; do not increase the error count. |
| 102 | +- Public functions and classes require concise docstrings. |
| 103 | +- Raise specific exceptions; avoid broad `except Exception:`. |
| 104 | + |
| 105 | +### CLI and UX |
| 106 | + |
| 107 | +- Predictable, idempotent commands with clear validation and errors. |
| 108 | +- No secrets in logs or tracebacks. |
| 109 | +- Prefer explicit flags over implicit behavior. |
| 110 | + |
| 111 | +## Testing |
| 112 | + |
| 113 | +Current state: `tests/` exists but has no active tests. |
| 114 | + |
| 115 | +If you introduce features or bug fixes, add targeted tests. |
| 116 | + |
| 117 | +- Unit tests for `utils` and adapter edge cases (timeouts, 401/403, empty pages). |
| 118 | +- Parametrized tests for config parsing. |
| 119 | +- Mark network or integration tests and keep them opt-in (for example, `-m integration`). |
| 120 | +- Keep tests atomic and single-purpose. Use parametrization rather than loops. |
| 121 | + |
| 122 | +Run: |
| 123 | + |
| 124 | +```bash |
| 125 | +poetry run pytest -q |
| 126 | +``` |
| 127 | + |
| 128 | +## Documentation |
| 129 | + |
| 130 | +- Update `docs/` for any user-visible changes (flags, config, adapters). |
| 131 | +- Generate CLI docs: |
| 132 | + |
| 133 | +```bash |
| 134 | +poetry run invoke docs.generate |
| 135 | +``` |
| 136 | + |
| 137 | +- Build site (ensure `cd docs && npm install` once): |
| 138 | + |
| 139 | +```bash |
| 140 | +poetry run invoke docs.docusaurus |
| 141 | +``` |
| 142 | + |
| 143 | +- Keep examples minimal, accurate, and redacted. |
| 144 | + |
| 145 | +### Linting documentation (markdownlint) |
| 146 | + |
| 147 | +Use `markdownlint` and `markdownlint-cli` for Markdown and MDX files. |
| 148 | + |
| 149 | +```bash |
| 150 | +# Check and fix Markdown and MDX in docs |
| 151 | +npx markdownlint-cli "docs/docs/**/*.{md,mdx}" |
| 152 | +npx markdownlint-cli --fix "docs/docs/**/*.{md,mdx}" |
| 153 | +``` |
| 154 | + |
| 155 | +## Invoke Tasks (reference) |
| 156 | + |
| 157 | +```bash |
| 158 | +poetry run invoke --list |
| 159 | +# linter.format-ruff Format Python code with ruff |
| 160 | +# linter.lint-ruff Lint Python code with ruff |
| 161 | +# linter.lint-pylint Lint Python code with pylint |
| 162 | +# linter.lint-yaml Lint YAML files with yamllint |
| 163 | +# docs.generate Generate CLI documentation |
| 164 | +# docs.docusaurus Build documentation website |
| 165 | +# format Alias for ruff format (if defined) |
| 166 | +# lint Run all linters |
| 167 | +``` |
| 168 | + |
| 169 | +## Known Issues and Limitations |
| 170 | + |
| 171 | +- Optional dependencies (for example, `pynetbox`, `pynautobot`) may be missing, producing import warnings. |
| 172 | +- `generate` and `sync` require running servers (Infrahub, NetBox, Nautobot). |
| 173 | +- Existing mypy debt exists; do not increase it and type the code you touch. |
| 174 | +- Docs npm audit may flag dev-only vulnerabilities; they do not affect the Python package. |
| 175 | + |
| 176 | +## Development Rules |
| 177 | + |
| 178 | +### Git and CI |
| 179 | + |
| 180 | +- Do not force-push on shared branches. |
| 181 | +- Do not amend to hide pre-commit fixes; use a follow-up commit. |
| 182 | +- Apply PR labels: `bugs`, `breaking`, `enhancements`, `features` (default to `enhancements`). |
| 183 | +- Always run the required workflow (format → lint → mypy → CLI sanity) before a PR. |
| 184 | + |
| 185 | +### Commit and PR Messages |
| 186 | + |
| 187 | +- Agents must identify themselves (for example, `🤖 Generated with Copilot`). |
| 188 | +- Commit subject: imperative “what changed.” Rationale goes in the PR body. |
| 189 | +- PR body includes: |
| 190 | + - Problem or tension and the solution in one to two short paragraphs. |
| 191 | + - Minimal code example or before/after snippet. |
| 192 | + - Note any user-visible changes (CLI flags, config keys). |
| 193 | + |
| 194 | +## Review Process |
| 195 | + |
| 196 | +- Read surrounding code and examples. Align with established patterns. |
| 197 | +- Verify claims via the smallest reproduction (CLI or unit). |
| 198 | +- Consider edge cases: auth failures, empty inputs, pagination, rate limits, timeouts. |
| 199 | +- Provide specific, actionable feedback. |
| 200 | + |
| 201 | +**Approval checklist:** |
| 202 | + |
| 203 | +- [ ] Format and lint clean on changed areas. |
| 204 | +- [ ] No increase in mypy errors; new code typed. |
| 205 | +- [ ] CLI behaviors validated (`--help`, `list`, targeted `generate`). |
| 206 | +- [ ] Docs updated if flags or config changed. |
| 207 | +- [ ] Error handling uses specific exception types and clear messages. |
| 208 | + |
| 209 | +## Operational and Safety Guidelines |
| 210 | + |
| 211 | +- Prefer dry runs (`diff`, `list`, `generate`) and include outputs in PRs when helpful. |
| 212 | +- Least privilege: only touch minimal required resources. |
| 213 | +- Idempotency: ensure safe re-runs and guard against partial failures. |
| 214 | +- Observability: contextual logging without secrets (request IDs, endpoints, object counts). |
| 215 | +- Concurrency: avoid collisions with live migrations or active syncs. Coordinate via PRs. |
| 216 | + |
| 217 | +If unsure, stop and ask with a concrete question. |
| 218 | + |
| 219 | +## Security and Secrets |
| 220 | + |
| 221 | +- Configure credentials via environment variables or secret managers. |
| 222 | +- Never print tokens or keys in logs, exceptions, or PRs. Redact examples and tests. |
| 223 | +- Keep example configs authentic but sanitized. |
| 224 | + |
| 225 | +## Platform-Specific Notes |
| 226 | + |
| 227 | +Mirror these principles to: |
| 228 | + |
| 229 | +- `CLAUDE.md` |
| 230 | +- `.github/copilot-instructions.md` |
| 231 | +- `GEMINI.md` |
| 232 | +- `GPT.md` |
| 233 | +- `.cursor/rules/dev-standard.mdc` |
| 234 | + |
| 235 | +Each should include the “Required Development Workflow” block and the “Approval checklist” verbatim. |
| 236 | + |
| 237 | +## Quickstart |
| 238 | + |
| 239 | +```bash |
| 240 | +# Setup |
| 241 | +pyenv local 3.12.x || use system Python 3.9–3.12 |
| 242 | +pip install poetry |
| 243 | +poetry install |
| 244 | + |
| 245 | +# Validate dev environment |
| 246 | +poetry run infrahub-sync --help |
| 247 | +poetry run infrahub-sync list --directory examples/ |
| 248 | + |
| 249 | +# Make a change, then: |
| 250 | +poetry run invoke format |
| 251 | +poetry run invoke lint |
| 252 | +poetry run mypy infrahub_sync/ --ignore-missing-imports |
| 253 | +poetry run infrahub-sync list --directory examples/ |
| 254 | + |
| 255 | +# If docs/CLI changed: |
| 256 | +poetry run invoke docs.generate |
| 257 | +poetry run invoke docs.docusaurus |
| 258 | +``` |
| 259 | + |
| 260 | +## Adding a New Adapter |
| 261 | + |
| 262 | +1. Create `infrahub_sync/adapters/<name>.py` following existing adapter patterns. |
| 263 | +2. Add connection config schema and an example under `examples/`. |
| 264 | +3. Provide `list` and `diff` pathways before enabling `sync`. |
| 265 | +4. Document required environment variables and expected error cases. |
| 266 | +5. Create a documentation page for the adapter in `docs/docs/adapters/`. |
| 267 | + - Include overview, configuration keys, environment variables, example YAML, and common errors. |
| 268 | + - Add it to the sidebar or navigation as needed. |
| 269 | + - Validate with markdownlint: |
| 270 | + |
| 271 | + ```bash |
| 272 | + npx markdownlint-cli "docs/docs/adapters/**/*.{md,mdx}" |
| 273 | + npx markdownlint-cli --fix "docs/docs/adapters/**/*.{md,mdx}" |
| 274 | + ``` |
0 commit comments