Skip to content

Commit 7c3bb44

Browse files
rebtoorclaude
authored andcommitted
[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. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Roberto Alfieri <ralfieri@redhat.com>
1 parent 93e8984 commit 7c3bb44

2 files changed

Lines changed: 300 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
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/` | Domain-specific playbooks in subdirectories (`adoption/`, `ceph/`, `bgp/`, etc.). Legacy numbered-stage playbooks are deprecated -- orchestration is handled by the `cifmw_setup` role. |
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+
where after the `cifmw_` prefix comes the role name, then the variable name
46+
(e.g., `cifmw_my_role_some_setting`).
47+
This is enforced by `ansible-lint` with `strict: true` and `profile: production`.
48+
49+
### FQCN required
50+
51+
All module calls must use fully-qualified collection names.
52+
The following FQCN rules are enabled in `.ansible-lint`:
53+
`fqcn-builtins`, `fqcn[action]`, `fqcn[action-core]`, `fqcn[canonical]`, `fqcn[deep]`.
54+
55+
### Generated files -- do not hand-edit
56+
57+
The following files are **generated** by `scripts/create_role_molecule.py`:
58+
59+
- `zuul.d/molecule.yaml`
60+
- `zuul.d/projects.yaml` (molecule section)
61+
62+
To regenerate: `make role_molecule`. To verify consistency: `make check_zuul_files`.
63+
If you hand-edit these files, CI will reject the change.
64+
65+
### Read-only / generated paths
66+
67+
Do **not** modify these paths directly:
68+
69+
| Path | Reason |
70+
|---|---|
71+
| `zuul.d/molecule.yaml` | Generated by `scripts/create_role_molecule.py`. |
72+
| `zuul.d/projects.yaml` | Generated (molecule section). |
73+
| `custom/` | Gitignored. Local-only overrides, never committed. |
74+
| `hooks/playbooks/roles/` | Excluded from ansible-lint. Owned by hook authors. |
75+
76+
All other paths (`roles/`, `playbooks/`, `plugins/`, `group_vars/`, `scenarios/`,
77+
`hooks/playbooks/`, `ci/`, `scripts/`, `docs/`) are safe to edit following the
78+
conventions in this file.
79+
80+
### Debugging patterns
81+
82+
Use `block`/`rescue`/`always` for complex task sequences. Dump relevant
83+
variables in the `rescue` block, then `ansible.builtin.fail` to stop
84+
execution. This makes CI failures much easier to diagnose.
85+
86+
### Do not be too verbose
87+
88+
There is no need to provide explanation for each variable in each task file.
89+
It is enough when the variable description is available in the role README
90+
file. Add comments only to complex code.
91+
92+
### Do not create too many variables
93+
94+
Balance the amount of variables: there is no need to create additional
95+
variables especially for static values that are only used once by another
96+
module or role. In that case, fewer variables means more clarity.
97+
98+
### Make tasks easier to debug
99+
100+
Tasks should not do too many things in a single step -- on failure that
101+
becomes difficult to debug. In some cases, adding more small, fast tasks
102+
is better than one large task. Add debug messages only in very complex
103+
places, not everywhere.
104+
105+
## Playbooks
106+
107+
Do not rely on the `playbooks/` directory as the primary orchestration layer.
108+
The numbered-stage playbooks (`01-bootstrap.yml`, `02-infra.yml`, etc.) are
109+
**deprecated** -- orchestration is now handled by the `cifmw_setup` role.
110+
111+
The `playbooks/` directory still contains:
112+
- **Subdirectories** (`adoption/`, `ceph/`, `bgp/`, `dcn/`, `multi-namespace/`)
113+
with domain-specific flows.
114+
- **Standalone playbooks** (`hooks.yml`, `update.yml`, `dcn.yml`, `nfs.yml`,
115+
`switches_config.yml`, etc.) for specific operations.
116+
117+
## Creating a new role
118+
119+
Always use the Makefile:
120+
121+
```
122+
make new_role ROLE_NAME=my_role
123+
```
124+
125+
This generates the skeleton, Molecule config, and updates Zuul jobs.
126+
Every new role must have:
127+
128+
1. A `README.md` documenting its parameters.
129+
2. Molecule test scenarios.
130+
3. Documentation that builds cleanly (checked in CI).
131+
132+
If the role cannot be tested via Molecule, remove the `molecule/` directory
133+
and run `make role_molecule` to regenerate Zuul jobs. Add a note in the
134+
role's `README.md` explaining why.
135+
136+
## Testing
137+
138+
### Commands
139+
140+
| Command | What it does |
141+
|---|---|
142+
| `make pre_commit` | Runs pre-commit hooks (shellcheck, black, ansible-lint) with dependency install. |
143+
| `make molecule` | Runs Molecule tests for all roles with dependency install. |
144+
| `make ansible_test` | Runs ansible-test (units + sanity + integration) with dependency install. |
145+
| `make tests` | Runs pre-commit + Molecule. |
146+
| `make check_zuul_files` | Regenerates Zuul YAML and fails if it differs from committed files. |
147+
| `make docs` | Builds Sphinx documentation under `docs/_build/html/`. |
148+
| `make spelling` | Runs `pyspelling` on docs. |
149+
| `make plugin-development-enable` | Rewrites import paths and sets `PYTHONPATH` for local plugin dev. |
150+
| `make plugin-development-disable` | Reverts the changes made by `plugin-development-enable`. |
151+
152+
### Container-based testing (requires Podman)
153+
154+
| Command | What it does |
155+
|---|---|
156+
| `make run_ctx_pre_commit` | Pre-commit in a container. |
157+
| `make run_ctx_molecule` | Molecule in a container. |
158+
| `make run_ctx_ansible_test` | ansible-test in a container. |
159+
| `make run_ctx_all_tests` | All of the above. |
160+
161+
### Molecule specifics
162+
163+
- Config: `.config/molecule/config_podman.yml` (host) or `config_local.yml` (container).
164+
- Test a single role: `TEST_SINGLE_ROLE=my_role make molecule` or `make run_ctx_molecule`.
165+
- Molecule scenarios live under `roles/<name>/molecule/`.
166+
167+
### Validation priority
168+
169+
When verifying a change, run checks in this order:
170+
171+
1. `pre-commit run --all-files` — fast lint pass (ansible-lint, black, shellcheck).
172+
2. `TEST_SINGLE_ROLE=<role> make molecule` — targeted Molecule test.
173+
3. `make ansible_test` — plugin unit/sanity/integration tests (only if plugins changed).
174+
4. `make docs` — only if documentation was modified.
175+
176+
### macOS limitations
177+
178+
The Makefile test targets (`make tests`, `make molecule`, `make ansible_test`,
179+
`make setup_tests`, `make setup_molecule`, and their `_nodeps` variants) **do not
180+
work on macOS**. The underlying scripts use `readlink -f`, which is not available
181+
on macOS. These targets are designed for Linux CI environments only.
182+
183+
## Linting and code style
184+
185+
- **ansible-lint**: `production` profile, `strict: true`. Config in `.ansible-lint`.
186+
- **Python**: Formatted with `black`.
187+
- **Shell**: Checked with `shellcheck` (severity=error, excludes SC2071).
188+
- **Pre-commit**: Config in `.pre-commit-config.yaml`. Run with `make pre_commit` or `make run_ctx_pre_commit`.
189+
- **Spelling**: `pyspelling` on docs. Run with `make spelling`.
190+
191+
### Excluded from linting
192+
193+
ansible-lint skips: `.github/`, `scripts/`, `docs/`, `containerfiles/`, `ci/`,
194+
and the generated Zuul files (`zuul.d/projects.yaml`, `zuul.d/molecule.yaml`).
195+
196+
## Commit conventions
197+
198+
- **Title**: Must begin with the role name in brackets or parentheses:
199+
`[my_role] Add feature X` or `(my_role) Fix bug Y`.
200+
If changes span multiple roles, use `[multiple]` or `(multiple)`.
201+
For cross-cutting changes use a category: `[ci]`, `[docs]`, `[Feature]`.
202+
- **Body**: Must be longer than 10 characters and describe **why** the change
203+
was made.
204+
- **Sign-off**: Required (`git commit --signoff`). The sign-off certifies a
205+
[DCO](https://developercertificate.org/). AI agents cannot sign off on behalf
206+
of a human -- the committer must add it themselves or amend the commit.
207+
- **AI attribution**: Use `Co-Authored-By:` for substantial AI-generated code,
208+
`Assisted-By:` for minor AI help. Disclose the scope in the PR description.
209+
- **Ticket references**: Link Jira cards in the commit message body:
210+
`Closes: ANVIL-123` (resolves the ticket) or
211+
`Related-Issue: #OSPRH-12345` (related but does not close).
212+
- **Cross-repo dependencies**: When a change depends on an unmerged PR/MR in
213+
another repository, add `Depends-On: <PR-or-MR-URL>` in the PR/MR
214+
description. Zuul uses this to test the changes together.
215+
216+
### Commit strategy
217+
218+
To keep a clean git history, prefer a single commit per feature or fix:
219+
220+
1. Create the initial commit normally.
221+
2. For subsequent changes on the same branch, amend the existing commit
222+
(`git commit --amend`) instead of creating new ones.
223+
3. After amending, use `git push --force` to update the remote branch.
224+
225+
Never push directly to `main` — it is a protected branch. Always work on
226+
a feature branch. Force pushing is only appropriate for **solo feature
227+
branches**, never for `main` or shared branches.
228+
229+
If a change is not directly related to the main goal of the pull request
230+
but is required for it to work, add it as a **separate commit**. When
231+
amending, be careful to edit only the commits that belong to the same
232+
pull request.
233+
234+
## Branch workflow
235+
236+
- The default branch is `main`.
237+
- Feature work happens on topic branches.
238+
- PRs target `main` unless otherwise specified.
239+
- Branch names should be descriptive (e.g., `fix-reproducer-pull-secret`,
240+
`feature/OSPRH-12345-new-role`).
241+
242+
## PR process
243+
244+
- PRs are auto-set to draft on open. To undraft, push a non-`nit:` change.
245+
- Minimum **2 approvals** required (excluding the author).
246+
- Security-sensitive code requires additional maintainer review.
247+
- Ownership is defined in `OWNERS` and `OWNERS_ALIASES`.
248+
249+
## Relationship to ci-framework-jobs
250+
251+
The `ci-framework-jobs` repository holds downstream Zuul job definitions that
252+
consume this repository. Jobs in that repo declare
253+
`required-projects: openstack-k8s-operators/ci-framework` and
254+
`roles: zuul: openstack-k8s-operators/ci-framework` so Zuul checks out this
255+
repo and exposes its roles during job execution. Uni jobs orchestrate this
256+
repo's `reproducer.yml` playbook as their main entry point.
257+
258+
When making changes here that affect CI behavior, coordinate with the
259+
corresponding job definitions in `ci-framework-jobs`.
260+
261+
## Plugin development
262+
263+
To develop collection plugins locally without installing the collection:
264+
265+
```
266+
make plugin-development-enable
267+
```
268+
269+
This rewrites import paths and sets `PYTHONPATH`. Revert with:
270+
271+
```
272+
make plugin-development-disable
273+
```
274+
275+
Plugins are tested with `ansible-test`, not Molecule.
276+
277+
## Documentation first
278+
279+
Before searching the web or relying on general knowledge, check local
280+
documentation:
281+
- `docs/source/` — Sphinx sources for the ci-framework collection.
282+
- Role-level `README.md` files under `roles/<name>/`.
283+
- The downstream CI docs repository at
284+
`https://gitlab.cee.redhat.com/ci-framework/docs` covers job types,
285+
pipelines, troubleshooting, and glossary.
286+
287+
## Confirm before acting
288+
289+
Before performing expensive or broad-impact operations, confirm with the
290+
user first:
291+
292+
- Running full test suites (`make tests`, `make molecule`) — ask whether a
293+
targeted run (`TEST_SINGLE_ROLE=<role>`) is sufficient.
294+
- Modifying `group_vars/all.yml` — changes here affect every playbook run.
295+
- Editing roles used by multiple playbooks — flag the blast radius.
296+
- Cross-repo changes that require coordinated updates in `ci-framework-jobs`
297+
or `architecture`.

CLAUDE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# CLAUDE.md
2+
3+
@AGENTS.md

0 commit comments

Comments
 (0)