diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..73daa61c4 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,102 @@ +# Core Directives & Hierarchy + +This section outlines the absolute order of operations. These rules have the highest priority and must not be violated. + +1. **Primacy of User Directives**: A direct and explicit command from the user is the highest priority. If the user instructs to use a specific tool, edit a file, or perform a specific search, that command **must be executed without deviation**, even if other rules would suggest it is unnecessary. All other instructions are subordinate to a direct user order. +2. **Factual Verification Over Internal Knowledge**: When a request involves information that could be version-dependent, time-sensitive, or requires specific external data (e.g., library documentation, latest best practices, API details), prioritize using tools to find the current, factual answer over relying on general knowledge. +3. **Adherence to Philosophy**: In the absence of a direct user directive or the need for factual verification, all other rules below regarding interaction, code generation, and modification must be followed. + +## General Interaction & Philosophy + +- **Code on Request Only**: Your default response should be a clear, natural language explanation. Do NOT provide code blocks unless explicitly asked, or if a very small and minimalist example is essential to illustrate a concept. Tool usage is distinct from user-facing code blocks and is not subject to this restriction. +- **Direct and Concise**: Answers must be precise, to the point, and free from unnecessary filler or verbose explanations. Get straight to the solution without "beating around the bush". +- **Adherence to Best Practices**: All suggestions, architectural patterns, and solutions must align with widely accepted industry best practices and established design principles. Avoid experimental, obscure, or overly "creative" approaches. Stick to what is proven and reliable. +- **Explain the "Why"**: Don't just provide an answer; briefly explain the reasoning behind it. Why is this the standard approach? What specific problem does this pattern solve? This context is more valuable than the solution itself. + +## Minimalist & Standard Code Generation + +- **Principle of Simplicity**: Always provide the most straightforward and minimalist solution possible. The goal is to solve the problem with the least amount of code and complexity. Avoid premature optimization or over-engineering. +- **Standard First**: Heavily favor standard library functions and widely accepted, common programming patterns. Only introduce third-party libraries if they are the industry standard for the task or absolutely necessary. +- **Avoid Elaborate Solutions**: Do not propose complex, "clever", or obscure solutions. Prioritize readability, maintainability, and the shortest path to a working result over convoluted patterns. +- **Focus on the Core Request**: Generate code that directly addresses the user's request, without adding extra features or handling edge cases that were not mentioned. + +## Surgical Code Modification + +- **Preserve Existing Code**: The current codebase is the source of truth and must be respected. Your primary goal is to preserve its structure, style, and logic whenever possible. +- **Minimal Necessary Changes**: When adding a new feature or making a modification, alter the absolute minimum amount of existing code required to implement the change successfully. +- **Explicit Instructions Only**: Only modify, refactor, or delete code that has been explicitly targeted by the user's request. Do not perform unsolicited refactoring, cleanup, or style changes on untouched parts of the code. +- **Integrate, Don't Replace**: Whenever feasible, integrate new logic into the existing structure rather than replacing entire functions or blocks of code. + +## Intelligent Tool Usage + +- **Use Tools When Necessary**: When a request requires external information or direct interaction with the environment, use the available tools to accomplish the task. Do not avoid tools when they are essential for an accurate or effective response. +- **Directly Edit Code When Requested**: If explicitly asked to modify, refactor, or add to the existing code, apply the changes directly to the codebase when access is available. Avoid generating code snippets for the user to copy and paste in these scenarios. The default should be direct, surgical modification as instructed. +- **Purposeful and Focused Action**: Tool usage must be directly tied to the user's request. Do not perform unrelated searches or modifications. Every action taken by a tool should be a necessary step in fulfilling the specific, stated goal. +- **Declare Intent Before Tool Use**: Before executing any tool, you must first state the action you are about to take and its direct purpose. This statement must be concise and immediately precede the tool call. + +## General principles + +- Write modular, testable code (see language-specific instructions for testing guidelines) +- Prefer explicit over implicit +- Follow established patterns in the same module — check before introducing new ones +- Avoid boilerplate unless explicitly requested +- Suggest refactoring only when duplication is clear + +## Code quality + +- Prefer clear, descriptive names over explanatory comments +- Only comment to explain *why*, not *what* — never comment obvious logic +- Docstrings: concise, purpose/usage only, no implementation detail +- Add copyright header to every new file using the language's comment syntax: + - Python/YAML: `#` + - Go: `//` + - Example (Python): `# Copyright 2026 Canonical Ltd. This software is licensed under the GNU Affero General Public License version 3 (see the file LICENSE).` + +## Security + +- Never hardcode credentials, secrets, or tokens +- Validate and sanitize all user inputs +- Use parameterized queries — never construct SQL via string concatenation +- Avoid deprecated or insecure libraries +- Use secure defaults for cryptographic operations +- Be especially careful with authentication and authorization code + +## Subdirectory reference + +| Path | Purpose & key constraint | +|------|--------------------------| +| `src/maasserver` | Legacy Django region controller. Use `deferToDatabase` for async DB. Prefer adding new features to v3 API. | +| `src/maasapiserver` | FastAPI v3 API (presentation layer). Extend `Handler`, use `@handler`, Pydantic models, `check_permissions`. Mock services in tests. | +| `src/maasservicelayer` | Business logic (service + repository layers). SQLAlchemy Core, `BaseRepository`/`BaseService`, Alembic migrations. See `src/maasservicelayer/README.md`. | +| `src/maastemporalworker` | Temporal workers. Pyright-compliant type hints, appropriate retry/timeout policies. | +| `src/provisioningserver` | Rack controller. Twisted deferreds; legacy async — handle reactor carefully. | +| `src/metadataserver` | Cloud-init metadata service. Django patterns. | +| `src/maascli` | CLI. Clear user-facing errors, validate inputs early. | +| `src/apiclient` | API client library. Graceful auth and error handling. | +| `src/maascommon` | Shared utilities. Keep dependencies minimal; Pyright-compliant. Changes here affect all components. | +| `src/maastesting` | Test utilities and fixtures. Add reusable helpers here. | +| `src/maasagent` | Go agent (microcluster, Temporal, DHCP/DNS, Prometheus, OpenTelemetry). | +| `src/host-info` | Go hardware info utility. Minimal dependencies. | +| `src/perftests` | Performance benchmarks. | +| `src/tests` | Integration and cross-component tests. | + +## Excluded directories + +Do not read or modify: +- `src/maas-offline-docs` +- `src/maasui` + +## Pre-submission checks + +``` +make lint # Python linting and formatting +make test # Python tests +cd src/maasagent && make test +cd src/host-info && go test ./... +``` + +## When in doubt + +1. Check existing code in the same subdirectory +2. Review the subdirectory's README if present +3. Consult `pyproject.toml` or `go.mod` for configuration \ No newline at end of file diff --git a/.github/instructions/go.instructions.md b/.github/instructions/go.instructions.md new file mode 100644 index 000000000..f47a2008d --- /dev/null +++ b/.github/instructions/go.instructions.md @@ -0,0 +1,44 @@ +--- +applyTo: "**/*.go" +--- + +## Subdirectory Context + +See the subdirectory reference table in `copilot-instructions.md` for detailed constraints on: `src/maasagent` (microcluster-based agent with Temporal, DHCP/DNS, observability) and `src/host-info` (standalone hardware utility with minimal dependencies). + +## Linting, Formatting & Testing + +- Use `make lint-go` to check Go code before committing +- Use `make lint-go-fix` to auto-fix lint issues where possible +- Run the targeted Go lint instead of `make lint` when only Go files changed +- Use `make format-go` to format Go files instead of `make format` when only Go files changed +- Use `make test-go` to run Go tests instead of `make test` when only Go files changed + +## Style + +- Always run `gofmt` / `go fmt` before committing +- Follow standard Go idioms; avoid clever or non-idiomatic patterns +- Full style reference: `go-style-guide.md` + +## Versions & modules + +- `src/maasagent`: Go 1.24.4 +- `src/host-info`: Go 1.18 +- Check `go.mod` before adding any new dependency + +## Testing + +- Prefer table-driven tests +- Use `testify` in `src/maasagent` +- Standard `testing` package in `src/host-info` + +## Subdirectory specifics + +**`src/maasagent`** — microcluster-based agent +- Follow microcluster patterns +- Integrates Temporal workflows, DHCP/DNS services, Prometheus metrics, OpenTelemetry tracing +- Keep observability instrumentation consistent with existing patterns + +**`src/host-info`** — hardware info utility +- Minimal dependencies; do not introduce new ones without good reason +- Standalone binary; keep it simple \ No newline at end of file diff --git a/.github/instructions/python.instructions.md b/.github/instructions/python.instructions.md new file mode 100644 index 000000000..0c8f365f8 --- /dev/null +++ b/.github/instructions/python.instructions.md @@ -0,0 +1,73 @@ +--- +applyTo: "**/*.py" +--- + +## Subdirectory Context + +See the subdirectory reference table in `copilot-instructions.md` for detailed constraints on: `maasserver`, `maasapiserver`, `maasservicelayer`, `maastemporalworker`, `provisioningserver`, `metadataserver`, `maascli`, `apiclient`, `maascommon`, `maastesting`. Different subdirectories have different async, database, and testing patterns. + +## Style + +- Max line length: 79 chars (see `pyproject.toml`) +- 4-space indentation, double quotes, Ruff formatter + linter +- Target Python 3.14+ + +## Imports + +isort order: +1. Standard library +2. Third-party +3. MAAS first-party in this order: `apiclient`, `maasapiserver`, `maascli`, `maascommon`, `maasserver`, `maasservicelayer`, `maastesting`, `metadataserver`, `provisioningserver` + +## Type hints + +- Required on all function signatures +- New code in `maascommon`, `maasservicelayer`, `maasapiserver`, `maastemporalworker` must be Pyright-compliant +- Use Pydantic models for data validation + +## Async + +- Use `async`/`await` in async contexts +- v3 API: prefer async patterns +- Legacy Django: use `deferToDatabase` for DB calls in async contexts + +## Database + +- New code: SQLAlchemy Core (not ORM) in the service layer +- Legacy code: Django ORM where already established +- Always use parameterized queries; use transactions appropriately + +## Linting + +Run the narrowest target that covers your changes: + +| Target | When to use | +|--------|-------------| +| `make lint-py` | General Python style and formatting (Ruff); use after any `.py` change | +| `make lint-py-imports` | After adding, removing, or reordering imports | +| `make lint-py-builders` | After modifying builder classes in `maasservicelayer` | +| `make lint-py-linefeeds` | If you touched line endings or file encoding | +| `make lint-oapi` | After changing any OpenAPI spec or `maasapiserver` handler that affects the spec | +| `make lint` | Full suite — run before submitting a PR or when unsure | + +Prefer `make lint-py` for routine Python edits; add `make lint-py-imports` whenever import blocks change. + +## Formatting + +- Use `make format-py` to auto-format Python files after any edit +- Use `make format` only when multiple languages are affected + +## Testing + +- Use `make test-py` to run the Python test suite; use `make test` only when multiple languages are affected +- Use `pytest` for new code; follow existing patterns in the subdirectory +- Use appropriate fixtures (`db_connection`, `services_mock`, etc.) +- Mock external dependencies +- No trivial assertions; test meaningful behavior only + +## Service layer patterns + +- Use builders (Pydantic models) for create/update operations +- `ClauseFactory` for reusable query filters +- `QuerySpec` for repository filtering +- Three-tier architecture: repository → service → API diff --git a/.github/prompts/architect.prompt.md b/.github/prompts/architect.prompt.md new file mode 100644 index 000000000..4c6837697 --- /dev/null +++ b/.github/prompts/architect.prompt.md @@ -0,0 +1,48 @@ +--- +mode: agent +description: Produce architectural plans and design guidance without writing code +--- + +# Software Architect Role + +When operating in the **Software Architect** role, the following rules override the standard code modification and generation behaviors: + +## Core Responsibilities + +- **No Code Modification**: Do not edit, create, or directly modify any code files. Your role is purely advisory and architectural. All implementation is delegated to the development team. +- **Documentation Over Implementation**: Produce clear, concise architectural documentation that explains *how* a task should be accomplished, not the implementation itself. +- **Engineering Focus**: Concentrate solely on technical architecture, design patterns, system structure, data flow, and engineering decisions. Exclude project management concerns such as timelines, resource allocation, or team coordination. + +## Implementation Plan Structure + +- **Logical Decomposition**: Break down the requested task into discrete, logical implementation blocks. Each block should represent a cohesive unit of work that can be implemented and reviewed independently. +- **Reviewability**: Ensure each block is sized appropriately for code review—small enough to be thoroughly reviewed (typically affecting 1-3 files or a single module), but large enough to represent meaningful progress. +- **Clear Boundaries**: Define explicit boundaries between blocks, including what files/modules each block affects and the dependencies between blocks. +- **Sequential or Parallel Paths**: Indicate which blocks must be completed sequentially and which can be worked on in parallel. + +## Documentation Requirements + +Each architectural plan must include: + +1. **Overview**: A brief statement of the goal and the high-level architectural approach. +2. **Design Decisions**: Key architectural choices and the reasoning behind them (why this pattern, why this structure). +3. **Implementation Blocks**: A numbered, ordered list of implementation blocks, each containing: + - **Block Title**: A clear, descriptive name + - **Scope**: Which files, modules, or components are affected + - **Objective**: What this block achieves + - **Approach**: The technical approach and patterns to use + - **Dependencies**: What must be completed before this block + - **Testing Considerations**: What should be tested after this block +4. **Integration Points**: How the blocks connect and integrate with existing systems. +5. **Technical Risks**: Any architectural concerns or technical risks to be aware of. + +## Interaction Style + +- **Concise and Actionable**: Documentation should be brief but complete. Avoid unnecessary elaboration. +- **Technically Precise**: Use accurate technical terminology and be specific about patterns, interfaces, and structures. +- **Developer-Oriented**: Write for an experienced developer who will implement the plan. Assume technical competence. +- **Explain Architectural Reasoning**: Always explain the reasoning and trade-offs behind architectural choices. Clarify why this pattern or structure is chosen over alternatives. + +--- + +**Activation**: This role is activated when the user explicitly requests architectural guidance, an implementation plan, or operates in a context where code modification is inappropriate (e.g., high-level design phase, architectural review). \ No newline at end of file diff --git a/.github/prompts/code-review.prompt.md b/.github/prompts/code-review.prompt.md new file mode 100644 index 000000000..f1d8b6568 --- /dev/null +++ b/.github/prompts/code-review.prompt.md @@ -0,0 +1,69 @@ +--- +mode: agent +description: Review all branch changes against master for architectural consistency and integrity +--- + +You are a code reviewer focused on architectural consistency and change integrity. + +## Setup + +Before reviewing, gather context using the available tools: +1. Run `git log master..HEAD --oneline` to list commits on this branch +2. Run `git diff master...HEAD` to get the complete diff + +## Review Scope + +Review all changes in the current branch (compared to master) **as a cohesive unit**. Since the project uses squash-merge, treat the branch as a single logical change set. Use commit messages as context for understanding intent, but evaluate the overall diff holistically. + +## Review Process + +1. Understand the intended change from the commit message(s) +2. Examine the complete diff for: + - Alignment between stated intent and actual changes + - Adherence to patterns in the repository instructions and related docs + - Maintenance of architectural principles + - No unrelated or scope-creeping modifications +3. Assess the branch as a cohesive whole, not individual commits + +## What to Flag + +**Must Fix**: Architectural violations, undocumented patterns, scope creep outside stated intent + +**Need Information**: Unclear design decisions, missing context, questionable architectural choices that need explanation + +**Nit-picks**: Minor inconsistencies, documentation gaps, clarity improvements + +## Standards to Check Against + +- Repository coding instructions (automatically available in this session) +- Architecture and design docs in the repo +- Existing code patterns and conventions +- Stated intent vs. actual changes + +## Guidelines + +- Be objective and specific; cite the actual issue with file path and line references +- Don't flag style issues (formatting, naming) unless they harm readability or violate documented conventions +- Focus on genuine architectural and integrity issues only +- Suggest clarifications and context, not code rewrites +- Keep language direct and concise +- Flag over-engineered solutions when a simpler approach is available +- Check if new code also introduces reasonable test coverage + +## Output Format + +Structure the response as a single report with four sections: + +### Commit message +Write a conventional commit message for this branch (type, optional scope, description, body with reasoning, footer with ticket reference if applicable). For detailed conventional commits specification and examples, use the `/commit-message` prompt. + +### Must Fix +Critical issues blocking merge. If none, write "None." + +### Need Information +Unclear decisions or missing context requiring explanation before merge. If none, write "None." + +### Nit-picks +Minor inconsistencies, documentation gaps, or clarity improvements. If none, write "None." + +For every finding, include the file path and line reference. diff --git a/.github/prompts/commit-message.prompt.md b/.github/prompts/commit-message.prompt.md new file mode 100644 index 000000000..06e7926a9 --- /dev/null +++ b/.github/prompts/commit-message.prompt.md @@ -0,0 +1,80 @@ +--- +mode: agent +description: Write a conventional commit message for the current changes +--- + +Inspect the staged or unstaged changes with `git diff --cached` (falling back to `git diff HEAD` if nothing is staged), then write a conventional commit message following the rules below. + +## Format + +``` +[(scope)][!]: + +[body] + +[footer(s)] +``` + +## Types + +| Type | When to use | +| :--- | :--- | +| `feat` | New feature | +| `fix` | Bug fix | +| `refactor` | Code change that is neither a fix nor a feature | +| `perf` | Performance improvement | +| `test` | Adding or correcting tests | +| `build` | Build, packaging, or dependency changes | +| `chore` | Changes that don't fit other types | +| `docs` | Documentation-only changes | + +## Scopes + +Use one of these when the change is clearly scoped to a component: + +`bootresources` · `dhcp` · `dns` · `network` · `power` · `security` · `storage` · `tftp` · `ci` + +For dependency changes use `build(deps):` — `deps` is a scope, not a standalone type. + +## Rules + +- **description**: 72 characters or less; high-level summary of the problem solved or feature added — no implementation detail lists +- **body**: explain *why*, not *what*; omit if the description is self-evident +- **`!`**: add before the colon for breaking changes; add `BREAKING CHANGE: ` in the footer +- **ticket reference**: mandatory for `fix`; include for all other types when a relevant issue exists + - Launchpad: `Resolves LP:2066936` + - GitHub: `Resolves GH:123` + - Jira: `Resolves JIRA-123` +- **author attribution**: Do NOT include Co-authored-by footers for AI tools or bots. This project maintains author integrity by crediting actual humans only. + +## Examples + +``` +feat(bootresources): check if controller has enough disk space + +Controllers were silently failing or retrying indefinitely when disk +space was insufficient. This adds pre-flight checks to fail fast with +a clear user-facing error rather than producing confusing partial state. +``` + +``` +fix(network): correct VLAN configuration parsing + +The parser was incorrectly handling tagged VLANs with non-standard +MTU values, causing network interface initialization to fail. + +Resolves LP:2066936 +``` + +``` +feat(bootresources)!: replace tcpdump with maas-netmon + +New binary `maas-netmon` is introduced for ARP network discovery. + +BREAKING CHANGE: Binary doesn't read PCAP format, thus it is not +possible to pass in stdin or file as an argument anymore. +``` + +## Output + +Print only the commit message — no explanation, no surrounding text. \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index 6d7b64822..71565329e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,249 +1,44 @@ # AI Coding Agent Guidelines -This document provides guidelines for AI coding agents (such as GitHub Copilot, Cursor, Cline, etc.) working on the MAAS project. These rules help ensure consistency, quality, and security across the codebase. - -## Table of Contents - -- [General Principles](#general-principles) -- [Code Quality and Verbosity](#code-quality-and-verbosity) -- [Security Requirements](#security-requirements) -- [Documentation Standards](#documentation-standards) -- [Collaboration Practices](#collaboration-practices) -- [Conventional Commits](#conventional-commits) -- [Python Guidelines](#python-guidelines) -- [Go Guidelines](#go-guidelines) -- [Subdirectory-Specific Rules](#subdirectory-specific-rules) - -## General Principles - -- Write code that is modular and testable -- Prefer explicit over implicit code -- Follow the project's established patterns and idioms -- Suggest refactoring when code duplication is detected -- Avoid generating large boilerplate unless explicitly requested -- Always check existing code patterns in the same module before introducing new patterns - -## Code Quality and Verbosity - -Write clean, readable code that speaks for itself: - -- **Better naming over comments**: Use clear, descriptive names for variables, functions, and tests instead of explaining unclear code with comments. Avoid abbreviations unless widely understood. -- **Avoid trivial comments**: Don't comment on obvious logic or implementation details -- **Concise documentation**: Keep it simple and straightforward -- **Clean test code**: No verbose docstrings in tests; fixtures should be self-documenting without obvious comments -- **Reasonable merge proposals**: Keep changes focused and reasonably sized -- **Copyright headers**: Add copyright header to all new files (update year as needed): - ``` - # Copyright 2026 Canonical Ltd. This software is licensed under the - # GNU Affero General Public License version 3 (see the file LICENSE). - ``` - -### When to Comment - -Only add comments when: -- Explaining *why* something is done (not *what* is being done) -- Documenting non-obvious business logic or domain knowledge -- Clarifying complex algorithms -- Noting important gotchas or edge cases -- Providing context that cannot be expressed in code - -## Security Requirements - -Across all parts of the codebase: - -- Never hardcode credentials, secrets, or tokens -- Validate and sanitize all user inputs -- Use parameterized queries for database access -- Avoid deprecated or insecure libraries -- Follow security best practices for the specific technology stack -- Be especially careful with authentication and authorization code -- Always use secure defaults for cryptographic operations - -## Documentation Standards - -- Keep inline comments focused on *why*, not *what* -- Use concise docstrings for public functions, classes, and modules (purpose and usage, not implementation) -- **Avoid redundancy and obvious statements**: Don't repeat what the code already shows or state the obvious -- Update README files when functionality changes -- Document API changes immediately -- Keep architecture documentation synchronized with code changes -- Include type hints where applicable +Entry point for AI coding agents (GitHub Copilot, Cursor, Cline, etc.) working on the MAAS project. The canonical rules live in the `.github/` directory — read those files before proceeding. -## Collaboration Practices - -- Follow the project's code review and pull request process -- Tag relevant team members for specialized reviews -- Reference related issues in commits and pull requests -- Link to relevant documentation when making architectural changes -- Ensure code is compatible with the project's current dependency versions - -## Conventional Commits - -All commits and pull/merge requests must follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. This ensures consistent, readable commit history and enables automated changelog generation. - -### Commit Message Format - -``` -[(scope)][!]: - -[body] - -[footer(s)] -``` - -- **type**: Kind of change (feat, fix, refactor, perf, test, build, chore, docs) -- **scope**: Optional - affected component or system (e.g., bootresources, network, security, deps) -- **!**: Add before colon if commit introduces breaking changes -- **description**: Brief summary, aim for 72 characters or less -- **body**: Optional - detailed explanation of the change -- **footer**: Optional - metadata like `Resolves LP:2066936` or `BREAKING CHANGE: description` - -### Allowed Types - -| Type | Purpose | -| :--- | :--- | -| **feat** | A new feature | -| **fix** | A bug fix | -| **refactor** | Code change that doesn't fix a bug or add a feature | -| **perf** | Performance improvement | -| **test** | Adding or correcting tests | -| **build** | Build, packaging, or dependency changes | -| **chore** | Changes that don't fit other types (e.g., version bumps) | -| **docs** | Documentation-only changes | - -### Allowed Scopes (MAAS) - -Use one of these scopes where applicable: - -- **bootresources**: Images download and synchronization -- **dhcp**: DHCP service -- **dns**: DNS service -- **network**: Networking-related changes -- **power**: Power drivers and machine power management -- **security**: Security improvements or fixes -- **storage**: Storage management -- **tftp**: TFTP service -- **deps**: Dependency changes — used as a scope under the `build` type (e.g., `build(deps): upgrade SQLAlchemy to 2.x`), not as a standalone type -- **ci**: CI/CD changes - -### Guidelines - -- Ticket references are **mandatory** for `fix` commits. For all other types, include them when a relevant issue exists. Supported trackers: `Resolves LP:2066936` (Launchpad), `Resolves GH:123` (GitHub), `Resolves JIRA-123` (Jira). -- **Description (title)**: Provide a high-level overview only. Do not enumerate individual changes or list implementation details. Focus on the problem being solved or the feature being added. -- **Body**: Use the body to explain the reasoning, context, and any non-obvious implementation details. Keep it concise and focused on the "why" rather than exhaustively documenting the "what". - -### Examples - -Good commit with breaking change: -``` -feat(bootresources)!: replace tcpdump with maas-netmon - -New binary `maas-netmon` is introduced for ARP network discovery. - -BREAKING CHANGE: Binary doesn't read PCAP format, thus it is not -possible to pass in stdin or file as an argument anymore. -``` - -Good bug fix: -``` -fix(network): correct VLAN configuration parsing - -The parser was incorrectly handling tagged VLANs with non-standard -MTU values, causing network interface initialization to fail. - -Resolves LP:2066936 -``` - -Good feature: -``` -feat(bootresources): check if controller has enough disk space - -Controllers were silently failing or retrying indefinitely when disk -space was insufficient. This adds pre-flight checks to fail fast with -a clear user-facing error rather than producing confusing partial state. -``` - -## Python Guidelines +## Canonical Instruction Files -MAAS Python code must adhere to the following standards: +Read these files before writing any code. They contain the authoritative rules for this codebase: -### Code Style +| File | Content | +|------|---------| +| `.github/copilot-instructions.md` | Core directives, interaction philosophy, code quality, security, subdirectory reference | +| `.github/instructions/python.instructions.md` | Python coding guidelines (style, imports, async, DB, testing, service layer patterns) | +| `.github/instructions/go.instructions.md` | Go coding guidelines (style, versions, testing, subdirectory specifics) | -- **Line length**: Maximum 79 characters (as configured in `pyproject.toml`) -- **Indentation**: 4 spaces (no tabs) -- **Quotes**: Use double quotes for strings -- **Formatting**: Use Ruff formatter (configured in `pyproject.toml`) -- **Linting**: Follow Ruff linting rules (pycodestyle, pyflakes, isort, flake8-bugbear) +## GitHub Copilot -### Python Version Compatibility +The files above are applied automatically in Copilot Chat sessions. The following task prompts are also available: -- Target Python 3.9+ (check `pyproject.toml` for exact supported versions) -- Avoid using features from Python versions not yet supported -- Use type hints from `typing` module for compatibility +| Prompt | Invoke with | Purpose | +|--------|-------------|---------| +| `.github/prompts/architect.prompt.md` | `/architect` | Architectural planning and design guidance | +| `.github/prompts/code-review.prompt.md` | `/code-review` | Branch code review against `master` | +| `.github/prompts/commit-message.prompt.md` | `/commit-message` | Write conventional commit messages | -### Import Organization - -Follow the isort configuration in `pyproject.toml`: - -1. Standard library imports -2. Third-party library imports -3. MAAS first-party imports (in this order): - - `apiclient` - - `maasapiserver` - - `maascli` - - `maascommon` - - `maasserver` - - `maasservicelayer` - - `maastesting` - - `metadataserver` - - `provisioningserver` - -### Type Hints - -- Use type hints for function signatures -- For new code in `maascommon`, `maasservicelayer`, `maasapiserver`, and `maastemporalworker`, ensure Pyright compliance -- Use Pydantic models for data validation where appropriate - -### Async Code - -- Use `async`/`await` patterns in asynchronous contexts -- Be aware of the difference between sync and async database access patterns -- In v3 API code, prefer async patterns -- In legacy Django code, use `deferToDatabase` for database operations in async contexts - -### Database Access - -- **New code**: Use SQLAlchemy Core (not ORM) in the service layer -- **Legacy code**: Continue using Django ORM where already established -- Always use parameterized queries -- Never construct SQL with string concatenation -- Use transactions appropriately - -### Testing - -- Write tests using `pytest` for new code -- Follow existing test patterns in the subdirectory -- Use appropriate fixtures (`db_connection`, `services_mock`, etc.) -- Mock external dependencies appropriately -- **Avoid trivial assertions**: Don't test obvious behavior or framework functionality -- **Keep tests minimal**: Write only necessary tests that verify meaningful behavior - -### Common Patterns +## Conventional Commits -- Use builders (Pydantic models) for creating/updating entities in the service layer -- Implement `ClauseFactory` for reusable query filters -- Use `QuerySpec` for filtering in repository methods -- Follow the three-tier architecture in v3 API code (repository → service → API) +All commits and pull/merge requests must follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification. Full specification with allowed types, scopes, and examples: `.github/prompts/commit-message.prompt.md`. -## Go Guidelines +Quick reference: +- Format: `[(scope)][!]: ` +- Ticket reference mandatory for `fix`: `Resolves LP:2066936` (Launchpad), `Resolves GH:123` (GitHub) +- Description: high-level summary only, 72 chars or less; no implementation detail lists +- Body: explain the *why*, not the *what* -MAAS Go code (primarily in `maasagent` and `host-info`) follows the standards documented in [`go-style-guide.md`](go-style-guide.md). +## Collaboration Practices -Key points: -- Follow standard Go formatting (`gofmt` / `go fmt`) -- Check `go.mod` for Go version (currently Go 1.24.4 for `maasagent`, Go 1.18 for `host-info`) -- Use table-driven tests where appropriate -- Follow the microcluster patterns in `maasagent` +- Follow the project's code review and pull request process +- Tag relevant team members for specialized reviews +- Reference related issues in commits and pull requests +- Link to relevant documentation when making architectural changes +- Ensure code is compatible with the project's current dependency versions ## Subdirectory-Specific Rules @@ -385,7 +180,6 @@ Key points: - OpenTelemetry tracing - **Testing**: Use Go testing with testify - **Dependencies**: Check `go.mod` before adding dependencies -- **Notes**: Modern Go service; follow Go best practices ### `src/host-info` @@ -396,16 +190,13 @@ Key points: - Hardware detection and reporting - Minimal dependencies - **Testing**: Standard Go tests -- **Notes**: Standalone utility for hardware information gathering +- **Notes**: Standalone utility; do not introduce new dependencies without good reason ### `src/perftests` -**Purpose**: Performance testing +**Purpose**: Performance benchmarks - **Technology**: Python -- **Key Patterns**: - - Performance benchmarks - - Load testing scenarios - **Notes**: Add performance tests for critical paths ### `src/tests` @@ -413,46 +204,62 @@ Key points: **Purpose**: Integration and cross-component tests - **Technology**: Python, pytest -- **Key Patterns**: - - Integration tests - - End-to-end scenarios - **Notes**: Tests that span multiple components ## Excluded Directories -The following directories should be ignored by AI coding agents: +Do not read or modify: - `src/maas-offline-docs`: Documentation artifacts - `src/maasui`: UI components (separate frontend codebase) ## Running Checks -Before submitting code, ensure: +### Formatting -```bash -# Python linting and formatting -make lint +Prefer the specialized format target that matches the files you changed. + +| Target | When to use | +|--------|-------------| +| `make format` | Full format pass — when multiple categories are affected | +| `make format-py` | Any Python change | +| `make format-go` | Any Go change | + +### Linting + +Prefer the specialized lint target that matches the files you changed — it is faster and gives more focused output. Fall back to `make lint` when multiple categories are affected. -# Python tests -make test +| Target | When to use | +|--------|-------------| +| `make lint` | Full lint pass — run before submitting a PR or when multiple categories are affected | +| `make lint-py` | Any Python change (runs Ruff linter + formatter check) | +| `make lint-py-imports` | After adding, removing, or reordering imports in Python files | +| `make lint-py-builders` | After modifying builder classes or Pydantic create/update models | +| `make lint-py-linefeeds` | If you suspect mixed or incorrect line endings in Python files | +| `make lint-go` | Any Go change | +| `make lint-go-fix` | Go change where you want auto-fix applied (runs `gofmt`/`golangci-lint --fix`) | +| `make lint-oapi` | After modifying any OpenAPI spec file (e.g. in `src/maasapiserver`) | +| `make lint-shell` | After modifying any shell script | -# Go tests (in respective directories) -cd src/maasagent && make test -cd src/host-info && go test ./... +### Tests + +Prefer the specialized test target that matches the files you changed. + +| Target | When to use | +|--------|-------------| +| `make test` | Full test suite — run before submitting a PR or when multiple components are affected | +| `make test-py` | Any Python change | +| `make test-go` | Any Go change | + +```bash +cd src/maasagent && make test # Go agent tests (alternative) +cd src/host-info && go test ./... # host-info tests ``` ## Additional Resources - Python configuration: `pyproject.toml` +- Go style guide: `go-style-guide.md` - Go configuration: `src/maasagent/go.mod`, `src/host-info/go.mod` - Service layer architecture: `src/maasservicelayer/README.md` - Database migrations: `src/maasservicelayer/db/alembic/` - -## Questions and Clarifications - -When in doubt: - -1. Check existing code in the same subdirectory for patterns -2. Review the subdirectory's README if available -3. Consult `pyproject.toml` or `go.mod` for configuration -4. Ask the human reviewer for clarification on architectural decisions