Without guardrails, AI tools generate PRs that ignore Fedora Infra's conventions — wrong file extensions (`.yaml` vs `.yml`), missing `vars_files` triplets, broken idempotency, relative paths instead of the required hardcoded `/srv/web/infra/ansible/` layout, and suggestions to "fix" intentional patterns like the `vars/all/*.yaml` exception or the `fedora_messaging_callback.py` custom plugin. AGENTS.md gives AI agents the same context a new human contributor would get from reading README.md, CONVENTIONS, STYLEGUIDE, and `.ai_review/project.md` — but in a single file that AI tools automatically load before generating code. This means AI-assisted PRs should arrive already following our linting rules, architectural patterns (OpenShift app vs group playbook), staging/prod conventions (`_stg` group_vars, `env`/`env_suffix`), and tag discipline. The file also includes the Fedora AI-Assisted Contribution Policy requirements, ensuring AI agents prompt contributors to include the Assisted-by: commit message trailer and respect the project's rules on accountability, transparency, and human-final review. The net effect is fewer round-trips in review: maintainers spend less time explaining the same conventions repeatedly and can focus review on whether the change is correct, not whether it follows the style guide. Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: Justin Wheeler <jwheel@redhat.com>
6.4 KiB
AGENTS.md
This file provides guidance to AI coding agents when working with code in this repository.
Project Overview
Ansible automation for the entire Fedora Project infrastructure. Manages hundreds of bare-metal hosts, VMs, and OpenShift 4 applications across production and staging environments. The control host is batcave01 (/srv/web/infra/ansible public, /srv/private/ansible private).
Repository is hosted at https://forge.fedoraproject.org/infra/ansible
Linting
Run yamllint on changed files:
yamllint path/to/file.yml
Run ansible-lint on changed files:
ansible-lint path/to/file.yml
CI runs both linters on changed files only (Forgejo Actions on quay.io/fedora/fedora:latest). The community.zabbix collection is installed before ansible-lint runs.
Linting configuration
- yamllint (
.yamllint.yaml): 2-space indentation (warning level), line-length disabled, octal values forbidden, truthy values restricted totrue/false/yes/no, templates directories ignored. - ansible-lint (
.ansible-lint): Runs in offline mode. Skipped rules:yaml,role-name[path],var-naming[no-role-prefix],no-changed-when,ignore-errors. Usesmock_modulesandmock_rolesto pass syntax checks without all dependencies.
Architecture
Directory structure
playbooks/groups/— One playbook per service group (multi-host). Filename should be descriptive.playbooks/hosts/— One playbook per unique host. Filename MUST beFQDN.yml.playbooks/openshift-apps/— ~60 OCP4 application deployments.playbooks/manual/— Admin-only playbooks, never run by cron.playbooks/include/— Shared playbook fragments (proxy, virt, cert).roles/— 134 roles. Flat structure with some namespacing (openshift/,openshift-apps/,awx/,rabbit/).roles/base/— Applied to ALL managed hosts. Changes here have maximum blast radius.inventory/— Host definitions,group_vars/(150 files),host_vars/, andzzz-inventory.config(constructed inventory plugin, loads last due tozzz-prefix).vars/all/— Fedora release cycle variables. Changed every ~6 months during branching/release. Incorrect values break builds across the entire infrastructure.vars/global.yml— Global vars (paths, SSL, base packages).tasks/— Reusable task snippets included in playbooks.library/— Custom Ansible modules (delete_old_oci_images.py,virt_boot, etc.).callback_plugins/— Custom callbacks (fedora_messaging_callback.py,logdetail.py). Don't suggest replacing these.main.yml— Master playbook importing all group/host playbooks. Used with-t tagto run specific tags across all hosts. Nightly--check --diffcron runs all playbooks.
Two main deployment patterns
OpenShift app pattern (dominant for new services):
- Playbook in
playbooks/openshift-apps/<app>.ymltargetsos_control[0]:os_control_stg[0] - Uses composable
openshift/*roles:project,object,keytab,secret-file,imagestream,route,rollout - App templates in
roles/openshift-apps/<app>/templates/ - Uses
gather_facts: false(runsoccommands on control node, not on apps)
Group playbook pattern (traditional VM services):
- Playbook in
playbooks/groups/<group>.ymlwithhosts:matching inventory group - Must include standard vars_files (see below)
Staging vs Production
Same inventory, not separate inventories. Staging hosts use _stg suffixed group_vars files. Controlled by:
env—"production"or"staging"env_suffix—""for prod,".stg"for staging
Fedora AI-Assisted Contribution Policy
This repository is part of the Fedora Project and subject to the Fedora AI-Assisted Contributions Policy. Key requirements:
- Accountability: The human contributor is always the author and is fully accountable for the entirety of AI-assisted contributions. All submissions must meet project standards for quality, license compliance, and utility.
- Transparency: Use of AI tools MUST be disclosed when the significant part of the contribution is taken from a tool without changes. For git contributions, use an
Assisted-by:commit message trailer (e.g.,Assisted-by: ChatGPTv5orAssisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>). - No AI-only judgments: AI MUST NOT be used as the sole or final arbiter for substantive or subjective judgments on contributions, nor for evaluating a person's standing in the community. Automated objective validation (CI/CD, testing, linting) is permitted.
When generating commit messages, always include the Assisted-by: trailer naming the specific AI model and version used.
Coding Conventions
Required vars_files in all group/host playbooks
vars_files:
- /srv/web/infra/ansible/vars/global.yml
- "{{ private }}/vars.yml"
- /srv/web/infra/ansible/vars/{{ ansible_distribution }}.yml
These hardcoded paths are the production layout on batcave01. Do not make them relative or configurable.
Style rules
- Use
.ymlnot.yamlfor file extensions. Exception:vars/all/*.yamlis historical — don't "fix" this. - Add
.j2extension to all Jinja2 templates. A.ymlfile intemplates/without.j2won't render Jinja expressions. - 2-space YAML indentation. Line length is not enforced.
- Prefer readable multi-line module args over single-line
module: name=x arg=yformat. - Standard tags:
packages(installs/removes packages),config(installs config files). buildandrollouttags useneverto prevent accidental execution.- All playbooks must be idempotent — they can be run at any time by the nightly cron.
Common pitfalls
- Forgetting to update multiple files in
vars/all/together during release transitions (e.g., branching requiresFedoraBranched.yaml,00-FedoraCycleNumber.yaml,FedoraBranchedBodhi.yaml, andFrozen.yaml). - Breaking idempotency — generates noise in nightly
--check --diffand masks real drift. - OpenShift apps must target
os_control[0]:os_control_stg[0], not all control nodes.
Domain terminology
- batcave01 — Ansible control host
- FAS/IPA — Fedora Account System (identity provider)
- Koji — Build system (VM-based, not OpenShift)
- Bodhi — Update management (runs on OpenShift)
- dist-git/src.fedoraproject.org — Package source repositories
- fedora-messaging/RabbitMQ — AMQP message bus connecting services