Document current repo workflows

This commit is contained in:
Fabio Scotto di Santolo
2026-03-18 18:26:39 +01:00
parent cd65dd20e2
commit a125f70860
2 changed files with 232 additions and 160 deletions

219
AGENTS.md
View File

@@ -1,151 +1,168 @@
# AGENTS.md # AGENTS.md
Guidance for agentic coding tools working in this repository.
Project type: Ansible-based infrastructure plus managed dotfiles.
Guidance for coding agents working in this repository. ## Repository snapshot
Project type: Ansible infrastructure + managed dotfiles.
## Repository scope and layout
- Entry playbook: `ansible/site.yml` - Entry playbook: `ansible/site.yml`
- Ansible config: `ansible.cfg`
- Inventory: `ansible/inventory/hosts.yml` - Inventory: `ansible/inventory/hosts.yml`
- Group vars: `ansible/inventory/group_vars/*.yml` - Group vars: `ansible/inventory/group_vars/*.yml`
- Host vars: `ansible/inventory/host_vars/*.yml` - Host vars: `ansible/inventory/host_vars/*.yml`
- Roles: `ansible/roles/*/tasks/main.yml` - Roles: `ansible/roles/*/tasks/main.yml`
- Dotfiles source of truth: `dotfiles/` - Dotfiles source of truth: `dotfiles/`
- Ansible config file: `ansible.cfg` - Scripts: `scripts/`
- Sensitive local material/examples: `secrets/`
- Active orchestration: `all -> dotfiles_common`; `void -> packages_void, services_runit, profile_desktop_i3`
- Roles present but not currently wired into `ansible/site.yml`: `base`, `dotfiles`, `packages_ubuntu`, `services_systemd`, `profile_workstation_gnome`, `profile_server`
Current `ansible.cfg` defaults: ## Local instruction files
- `inventory = ansible/inventory/hosts.yml` Checked in this repository when this file was written:
- `roles_path = ansible/roles`
- `host_key_checking = False`
- `retry_files_enabled = False`
## Local instruction files (Cursor/Copilot)
Checked in this repository:
- `.cursorrules`: not present - `.cursorrules`: not present
- `.cursor/rules/`: not present - `.cursor/rules/`: not present
- `.github/copilot-instructions.md`: not present - `.github/copilot-instructions.md`: not present
If any of these appear later, treat them as higher-priority local instructions.
If any of the files above appear later, treat them as higher-priority local instructions. ## Working assumptions
- Favor idempotent, host-safe changes over cleverness.
- Preserve the intended layering: `all -> OS -> profile -> host`.
- Validate on one host before broad rollout.
- The repo contains both first-party dotfiles and vendored third-party plugin code.
## Build, lint, and test commands ## Build, lint, and test commands
There is no compile/build step in this repo. There is no compile/build step. Validation is Ansible syntax checks, inventory inspection, dry-runs, and linting.
Validation is Ansible syntax checks, dry-runs, inventory checks, and linting. Install base tooling if needed:
```bash
Core apply run: python3 -m pip install ansible
```
Core commands:
```bash ```bash
ansible-playbook ansible/site.yml ansible-playbook ansible/site.yml
```
Safe dry-run with changes preview:
```bash
ansible-playbook ansible/site.yml --check --diff ansible-playbook ansible/site.yml --check --diff
```
Target a single host (useful for SSH-first rollout):
```bash
ansible-playbook ansible/site.yml --limit ikaros ansible-playbook ansible/site.yml --limit ikaros
ansible-playbook ansible/site.yml --limit nymph
ansible-playbook ansible/site.yml --syntax-check
ansible-inventory --graph
ansible-inventory --host ikaros
``` ```
Linting if available locally:
Linting (if installed locally):
```bash ```bash
ansible-lint ansible/site.yml ansible-lint ansible/site.yml
ansible-lint ansible/roles ansible-lint ansible/roles
yamllint ansible/ yamllint ansible/
``` ```
## Single-test equivalents (important) ## Single-test equivalents
There is no Molecule/pytest suite. There is no Molecule, pytest, or dedicated unit-test suite. Use these as the closest equivalent to a single targeted test.
Use one of these as a "single test" workflow. Fastest confidence check:
Fast syntax-only validation:
```bash ```bash
ansible-playbook ansible/site.yml --syntax-check ansible-playbook ansible/site.yml --syntax-check
``` ```
Best default host-scoped safety check:
Best default single-host safety check:
```bash ```bash
ansible-playbook ansible/site.yml --limit nymph --check --diff ansible-playbook ansible/site.yml --limit ikaros --check --diff
``` ```
Start from one task when validating a narrow change:
Single-role smoke test using `--start-at-task` (dotfiles path):
```bash ```bash
ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Copy common dotfiles" --check --diff ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Copy common dotfiles" --check --diff
```
Single-role smoke test using `--start-at-task` (Void packages path):
```bash
ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Install Void nonfree repository if needed" --check --diff ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Install Void nonfree repository if needed" --check --diff
ansible-playbook ansible/site.yml --limit ikaros --start-at-task "Copy desktop dotfiles" --check --diff
```
Inventory-only resolution for one machine:
```bash
ansible-inventory --host ikaros
``` ```
Notes: Notes:
- Current active stack in `ansible/site.yml`: `dotfiles_common`, `packages_void`, `services_runit`, `profile_desktop_i3`. - Keep task names stable and unique enough for `--start-at-task`.
- Ubuntu/systemd/workstation/server roles exist in the repo but are not currently included by `ansible/site.yml`. - Prefer `--check --diff` before package, service, PAM, or session changes.
- Minimum dependencies: Python 3, Ansible, target host access (local or SSH). Setup: `python3 -m pip install ansible`. - Use `--limit` aggressively to avoid accidental multi-host rollout.
## Code style guidelines ## Code style guidelines
### General principles
- Prefer minimal, scoped changes that match the existing layout.
- Preserve idempotency and avoid hidden mutable state.
- Prefer declarative modules over imperative commands.
- Keep orchestration in playbooks and implementation in roles.
- Avoid unrelated refactors while solving a targeted task.
### Core principles ### Ansible modules and task structure
- Prefer declarative, idempotent, host-safe automation. - Use FQCN module names such as `ansible.builtin.copy` and `community.general.xbps`.
- Keep layering explicit: `all -> OS -> profile -> host`. - Prefer purpose-built modules over `ansible.builtin.command` or `ansible.builtin.shell`.
- Keep changes minimal, scoped, and reversible. - Use `command` only when no good module exists.
- Avoid speculative refactors unrelated to the requested task. - Use `shell` only when shell features are genuinely required.
- When using `command` or `shell`, set `changed_when` and `failed_when` when defaults are misleading.
- Keep task names imperative, outcome-based, and unique enough to support `--start-at-task`.
### YAML formatting
### Modules, imports, and task structure - Start YAML files with `---`.
- Use FQCN modules (`ansible.builtin.copy`, `community.general.xbps`). - Use 2-space indentation; do not use tabs.
- Prefer dedicated modules over `ansible.builtin.command` and `ansible.builtin.shell`. - Keep lists and maps in stable, readable order.
- Use `command`/`shell` only when no module exists; explain intent in task name. - Quote file modes as strings: `"0644"`, `"0755"`, `"0600"`, `"0700"`.
- For `command`/`shell`, define `changed_when` and `failed_when` when defaults are unsafe. - Prefer multiline Jinja when a one-line expression becomes hard to read.
- Keep `ansible/site.yml` orchestration-only; place implementation details in roles. - Avoid formatting-only churn in untouched sections.
- Keep roles domain-focused (packages, services, profiles, dotfiles).
### YAML formatting and file hygiene
- Start YAML documents with `---`.
- Use 2-space indentation; never tabs.
- Keep key ordering stable and meaningful.
- Quote file modes as strings (`"0644"`, `"0755"`, `"0600"`, `"0700"`).
- Use multiline Jinja for long expressions.
- Avoid trailing whitespace and formatting-only churn.
### Variables, types, and templating ### Variables, types, and templating
- Use `snake_case` names for variables. - Use `snake_case` consistently.
- Use semantically scoped names (`common_packages`, `void_packages_base`, `profile_packages`, `host_packages`). - Follow existing naming families like `common_packages`, `profile_packages`, and `host_packages`.
- Keep booleans as booleans (`true`/`false`), not quoted strings. - Keep booleans as booleans, not quoted strings.
- Keep lists/maps as YAML collections, not comma-separated strings. - Keep structured data as YAML collections, not comma-separated strings.
- Guard optional values with `default([])` and `default({})`. - Guard optional values with `default([])`, `default({})`, or `default('')` as appropriate.
- Build home-relative paths from `{{ user_home }}` consistently. - Build user paths from `{{ user_home }}` instead of hardcoding home directories.
### Naming conventions ### Naming conventions
- Role directory names: lowercase with underscores. - Role names stay lowercase with underscores.
- Task names: imperative, outcome-based, and unique enough for `--start-at-task`. - Inventory groups and matching var files should stay semantically aligned.
- Keep inventory group names aligned with related var files. - New variables should fit existing patterns instead of inventing one-off names.
### Error handling and safety ### Error handling and safety
- Guard OS/profile-specific behavior with `when` clauses. - Guard OS-specific or profile-specific behavior with `when` clauses.
- Prefer explicit loop inputs over implicit assumptions. - Prefer explicit loops and inputs over assumptions.
- Do not suppress failures unless there is a clear operational reason. - Do not suppress failures without a clear operational reason.
- Validate risky changes with `--check --diff` before full apply. - Use `failed_when: false` only for intentional state probes.
- Avoid destructive operations in user homes unless explicitly required.
- Keep tasks non-interactive and automation-safe. - Keep tasks non-interactive and automation-safe.
- Avoid destructive operations in user homes unless the request clearly requires them.
### Dotfiles and shell script style ### Dotfiles and script conventions
- Prefer POSIX `sh`; use Bash only when Bash features are required. - Prefer POSIX `sh` for simple login/session scripts.
- Bash scripts must use `#!/usr/bin/env bash`. - Use Bash only when Bash features are required; then use `#!/usr/bin/env bash`.
- Quote expansions (`"$var"`) unless intentional word splitting is required. - Quote variable expansions unless intentional word splitting is required.
- Preserve executable bits for copied scripts (`mode: preserve` where appropriate). - Preserve executable bits for deployed scripts where appropriate.
- Keep session-start changes conservative; verify startup paths and environment assumptions.
### Imports and external code
- There are no Python import conventions to optimize for here; most changes are YAML and shell.
- Treat `dotfiles/common/.tmux/plugins/` as vendored upstream code unless the task explicitly targets it.
- Prefer changing first-party wrapper/config files before patching vendored plugin internals.
## Editing guidance by area
- `ansible/site.yml`: keep it small and orchestration-focused.
- `ansible/inventory/group_vars/*.yml`: shared defaults by layer.
- `ansible/inventory/host_vars/*.yml`: host-specific overrides only.
- `ansible/roles/*/tasks/main.yml`: role implementation details.
- `dotfiles/`: user-facing config and session scripts deployed by roles.
- `secrets/vault.yml`: treat as sensitive; do not expose values in tracked plain text.
## Validation expectations before finishing
Run the narrowest useful checks for the area you changed.
Default minimum:
```bash
ansible-playbook ansible/site.yml --syntax-check
```
Preferred for role or vars changes:
```bash
ansible-playbook ansible/site.yml --limit <host> --check --diff
```
Useful supporting checks:
```bash
ansible-inventory --graph
ansible-inventory --host <host>
ansible-lint ansible/site.yml
yamllint ansible/
```
## Agent workflow expectations ## Agent workflow expectations
- Do not modify unrelated files. - Read the relevant inventory, vars, role tasks, and deployed dotfiles before editing.
- Read inventory, vars, and relevant roles before editing. - Do not change unrelated files to "clean things up".
- Keep AGENTS and README aligned when workflows/commands change. - Keep README and AGENTS aligned when workflows materially change.
- When adding roles or domains, also add validation and targeting guidance. - If you add a new operational area, also add the validation command agents should run.
- Prefer `--limit <host>` validation before broader runs. - Prefer host-limited validation before broad apply.
- Call out any verification you could not run.
## Pre-merge checklist
Run before proposing/finalizing changes:
- `ansible-playbook ansible/site.yml --syntax-check`
- `ansible-playbook ansible/site.yml --check --diff --limit <host>`
- `ansible-inventory --graph`
- If available: `ansible-lint ansible/site.yml` and `yamllint ansible/`

173
README.md
View File

@@ -47,9 +47,14 @@ Il repository è diviso in due componenti principali:
--- ---
# Macchine gestite # Macchine gestite
Il sistema attualmente gestisce tre tipologie di profilo. Il repository modella attualmente tre tipologie di profilo.
Nota sullo stato attuale del playbook principale:
- `ansible/site.yml` applica oggi in automatico il profilo desktop su host Void Linux
- i profili workstation e server sono gia presenti in inventory e nei ruoli, ma non sono ancora inclusi nel playbook principale
## Desktop ## Desktop
@@ -66,7 +71,15 @@ Macchine:
- `ikaros` - `ikaros`
- `nymph` - `nymph`
Queste macchine condividono la stessa configurazione base desktop e vengono mantenute allineate tramite Ansible. Queste macchine condividono la stessa configurazione base desktop e vengono mantenute allineate tramite Ansible.
Lo stato attuale del profilo desktop include, tra le altre cose:
- dotfiles comuni e desktop
- sessione i3 e servizi desktop correlati
- pacchetti Void Linux e servizi runit
- Flatpak con remoto Flathub
- GNOME Keyring e bootstrap della posta via script dedicato
--- ---
@@ -84,7 +97,9 @@ Macchina:
- `deadalus` - `deadalus`
Questo profilo è pensato per sviluppo e lavoro. Questo profilo è pensato per sviluppo e lavoro.
Il modello e la struttura dei ruoli sono presenti, ma l'orchestrazione automatica tramite `ansible/site.yml` verra completata in una fase successiva.
--- ---
@@ -102,7 +117,9 @@ Macchina:
- `prometheus` - `prometheus`
Profilo minimale orientato a servizi server. Profilo minimale orientato a servizi server.
Anche questo profilo e gia rappresentato in inventory e nei ruoli, ma non e ancora agganciato al playbook principale.
--- ---
@@ -139,23 +156,38 @@ Questo approccio consente di:
# Ruoli Ansible # Ruoli Ansible
I principali ruoli attualmente presenti sono: I principali ruoli attualmente presenti sono:
| Role | Descrizione | | Role | Descrizione |
| ------------------------- | ----------------------------------- | | ------------------------- | ----------------------------------- |
| base | configurazione base comune | | base | configurazione base comune |
| packages_void | installazione pacchetti su Void | | packages_void | installazione pacchetti su Void |
| packages_ubuntu | installazione pacchetti su Ubuntu | | packages_ubuntu | installazione pacchetti su Ubuntu |
| services_runit | gestione servizi runit | | services_runit | gestione servizi runit |
| services_systemd | gestione servizi systemd | | services_systemd | gestione servizi systemd |
| profile_desktop_i3 | configurazione desktop i3 | | profile_desktop_i3 | configurazione desktop i3 |
| profile_workstation_gnome | configurazione workstation GNOME | | profile_workstation_gnome | configurazione workstation GNOME |
| profile_server | configurazione server | | profile_server | configurazione server |
| dotfiles | distribuzione configurazioni utente | | dotfiles_common | distribuzione dotfiles comuni |
| dotfiles | distribuzione configurazioni utente |
---
---
# Dotfiles
# Stato attuale del playbook principale
Il playbook `ansible/site.yml` e attualmente composto da due blocchi:
```text
all -> dotfiles_common
void -> packages_void + services_runit + profile_desktop_i3
```
Questo significa che, allo stato attuale:
- i desktop Void (`ikaros`, `nymph`) sono il target operativo principale
- inventory, gruppi e ruoli per workstation Ubuntu e server Ubuntu restano nel repository come base per l'estensione futura
# Dotfiles
La directory `dotfiles/` contiene le configurazioni utente versionate. La directory `dotfiles/` contiene le configurazioni utente versionate.
@@ -180,48 +212,71 @@ Le configurazioni sono applicate tramite Ansible e organizzate per livelli:
# Requisiti # Requisiti
Per utilizzare il repository sono necessari: Per utilizzare il repository sono necessari:
- Python 3 - Python 3
- Ansible - Ansible
- accesso SSH alle macchine target - collection `community.general`
- accesso locale o SSH alle macchine target, in base a come e definito l'inventory
Installazione Ansible:
Installazione base:
```bash
pip install ansible ```bash
``` pip install ansible
ansible-galaxy collection install community.general
```
Gestione segreti:
- il repository supporta il caricamento opzionale di `secrets/vault.yml`
- `secrets/vault.yml.example` funge da template/esempio
- se `secrets/vault.yml` non e presente, il playbook continua comunque senza caricare variabili locali opzionali
--- ---
# Utilizzo # Utilizzo
Eseguire il playbook principale: Eseguire il playbook principale:
```bash ```bash
ansible-playbook ansible/site.yml ansible-playbook ansible/site.yml
``` ```
Questo comando: Allo stato attuale questo comando:
- installa i pacchetti richiesti - distribuisce i dotfiles comuni a tutti gli host
- configura i servizi - per gli host Void applica pacchetti, servizi runit e profilo desktop i3
- applica il profilo macchina - carica `secrets/vault.yml` solo se presente
- distribuisce i dotfiles
Per validare prima di applicare:
```bash
ansible-playbook ansible/site.yml --syntax-check
ansible-playbook ansible/site.yml --limit ikaros --check --diff
```
--- ---
# Bootstrap di una nuova macchina # Bootstrap di una nuova macchina
Una nuova macchina può essere inizializzata con i seguenti passaggi: Una nuova macchina può essere inizializzata con i seguenti passaggi:
```bash ```bash
git clone <repo> git clone <repo>
cd infra cd infra
ansible-playbook ansible/site.yml ansible-galaxy collection install community.general
``` ansible-playbook ansible/site.yml
```
Dopo l'esecuzione del playbook la macchina verrà configurata secondo il profilo definito.
Dopo l'esecuzione del playbook la macchina verra configurata secondo il profilo definito e i ruoli attualmente orchestrati.
Per il flusso mail desktop esiste inoltre uno script dedicato:
```bash
scripts/bootstrap_mail.sh
```
Lo script si occupa del bootstrap dei secret nel keyring, del primo sync con `mbsync` e dell'inizializzazione di `mu` usando la configurazione mail generata dai template.
--- ---
@@ -241,14 +296,14 @@ Questo consente di ricreare qualsiasi macchina partendo esclusivamente dal repos
# Roadmap # Roadmap
Possibili evoluzioni future: Possibili evoluzioni future:
- gestione segreti con `ansible-vault` - completamento dell'orchestrazione per workstation Ubuntu e server Ubuntu
- hardening sicurezza server - hardening sicurezza server
- configurazione backup - configurazione backup
- testing automatico playbook - testing automatico playbook
- integrazione CI - integrazione CI
- supporto ad altre distribuzioni Linux - supporto ad altre distribuzioni Linux
--- ---