Improve AGENTS guide for Ansible workflows

This commit is contained in:
Fabio Scotto di Santolo
2026-03-16 16:54:43 +01:00
parent fbd58a8fe7
commit 4f14ccb740

158
AGENTS.md
View File

@@ -1,9 +1,9 @@
# AGENTS.md # AGENTS.md
Guide for coding agents in this repository. Agent guide for this repository.
Project type: Ansible infrastructure + managed dotfiles. Project type: Ansible infrastructure with managed dotfiles.
## Repository map ## Scope and layout
- Entry playbook: `ansible/site.yml` - Entry playbook: `ansible/site.yml`
- Inventory: `ansible/inventory/hosts.yml` - Inventory: `ansible/inventory/hosts.yml`
- Group vars: `ansible/inventory/group_vars/*.yml` - Group vars: `ansible/inventory/group_vars/*.yml`
@@ -12,55 +12,39 @@ Project type: Ansible infrastructure + managed dotfiles.
- Dotfiles source: `dotfiles/` - Dotfiles source: `dotfiles/`
- Ansible config: `ansible.cfg` - Ansible config: `ansible.cfg`
`ansible.cfg` defaults in use: Current `ansible.cfg` defaults:
- `inventory = ansible/inventory/hosts.yml` - `inventory = ansible/inventory/hosts.yml`
- `roles_path = ansible/roles` - `roles_path = ansible/roles`
- `host_key_checking = False` - `host_key_checking = False`
- `retry_files_enabled = False` - `retry_files_enabled = False`
## Cursor / Copilot rules status ## Cursor and Copilot instructions
Checked and not found: Checked in this repo and not found:
- `.cursorrules` - `.cursorrules`
- `.cursor/rules/` - `.cursor/rules/`
- `.github/copilot-instructions.md` - `.github/copilot-instructions.md`
If these files are added later, treat them as higher-priority local instructions. If any of these are added later, treat them as higher-priority local instructions.
## Dependencies ## Build, lint, and test commands
Required:
- Python 3
- Ansible
- Access to target hosts (local or SSH, depending on inventory)
Install baseline:
```bash
python3 -m pip install ansible
```
Optional quality tools:
```bash
python3 -m pip install ansible-lint yamllint
```
## Build / lint / test commands
There is no compile/build artifact in this repo. There is no compile/build artifact in this repo.
Use syntax checks, dry-runs, and linting as validation. Validation is done with syntax checks, dry-runs, inventory checks, and linting.
Main run: Main apply run:
```bash ```bash
ansible-playbook ansible/site.yml ansible-playbook ansible/site.yml
``` ```
Run only one host:
```bash
ansible-playbook ansible/site.yml --limit ikaros
```
Dry-run with diff: Dry-run with diff:
```bash ```bash
ansible-playbook ansible/site.yml --check --diff ansible-playbook ansible/site.yml --check --diff
``` ```
Run one host:
```bash
ansible-playbook ansible/site.yml --limit ikaros
```
Inventory sanity checks: Inventory sanity checks:
```bash ```bash
ansible-inventory --graph ansible-inventory --graph
@@ -75,91 +59,109 @@ yamllint ansible/
``` ```
## Single-test equivalents (important) ## Single-test equivalents (important)
No dedicated test harness (pytest/molecule) exists yet. There is no dedicated test harness (no Molecule/pytest suite).
Use these targeted commands as "single test" workflows. Use these as targeted single-test workflows:
Syntax-check one playbook: Syntax-check only:
```bash ```bash
ansible-playbook ansible/site.yml --syntax-check ansible-playbook ansible/site.yml --syntax-check
``` ```
Test one host in dry-run mode: Dry-run one host (best single test):
```bash ```bash
ansible-playbook ansible/site.yml --limit nymph --check --diff ansible-playbook ansible/site.yml --limit nymph --check --diff
``` ```
Start at one task: Start from one known task name:
```bash ```bash
ansible-playbook ansible/site.yml --start-at-task "Copy .bashrc" --limit ikaros ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Copy .bashrc" --check --diff
``` ```
Run one tag subset (requires tagged tasks): Run one role by task boundary (practical approximation):
```bash ```bash
ansible-playbook ansible/site.yml --tags dotfiles --limit ikaros ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Install Void nonfree repository if needed" --check --diff
``` ```
List hosts targeted by current inventory:
```bash
ansible all --list-hosts
```
Notes:
- `--tags` is preferred for targeted runs once tasks are tagged consistently.
- Today, `site.yml` actively applies `dotfiles_common`, `packages_void`, `services_runit`, and `profile_desktop_i3`.
- Dependencies: Python 3, Ansible, and host access (local or SSH depending on inventory).
- Setup: `python3 -m pip install ansible` (plus optional `ansible-lint yamllint`).
## Code style guidelines ## Code style guidelines
### General principles ### Core principles
- Keep changes idempotent and declarative. - Keep automation idempotent, declarative, and host-safe.
- Preserve layering: `common -> OS -> profile -> host`. - Preserve variable layering: `all -> OS -> profile -> host`.
- Avoid unrelated refactors; keep edits minimal and local. - Keep edits minimal and local; avoid opportunistic refactors.
- Prefer readability over compression in YAML/Jinja.
### Ansible modules, imports, and structure ### Modules, imports, and role structure
- Use FQCN module names (`ansible.builtin.copy`, `community.general.xbps`). - Use FQCN modules (`ansible.builtin.copy`, `community.general.xbps`).
- Prefer modules over raw `shell`/`command`. - Prefer modules over `ansible.builtin.shell`/`ansible.builtin.command`.
- Use `import_tasks`/`include_tasks` when role task files grow. - If command/shell is necessary, document intent via task name and guards.
- Keep `site.yml` orchestration-focused; implementation lives in roles. - Keep `ansible/site.yml` orchestration-focused; implementation belongs in roles.
- Keep role scope narrow (packages vs services vs dotfiles). - Split large role task files with `import_tasks`/`include_tasks`.
- Keep each role narrow in purpose (packages, services, profile, dotfiles).
### Formatting ### YAML formatting
- Start YAML files with `---`. - Start YAML files with `---`.
- Use 2-space indentation; never tabs in YAML. - Use 2-space indentation, never tabs.
- Quote modes as strings: `"0644"`, `"0755"`, `"0600"`. - Keep key ordering stable and meaningful.
- Keep long Jinja expressions multiline and readable. - Quote file modes as strings: `"0644"`, `"0755"`, `"0600"`, `"0700"`.
- No trailing whitespace. - Keep long Jinja expressions multiline.
- Avoid trailing whitespace.
### Variables and types ### Variables and types
- Use `snake_case` variable names. - Use `snake_case` variable names.
- Keep names semantically scoped (`common_packages`, `profile_packages`, `host_packages`). - Use semantically scoped names (`common_packages`, `void_packages_base`, `host_packages`).
- Use true YAML types: lists for lists, booleans as `true`/`false`. - Keep booleans as `true`/`false`, not quoted strings.
- Use `default([])` / `default({})` for optional vars. - Keep lists and dicts as real YAML collections.
- Keep paths consistent, usually templated from `{{ user_home }}`. - Use `default([])` / `default({})` for optional variables.
- Put global defaults in `group_vars/all.yml`; specialize in group/host vars. - Build paths consistently from `{{ user_home }}` and related vars.
- Put shared defaults in `group_vars/all.yml`; specialize in group/host vars.
### Naming conventions ### Naming conventions
- Roles: lowercase with underscores. - Role directories: lowercase with underscores.
- Tasks: imperative, explicit outcome (`Install packages on Void Linux`). - Task names: imperative and outcome-based (`Enable host runit services`).
- Inventory group and var file names must stay aligned. - Inventory group names and matching var filenames should stay aligned.
- Host var files should match hostnames exactly. - Host var filenames must match hostnames exactly.
### Error handling and safety ### Error handling and safety
- Guard OS/profile-specific actions with `when`. - Guard OS/profile-specific steps with `when`.
- For `command`/`shell`, set `changed_when`/`failed_when` where needed. - Use explicit `loop` inputs and default guards for optional lists.
- Do not suppress failures without clear justification. - For `command`/`shell`, define `changed_when` and `failed_when` when needed.
- Validate risky changes with `--check --diff` before real apply. - Do not suppress failures unless there is a clear operational reason.
- Avoid destructive user-file operations unless explicitly required. - Validate risky changes with `--check --diff` before full apply.
- Avoid destructive file operations in user homes unless explicitly required.
- Avoid touching secrets material; never commit credentials.
### Shell and dotfiles ### Dotfiles and shell scripts
- Prefer POSIX `sh` unless Bash features are required. - Prefer POSIX `sh`; use Bash only when required.
- If Bash is required, use `#!/usr/bin/env bash`. - If Bash is required, use shebang `#!/usr/bin/env bash`.
- Quote expansions (`"$var"`) unless intentional word splitting is required. - Quote expansions (`"$var"`) unless intentional splitting is required.
- Keep automation-invoked scripts non-interactive. - Keep scripts non-interactive when invoked by automation.
## Agent operating expectations ## Agent expectations
- Never commit or expose data from `secrets/`.
- Do not modify unrelated files. - Do not modify unrelated files.
- Keep docs (`README.md`, `AGENTS.md`) current when workflows change. - Never commit or expose data from `secrets/`.
- If adding new task domains, add tags to improve targeted runs. - Keep `AGENTS.md` and `README.md` in sync with workflow changes.
- When adding new role domains, add tags to support targeted execution.
## Pre-merge checklist ## Pre-merge checklist
Run before submitting changes:
```bash ```bash
ansible-playbook ansible/site.yml --syntax-check ansible-playbook ansible/site.yml --syntax-check
ansible-playbook ansible/site.yml --check --diff --limit <host> ansible-playbook ansible/site.yml --check --diff --limit <host>
ansible-inventory --graph ansible-inventory --graph
``` ```
If lint tools are installed: If lint tooling is installed:
```bash ```bash
ansible-lint ansible/site.yml ansible-lint ansible/site.yml
yamllint ansible/ yamllint ansible/