Skip to content

Commit d4002ee

Browse files
committed
[ci] Add AGENTS.md and CLAUDE.md for AI agent guidance
Add structured documentation for AI coding agents working on this repository. AGENTS.md provides repo-wide context: variable naming rules, generated file warnings, testing commands, commit conventions, and repository layout. CLAUDE.md adds Claude-specific behavioral guidance and references AGENTS.md as the primary source of truth. Signed-off-by: Roberto Alfieri <ralfieri@redhat.com>
1 parent 4b40434 commit d4002ee

2 files changed

Lines changed: 262 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# AGENTS.md
2+
3+
## What is this repository
4+
5+
CI-Framework is an Ansible collection (`cifmw.general`) that bootstraps
6+
development and CI environments for RHOSO (Red Hat OpenStack Services on
7+
OpenShift). It is **not** intended for production or long-lived deployments.
8+
9+
The upstream repository lives at
10+
`https://github.com/openstack-k8s-operators/ci-framework`.
11+
12+
## Tech stack
13+
14+
- **Ansible** collection (requires `ansible-core >= 2.15`).
15+
- **Python 3** modules and plugins under `plugins/`.
16+
- **Molecule** + Podman for per-role testing.
17+
- **ansible-test** for unit, sanity, and integration tests on plugins.
18+
- **Sphinx** for documentation (hosted on ReadTheDocs).
19+
- **Zuul**, **GitHub Actions**, and **Prow** for CI.
20+
21+
## Repository layout
22+
23+
| Path | Description |
24+
|---|---|
25+
| `roles/` | Ansible roles. Each has `defaults/`, `tasks/`, `molecule/`, `README.md`. |
26+
| `playbooks/` | End-to-end flows. Numbered stages (`01-bootstrap.yml` ... `99-logs.yml`), plus subdirectories for adoption, ceph, etc. |
27+
| `plugins/` | Collection plugins: `action/`, `filter/`, `modules/`, `module_utils/`. Test with `ansible-test`, not Molecule. |
28+
| `tests/` | `ansible-test` suites: `unit/` (pytest), `integration/targets/`, `sanity/ignore.txt`. |
29+
| `ci/` | CI-only playbooks: content provider, EDPM, kuttl, architecture validation, doc build, log collection. |
30+
| `scenarios/` | Scenario-oriented variable packs used by framework flows. |
31+
| `scripts/` | Environment setup, Molecule runner, ansible-test runner, Zuul/Molecule generation, snippet checks. |
32+
| `docs/` | Sphinx sources under `docs/source/`. |
33+
| `hooks/` | Hook playbooks consumed by the framework. Some hooks have their own `roles/` subdirectory. |
34+
| `custom/` | Local overrides (gitignored except `README.md`). Safe for local dev experiments, never committed. |
35+
| `containerfiles/` | Podman images for CI (`Containerfile.ci`, `Containerfile.tests`). |
36+
| `group_vars/` | Shared group variables (e.g., `all.yml`). Changes here affect every playbook run. |
37+
| `zuul.d/` | Zuul job and project definitions. **Some files are generated -- see below.** |
38+
| `_skeleton_role_/` | Template used by `ansible-galaxy role init` when creating new roles. |
39+
40+
## Critical rules
41+
42+
### Variable naming
43+
44+
All Ansible role variables **must** match the pattern `^cifmw_[a-z_][a-z0-9_]*$`.
45+
This is enforced by `ansible-lint` with `strict: true` and `profile: production`.
46+
47+
### FQCN required
48+
49+
All module calls must use fully-qualified collection names.
50+
The following FQCN rules are enabled in `.ansible-lint`:
51+
`fqcn-builtins`, `fqcn[action]`, `fqcn[action-core]`, `fqcn[canonical]`, `fqcn[deep]`.
52+
53+
### Generated files -- do not hand-edit
54+
55+
The following files are **generated** by `scripts/create_role_molecule.py`:
56+
57+
- `zuul.d/molecule.yaml`
58+
- `zuul.d/projects.yaml` (molecule section)
59+
60+
To regenerate: `make role_molecule`. To verify consistency: `make check_zuul_files`.
61+
If you hand-edit these files, CI will reject the change.
62+
63+
### Read-only / generated paths
64+
65+
Do **not** modify these paths directly:
66+
67+
| Path | Reason |
68+
|---|---|
69+
| `zuul.d/molecule.yaml` | Generated by `scripts/create_role_molecule.py`. |
70+
| `zuul.d/projects.yaml` | Generated (molecule section). |
71+
| `custom/` | Gitignored. Local-only overrides, never committed. |
72+
| `hooks/playbooks/roles/` | Excluded from ansible-lint. Owned by hook authors. |
73+
74+
All other paths (`roles/`, `playbooks/`, `plugins/`, `group_vars/`, `scenarios/`,
75+
`hooks/playbooks/`, `ci/`, `scripts/`, `docs/`) are safe to edit following the
76+
conventions in this file.
77+
78+
### Debugging patterns
79+
80+
Use `block`/`rescue` for complex task sequences. Dump relevant variables in
81+
the `rescue` block, then `ansible.builtin.fail` to stop execution. This
82+
makes CI failures much easier to diagnose.
83+
84+
## Playbook numbering
85+
86+
Top-level playbooks in `playbooks/` follow a numbered-stage convention:
87+
88+
| Prefix | Stage |
89+
|---|---|
90+
| `01-` | Bootstrap |
91+
| `02-` | Infrastructure |
92+
| `03-` | Build packages |
93+
| `04-` | Build containers |
94+
| `05-` | Build operators |
95+
| `06-` | Deploy |
96+
| `07-` | Admin setup |
97+
| `08-` | Run tests |
98+
| `09-` | Compliance |
99+
| `99-` | Log collection (always runs last) |
100+
101+
Do **not** reuse or reorder existing numbers. Non-stage playbooks (e.g.,
102+
`hooks.yml`, `update.yml`) live alongside without a number prefix.
103+
104+
## Creating a new role
105+
106+
Always use the Makefile:
107+
108+
```
109+
make new_role ROLE_NAME=my_role
110+
```
111+
112+
This generates the skeleton, Molecule config, and updates Zuul jobs.
113+
Every new role must have:
114+
115+
1. A `README.md` documenting its parameters.
116+
2. Molecule test scenarios.
117+
3. Documentation that builds cleanly (checked in CI).
118+
119+
If the role cannot be tested via Molecule, remove the `molecule/` directory
120+
and run `make role_molecule` to regenerate Zuul jobs. Add a note in the
121+
role's `README.md` explaining why.
122+
123+
## Testing
124+
125+
### Commands
126+
127+
| Command | What it does |
128+
|---|---|
129+
| `make pre_commit` | Runs pre-commit hooks (shellcheck, black, ansible-lint) with dependency install. |
130+
| `make molecule` | Runs Molecule tests for all roles with dependency install. |
131+
| `make ansible_test` | Runs ansible-test (units + sanity + integration) with dependency install. |
132+
| `make tests` | Runs pre-commit + Molecule. |
133+
| `make check_zuul_files` | Regenerates Zuul YAML and fails if it differs from committed files. |
134+
| `make docs` | Builds Sphinx documentation under `docs/_build/html/`. |
135+
| `make spelling` | Runs `pyspelling` on docs. |
136+
| `make plugin-development-enable` | Rewrites import paths and sets `PYTHONPATH` for local plugin dev. |
137+
| `make plugin-development-disable` | Reverts the changes made by `plugin-development-enable`. |
138+
139+
### Container-based testing (requires Podman)
140+
141+
| Command | What it does |
142+
|---|---|
143+
| `make run_ctx_pre_commit` | Pre-commit in a container. |
144+
| `make run_ctx_molecule` | Molecule in a container. |
145+
| `make run_ctx_ansible_test` | ansible-test in a container. |
146+
| `make run_ctx_all_tests` | All of the above. |
147+
148+
### Molecule specifics
149+
150+
- Config: `.config/molecule/config_podman.yml` (host) or `config_local.yml` (container).
151+
- Test a single role: `TEST_SINGLE_ROLE=my_role make molecule` or `make run_ctx_molecule`.
152+
- Molecule scenarios live under `roles/<name>/molecule/`.
153+
154+
## Linting and code style
155+
156+
- **ansible-lint**: `production` profile, `strict: true`. Config in `.ansible-lint`.
157+
- **Python**: Formatted with `black`.
158+
- **Shell**: Checked with `shellcheck` (severity=error, excludes SC2071).
159+
- **Pre-commit**: Config in `.pre-commit-config.yaml`. Run with `make pre_commit` or `make run_ctx_pre_commit`.
160+
- **Spelling**: `pyspelling` on docs. Run with `make spelling`.
161+
162+
### Excluded from linting
163+
164+
ansible-lint skips: `.github/`, `scripts/`, `docs/`, `containerfiles/`, `ci/`,
165+
and the generated Zuul files (`zuul.d/projects.yaml`, `zuul.d/molecule.yaml`).
166+
167+
## Commit conventions
168+
169+
- **Title**: Must begin with the role name in brackets or parentheses:
170+
`[my_role] Add feature X` or `(my_role) Fix bug Y`.
171+
For cross-cutting changes use a category: `[ci]`, `[docs]`, `[Feature]`.
172+
- **Body**: Must be longer than 10 characters and describe **why** the change
173+
was made.
174+
- **Sign-off**: Required (`git commit --signoff`). The sign-off certifies a
175+
[DCO](https://developercertificate.org/). AI agents cannot sign off on behalf
176+
of a human -- the committer must add it themselves or amend the commit.
177+
- **AI attribution**: Use `Co-Authored-By:` for substantial AI-generated code,
178+
`Assisted-By:` for minor AI help. Disclose the scope in the PR description.
179+
180+
## Branch workflow
181+
182+
- The default branch is `main`.
183+
- Feature work happens on topic branches.
184+
- PRs target `main` unless otherwise specified.
185+
- Branch names should be descriptive (e.g., `fix-reproducer-pull-secret`,
186+
`feature/OSPRH-12345-new-role`).
187+
188+
## PR process
189+
190+
- PRs are auto-set to draft on open. To undraft, push a non-`nit:` change.
191+
- Minimum **2 approvals** required (excluding the author).
192+
- Security-sensitive code requires additional maintainer review.
193+
- Ownership is defined in `OWNERS` and `OWNERS_ALIASES`.
194+
195+
## Relationship to ci-framework-jobs
196+
197+
The `ci-framework-jobs` repository holds downstream Zuul job definitions that
198+
consume this repository. Jobs in that repo declare
199+
`required-projects: openstack-k8s-operators/ci-framework` and
200+
`roles: zuul: openstack-k8s-operators/ci-framework` so Zuul checks out this
201+
repo and exposes its roles during job execution. Uni jobs orchestrate this
202+
repo's `reproducer.yml` playbook as their main entry point.
203+
204+
When making changes here that affect CI behavior, coordinate with the
205+
corresponding job definitions in `ci-framework-jobs`.
206+
207+
## Plugin development
208+
209+
To develop collection plugins locally without installing the collection:
210+
211+
```
212+
make plugin-development-enable
213+
```
214+
215+
This rewrites import paths and sets `PYTHONPATH`. Revert with:
216+
217+
```
218+
make plugin-development-disable
219+
```
220+
221+
Plugins are tested with `ansible-test`, not Molecule.

CLAUDE.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# CLAUDE.md
2+
3+
Read and follow all instructions in [AGENTS.md](./AGENTS.md) before starting any task.
4+
That file contains repository context, coding conventions, testing commands, and
5+
commit rules that apply to every change in this repo.
6+
7+
## Claude-specific guidance
8+
9+
### Ansible awareness
10+
11+
- Always use FQCN for module calls (e.g., `ansible.builtin.file`, not `file`).
12+
- All role variables must be prefixed `cifmw_` — never introduce bare variable names.
13+
- When writing tasks, prefer `ansible.builtin.*` modules over `shell`/`command`
14+
unless there is no module equivalent.
15+
- Use `block`/`rescue`/`always` for error handling, not `ignore_errors`.
16+
17+
### Before committing
18+
19+
- Install pre-commit (`pip install pre-commit && pre-commit install`) and run
20+
`pre-commit run --all-files` to validate changes before suggesting a commit.
21+
- Do **not** add `--signoff` to commits — the human committer must sign off
22+
themselves to satisfy DCO requirements.
23+
- Follow the commit title format: `[role_name] Short description`.
24+
25+
### Validation priority
26+
27+
When asked to verify a change, run checks in this order:
28+
29+
1. `pre-commit run --all-files` — fast lint pass (ansible-lint, black, shellcheck).
30+
2. `TEST_SINGLE_ROLE=<role> make molecule` — targeted Molecule test.
31+
3. `make ansible_test` — plugin unit/sanity/integration tests (only if plugins changed).
32+
4. `make docs` — only if documentation was modified.
33+
34+
### macOS limitations
35+
36+
The Makefile test targets (`make tests`, `make molecule`, `make ansible_test`,
37+
`make setup_tests`, `make setup_molecule`, and their `_nodeps` variants) **do not
38+
work on macOS**. The underlying scripts (`scripts/setup_env`,
39+
`scripts/setup_molecule`, `scripts/run_molecule`, `scripts/run_ansible_test`) all
40+
use `readlink -f`, which is not available on macOS. These targets are designed for
41+
Linux CI environments only. Do not attempt to run them locally on macOS.

0 commit comments

Comments
 (0)