Skip to content

Commit 76c1ba0

Browse files
Merge pull request #94 from TheRealJon/CONSOLE-4873
CONSOLE-4873: Add AI agent documentation
2 parents bc6a745 + bd92fc4 commit 76c1ba0

3 files changed

Lines changed: 235 additions & 28 deletions

File tree

AGENTS.md

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
# AI Agent Instructions for OpenShift Console Plugin Template
2+
3+
This document provides context and guidelines for AI coding assistants working on this codebase.
4+
5+
## Project Overview
6+
7+
This is a **template repository** for creating OpenShift Console dynamic plugins. It's meant to be used via GitHub's "Use this template" feature, NOT forked. The template provides a minimal starting point for extending the OpenShift Console UI with custom pages and functionality.
8+
9+
> **⚠️ WARNING:**
10+
> This repository is used by multiple large-scale enterprise web applications. Please proceed with caution when making any changes to this codebase. Changes here can affect downstream projects that depend on this template.
11+
>
12+
> **Only make changes that should be standard practice for ALL plugins created from this template.** If a change is specific to one plugin use case, it belongs in the instantiated plugin repository, not in this template.
13+
14+
**Key Technologies:**
15+
- TypeScript + React 17
16+
- PatternFly 6 (UI component library)
17+
- Webpack 5 with Module Federation
18+
- react-i18next for internationalization
19+
- Cypress for e2e testing
20+
- Helm for deployment
21+
22+
**Compatibility:** Requires OpenShift 4.12+ (uses ConsolePlugin CRD v1 API)
23+
24+
## Architecture & Patterns
25+
26+
### Dynamic Plugin System
27+
28+
This plugin uses webpack module federation to load at runtime into the OpenShift Console. Key files:
29+
30+
- `console-extensions.json`: Declares what the plugin adds to console (routes, nav items, etc.)
31+
- `package.json` `consolePlugin` section: Plugin metadata and exposed modules mapping
32+
- `webpack.config.ts`: Configures module federation and build
33+
34+
**Critical:** Any component referenced in `console-extensions.json` must have a corresponding entry in `package.json` under `consolePlugin.exposedModules`.
35+
36+
### Component Structure
37+
38+
- Use functional components with hooks (NO class components)
39+
- All components should be TypeScript (`.tsx`)
40+
- Follow PatternFly component patterns
41+
- Use PatternFly CSS variables instead of hex colors (dark mode compatibility)
42+
43+
### Styling Constraints
44+
45+
**IMPORTANT:** The `.stylelintrc.yaml` enforces strict rules to prevent breaking console:
46+
47+
- **NO hex colors** - use PatternFly CSS variables (e.g., `var(--pf-v6-global-palette--blue-500)`)
48+
- **NO naked element selectors** (like `table`, `div`) - prevents overwriting console styles
49+
- **NO `.pf-` or `.co-` prefixed classes** - these are reserved for PatternFly and console
50+
- **Prefix all custom classes** with plugin name (e.g., `console-plugin-template__nice`)
51+
52+
Don't disable these rules without understanding they protect against layout breakage!
53+
54+
## Internationalization (i18n)
55+
56+
**Namespace Convention:** `plugin__<plugin-name>` (e.g., `plugin__console-plugin-template`)
57+
58+
### In React Components:
59+
```tsx
60+
const { t } = useTranslation('plugin__console-plugin-template');
61+
return <h1>{t('Hello, World!')}</h1>;
62+
```
63+
64+
### In console-extensions.json:
65+
```json
66+
"name": "%plugin__console-plugin-template~My Label%"
67+
```
68+
69+
**After adding/changing messages:** Run `yarn i18n` to update locale files in `/locales`
70+
71+
## File Organization
72+
73+
```
74+
src/
75+
components/ # React components
76+
ExamplePage.tsx # Example page component
77+
*.css # Component styles (scoped with plugin prefix)
78+
console-extensions.json # Plugin extension declarations
79+
package.json # Plugin metadata in consolePlugin section
80+
tsconfig.json # TypeScript config (strict: false currently)
81+
webpack.config.ts # Module federation + build config
82+
locales/ # i18n translation files
83+
charts/ # Helm chart for deployment
84+
integration-tests/ # Cypress e2e tests
85+
```
86+
87+
## Development Workflow
88+
89+
### Local Development
90+
1. `yarn install` - install dependencies
91+
2. `yarn start` - starts webpack dev server on port 9001 with CORS
92+
3. `yarn start-console` - runs OpenShift console in container (requires cluster login)
93+
4. Navigate to http://localhost:9000/example
94+
95+
### Code Quality
96+
- `yarn lint` - runs eslint, prettier, and stylelint (with --fix)
97+
- Linting is mandatory before commits
98+
- Follow existing code patterns in the repo
99+
100+
### Testing
101+
- `yarn test-cypress` - opens Cypress UI
102+
- `yarn test-cypress-headless` - runs Cypress in CI mode
103+
- Add e2e tests for new pages/features
104+
105+
## TypeScript Configuration
106+
107+
Current config has `strict: false` but enforces:
108+
- `noUnusedLocals: true`
109+
- All files should use `.tsx` extension
110+
- Target: ES2020
111+
112+
**Modernization opportunity:** When touching files, consider enabling stricter TypeScript checks.
113+
114+
## Common Development Tasks
115+
116+
### Adding a New Page
117+
1. Create component in `src/components/MyPage.tsx`
118+
2. Add to `package.json` `exposedModules`: `"MyPage": "./components/MyPage"`
119+
3. Add route in `console-extensions.json`:
120+
```json
121+
{
122+
"type": "console.page/route",
123+
"properties": {
124+
"path": "/my-page",
125+
"component": { "$codeRef": "MyPage" }
126+
}
127+
}
128+
```
129+
4. Optional: Add nav item in `console-extensions.json`
130+
5. Run `yarn i18n` if you added translatable strings
131+
132+
### Adding a Navigation Item
133+
```json
134+
{
135+
"type": "console.navigation/href",
136+
"properties": {
137+
"id": "my-nav-item",
138+
"name": "%plugin__console-plugin-template~My Page%",
139+
"href": "/my-page",
140+
"perspective": "admin",
141+
"section": "home"
142+
}
143+
}
144+
```
145+
146+
### Updating Plugin Name
147+
When instantiating from template, update:
148+
1. `package.json` - `name` and `consolePlugin.name`
149+
2. `package.json` - `consolePlugin.displayName` and `description`
150+
3. All i18n namespace references (`plugin__<name>`)
151+
4. CSS class prefixes
152+
5. Helm chart values
153+
154+
## Build & Deployment
155+
156+
### Building Image
157+
```bash
158+
docker build -t quay.io/my-repository/my-plugin:latest .
159+
# For Apple Silicon: add --platform=linux/amd64
160+
```
161+
162+
### Deploying via Helm
163+
```bash
164+
helm upgrade -i my-plugin charts/openshift-console-plugin \
165+
-n my-namespace \
166+
--create-namespace \
167+
--set plugin.image=my-plugin-image-location
168+
```
169+
170+
**Note:** OpenShift 4.10 requires `--set plugin.securityContext.enabled=false`
171+
172+
## Important Constraints & Gotchas
173+
174+
1. **Template, not fork:** Users should use "Use this template", not fork
175+
2. **i18n namespace must match ConsolePlugin resource name** with `plugin__` prefix
176+
3. **CSS class prefixes prevent style conflicts** - always prefix with plugin name
177+
4. **Module federation requires exact module mapping** - `exposedModules` must match `$codeRef` values
178+
5. **PatternFly CSS variables only** - hex colors break dark mode
179+
6. **No webpack HMR for extensions** - changes to `console-extensions.json` require restart
180+
7. **TypeScript not in strict mode** - legacy choice, can be modernized
181+
8. **React 17, not 18** - matches console's React version
182+
183+
## Extension Points
184+
185+
See [Console Plugin SDK README](https://github.com/openshift/console/tree/master/frontend/packages/console-dynamic-plugin-sdk) for available extension types:
186+
187+
- `console.page/route` - add new pages
188+
- `console.navigation/href` - add nav items
189+
- `console.navigation/section` - add nav sections
190+
- `console.tab` - add tabs to resource pages
191+
- `console.action/provider` - add actions to resources
192+
- `console.flag` - feature flags
193+
- Many more...
194+
195+
## Code Style Preferences
196+
197+
- Functional components with hooks (NO classes)
198+
- TypeScript for all new files
199+
- Use PatternFly components whenever possible
200+
- Keep components focused and composable
201+
- Prefer named exports for components
202+
- Use `React.FC` or explicit return types
203+
- CSS-in-files (not CSS-in-JS)
204+
205+
## Testing Strategy
206+
207+
- **E2E tests (Cypress):** For user flows and page rendering
208+
- **Component tests:** Add when components have complex logic
209+
- **Test data attributes:** Use `data-test` attributes for selectors
210+
- Run tests locally before opening PRs
211+
212+
## References
213+
214+
- [Console Plugin SDK](https://github.com/openshift/console/tree/master/frontend/packages/console-dynamic-plugin-sdk)
215+
- [PatternFly React](https://www.patternfly.org/get-started/develop)
216+
- [Dynamic Plugin Enhancement Proposal](https://github.com/openshift/enhancements/blob/master/enhancements/console/dynamic-plugins.md)
217+
218+
## Quick Decision Guide
219+
220+
**When should I...**
221+
222+
- **Use this template?** When creating a NEW OpenShift Console plugin from scratch
223+
- **Add a page?** Update console-extensions.json + exposedModules + create component
224+
- **Style something?** Use PatternFly components and CSS variables, prefix custom classes
225+
- **Add translations?** Use `t()` function, run `yarn i18n` after
226+
- **Test changes?** Run locally with `yarn start` + `yarn start-console`, add Cypress tests
227+
- **Deploy?** Build image, push to registry, install via Helm chart

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AGENTS.md

integration-tests/tests/example-page.cy.ts

Lines changed: 7 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,18 @@ const PLUGIN_TEMPLATE_NAME = 'console-plugin-template';
44
const PLUGIN_TEMPLATE_PULL_SPEC = Cypress.env('PLUGIN_TEMPLATE_PULL_SPEC');
55
export const isLocalDevEnvironment = Cypress.config('baseUrl').includes('localhost');
66

7-
export const guidedTour = {
8-
close: () => {
9-
cy.get('body').then(($body) => {
10-
if ($body.find(`[data-test="guided-tour-modal"]`).length > 0) {
11-
cy.get(`[data-test="tour-step-footer-secondary"]`).contains('Skip tour').click();
12-
}
13-
});
14-
},
15-
isOpen: () => {
16-
cy.get('body').then(($body) => {
17-
if ($body.find(`[data-test="guided-tour-modal"]`).length > 0) {
18-
cy.get(`[data-test="guided-tour-modal"]`).should('be.visible');
19-
}
20-
});
21-
},
22-
};
23-
247
const installHelmChart = (path: string) => {
258
cy.exec(
269
`cd ../../console-plugin-template && ${path} upgrade -i ${PLUGIN_TEMPLATE_NAME} charts/openshift-console-plugin -n ${PLUGIN_TEMPLATE_NAME} --create-namespace --set plugin.image=${PLUGIN_TEMPLATE_PULL_SPEC}`,
2710
{
2811
failOnNonZeroExit: false,
2912
},
30-
)
31-
.get('[data-test="refresh-web-console"]', { timeout: 300000 })
32-
.should('exist')
33-
.then((result) => {
34-
cy.reload();
35-
cy.visit(`/dashboards`);
36-
cy.log('Error installing helm chart: ', result.stderr);
37-
cy.log('Successfully installed helm chart: ', result.stdout);
38-
});
13+
).then((result) => {
14+
result.stderr && cy.log('Error installing helm chart: ', result.stderr);
15+
result.stdout && cy.log('Successfully installed helm chart: ', result.stdout);
16+
cy.visit('/k8s/cluster/operator.openshift.io~v1~Console/cluster/console-plugins');
17+
cy.get('[data-test="console-plugin-template-status"]').should('include.text', 'loaded');
18+
});
3919
};
4020
const deleteHelmChart = (path: string) => {
4121
cy.exec(
@@ -52,8 +32,7 @@ const deleteHelmChart = (path: string) => {
5232
describe('Console plugin template test', () => {
5333
before(() => {
5434
cy.login();
55-
guidedTour.isOpen();
56-
guidedTour.close();
35+
cy.get(`[data-test="tour-step-footer-secondary"]`).contains('Skip tour').click();
5736
if (!isLocalDevEnvironment) {
5837
console.log('this is not a local env, installig helm');
5938

0 commit comments

Comments
 (0)