diff --git a/.gitignore b/.gitignore index 28b624e..3d70b7d 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ AGENTS.override.md .claude/pr/* .mcp* .tmp +.pi-subagents # Editors *.code-workspace diff --git a/.pi/prompts/create-pr.md b/.pi/prompts/create-pr.md new file mode 120000 index 0000000..faf199e --- /dev/null +++ b/.pi/prompts/create-pr.md @@ -0,0 +1 @@ +../../.claude/commands/create-pr.md \ No newline at end of file diff --git a/.pi/prompts/pdf-transcription-demo.md b/.pi/prompts/pdf-transcription-demo.md new file mode 120000 index 0000000..473af60 --- /dev/null +++ b/.pi/prompts/pdf-transcription-demo.md @@ -0,0 +1 @@ +../../.claude/commands/pdf-transcription-demo.md \ No newline at end of file diff --git a/README.md b/README.md index 087d707..60e42c0 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Check out the **[Github page](https://github.com/openshift/faas-console-plugin)* | [PR Template](.github/pull_request_template.md) | Pull request description format | | [Jira Epic](docs/templates/jira-epic-template.md) | Template for creating Jira epics | | [Jira Story](docs/templates/jira-story-template.md) | Template for creating Jira stories | +| [Jira Bug](docs/templates/jira-bug-template.md) | Template for filing Jira bugs | ### Slash Commands diff --git a/docs/AGILE.md b/docs/AGILE.md index 88ac264..398db37 100644 --- a/docs/AGILE.md +++ b/docs/AGILE.md @@ -18,6 +18,7 @@ We use Jira for planning and tracking. Issues are organized as: - **Epics** group related stories under a single initiative (see [epic template](templates/jira-epic-template.md)) - **Stories** describe a unit of deliverable work (see [story template](templates/jira-story-template.md)) +- **Bugs** describe a defect to fix (see [bug template](templates/jira-bug-template.md)) - **Sub-tasks** break a story into smaller pieces when needed ## Jira Story Status diff --git a/docs/TESTING.md b/docs/TESTING.md index 669e105..23a8892 100644 --- a/docs/TESTING.md +++ b/docs/TESTING.md @@ -13,6 +13,8 @@ Red/green/refactor TDD — **one test at a time**: Do NOT write all test cases first and then implement everything at once. +**Bug fixes require a regression test.** Add a unit test that reproduces the bug, or an e2e test if the bug is not testable at the unit level. + ## Test Layers | Layer | Tool | Scope | @@ -326,7 +328,6 @@ test.describe('My feature', () => { }); ``` - --- ## Backend (Go) diff --git a/docs/references/ocp-dynamic-plugin-reference.md b/docs/references/ocp-dynamic-plugin-reference.md index ebed7c4..45a2cb8 100644 --- a/docs/references/ocp-dynamic-plugin-reference.md +++ b/docs/references/ocp-dynamic-plugin-reference.md @@ -208,3 +208,35 @@ return

{t('Hello, World!')}

; 1. Module federation requires exact module mapping: `exposedModules` must match `$codeRef` values 2. No webpack HMR for extensions: changes to `console-extensions.json` require restart 3. React 17, not 18: matches console's React version + +## Plugin Inventory + +[OCP Dynamic Plugin Inventory](https://docs.google.com/spreadsheets/d/1wcCdc1s4ewzxtUJ42VdRhAJ9wFA8UwoTajGSftrr5fM/edit?gid=0#gid=0) + +| Plugin | Repo | Description | +|--------|------|-------------| +| Console Plugin Template | [openshift/console-plugin-template](https://github.com/openshift/console-plugin-template) | Starter template for OCP dynamic plugins | +| Console Demo Plugin | [openshift/console (demo)](https://github.com/openshift/console/tree/main/dynamic-demo-plugin) | SDK feature testing and reference | +| KubeVirt | [kubevirt-ui/kubevirt-plugin](https://github.com/kubevirt-ui/kubevirt-plugin) | Virtual machine management UI | +| Forklift | [kubev2v/forklift-console-plugin](https://github.com/kubev2v/forklift-console-plugin) | VM migration from other platforms to KubeVirt | +| Monitoring | [openshift/monitoring-plugin](https://github.com/openshift/monitoring-plugin) | Prometheus monitoring dashboards and alerts | +| Logging | [openshift/logging-view-plugin](https://github.com/openshift/logging-view-plugin) | Log viewing and querying | +| Distributed Tracing | [openshift/distributed-tracing-console-plugin](https://github.com/openshift/distributed-tracing-console-plugin) | Distributed tracing with Tempo/Jaeger | +| Console Dashboards | [openshift/console-dashboards-plugin](https://github.com/openshift/console-dashboards-plugin) | Custom dashboard support for OCP console | +| Troubleshooting Panel | [openshift/troubleshooting-panel-console-plugin](https://github.com/openshift/troubleshooting-panel-console-plugin) | Guided troubleshooting for cluster issues | +| Networking | [openshift/networking-console-plugin](https://github.com/openshift/networking-console-plugin) | Network policies, routes, and services | +| Network Observability | [netobserv/network-observability-console-plugin](https://github.com/netobserv/network-observability-console-plugin) | Network traffic flow visualization | +| OpenShift Pipelines | [openshift-pipelines/console-plugin](https://github.com/openshift-pipelines/console-plugin) | Tekton pipeline builder and viewer | +| OpenShift GitOps | [redhat-developer/gitops-console-plugin](https://github.com/redhat-developer/gitops-console-plugin) | ArgoCD/GitOps application status | +| OpenShift Data Foundation | [red-hat-storage/odf-console](https://github.com/red-hat-storage/odf-console) | Ceph/NooBaa storage management | +| Service Mesh (Kiali) | [kiali/openshift-servicemesh-plugin](https://github.com/kiali/openshift-servicemesh-plugin) | Istio service mesh observability | +| ACM / MCE | [stolostron/console](https://github.com/stolostron/console) | Advanced Cluster Management multi-cluster UI | +| Cluster Templates | [stolostron/cluster-templates-operator](https://github.com/stolostron/cluster-templates-operator) | Cluster provisioning templates | +| Crane (Migration) | [migtools/crane-ui-plugin](https://github.com/migtools/crane-ui-plugin) | Application migration toolkit | +| NMState | [nmstate/nmstate-console-plugin](https://github.com/nmstate/nmstate-console-plugin) | Declarative node network configuration | +| Console Telemetry | [christianvogt/console-telemetry-plugin](https://github.com/christianvogt/console-telemetry-plugin) | Usage telemetry collection for console | +| Lightspeed | [openshift/lightspeed-console](https://github.com/openshift/lightspeed-console) | AI assistant for OpenShift | +| Cryostat | [cryostatio/cryostat-openshift-console-plugin](https://github.com/cryostatio/cryostat-openshift-console-plugin) | JFR profiling and recording management | +| Node Remediation | [medik8s/node-remediation-console](https://github.com/medik8s/node-remediation-console) | Automated node health check and remediation | +| Skupper | [bartoval/skupper-site-console](https://github.com/bartoval/skupper-site-console) | Multi-cluster service connectivity | +| Kuadrant | [Kuadrant/kuadrant-console-plugin](https://github.com/Kuadrant/kuadrant-console-plugin) | API gateway policies (rate limiting, auth) | diff --git a/docs/templates/jira-bug-template.md b/docs/templates/jira-bug-template.md new file mode 100644 index 0000000..9d9c5e6 --- /dev/null +++ b/docs/templates/jira-bug-template.md @@ -0,0 +1,37 @@ +# Jira Bug Template + +``` +### Summary + + + +Every bug fix requires a regression test (see [Testing](../TESTING.md#approach)). + +### Steps to Reproduce + +1. + +### Expected Behavior + + + +### Actual Behavior + + + +### Environment + + + +### Root Cause (optional) + + + +### Fix (optional) + + + +### References + + +``` diff --git a/e2e/use-cases/edit/edit-javascript-function.test.ts b/e2e/use-cases/edit/edit-javascript-function.test.ts new file mode 100644 index 0000000..eeb7506 --- /dev/null +++ b/e2e/use-cases/edit/edit-javascript-function.test.ts @@ -0,0 +1,60 @@ +import { test, expect } from '../../fixtures/authenticated-page'; +import { navigateToEditPage } from '../../helpers/navigation'; +import { PRESEEDED_FUNC_NAME } from '../../mocks/github'; + +test.describe('Edit JavaScript function', () => { + test('regression SRVOCF-1007: editor loads JS files without Monaco worker errors', async ({ + page, + }) => { + const consoleErrors: string[] = []; + page.on('pageerror', (err) => consoleErrors.push(err.message)); + + await test.step('navigate to edit page', async () => { + await navigateToEditPage(page, PRESEEDED_FUNC_NAME); + await expect(page.getByRole('heading', { name: 'Edit function' })).toBeVisible({ + timeout: 10_000, + }); + }); + + await test.step('verify editor loads with JavaScript syntax highlighting', async () => { + const editor = page.locator('.monaco-editor'); + await expect(editor.first()).toBeVisible({ timeout: 10_000 }); + await expect(editor.first()).toContainText('module.exports'); + + // Language label shows JAVASCRIPT + await expect(page.getByText('JAVASCRIPT')).toBeVisible(); + }); + + await test.step('verify no webpack error overlay appeared', async () => { + const overlay = page.locator('#webpack-dev-server-client-overlay'); + await expect(overlay).toHaveCount(0); + }); + + await test.step('verify no "Unexpected usage" errors in console', async () => { + const workerErrors = consoleErrors.filter((msg) => msg.includes('Unexpected usage')); + expect(workerErrors).toHaveLength(0); + }); + + await test.step('verify file tree loaded', async () => { + const tree = page.getByRole('tree', { name: 'File tree' }); + await expect(tree.getByText('func.yaml')).toBeVisible(); + await expect(tree.getByText('index.js')).toBeVisible(); + }); + + await test.step('verify switching files works without errors', async () => { + const tree = page.getByRole('tree', { name: 'File tree' }); + await tree.getByText('func.yaml', { exact: true }).click(); + + const editor = page.locator('.monaco-editor'); + await expect(editor.first()).toContainText('runtime: node'); + + // Switch back to JS file + await tree.getByText('index.js', { exact: true }).click(); + await expect(editor.first()).toContainText('module.exports'); + + // Still no worker errors after switching + const workerErrors = consoleErrors.filter((msg) => msg.includes('Unexpected usage')); + expect(workerErrors).toHaveLength(0); + }); + }); +}); diff --git a/src/pages/function-edit/FunctionEditPage.tsx b/src/pages/function-edit/FunctionEditPage.tsx index 0ee7216..c13267d 100644 --- a/src/pages/function-edit/FunctionEditPage.tsx +++ b/src/pages/function-edit/FunctionEditPage.tsx @@ -1,5 +1,6 @@ import { CodeEditor, DocumentTitle, ListPageHeader } from '@openshift-console/dynamic-plugin-sdk'; import type { Language } from '@patternfly/react-code-editor'; +import type { Monaco } from '@monaco-editor/react'; import { DescriptionList, DescriptionListDescription, @@ -90,6 +91,15 @@ function FunctionEditPageContent() { } isLanguageLabelVisible + editorProps={{ + beforeMount: (monaco: Monaco) => { + // SRVOCF-1007: the OCP console does not bundle Monaco's TS worker. + // Disable all worker-dependent features for JS/TS so the missing + // worker is never requested. Monarch syntax highlighting is unaffected. + monaco.languages.typescript.javascriptDefaults.setModeConfiguration({}); + monaco.languages.typescript.typescriptDefaults.setModeConfiguration({}); + }, + }} />