From 7012a1a331d37d97347bb6c10f0e6682c02c110b Mon Sep 17 00:00:00 2001 From: Jon Schlueter Date: Fri, 7 Aug 2026 11:46:07 -0400 Subject: [PATCH 1/6] =?UTF-8?q?docs:=20add=20AGENTS/CLAUDE=20=E2=80=94=20c?= =?UTF-8?q?ontributor=20orientation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds agent-bootstrappable orientation for both human contributors and AI agents loading this repo as context. Covers the S2I build model, repo structure, RPM source rules, CI, and common anti-patterns. Register is intentionally hybrid (prose for orientation, directive for rules). A follow-on pass to tighten Anti-Patterns and RPM Source Rules sections to imperative register would sharpen it. CI Tooling Conventions section is a placeholder stub — a natural home for CI/tooling code constraints as that work stabilizes. Interesting experiment from day-of-learning efforts Assisted-by: Claude Sonnet 4.6 (1M context) Signed-off-by: Jon Schlueter --- AGENTS.md | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 1 + 2 files changed, 157 insertions(+) create mode 100644 AGENTS.md create mode 100644 CLAUDE.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..dbefcab7 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,156 @@ +# s2i-openstack-containers — Contributor Orientation + +## What This Is + +This is where the source-to-container work happens. This repo contains the packaging +definitions for OpenStack service containers, built using the Source-to-Image (S2I) +approach — each service is built directly from its upstream Python source rather than +from RPMs. + +Container definitions are organized by component group: each upstream service group gets +its own directory under `containers/`, with individual container definitions as +subdirectories within it. For example, `containers/cyborg/` is the group; +`containers/cyborg/cyborg/` and `containers/cyborg/cyborg-agent/` are the individual +containers. + +For Python-based services, pip-freeze style lock files are the current recommendation +for capturing Python dependencies. Some tooling is available to help with onboarding — +see [Adding a New Service](#adding-a-new-service). For the history of how this approach +evolved, see [Background](#background). + +## How the Pieces Fit + +``` +containers/ (this repo — upstream packaging) + ├── Component CI and testing lives HERE + ├── Feeds upstream testing infrastructure (Zuul — in progress, see open PRs) + └── Output feeds a downstream build pipeline + └── Build pipeline output → integration testing (fix-forward model) +``` + +The downstream build pipeline is a **build system**, not a testing system. Its job is +to produce release-ready container images from the definitions in this repo. Integration +testing runs against those images after the fact, and failures there are handled +fix-forward — fix the issue and push again rather than blocking the pipeline. + +> **Note:** Component CI belongs here (upstream), not inside or downstream of the build +> pipeline. If you find yourself wiring a CI job into the build pipeline, that's the +> signal to step back. + +> **Note:** The upstream testing infrastructure (Zuul integration, content provider jobs) +> is actively being worked out. See the open pull requests for current work in this area. +> Details will be added here as they stabilize. + +## Repo Structure + +Containers are organized in a two-level hierarchy under `containers/`: + +``` +containers/ + base/ # shared base image — inherited by all service images + / # one directory per upstream service group + / # one subdirectory per individual container in the group +``` + +**`containers/base/`** is the foundation. It defines the shared build scripts, the +authoritative RPM repo source list (`rpms.repo`), and the base Python environment. +All service containers inherit from it. + +Each **component group directory** contains the individual container definitions for +services that share the same upstream source. A group may also have a `common/` +directory for shared configuration across its containers. + +Each **container directory** should have: +- A source reference (where to pull upstream source from) +- RPM dependency specification +- Python dependency lock files (pip-freeze style) +- A `Containerfile` if the container needs anything beyond the base image + +For current best practices, file naming conventions, and worked examples, refer to the +existing containers in this repo (`containers/cyborg/`, `containers/watcher/`) and the +reference PRs listed in [Adding a New Service](#adding-a-new-service). + +> **Note:** `rpms.repo` lives in `containers/base/` and is the authoritative RPM repo +> source list for all containers. Do not add per-container or per-group `.repo` files. + +## Adding a New Service + +> **Note:** This section is a starting point — it reflects early patterns and will be +> refined as more services are onboarded. If something here conflicts with what you see +> in a recently merged container, the merged code wins. Feedback and corrections via PR +> are welcome. + +The general pattern: create a directory for your component group under `containers/` +(or add to an existing group if one exists for your upstream), add a subdirectory for +each individual container, and populate it with the files described in +[Repo Structure](#repo-structure). Use an existing container as your template. + +**Tooling:** `openstack_image_builder` (OIB) is being developed to assist with image +selection and build orchestration — see open pull requests for current state. A +generate-containerfile skill for Claude Code is also available from a working group +maintainer for bootstrapping the initial file set from a service name. + +**Questions and onboarding help:** Reach out to the maintainers — preferred contact +channels are being established by the working group. + +## RPM Source Rules + +- Start with RHEL and CentOS Stream base and appstream — use these for everything available there +- The downstream pipeline builds against RHEL; packages must be available in RHEL or approved supplemental repos +- Supplemental repos are acceptable for packages not available in base — identify them by what they provide, not by repo name +- No RDO packages +- `containers/base/rpms.repo` is the authoritative repo source list — see [Repo Structure](#repo-structure) + +## CI + +- **GitHub Actions** — build workflow active; runs on pull requests; see `.github/workflows/` +- **Zuul, Molecule, and broader testing infrastructure** — actively being developed; see open pull requests for current state +- **Local builds** — `build.sh` is the sole container-build implementation; see `Makefile` for local dev targets + +### CI Tooling Conventions + +> **Note:** This section covers conventions for contributing to the CI and tooling code +> in this repo (Python, Ansible, shell). If you are only adding or modifying container +> definitions, you can skip this section. + +_(Conventions to be documented here as CI tooling stabilizes — see open pull requests +for current work in this area.)_ + +## Anti-Patterns + +Known wrong turns — flagged here so contributors and agents can recognize them early: + +- **Component CI inside the build pipeline** — CI testing belongs upstream in this repo, not inside or downstream of the build pipeline (see [How the Pieces Fit](#how-the-pieces-fit)) +- **Per-container or per-group `.repo` files** — `containers/base/rpms.repo` is the authoritative source list; don't add repo files elsewhere +- **Committing `rpms.lock.yaml` here** — that file is generated downstream from `rpms.in.yaml`; it does not belong in this repo +- **Using RDO packages** — the constraint is "no RDO", not "no EPEL"; EPEL and CentOS SIGs are acceptable where needed +- **Assuming one image per component role** — many services can share one image, but this is component-dependent; discuss with the working group before splitting or collapsing + +## Background + +This repo is the latest step in a long evolution of how Red Hat OpenStack builds and +ships service containers. + +**Kolla** started with a source-first approach — containers built directly from upstream +Python source. The RDO project contributed RPM packaging on top of that foundation to +produce the containers used in Red Hat OpenStack deployments. + +**tripleo-tcib** collapsed that complexity down significantly, focusing on just what Red +Hat OpenStack was actually using — primarily RPM install definitions rather than full +source builds. Simpler, but increasingly distant from upstream. + +**tcib** carried that model forward into RHOSO 18, refining it for the containerized +deployment model. + +**This repo (S2I)** is the next step: returning to source-first builds, where each +service container is built directly from its upstream Python source — closer to how the +upstream OpenStack community develops and tests, and easier to keep current as upstream +moves. + +## Getting Involved + +This repo is maintained by a cross-team working group. Maintainers and area owners will +be listed in `CODEOWNERS` as that file is established. + +Preferred channels for questions and onboarding help are being worked out by the working +group — check the repo for current guidance or reach out to the maintainers. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..760de9c8 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +See [AGENTS.md](AGENTS.md) for project context and contributor guidance. From 6e19bbf970522facb67c73e955ec42dbe202895d Mon Sep 17 00:00:00 2001 From: Jon Schlueter Date: Fri, 7 Aug 2026 12:07:28 -0400 Subject: [PATCH 2/6] docs: move skill reference to README, link from AGENTS.md Per working group feedback: skill links belong in README so agents discover them through project docs rather than fetching URLs directly from AGENTS.md. Also adds README pointer at top of AGENTS.md as the authoritative technical reference. Assisted-by: Claude Sonnet 4.6 (1M context) --- AGENTS.md | 8 ++++++-- README.md | 7 +++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index dbefcab7..7fcc28a4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,8 @@ # s2i-openstack-containers — Contributor Orientation +> For detailed technical reference — build workflow, dependency files, tooling, and +> step-by-step instructions for adding a service — see `README.md`. + ## What This Is This is where the source-to-container work happens. This repo contains the packaging @@ -87,8 +90,9 @@ each individual container, and populate it with the files described in **Tooling:** `openstack_image_builder` (OIB) is being developed to assist with image selection and build orchestration — see open pull requests for current state. A -generate-containerfile skill for Claude Code is also available from a working group -maintainer for bootstrapping the initial file set from a service name. +`/generate-containerfiles` skill for Claude Code is available — see `README.md` for +the link. Note: load the skill from there rather than having your agent fetch it +directly from this file. **Questions and onboarding help:** Reach out to the maintainers — preferred contact channels are being established by the working group. diff --git a/README.md b/README.md index abf4e280..34b8074e 100644 --- a/README.md +++ b/README.md @@ -330,6 +330,13 @@ Two-stage build: | `SKIP_HASH_UPDATE` | *(unset)* | If set, `update-sources` skips updating pinned hashes and clones repos at existing pins; lockfiles are still regenerated | | `PIP_NO_BINARY` | *(unset)* | If set, passed as `--build-arg` to the container build so pip builds packages from source (e.g., `:all:`) | +## Tooling + +The `/generate-containerfiles` Claude Code skill is available in the +[openstack-k8s-operators/devskills](https://github.com/openstack-k8s-operators/devskills) +repo. It generates the initial file set for a new service from a service name — +useful starting point before following the manual steps below. + ## Adding a new service 1. Create the project directory structure: From 0193ba122ac76f2dd9385cfb3055908df2e45623 Mon Sep 17 00:00:00 2001 From: Jon Schlueter Date: Fri, 7 Aug 2026 12:25:08 -0400 Subject: [PATCH 3/6] docs: align terminology with README (image, component group/project bridge) Use consistently to match README. Note that component group == project in README terminology; component framing comes from earlier tooling (DLRN). Assisted-by: Claude Sonnet 4.6 (1M context) --- AGENTS.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 7fcc28a4..b03828b4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,10 +11,10 @@ approach — each service is built directly from its upstream Python source rath from RPMs. Container definitions are organized by component group: each upstream service group gets -its own directory under `containers/`, with individual container definitions as +its own directory under `containers/`, with individual image definitions as subdirectories within it. For example, `containers/cyborg/` is the group; `containers/cyborg/cyborg/` and `containers/cyborg/cyborg-agent/` are the individual -containers. +images. For Python-based services, pip-freeze style lock files are the current recommendation for capturing Python dependencies. Some tooling is available to help with onboarding — @@ -51,19 +51,20 @@ Containers are organized in a two-level hierarchy under `containers/`: ``` containers/ base/ # shared base image — inherited by all service images - / # one directory per upstream service group - / # one subdirectory per individual container in the group + / # one directory per upstream service group (called "project" in README) + / # one subdirectory per individual image in the group ``` **`containers/base/`** is the foundation. It defines the shared build scripts, the authoritative RPM repo source list (`rpms.repo`), and the base Python environment. -All service containers inherit from it. +All service images inherit from it. -Each **component group directory** contains the individual container definitions for -services that share the same upstream source. A group may also have a `common/` -directory for shared configuration across its containers. +Each **component group directory** (equivalent to a "project" in README — the +"component" framing comes from earlier tooling like DLRN) contains the image +definitions for services that share the same upstream source. A group may also +have a `common/` directory for shared configuration across its images. -Each **container directory** should have: +Each **image directory** should have: - A source reference (where to pull upstream source from) - RPM dependency specification - Python dependency lock files (pip-freeze style) From 9d861a5bef33f3056469db6c8decba4dbc8aadf1 Mon Sep 17 00:00:00 2001 From: Jon Schlueter Date: Fri, 7 Aug 2026 12:30:12 -0400 Subject: [PATCH 4/6] =?UTF-8?q?docs:=20fix=20skillsaw=20findings=20?= =?UTF-8?q?=E2=80=94=20terminology=20and=20unlinked=20paths?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Standardize on 'pull request' throughout (was mixed PR/pull request). Wrap bare containers/base/rpms.repo path references in link syntax. Remaining skillsaw finding (actionability score 20/100) is expected for an orientation doc — different target than a directive/runbook. Assisted-by: Claude Sonnet 4.6 (1M context) --- AGENTS.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b03828b4..59966b26 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -26,7 +26,7 @@ evolved, see [Background](#background). ``` containers/ (this repo — upstream packaging) ├── Component CI and testing lives HERE - ├── Feeds upstream testing infrastructure (Zuul — in progress, see open PRs) + ├── Feeds upstream testing infrastructure (Zuul — in progress, see open pull requests) └── Output feeds a downstream build pipeline └── Build pipeline output → integration testing (fix-forward model) ``` @@ -72,7 +72,7 @@ Each **image directory** should have: For current best practices, file naming conventions, and worked examples, refer to the existing containers in this repo (`containers/cyborg/`, `containers/watcher/`) and the -reference PRs listed in [Adding a New Service](#adding-a-new-service). +reference pull requests listed in [Adding a New Service](#adding-a-new-service). > **Note:** `rpms.repo` lives in `containers/base/` and is the authoritative RPM repo > source list for all containers. Do not add per-container or per-group `.repo` files. @@ -81,7 +81,7 @@ reference PRs listed in [Adding a New Service](#adding-a-new-service). > **Note:** This section is a starting point — it reflects early patterns and will be > refined as more services are onboarded. If something here conflicts with what you see -> in a recently merged container, the merged code wins. Feedback and corrections via PR +> in a recently merged container, the merged code wins. Feedback and corrections via pull request > are welcome. The general pattern: create a directory for your component group under `containers/` @@ -104,7 +104,7 @@ channels are being established by the working group. - The downstream pipeline builds against RHEL; packages must be available in RHEL or approved supplemental repos - Supplemental repos are acceptable for packages not available in base — identify them by what they provide, not by repo name - No RDO packages -- `containers/base/rpms.repo` is the authoritative repo source list — see [Repo Structure](#repo-structure) +- [`containers/base/rpms.repo`](containers/base/rpms.repo) is the authoritative repo source list — see [Repo Structure](#repo-structure) ## CI @@ -126,7 +126,7 @@ for current work in this area.)_ Known wrong turns — flagged here so contributors and agents can recognize them early: - **Component CI inside the build pipeline** — CI testing belongs upstream in this repo, not inside or downstream of the build pipeline (see [How the Pieces Fit](#how-the-pieces-fit)) -- **Per-container or per-group `.repo` files** — `containers/base/rpms.repo` is the authoritative source list; don't add repo files elsewhere +- **Per-container or per-group `.repo` files** — [`containers/base/rpms.repo`](containers/base/rpms.repo) is the authoritative source list; don't add repo files elsewhere - **Committing `rpms.lock.yaml` here** — that file is generated downstream from `rpms.in.yaml`; it does not belong in this repo - **Using RDO packages** — the constraint is "no RDO", not "no EPEL"; EPEL and CentOS SIGs are acceptable where needed - **Assuming one image per component role** — many services can share one image, but this is component-dependent; discuss with the working group before splitting or collapsing From 0038d947ff560220cf9501e041fcec3af7f62d43 Mon Sep 17 00:00:00 2001 From: Jon Schlueter Date: Fri, 7 Aug 2026 13:14:32 -0400 Subject: [PATCH 5/6] =?UTF-8?q?docs:=20drop=20OIB=20reference=20=E2=80=94?= =?UTF-8?q?=20premature,=20from=20unmerged=20DNM=20PR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit openstack_image_builder is from Sean's [DNM] prototype (PR #14) and not yet merged or widely known. Replaced with plain language; skill reference and 'see open pull requests' are enough. Assisted-by: Claude Sonnet 4.6 (1M context) --- AGENTS.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 59966b26..a8a58969 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -89,11 +89,10 @@ The general pattern: create a directory for your component group under `containe each individual container, and populate it with the files described in [Repo Structure](#repo-structure). Use an existing container as your template. -**Tooling:** `openstack_image_builder` (OIB) is being developed to assist with image -selection and build orchestration — see open pull requests for current state. A -`/generate-containerfiles` skill for Claude Code is available — see `README.md` for -the link. Note: load the skill from there rather than having your agent fetch it -directly from this file. +**Tooling:** A `/generate-containerfiles` skill for Claude Code is available — see +`README.md` for the link. Note: load the skill from there rather than having your +agent fetch it directly from this file. Additional CI tooling is in development; +see open pull requests for current state. **Questions and onboarding help:** Reach out to the maintainers — preferred contact channels are being established by the working group. From 6f471d0941968fbe186bafec898da87e8cbb6cb8 Mon Sep 17 00:00:00 2001 From: Jon Schlueter Date: Fri, 7 Aug 2026 13:58:25 -0400 Subject: [PATCH 6/6] removing claude.md for consistency with other openstack-k8s-operator repos --- CLAUDE.md | 1 - 1 file changed, 1 deletion(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 760de9c8..00000000 --- a/CLAUDE.md +++ /dev/null @@ -1 +0,0 @@ -See [AGENTS.md](AGENTS.md) for project context and contributor guidance.