From 1fa8b2acb0f054a34b55c990127e67d4b35acefd Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 17:32:02 -0700 Subject: [PATCH 01/18] docs(tests): use make and bun in frontend tests The frontend tests page still told contributors to run npm scripts, called the linter tslint, and described a Jenkins, Snyk and Code Climate pipeline that no longer runs. Point it at the make targets and bun scripts the repo uses today, document the PROJECT/SCOPE and E2E variables, and list the GitHub Actions checks a PR actually gets. --- docs/developer/frontend-tests.md | 99 +++++++++++++++----------------- 1 file changed, 47 insertions(+), 52 deletions(-) diff --git a/docs/developer/frontend-tests.md b/docs/developer/frontend-tests.md index 7e22e8a6f1..a911c51011 100644 --- a/docs/developer/frontend-tests.md +++ b/docs/developer/frontend-tests.md @@ -5,77 +5,72 @@ sidebar_label: Tests ## Test +Run every command from the repository root. Stratos tooling runs through +[Bun](https://bun.sh); the `make` targets are the supported entry points. +[TESTING.md](https://github.com/cloudfoundry/stratos/blob/develop/TESTING.md) +has the full testing guide. + ### Lint -Run `npm run lint` to execute tslint lint checking. +Run `make check lint` to run the frontend and backend linters: ESLint over the +frontend packages and `e2e/`, then `gofmt`, `go vet` and `golangci-lint` over +each Go module. ### Unit tests -Run `npm test` to execute the unit tests via [Vitest](https://vitest.dev). Coverage information can be found in `./coverage` - -To execute an individual package run `npm run test:`. For example: -- `npm run test:core` - Test core package -- `npm run test:store` - Test store package -- `npm run test:cloud-foundry` - Test Cloud Foundry package +Run `make test frontend` to execute the unit tests via [Vitest](https://vitest.dev). -To run tests in watch mode: `npm run test:watch` +To narrow a run, name the Vitest project and, optionally, a path: -### End-to-end tests +- `make test frontend PROJECT=core`: test the core package +- `make test frontend PROJECT="core git"`: test several packages +- `make test frontend PROJECT=core SCOPE=src/frontend/packages/core/src/shared/components/stepper`: test one directory -Run `npm run e2e` to execute the end-to-end tests via [Playwright](https://playwright.dev/). +The projects are `core`, `store`, `cloud-foundry`, `kubernetes`, +`cf-autoscaler`, `git`, `shared` and `extension`. -Additional E2E commands: -- `npm run e2e:dev` - Run tests against local instance on `https://127.0.0.1:4200` -- `npm run e2e:ui` - Run tests with Playwright UI mode -- `npm run e2e:debug` - Run tests in debug mode -- `npm run e2e:headed` - Run tests in headed mode (see browser) -- `npm run e2e:report` - View test report +Other unit-test commands: -More information on the E2E tests and pre-requisites for running them is available here - [E2E Tests](developers-guide-e2e-tests.md). +- `make check coverage`: run the unit tests with coverage; the report is written to `./coverage` +- `bun run test:watch`: run Vitest in watch mode +- `bun run test:ui`: run Vitest with its browser UI -### Code Climate +Before opening a pull request, run `make check gate` (lint plus unit tests). -We use [Code Climate](https://codeclimate.com/github/cloudfoundry-incubator/stratos) to check for general code quality issues. This executes against Pull -Requests on creation/push. +### End-to-end tests -#### Running Code Climate locally -> Generally we would not advise doing this and just rely on the code climate gate to run when pull requests are submitted +Run `make test e2e` to execute the end-to-end tests via +[Playwright](https://playwright.dev/). It runs Chromium by default and starts a +local backend unless `E2E_BASE_URL` points at a deployed Stratos. -To run locally see instructions [here](https://github.com/codeclimate/codeclimate) to install Code Climate CLI -and engine via docker. Once set ensure you're in the root of the project and execute the following (it may take a while) +Useful options: -``` -codeclimate analyze -``` +- `make test e2e DRYRUN=yes`: list the tests that would run, without running them +- `make test e2e E2E_BROWSERS=chromium,firefox`: choose browsers (`all` runs every configured browser) +- `make test e2e E2E_BASE_URL=https://`: run against a deployed Stratos +- `make check e2e`: run only the core suites +- `make e2e clean`: remove the CF resources that test runs left behind -> [!NOTE] -> Unfortunately this highlights all current issues and not those that are the diff between any master and feature branch. Analyze -> can be ran against a single/sub set of files, again with all current issues, but a little more digestible. +For interactive work, call Playwright through the package scripts: -``` -codeclimate analyze -``` +- `bun run e2e:ui`: run tests with Playwright UI mode +- `bun run e2e:debug`: run tests in debug mode +- `bun run e2e:headed`: run tests in headed mode (see the browser) +- `bun run e2e:report`: view the last test report -In a feature branch to compare files that have changed to master, for instance, use the following +More information on the E2E tests and the prerequisites for running them is +available here - [E2E Tests](developers-guide-e2e-tests.md). -``` -git checkout feature-branch-A -codeclimate analyze $(git diff --name-only master) -``` +### Continuous integration -You can also run the above command via npm +Each pull request, and each push to it, runs these GitHub Actions checks: -``` -npm run climate -``` +- Lint check (`make check lint`) +- Frontend unit tests, one job per Vitest project +- Backend unit tests (`make test backend`) +- Build check (`make build frontend`, `make build backend`) +- CodeQL analysis for Go and JavaScript/TypeScript +- Docs lint, website build and booklets build +- Advisory checks: E2E impact (which E2E specs cover the change) and the changelog fragment -### Stratos Continue Integration -For each new pull request and any subsequent pushes to it the following actions are executed -- Code quality analysis via Code Climate - https://codeclimate.com/ -- Jenkins CI run, covering.. - - Frontend lint check - - Backend lint check - - Frontend unit tests - - Backend unit tests - - End to end tests -- Security anaylsis via Snyk - https://snyk.io/ +End-to-end tests are not part of the pull request checks. From 3b5070bfff3d5ac029ec9da680c4359fbfc4cf7f Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 17:32:15 -0700 Subject: [PATCH 02/18] docs(changelog): note the frontend tests guide --- changelog.d/0003-frontend-tests-docs.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 changelog.d/0003-frontend-tests-docs.md diff --git a/changelog.d/0003-frontend-tests-docs.md b/changelog.d/0003-frontend-tests-docs.md new file mode 100644 index 0000000000..ff606bc6e6 --- /dev/null +++ b/changelog.d/0003-frontend-tests-docs.md @@ -0,0 +1,3 @@ +[Chores] +- The frontend tests guide now gives the `make` and `bun` commands the + repo uses, and lists the checks a pull request runs. From 68ad52fc9bbf85bffd2fec88152d3c762d723081 Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 17:46:38 -0700 Subject: [PATCH 03/18] chore: drop the Code Climate leftovers Code Climate no longer reports on pull requests, and its project page now redirects to a Qlty sign-in. Remove .codeclimate.yml (unchanged since 2020), the climate package script and the docs pointer to the project page. --- .codeclimate.yml | 32 -------------------------------- docs/introduction.md | 2 -- package.json | 1 - 3 files changed, 35 deletions(-) delete mode 100644 .codeclimate.yml diff --git a/.codeclimate.yml b/.codeclimate.yml deleted file mode 100644 index 5650724125..0000000000 --- a/.codeclimate.yml +++ /dev/null @@ -1,32 +0,0 @@ -version: "2" -checks: - method-complexity: - config: - threshold: 8 - similar-code: - config: - threshold: 200 -plugins: - fixme: - enabled: true - git-legal: - enabled: true - markdownlint: - enabled: true - scss-lint: - enabled: false -exclude_patterns: -- "config/" -- "db/" -- "dist/" -- "features/" -- "**/node_modules/" -- "script/" -- "**/spec/" -- "**/test/" -- "**/tests/" -- "**/vendor/" -- "**/*.d.ts" -- "**/__vendor/" -- "**/*_test.go" -- "website/" \ No newline at end of file diff --git a/docs/introduction.md b/docs/introduction.md index f855495bd9..1dc397bbc2 100644 --- a/docs/introduction.md +++ b/docs/introduction.md @@ -43,8 +43,6 @@ Get an [Overview](overview.md) of Stratos, its components and the different ways Browse through features and issues in the project's [issues](https://github.com/cloudfoundry/stratos/issues) page. -What kind of code is in Stratos? We've integrated [Code Climate](https://codeclimate.com) for some code quality and maintainability metrics. Take a stroll around the [project page](https://codeclimate.com/github/cloudfoundry/stratos) - ## Contributing We very much welcome developers who would like to get involved and contribute to the development of the Stratos project. Please refer to the [Contributing guide](contributing_guide.md) for more information. diff --git a/package.json b/package.json index dfe75af481..2c3fdfae8d 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,6 @@ "e2e:screenshot:v4": "E2E_BASE_URL=https://console481.run.adepttech.ca E2E_PROFILE=adepttech STRATOS_SCREENSHOT_LABEL=v4 playwright test e2e/tests/core/screenshots.spec.ts", "e2e:screenshot:v5": "E2E_BASE_URL=https://console.run.adepttech.ca E2E_PROFILE=adepttech STRATOS_SCREENSHOT_LABEL=v5 playwright test e2e/tests/core/screenshots.spec.ts", "e2e:screenshot:compare": "bun e2e/scripts/compare-screenshots.ts v4 v5", - "climate": "codeclimate analyze $(git diff --name-only main)", "gate-check": "bun run lint && bun run test && bun scripts/check-build-warnings.mjs", "store-git-metadata": "bun build/store-git-metadata.cjs", "build-devkit": "cd src/frontend/packages/devkit && bun run build", From 873b45b1b9b69c646395b8cd9fe8e916cc5f8828 Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 17:46:38 -0700 Subject: [PATCH 04/18] chore(theme): remove the stray main.scss backup main.scss.backup was committed with the Material-to-Tailwind conversion and nothing reads it; main.scss is the live stylesheet. --- .../packages/theme/styles/main.scss.backup | 583 ------------------ 1 file changed, 583 deletions(-) delete mode 100644 src/frontend/packages/theme/styles/main.scss.backup diff --git a/src/frontend/packages/theme/styles/main.scss.backup b/src/frontend/packages/theme/styles/main.scss.backup deleted file mode 100644 index d1fa6dc13b..0000000000 --- a/src/frontend/packages/theme/styles/main.scss.backup +++ /dev/null @@ -1,583 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -/* Icon font styles - supports both material-icons and custom icon fonts */ -.material-icons, -.icon { - font-weight: normal; - font-style: normal; - font-size: 24px; - line-height: 1; - letter-spacing: normal; - text-transform: none; - display: inline-block; - white-space: nowrap; - word-wrap: normal; - direction: ltr; - -webkit-font-smoothing: antialiased; -} - -/* CSS Custom Properties for theme customization */ -:root { - /* Brand colors - these will be overridden by StratosThemeService */ - --color-primary: #1e293b; - --color-secondary: #60a5fa; - --color-accent: #60a5fa; - --color-success: #22c55e; - --color-warning: #f59e0b; - --color-danger: #ef4444; - --color-info: #3b82f6; - - /* Navigation colors - these will be overridden by StratosThemeService */ - --nav-bg: #1e293b; - --nav-text: #ffffff; - --nav-text-muted: rgba(255, 255, 255, 0.7); - --nav-hover: rgba(255, 255, 255, 0.1); - --nav-active: rgba(255, 255, 255, 0.15); - --nav-border: rgba(255, 255, 255, 0.1); - --nav-tooltip: #374151; - - /* Layout colors - these will be overridden by StratosThemeService */ - --app-bg: #f8fafc; - --body-bg: #f1f5f9; - --app-text: #1e293b; - --text-muted: #64748b; - --header-bg: #ffffff; - --header-text: #1e293b; - --header-border: #e2e8f0; - --content-bg: #ffffff; - --content-secondary: #f8fafc; - --content-border: #e2e8f0; - --content-text: #1e293b; - --content-muted: #64748b; - - /* Login page */ - --login-bg: #f5f5f5; - --login-bg-image: url('/core/assets/login-bg.jpg'); - --login-card-bg: #ffffff; - - /* Logo */ - --logo-bg: #ffffff; -} - -/* Base layout styles */ -* { - box-sizing: border-box; -} - -html { - @apply h-full; - background-color: var(--app-bg); - color: var(--app-text); -} - -body { - @apply h-full m-0 p-0; - font-family: 'Inter', system-ui, sans-serif; -} - -/* Component base styles */ -@layer components { - /* Modern Button System */ - .btn { - @apply inline-flex items-center justify-center gap-2 px-3.5 py-2 border border-transparent text-sm font-medium rounded-md transition-all duration-200 cursor-pointer; - @apply focus:outline-none focus:ring-2 focus:ring-offset-2; - @apply disabled:opacity-50 disabled:cursor-not-allowed disabled:shadow-none; - line-height: 1.5; - } - - /* Primary Button */ - .btn-primary { - @apply text-white shadow-sm; - background-color: var(--color-primary); - } - - .btn-primary:hover:not(:disabled) { - @apply shadow-md; - background-color: color-mix(in srgb, var(--color-primary) 90%, black); - transform: translateY(-1px); - } - - .btn-primary:active:not(:disabled) { - transform: translateY(0); - } - - .btn-primary:focus { - --tw-ring-color: var(--color-primary); - } - - /* Secondary Button */ - .btn-secondary { - @apply text-gray-700 bg-white border-gray-300 shadow-sm; - } - - .btn-secondary:hover:not(:disabled) { - @apply bg-gray-50 border-gray-400 shadow; - } - - .btn-secondary:focus { - --tw-ring-color: var(--color-primary); - } - - /* Success Button */ - .btn-success { - @apply text-white shadow-sm; - background-color: var(--color-success); - } - - .btn-success:hover:not(:disabled) { - @apply shadow-md; - background-color: color-mix(in srgb, var(--color-success) 90%, black); - transform: translateY(-1px); - } - - .btn-success:focus { - --tw-ring-color: var(--color-success); - } - - /* Warning Button */ - .btn-warning { - @apply text-white shadow-sm; - background-color: var(--color-warning); - } - - .btn-warning:hover:not(:disabled) { - @apply shadow-md; - background-color: color-mix(in srgb, var(--color-warning) 90%, black); - transform: translateY(-1px); - } - - .btn-warning:focus { - --tw-ring-color: var(--color-warning); - } - - /* Danger Button */ - .btn-danger { - @apply text-white shadow-sm; - background-color: var(--color-danger); - } - - .btn-danger:hover:not(:disabled) { - @apply shadow-md; - background-color: color-mix(in srgb, var(--color-danger) 90%, black); - transform: translateY(-1px); - } - - .btn-danger:focus { - --tw-ring-color: var(--color-danger); - } - - /* Info Button */ - .btn-info { - @apply text-white shadow-sm; - background-color: var(--color-info); - } - - .btn-info:hover:not(:disabled) { - @apply shadow-md; - background-color: color-mix(in srgb, var(--color-info) 90%, black); - transform: translateY(-1px); - } - - .btn-info:focus { - --tw-ring-color: var(--color-info); - } - - /* Ghost Button (transparent with border) */ - .btn-ghost { - @apply bg-transparent border-gray-300 text-gray-700; - } - - .btn-ghost:hover:not(:disabled) { - @apply bg-gray-100 border-gray-400; - } - - /* Outline Variants */ - .btn-outline-primary { - @apply bg-transparent border-2 text-gray-700; - border-color: var(--color-primary); - color: var(--color-primary); - } - - .btn-outline-primary:hover:not(:disabled) { - background-color: var(--color-primary); - @apply text-white shadow-sm; - } - - .btn-outline-secondary { - @apply bg-transparent border-2 border-gray-300 text-gray-700; - } - - .btn-outline-secondary:hover:not(:disabled) { - @apply bg-gray-100 border-gray-400; - } - - /* Icon Buttons */ - .btn-icon { - @apply rounded-md; - width: 36px !important; - height: 36px !important; - min-width: 36px !important; - min-height: 36px !important; - padding: 0.5rem !important; - display: inline-flex !important; - align-items: center !important; - justify-content: center !important; - } - - .btn-icon-sm { - @apply rounded-md; - width: 32px !important; - height: 32px !important; - min-width: 32px !important; - min-height: 32px !important; - padding: 0.375rem !important; - display: inline-flex !important; - align-items: center !important; - justify-content: center !important; - } - - .btn-icon-lg { - @apply rounded-md; - width: 44px !important; - height: 44px !important; - min-width: 44px !important; - min-height: 44px !important; - padding: 0.625rem !important; - display: inline-flex !important; - align-items: center !important; - justify-content: center !important; - } - - /* Button Sizes */ - .btn-sm { - @apply px-3 py-1.5 text-xs; - } - - .btn-lg { - @apply px-6 py-3 text-base; - } - - /* Button with icon */ - .btn .material-icons, - .btn .icon { - font-size: 20px !important; - width: 20px !important; - height: 20px !important; - line-height: 20px !important; - } - - .btn-icon .material-icons, - .btn-icon .icon { - font-size: 20px !important; - width: 20px !important; - height: 20px !important; - line-height: 20px !important; - } - - .btn-sm .material-icons, - .btn-sm .icon { - font-size: 18px !important; - width: 18px !important; - height: 18px !important; - } - - .btn-lg .material-icons, - .btn-lg .icon { - font-size: 24px !important; - width: 24px !important; - height: 24px !important; - } - - /* Input styles */ - .input { - @apply block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-2 focus:border-transparent; - --tw-ring-color: var(--color-primary); - } - - /* Card styles */ - .card { - @apply bg-white rounded-lg shadow border border-gray-200; - } - - .card-header { - @apply px-6 py-4 border-b border-gray-200; - } - - .card-body { - @apply px-6 py-4; - } - - .card-footer { - @apply px-6 py-4 border-t border-gray-200; - } - - /* Status indicators */ - .status-success { - @apply text-white px-2 py-1 rounded-full text-xs font-medium; - background-color: var(--color-success); - } - - .status-warning { - @apply text-white px-2 py-1 rounded-full text-xs font-medium; - background-color: var(--color-warning); - } - - .status-danger { - @apply text-white px-2 py-1 rounded-full text-xs font-medium; - background-color: var(--color-danger); - } - - .status-info { - @apply text-white px-2 py-1 rounded-full text-xs font-medium; - background-color: var(--color-info); - } - - /* Navigation styles */ - .nav { - background-color: var(--nav-bg); - color: var(--nav-text); - } - - .nav-item { - @apply transition-colors duration-200; - } - - .nav-item:hover { - background-color: var(--nav-hover); - } - - .nav-item.active { - background-color: var(--nav-active); - } - - /* Navigation utility classes */ - .bg-nav-bg { - background-color: var(--nav-bg) !important; - } - - .text-nav-text { - color: var(--nav-text) !important; - } - - .text-nav-muted { - color: var(--nav-text-muted) !important; - } - - .bg-nav-hover { - background-color: var(--nav-hover) !important; - } - - .bg-nav-active { - background-color: var(--nav-active) !important; - } -} - -/* Legacy Material component support - temporary compatibility layer */ -/* These styles will be removed once all components are migrated to Tailwind classes */ -.mat-mdc-button, -.mat-mdc-raised-button, -.mat-mdc-flat-button, -.mat-mdc-stroked-button, -.mat-mdc-icon-button { - @apply btn; -} - -.mat-mdc-raised-button.mat-primary, -.mat-mdc-flat-button.mat-primary { - @apply btn-primary; -} - -.mat-mdc-raised-button.mat-accent, -.mat-mdc-flat-button.mat-accent, -.mat-mdc-stroked-button { - @apply btn-secondary; -} - -.mat-mdc-raised-button.mat-warn, -.mat-mdc-flat-button.mat-warn { - @apply btn-danger; -} - -.mat-mdc-icon-button { - @apply btn-icon; - - .material-icons, - .icon { - font-size: 20px !important; - width: 20px !important; - height: 20px !important; - } -} - -.border-nav-border { - border-color: var(--nav-border) !important; -} - -.bg-nav-tooltip { - background-color: var(--nav-tooltip) !important; -} - -.bg-accent { - background-color: var(--color-accent) !important; -} - -/* Header styles */ -.header { - background-color: var(--header-bg); - color: var(--header-text); -} - -/* Login page styles */ -.login-page { - background-color: var(--login-bg); - background-image: var(--login-bg-image); - @apply bg-cover bg-center min-h-screen; -} - -.login-card { - background-color: var(--login-card-bg); -} - -/* Loading spinner */ -.spinner { - @apply inline-block w-4 h-4 border-2 border-solid border-gray-200 border-r-transparent rounded-full animate-spin; -} - -.spinner-primary { - border-color: var(--color-primary); - border-right-color: transparent; -} - -/* Table styles */ -.table { - @apply min-w-full divide-y divide-gray-200; -} - -.table th { - @apply px-6 py-3 bg-gray-50 text-left text-xs font-medium text-gray-500 uppercase tracking-wider; -} - -.table td { - @apply px-6 py-4 whitespace-nowrap text-sm text-gray-900; -} - -.table tbody tr { - @apply even:bg-gray-50; -} - -/* List styles */ -.list-item { - @apply border-b border-gray-200 last:border-b-0 hover:bg-gray-50 transition-colors duration-150; -} - -/* Progress bar */ -.progress { - @apply w-full bg-gray-200 rounded-full h-2; -} - -.progress-bar { - @apply h-2 rounded-full transition-all duration-300; - background-color: var(--color-primary); -} - -/* Alert styles */ -.alert { - @apply p-4 rounded-md border-l-4; -} - -.alert-success { - @apply bg-green-50 border-green-400 text-green-800; -} - -.alert-warning { - @apply bg-yellow-50 border-yellow-400 text-yellow-800; -} - -.alert-danger { - @apply bg-red-50 border-red-400 text-red-800; -} - -.alert-info { - @apply bg-blue-50 border-blue-400 text-blue-800; -} - -/* Modal styles */ -.modal-overlay { - @apply fixed inset-0 bg-black bg-opacity-50 z-50; -} - -.modal { - @apply fixed inset-0 z-50 overflow-y-auto; -} - -.modal-container { - @apply flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0; -} - -.modal-panel { - @apply transform overflow-hidden rounded-lg bg-white text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg; -} - -/* Tooltip */ -.tooltip { - @apply absolute z-10 invisible px-3 py-2 text-sm font-medium text-white bg-gray-900 rounded-lg shadow-sm opacity-0 transition-opacity duration-300; -} - -.tooltip:hover .tooltip-text { - @apply visible opacity-100; -} - -/* Modal styles */ -body.modal-open { - overflow: hidden; -} - -/* Primary button with theme colors */ -.bg-primary { - background-color: var(--color-primary) !important; -} - -.text-primary { - color: var(--color-primary) !important; -} - -.border-primary { - border-color: var(--color-primary) !important; -} - -.hover\:bg-primary:hover { - background-color: var(--color-primary) !important; -} - -/* Utility classes */ -@layer utilities { - .text-primary { - color: var(--color-primary); - } - - .text-secondary { - color: var(--color-secondary); - } - - .bg-primary { - background-color: var(--color-primary); - } - - .bg-secondary { - background-color: var(--color-secondary); - } - - .border-primary { - border-color: var(--color-primary); - } - - .border-secondary { - border-color: var(--color-secondary); - } - - .focus\:ring-primary:focus { - --tw-ring-color: var(--color-primary); - } -} \ No newline at end of file From b1754ea46893746a5e08817fe6c94776ae86c1de Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 17:48:27 -0700 Subject: [PATCH 05/18] chore: run tools through bun, not npx or npm The make e2e recipes and the tiered runner launched Playwright with npx, the version stamp ran tsc with npx, ngbuild.sh built the devkit with npm, and the STB workflow ran its checks with npm. Use bun run everywhere, as the rest of the Makefile and CI already do. Playwright lists the same 713 chromium tests either way, and tsc reports the same version. ngbuild.sh keeps npm for publish, unpublish and link, which act on the npm registry. --- .github/workflows/stb_tests.yml | 10 +++++----- Makefile | 6 +++--- build/ngbuild.sh | 2 +- scripts/e2e-impact.mjs | 2 +- scripts/e2e-run.mjs | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/stb_tests.yml b/.github/workflows/stb_tests.yml index 31d56a30d5..485414c610 100644 --- a/.github/workflows/stb_tests.yml +++ b/.github/workflows/stb_tests.yml @@ -80,15 +80,15 @@ jobs: # The integration suite runs in real browsers (vite.config.ts defines # integration-chromium/firefox/webkit projects); CI has no browser # binaries by default. NOTE: installs all three to keep CI == local - # `npm test`; narrow to chromium if the gate gets slow. + # `bun run test`; narrow to chromium if the gate gets slow. - name: Install Playwright browsers - run: npx playwright install --with-deps + run: bun run playwright install --with-deps - name: Typecheck - run: npm run typecheck + run: bun run typecheck - name: Lint - run: npm run lint + run: bun run lint - name: Unit + integration tests - run: npm test + run: bun run test diff --git a/Makefile b/Makefile index 6a3508a415..ab72b70ac2 100644 --- a/Makefile +++ b/Makefile @@ -87,7 +87,7 @@ include version.mk # Stratos-specific build metadata and stamps — the per-repo config the # vendorable core deliberately excludes. $(_HIDE)BUILD_NODE_VERSION := $(shell node --version 2>/dev/null || echo "unknown") -$(_HIDE)BUILD_TS_VERSION := $(shell npx tsc --version 2>/dev/null | awk '{print $$2}' || echo "unknown") +$(_HIDE)BUILD_TS_VERSION := $(shell bun run tsc --version 2>/dev/null | awk '{print $$2}' || echo "unknown") $(_HIDE)BUILD_BUN_VERSION := $(shell bun --version 2>/dev/null || echo "unknown") # Lazy (=) so the backend binary's baked-in version reflects the post-bump @@ -622,7 +622,7 @@ define test.e2e $(if $(PR),--pr $(PR) )$(call _e2e_toggle,dry-run,$(DRYRUN)); \ else \ echo "Running Playwright E2E tests..."; \ - $(if $(E2E_VIDEO),E2E_VIDEO=$(E2E_VIDEO) )$(if $(E2E_SCREENSHOTS),E2E_SCREENSHOTS=$(E2E_SCREENSHOTS) )npx playwright test \ + $(if $(E2E_VIDEO),E2E_VIDEO=$(E2E_VIDEO) )$(if $(E2E_SCREENSHOTS),E2E_SCREENSHOTS=$(E2E_SCREENSHOTS) )bun run playwright test \ $(call _e2e_browsers,$(E2E_BROWSERS)) \ $(call _e2e_flag,trace,$(E2E_TRACE)) \ $(call _e2e_toggle,list,$(DRYRUN)); \ @@ -727,7 +727,7 @@ $(call register, check, coverage, $($(_HIDE)BUILD_INFO_TS)) define check.e2e $(_ensure_host_backend) @echo "Running Playwright E2E core tests..." - @$(if $(E2E_VIDEO),E2E_VIDEO=$(E2E_VIDEO) )$(if $(E2E_SCREENSHOTS),E2E_SCREENSHOTS=$(E2E_SCREENSHOTS) )npx playwright test e2e/tests/core/ \ + @$(if $(E2E_VIDEO),E2E_VIDEO=$(E2E_VIDEO) )$(if $(E2E_SCREENSHOTS),E2E_SCREENSHOTS=$(E2E_SCREENSHOTS) )bun run playwright test e2e/tests/core/ \ $(call _e2e_browsers,$(E2E_BROWSERS)) \ $(call _e2e_flag,trace,$(E2E_TRACE)) \ $(call _e2e_toggle,list,$(DRYRUN)) diff --git a/build/ngbuild.sh b/build/ngbuild.sh index 4cf9156e1c..32e1f454bd 100755 --- a/build/ngbuild.sh +++ b/build/ngbuild.sh @@ -154,7 +154,7 @@ function build_devkit() { echo -e "${YELLOW}${BOLD}= Package: @stratosui/devkit${RESET}" echo - npm run build-devkit + bun run build-devkit rm -rf ${STRATOS}/npm_pkg/devkit cp -r ${STRATOS}/dist-devkit ${STRATOS}/npm_pkg/devkit diff --git a/scripts/e2e-impact.mjs b/scripts/e2e-impact.mjs index 8687ddcb9a..c5fe456db6 100644 --- a/scripts/e2e-impact.mjs +++ b/scripts/e2e-impact.mjs @@ -202,5 +202,5 @@ if (FILES_ONLY) { for (const s of specs) console.log(` ${s}`) } const all = [...new Set(report.flatMap((r) => r.specs))].sort() - console.log(`\nRun scoped: npx playwright test --project=setup --project=chromium ${all.join(' ')}`) + console.log(`\nRun scoped: bun run playwright test --project=setup --project=chromium ${all.join(' ')}`) } diff --git a/scripts/e2e-run.mjs b/scripts/e2e-run.mjs index 3ce223c3ae..eedfb8e295 100644 --- a/scripts/e2e-run.mjs +++ b/scripts/e2e-run.mjs @@ -116,10 +116,10 @@ let totals = { expected: 0, unexpected: 0, flaky: 0, skipped: 0 } let exitCode = 0 for (const run of runs) { const argv = ['playwright', 'test', ...run.args] - console.log(`\n>>> ${run.label}\n npx ${argv.join(' ')}`) + console.log(`\n>>> ${run.label}\n bun run ${argv.join(' ')}`) if (opt.dryRun) continue rmSync('e2e-reports/results.json', { force: true }) // a crashed run must not inherit the previous run's report - const r = spawnSync('npx', argv, { stdio: 'inherit' }) + const r = spawnSync('bun', ['run', ...argv], { stdio: 'inherit' }) if (r.status !== 0) exitCode = 1 try { const j = JSON.parse(readFileSync('e2e-reports/results.json', 'utf8')) From c5f4880a2b19b9a804f2ead223b044aaf9b99b2e Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 17:51:08 -0700 Subject: [PATCH 06/18] fix(e2e): drop the stale port 4200 defaults e2e:dev pointed Playwright at https://localhost:4200, the Angular CLI default; the dev frontend serves on 5440 (angular.json, make dev frontend). RequestHelper and EndpointManagementHelper defaulted to https://127.0.0.1:4200 and the cfApi fixture fell back to http://localhost:4200, but all 9 call sites pass a URL. Make baseURL required so a missing one fails loudly instead of hitting a wrong host. --- e2e/fixtures/test-base.ts | 5 ++++- e2e/helpers/endpoint-management.helper.ts | 2 +- e2e/helpers/request.helper.ts | 2 +- package.json | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/e2e/fixtures/test-base.ts b/e2e/fixtures/test-base.ts index 45838ca7ae..e2d3fafe8c 100644 --- a/e2e/fixtures/test-base.ts +++ b/e2e/fixtures/test-base.ts @@ -341,7 +341,10 @@ export const test = base.extend({ } // Create request helper with pre-authenticated state - const request = new RequestHelper(baseURL || 'http://localhost:4200'); + if (!baseURL) { + throw new Error('cfApi needs baseURL; playwright.config.ts sets it'); + } + const request = new RequestHelper(baseURL); await withDeadline(request.initFromStorageState(ADMIN_STATE), 15000, 'cfApi initFromStorageState'); // Get registered endpoints diff --git a/e2e/helpers/endpoint-management.helper.ts b/e2e/helpers/endpoint-management.helper.ts index 76d1b75d73..e44bce904a 100644 --- a/e2e/helpers/endpoint-management.helper.ts +++ b/e2e/helpers/endpoint-management.helper.ts @@ -32,7 +32,7 @@ export class EndpointManagementHelper { private baseURL: string; - constructor(baseURL: string = 'https://127.0.0.1:4200') { + constructor(baseURL: string) { this.baseURL = baseURL; this.adminRequest = new RequestHelper(baseURL); this.userRequest = new RequestHelper(baseURL); diff --git a/e2e/helpers/request.helper.ts b/e2e/helpers/request.helper.ts index ba8bd55189..a058183d30 100644 --- a/e2e/helpers/request.helper.ts +++ b/e2e/helpers/request.helper.ts @@ -23,7 +23,7 @@ export class RequestHelper { private secrets = SecretsHelper.load(); private authType?: AuthType; - constructor(baseURL: string = 'https://127.0.0.1:4200') { + constructor(baseURL: string) { this.baseURL = baseURL; } diff --git a/package.json b/package.json index 2c3fdfae8d..1339861842 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "e2e:ui": "playwright test --ui", "e2e:debug": "playwright test --debug", "e2e:headed": "playwright test --headed", - "e2e:dev": "E2E_BASE_URL=https://localhost:4200 playwright test", + "e2e:dev": "E2E_BASE_URL=https://localhost:5440 playwright test", "e2e:local": "E2E_BASE_URL=https://localhost playwright test", "e2e:report": "playwright show-report e2e-reports/html", "e2e:screenshot:v4": "E2E_BASE_URL=https://console481.run.adepttech.ca E2E_PROFILE=adepttech STRATOS_SCREENSHOT_LABEL=v4 playwright test e2e/tests/core/screenshots.spec.ts", From b2444cb524f7056848689b939d5299dde9d06530 Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 17:55:43 -0700 Subject: [PATCH 07/18] docs: bring the developer guides up to date The developer introduction, frontend and backend guides still taught the pre-v5 workflow: npm install/start/build, a global Angular CLI, Node 12 and Go 1.12 minimums, a jetstream binary in src/jetstream, port 4200 and Angular Material theming. Point them at make install, make dev frontend/backend, make build frontend/backend, dist/bin, port 5440, the Required Runtimes table and the theming docs. Also replace the remaining npm, npx and node commands in the extension guides, the issue template, TESTING.md, the lockdiff instructions and the plugin build diagram with their bun or make equivalents. --- TESTING.md | 4 ++-- docs/build-and-packaging.md | 4 ++-- docs/developer/backend.md | 8 ++++---- docs/developer/frontend.md | 32 +++++++++++++++----------------- docs/developer/introduction.md | 14 ++++++-------- docs/extensions/frontend.md | 2 +- docs/extensions/introduction.md | 2 +- docs/issue_template.md | 2 +- docs/plugin-architecture.md | 8 ++++---- 9 files changed, 36 insertions(+), 40 deletions(-) diff --git a/TESTING.md b/TESTING.md index e82083e77e..32aebd6d8d 100644 --- a/TESTING.md +++ b/TESTING.md @@ -155,13 +155,13 @@ Everything else stays in its existing group directory. **This ordering is enforced only by the tiered runner** (`make test e2e TIER=…` / `make test e2e GROUP=…`, which delegates to -`scripts/e2e-run.mjs`). A bare `npx playwright test` or `make test e2e` +`scripts/e2e-run.mjs`). A bare `bun run playwright test` or `make test e2e` (with no `TIER`/`GROUP` set) runs the plain Playwright test-runner directly — `dependent/` is not ordered last and can interleave with the parallel pool, reintroducing the blast-radius risk above. `make check e2e` also bypasses the tiered runner: it scopes directly to -`npx playwright test e2e/tests/core/`, so it no longer covers the +`bun run playwright test e2e/tests/core/`, so it no longer covers the endpoint lifecycle spec at all — `endpoints.spec.ts` lives in `dependent/`, outside that path. diff --git a/docs/build-and-packaging.md b/docs/build-and-packaging.md index aca4a7c219..715376bb28 100644 --- a/docs/build-and-packaging.md +++ b/docs/build-and-packaging.md @@ -408,8 +408,8 @@ that brought it into the tree. It reads `bun.lock` and npm `package-lock.json`, and takes `:` to read a version from git: ```bash -node scripts/lockdiff.mjs origin/develop:bun.lock bun.lock -node scripts/lockdiff.mjs origin/develop:src/frontend/packages/devkit/package-lock.json \ +bun scripts/lockdiff.mjs origin/develop:bun.lock bun.lock +bun scripts/lockdiff.mjs origin/develop:src/frontend/packages/devkit/package-lock.json \ src/frontend/packages/devkit/package-lock.json --detail ``` diff --git a/docs/developer/backend.md b/docs/developer/backend.md index ebc6c21df1..2c7f4763f1 100644 --- a/docs/developer/backend.md +++ b/docs/developer/backend.md @@ -11,7 +11,7 @@ We use Go Modules for dependency management. You will need the following installed/available: -* go 1.12 or later. +* Go at the version in [Required Runtimes](../developer-environment.md#required-runtimes). *For authentication, **either*** @@ -23,13 +23,13 @@ You will need the following installed/available: #### Build -From the `src/jetstream` folder, build the Stratos back-end with: +From the repository root, build the Stratos back-end for your machine with: ``` -npm run build-backend +make build backend PLATFORM=/ # for example darwin/arm64 or linux/amd64 ``` -The back-end executable is named `jetstream` and should be created within the `src/jetstream` folder. +The back-end executable is `dist/bin/jetstream`. `make dev backend` builds it for your machine automatically the first time, so the normal dev cycle needs no separate build. ### Configuration diff --git a/docs/developer/frontend.md b/docs/developer/frontend.md index b81754c3f3..10072e6aa1 100644 --- a/docs/developer/frontend.md +++ b/docs/developer/frontend.md @@ -18,48 +18,46 @@ If you feel comfortable with these and are happy with your dev environment pleas ## Set up Dependencies * Set up a Stratos backend. Both backend and frontend exist in this same repo. Follow the [Backend Development](./introduction.md#build--run-locally) set up guide. -* Install [NodeJs](https://nodejs.org) (if not already install) (minimum node version 12.13.0) -* Install [Angular CLI](https://cli.angular.io/) (if not already install) - `npm install -g @angular/cli` +* Install Node.js and Bun at the versions in [Required Runtimes](../developer-environment.md#required-runtimes). The Angular CLI comes with the project's dependencies; run it as `bunx ng`. ## Run the frontend -1. Run `npm install` -1. Run `npm start` for a dev server. (the app will automatically reload if you change any of the source files) - * If this times out please use `npm run start-high-mem` instead - * To change the port from the default 4200, add `-- --port [new port number]` - * To stop the automatic reload every time a resource changes add `-- --live-reload false` - * To do both the above use `-- --live-reload false --port [new port number]` -1. Navigate to `https://localhost:4200/`. The credentials to log in will be dependent on the Jetstream the console points at. Please refer +1. Run `make install` +1. Run `make dev frontend` for a dev server. The app reloads automatically when you change a source file. + * To change the ports, set `FRONTEND_PORT`, and `BACKEND_PORT` if the backend is not on 5443, for example + `make dev frontend FRONTEND_PORT=5540 BACKEND_PORT=5543` +1. Navigate to `https://localhost:5440/`. The credentials to log in will be dependent on the Jetstream the console points at. Please refer to the guides used when setting up the backend for more information ## Build > The normal dev cycle does not require a direct build. -Run `npm run build` to build the project. +Run `make build frontend` to build the frontend. -The build artefacts will be stored in the `dist/` directory. This will output a production build of the application. +The build artefacts will be stored in `dist/frontend/browser/`. This is a production build of the application. ## Creating angular items via angular cli -To create a new angular component run `ng generate component component-name`. You can use a similar command to create other types of angular -items `ng generate `. +To create a new angular component run `bunx ng generate component component-name`. You can use a similar command to create other types of angular +items `bunx ng generate `. ## Theming -We use the angular material theming mechanism. See [here](https://material.angular.io/guide/theming-your-components) for more information about theming new components added to stratos. +Stratos does not use Angular Material. Colours and other design tokens are CSS custom properties exposed to templates as Tailwind v4 classes. See +[Theming Architecture](../theming-architecture.md) and [Tailwind CSS v4 Usage](../tailwind-usage.md) before styling new components. ## Additional Information ### Extensions -Documentation on extensions can be found [here](../extensions/introduction.md). From a developers perspective extensions are managed by npm packages. +Documentation on extensions can be found [here](../extensions/introduction.md). From a developer's perspective extensions are packages. The default set are in `./src/frontend/packages`, any package added directly here will be automatically included by the build. -At build time the Stratos Devkit (`./src/frontend/packages/devkit`) will ensure all packages are imported correctly and theming, both component and console level, are applied correctly. -The devkit is automatically built in `postinstall` after `npm install` is ran. To directly build it `npm run dev-setup` can be executed. +At build time the Stratos Devkit (`./src/frontend/packages/devkit`) ensures all packages are imported correctly. +The devkit is built automatically by the `postinstall` step of `bun install` (which `make install` runs). To build it directly, run `bun run dev-setup`. ### Configuration diff --git a/docs/developer/introduction.md b/docs/developer/introduction.md index b72ad9c1c9..9d5125c081 100644 --- a/docs/developer/introduction.md +++ b/docs/developer/introduction.md @@ -16,21 +16,19 @@ Depending on what you are contributing, you will need to develop with the front- For a quick-start to get Stratos front and back ends built and running locally on a development system, follow the steps below. -You will need to have `go` and `nodejs` installed in your development environment. +You will need Node.js, Bun, Go, Git and Make; the [Required Runtimes](../developer-environment.md#required-runtimes) table lists the versions. ``` git clone https://github.com/cloudfoundry/stratos.git cd stratos -npm install -npm run build -npm run build-backend -cd src/jetstream -./jetstream +make install +make dev backend # terminal 1: backend on https://localhost:5443 +make dev frontend # terminal 2: frontend on https://localhost:5440 ``` -This will build both the frontend and backend and run the backend in a mode where it will also serve the static resources for the frontend. +Before the first `make dev backend`, create `src/jetstream/config.properties` with an encryption key and a login method; the contributor guide's [First-Time Setup](../contributing_guide.md#first-time-setup) gives the exact lines, including a local `admin` user. -You can open a web browser and navigate to (https://127.0.0.1:5443) and login with username `admin` and password `admin`. +Then open https://localhost:5440 in a web browser. > To develop the frontend we recommend reading through the [frontend](./frontend.md) doc. This includes a faster way to run Stratos and see your changes. diff --git a/docs/extensions/frontend.md b/docs/extensions/frontend.md index 916cca2dba..c77a7e18a1 100644 --- a/docs/extensions/frontend.md +++ b/docs/extensions/frontend.md @@ -309,7 +309,7 @@ productVersion: 2.0.0 In this example, we will walk through extending the Stratos front-end. A new tab will be added to the Cloud Foundry Application page. -This walk-through assumes that you have installed the Angular CLI globally - this can be done with `npm install -g @angular/cli`. +This walk-through uses the Angular CLI that comes with the project's dependencies; run it as `bunx ng`. ### Create a new extensions package diff --git a/docs/extensions/introduction.md b/docs/extensions/introduction.md index f14d0513d6..5a7a09d1a8 100644 --- a/docs/extensions/introduction.md +++ b/docs/extensions/introduction.md @@ -13,7 +13,7 @@ In order to customize Stratos, you will need to fork the Stratos GitHub reposito ### Frontend -Frontend customizations are placed in angular packages in the folder named `src/frontend/packages`. In the future you will be able to host these packages in npm and bring them into Stratos in the usual npm dependency way. There are no additional processes or build steps required for Stratos to then integrate these packages. All steps will be automatically applied under the hood during `npm install` and when `ng build`/`ng serve` runs. +Frontend customizations are placed in angular packages in the folder named `src/frontend/packages`. In the future you will be able to host these packages in npm and bring them into Stratos in the usual npm dependency way. There are no additional processes or build steps required for Stratos to then integrate these packages. All steps are applied automatically during `bun install` (run by `make install`) and when `make build frontend` or `make dev frontend` runs. Information on custom theming can be found in the [theming page](../theming-architecture.md). diff --git a/docs/issue_template.md b/docs/issue_template.md index c8b8913393..40e46ed4d8 100644 --- a/docs/issue_template.md +++ b/docs/issue_template.md @@ -11,7 +11,7 @@ * [ ] Cloud Foundry Application (cf push) * [ ] Kubernetes, using a helm chart * [ ] Docker, single container deploying all components -* [ ] npm run start +* [ ] Local dev server (make dev frontend) * [ ] Other (please specify below) ### Backend (Jet Stream) Deployment type diff --git a/docs/plugin-architecture.md b/docs/plugin-architecture.md index f095acadec..a122acbf0f 100644 --- a/docs/plugin-architecture.md +++ b/docs/plugin-architecture.md @@ -257,8 +257,8 @@ cd src/jetstream && go generate ./... → writes extra_plugins.go ``` -The Makefile's `build-backend` target runs `go generate` automatically -before `go build`. +`make build backend` runs `go generate` automatically before +`go build`. ### Frontend Build (prebuild) @@ -266,13 +266,13 @@ The frontend prebuild pipeline also reads `plugin-config.yaml` to generate the same `extra_plugins.go`: ``` -npm prebuild +bun run prebuild └── build-orchestrator.js └── backend.ts → reads plugin-config.yaml → validates plugin dirs exist → writes extra_plugins.go -npm build (ng build) +bun run build (ng build) └── Angular CLI compiles frontend ``` From fa6a33077e0945418a8ccae23dfbee1f0410da60 Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 17:55:55 -0700 Subject: [PATCH 08/18] docs(e2e): fix run commands, drop BrowserStack npm run e2e-dev no longer exists and assumed port 4200. Document make test e2e, E2E_BASE_URL for an already running Stratos, the bun run Playwright scripts and make e2e clean for leftover CF resources. Remove the BrowserStack section: nothing in e2e/ or playwright.config.ts reads the BROWSERSTACK_* variables; the support went with the Protractor suite. --- docs/developer/developers-guide-e2e-tests.md | 57 ++++---------------- 1 file changed, 10 insertions(+), 47 deletions(-) diff --git a/docs/developer/developers-guide-e2e-tests.md b/docs/developer/developers-guide-e2e-tests.md index a0c4414327..78a6439beb 100644 --- a/docs/developer/developers-guide-e2e-tests.md +++ b/docs/developer/developers-guide-e2e-tests.md @@ -110,60 +110,23 @@ Given the output of the script, the following template can be used to update the ``` ### Tidying up test generated CF entities -If tests are stopped before completing or fail to clean old test artifacts will exist in the CF. To clean some of these please see the script -at [deploy/ci/automation/e2e-clean-remnants.sh](https://github.com/cloudfoundry/stratos/blob/main/deploy/ci/automation/e2e-clean-remnants.sh) +If tests are stopped before completing or fail to clean old test artifacts will exist in the CF. Run `make e2e clean` to remove the +CF resources the tests label `stratos-e2e-test` (add `DRYRUN=yes` to see what it would delete). ## Running the tests -To run the tests against an instance of Stratos execute +To run the tests, starting a local Stratos for them on dedicated ports, execute ```bash -npm run e2e +make test e2e ``` -If running Stratos on `https://127.0.0.1:4200` then instead execute +To run them against a Stratos that is already running, set `E2E_BASE_URL`. For the dev frontend started with `make dev frontend`: ```bash -npm run e2e-dev +make test e2e E2E_BASE_URL=https://localhost:5440 ``` Additional test commands: -- `npm run e2e:ui` - Run tests with Playwright UI mode -- `npm run e2e:debug` - Run tests in debug mode -- `npm run e2e:headed` - Run tests in headed mode (see browser) -- `npm run e2e:report` - View test report - - -## Running tests on Browserstack - -You can run the E2E tests on Browserstack instead of with a local browser. - -To do so, configure the following environment variables: - -|Variable|Required|Description| -|---|---|---| -|BROWSERSTACK_USER|Yes|Your Browserstack user ID| -|BROWSERSTACK_KEY|Yes|Your Browserstack key| -|BROWSERSTACK_TARGET|Yes|The Browser (and OS) to use (see below)| -|BROWSERSTACK_PROJECT|No|Project name| -|BROWSERSTACK_BUILD|No|Build name| -|BROWSERSTACK_NAME|No|Name| -|BROWSERSTACK_RESOLUTION|No|Screen resolution to use| - -For more information on project, build and name, see: https://www.browserstack.com/automate/capabilities. - -The `BROWSERSTACK_TARGET` environment variable can be just a Browser name, e.g. `Chrome`, or a name and version (separated by a space), e.g. `Chrome 69`. - -You can also specify which OS to use by separating the OS and browser with a `/`, e.g. `Windows/Chrome`. You can also specify the OS version by separating with a space, e.g. `Windows 10/Chrome`. You can fully described the OS and Browser with `Windows 10/Chrome 69`. - -For more information on supported Operating Systems/devices and browsers, see https://www.browserstack.com/list-of-browsers-and-platforms?product=js_testing and https://playwright.dev/docs/test-runners. - -As an example, to run the E2E tests against a locally run Stratos dev system, use: - -``` -BROWSERSTACK_TARGET="Chrome" npm run e2e-dev -``` - -> Note: This assumes you have set the `BROWSERSTACK_USER` and `BROWSERSTACK_KEY` environment variables already. - -Running the tests in this manner uses the browserstack-local npm package to allow the tests to run against your local system. To ensure that `BrowserStackLocal` processes are not left running if a test run is aborted, all `BrowserStackLocal` processes are terminated when the E2E test process exits. - -> Note: When the E2E tests are run using BrowserStack, the test reporter is modified to include timing information to help correlate tests to the captured video of the test run. +- `bun run e2e:ui` - Run tests with Playwright UI mode +- `bun run e2e:debug` - Run tests in debug mode +- `bun run e2e:headed` - Run tests in headed mode (see browser) +- `bun run e2e:report` - View test report From 20281f5e66e1620732ddffa17a13f3b435749598 Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 17:55:55 -0700 Subject: [PATCH 09/18] docs(deploy): build the CF package from source Deploy from source checked out the stable tag (a 2021 v4 commit) and pushed the source tree, and Pre-building the UI described the custom buildpack that compiled the UI during staging. manifest.yml now pushes dist/cf-package with the binary_buildpack, so a bare cf push from a fresh clone has nothing to push. Check out a release tag, run make build release cf, then cf push. --- docs/deploy/cloud-foundry/cloud-foundry.md | 32 ++++++---------------- 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/docs/deploy/cloud-foundry/cloud-foundry.md b/docs/deploy/cloud-foundry/cloud-foundry.md index 0ae44bc6bc..e92ac2caf2 100644 --- a/docs/deploy/cloud-foundry/cloud-foundry.md +++ b/docs/deploy/cloud-foundry/cloud-foundry.md @@ -130,37 +130,21 @@ Each Stratos [GitHub release](https://github.com/cloudfoundry/stratos/releases) ### Deploy Stratos from source -To do so, `clone` the **stratos** repository, `cd` into the newly cloned repository and `push` to Cloud Foundry. This can be done with: +Build the same `cf push`-ready package a release contains, then push it. You need the tools in +[Required Runtimes](../../developer-environment.md#required-runtimes) installed locally. ``` git clone https://github.com/cloudfoundry/stratos cd stratos -git checkout tags/stable -b stable -./build/store-git-metadata.sh +git checkout # for example v5.5.5; omit to build the current develop branch +make install +make build release cf cf push ``` -If the cf push exceeds the time allowed see the instructions [here](#pre-building-the-ui) - -#### Pre-building the UI - -Due to the memory usage of the Angular compiler (see below), when deployed to Cloud Foundry via `cf push`, Stratos does not use AOT (Ahead-of-Time) compilation. - -If you wish to enable AOT or reduce the push time, you can pre-build the UI before pushing. - -This can be done with: - -``` -git clone https://github.com/cloudfoundry/stratos -cd stratos -npm install -npm run prebuild-ui -cf push -``` - -You will need a recent version of Node installed locally to do this. - -The `prebuild-ui` npm script performs a build of the front-end UI and then zips up the resulting folder into a package named `stratos-frontend-prebuild.zip`. The Stratos buildpack will unpack this zip file and use its contents instead of building the UI during staging, when this file is present. +`make build release cf` builds the UI, cross-compiles the backend for Linux/amd64 and stages both in `dist/cf-package`. The repository's +`manifest.yml` pushes that directory with the `binary_buildpack`, so nothing is built during staging. See +[CF Release Build Process](../../developer-environment.md#cf-release-build-process) for the individual steps. #### Memory Usage From aed4cc73f51c82bdb68acf3a501ff9207f0ea1ed Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 17:56:03 -0700 Subject: [PATCH 10/18] docs(changelog): cover the tooling and doc fixes --- changelog.d/0003-frontend-tests-docs.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/changelog.d/0003-frontend-tests-docs.md b/changelog.d/0003-frontend-tests-docs.md index ff606bc6e6..927ee8e366 100644 --- a/changelog.d/0003-frontend-tests-docs.md +++ b/changelog.d/0003-frontend-tests-docs.md @@ -1,3 +1,13 @@ +[BugFixes] +- `bun run e2e:dev` now targets the dev frontend on port 5440 instead of + 4200, where nothing listens. + [Chores] -- The frontend tests guide now gives the `make` and `bun` commands the - repo uses, and lists the checks a pull request runs. +- The developer, testing, extension and Cloud Foundry deploy guides now + give the `make` and `bun` commands the repo uses today, and the + frontend tests guide lists the checks a pull request runs. +- The Makefile, the tiered E2E runner and the STB workflow run their + tools through `bun` instead of `npx` or `npm`. +- Removed the unused Code Climate configuration and script, and the + BrowserStack instructions, which stopped working with the Protractor + suite. From 720c547b446ae26f202c0ad0228e2fda44155cf1 Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 18:13:21 -0700 Subject: [PATCH 11/18] docs(readme): fix the developer workflow section The README told contributors to run make dev-frontend and make build-frontend (renamed to make dev frontend and make build frontend), make bootstrap and bun run bootstrap (no such target; the script only prints that bootstrap is no longer needed), bun test (Bun's own runner, not Vitest) and bin/package (removed). Replace the setup, command and packaging sections with the current make targets and link the contributor guide for backend configuration. Also remove the link to a CLAUDE.md that is not in the repository, fix the theming link (the extensions/theming page no longer exists), and drop the "Tested with Browserstack" acknowledgement and its logo: BrowserStack testing ended with the Protractor suite. --- README.md | 132 +++++++----------------------- docs/images/Browserstack-logo.svg | 90 -------------------- 2 files changed, 29 insertions(+), 193 deletions(-) delete mode 100644 docs/images/Browserstack-logo.svg diff --git a/README.md b/README.md index 240094460a..71d07584f5 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ Please visit our new [documentation site](https://stratos.app/). There you can d 1. [Docker](https://stratos.app/docs/deploy/all-in-one), as a single container deploying all components. 1. Configuring advanced features such as [Single Sign On](https://stratos.app/docs/advanced/sso) and Cloud Foundry '[invite to org](https://stratos.app/docs/advanced/invite-user-guide)'. 1. Guides for [developers](https://stratos.app/docs/developer/introduction). -1. How to [extend](https://stratos.app/docs/extensions/introduction) Stratos [functionality](https://stratos.app/docs/extensions/frontend) and apply a custom [theme](https://stratos.app/docs/extensions/theming). +1. How to [extend](https://stratos.app/docs/extensions/introduction) Stratos [functionality](https://stratos.app/docs/extensions/frontend) and apply a custom [theme](https://stratos.app/docs/theming-architecture). ## Developer Workflow @@ -50,87 +50,41 @@ These are taken from `engines` in `package.json` and the `go` directive in ### First-Time Setup -On a fresh checkout, run the bootstrap script **once** to initialize the development environment: - ```bash git clone https://github.com/cloudfoundry/stratos.git cd stratos - -# One-time bootstrap (builds required infrastructure) -./bootstrap -# OR -make bootstrap -# OR -bun run bootstrap - -# Install dependencies -bun install - -# Start development server -make dev-frontend +make install # bun install; its postinstall step builds the devkit ``` -**What bootstrap does:** - -1. Verifies prerequisites (Node.js, Bun, Go) -2. Builds the devkit package (required by Angular CLI) -3. Generates extension module imports -4. Creates development proxy configuration -5. Stamps `build-info.ts` so vitest can run without a full build -6. Cleans up workspace +The backend needs `src/jetstream/config.properties` with an encryption key and +a login method before its first start. The +[contributor guide](docs/contributing_guide.md#first-time-setup) has the exact +steps, including a local `admin` user and the dev TLS certificate. -**Troubleshooting:** - -- If `bun install` fails with missing files: Run `make bootstrap` first -- If builds fail with "File not found" errors: Run `make bootstrap` -- Bootstrap only needs to run once per checkout +On a fresh worktree, `./bootstrap` also stamps `build-info.ts` so the unit +tests can run before the first build. ### Development Commands -```bash -# Frontend development server (https://127.0.0.1:5440) -make dev-frontend -# OR -bun run start - -# Build for production -make build # Both frontend and backend -make build-frontend # Frontend only -make build-backend # Backend only - -# Testing -bun test # All frontend tests -bun run test-frontend:core -bun run test-frontend:cloud-foundry -bun run test-backend # Backend tests -bun run e2e # End-to-end tests - -# Linting -bun run lint -``` - -### Full Stack Development - -Run these in separate terminals: +Run every command from the repository root. `make help` lists them all. ```bash -# Terminal 1: Frontend (port 5440) -make dev-frontend - -# Terminal 2: Backend API (port 5443) -make dev-backend - -# Access at: https://127.0.0.1:5440 +# Development servers, in separate terminals +make dev backend # https://localhost:5443 +make dev frontend # https://localhost:5440 + +# Build +make build # Frontend and every backend platform +make build frontend # Frontend only +make build backend PLATFORM=linux/amd64 # One backend platform + +# Tests and checks +make test frontend # Unit tests (Vitest) +make test backend # Go tests +make test e2e # End-to-end tests (Playwright) +make check gate # Lint and unit tests, as CI runs them ``` -For more detailed information, see [CLAUDE.md](CLAUDE.md). - -## Acknowledgements - -Tested with Browserstack - -Browserstack - ## Stratos UI pre-packager This feature helps in pre-building the @@ -172,44 +126,16 @@ Note: `sgs` creates security groups the first time, upgrades do not use `sgs`. ## Packaging -Requires `node`, `go`, and `zip`. - -Build and package for all targets (linux/amd64, linux/arm64): +Build the release packages with: ```bash -bin/package +make build release # CF zip and GitHub release archives, with SHA256SUMS +make build release cf # Only the cf push-ready zip (linux/amd64) ``` -To skip the build step and package from existing artifacts: - -```bash -bin/package --skip-build -``` - -To override the version (default: from `package.json`): - -```bash -VERSION="4.8.1" bin/package -``` - -This produces per-target zips in `dist/`: - -```text -dist/stratos-cf---.zip -``` - -Deploy with: - -```bash -cf push -f dist/cf-package--/manifest.yml \ - -p dist/stratos-cf---.zip -``` - -### NOTE - -The original packaging code was based on work from the -[Orange Cloud Foundry Github Repository](https://github.com/orange-cloudfoundry/stratos-ui-cf-packager/). -Many thanks to Benjamin & Arthur, we appreciate you both! +`VERSION=` overrides the version taken from `package.json`. The CF zip +is written to `dist/stratos-cf-.zip`; see +[CF Release Build Process](docs/developer-environment.md#cf-release-build-process). ## License diff --git a/docs/images/Browserstack-logo.svg b/docs/images/Browserstack-logo.svg deleted file mode 100644 index 195f64d2fe..0000000000 --- a/docs/images/Browserstack-logo.svg +++ /dev/null @@ -1,90 +0,0 @@ - - - - -Browserstack-logo-white - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 490e06bfedec129c1b5b1f90b1ea7a77c1cf43a3 Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 18:13:21 -0700 Subject: [PATCH 12/18] chore(deps): drop the unused browserstack-local Nothing in e2e/, playwright.config.ts or scripts/ loads it; it served the Protractor suite. Removing it drops browserstack-local and its exclusive dependencies (agent-base@6, https-proxy-agent@5, is-running, tree-kill) from bun.lock and nothing else. --- bun.lock | 13 +------------ package.json | 1 - 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/bun.lock b/bun.lock index 4ca1661128..4daf4742f9 100644 --- a/bun.lock +++ b/bun.lock @@ -78,7 +78,6 @@ "adm-zip": "0.6.1", "angular-eslint": "22.5.0", "baseline-browser-mapping": "^2.11.27", - "browserstack-local": "1.5.15", "copy-webpack-plugin": "14.0.0", "eslint": "^10.11.0", "fs-extra": "11.4.1", @@ -1071,7 +1070,7 @@ "adm-zip": ["adm-zip@0.6.1", "", {}, "sha512-Xwrja8nx9e5o2N1my4DsKCeKpdrnACyr1wtbPxBDgGzKzKyE9kRtBFA8mWldI+RVlD7CBZNWY/wQ2+ydwOR6kQ=="], - "agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + "agent-base": ["agent-base@9.0.0", "", {}, "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA=="], "ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="], @@ -1157,8 +1156,6 @@ "browserslist": ["browserslist@4.28.9", "", { "dependencies": { "baseline-browser-mapping": "^2.11.20", "caniuse-lite": "^1.0.30001810", "electron-to-chromium": "^1.5.420", "node-releases": "^2.0.54", "update-browserslist-db": "^1.3.2" }, "bin": { "browserslist": "cli.js" } }, "sha512-EWazOblFYUvlGZcfGhPUPmYh3nikUxBVb+y9MJun5f3hBi812X+8MSQTujLBtgK3cf51fJWbWfOjyeO954d+Eg=="], - "browserstack-local": ["browserstack-local@1.5.15", "", { "dependencies": { "agent-base": "^6.0.2", "https-proxy-agent": "^5.0.1", "is-running": "^2.1.0", "tree-kill": "^1.2.2" } }, "sha512-eiDZ5ZRHV5MiUIFlyK5H7MB0U7xHKDMQx0fPeV8KkobAUXe65mXugaRpd49dkuFhKT7TF84ZACNWE+dVra12iQ=="], - "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], @@ -1639,8 +1636,6 @@ "is-regexp": ["is-regexp@1.0.0", "", {}, "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA=="], - "is-running": ["is-running@2.1.0", "", {}, "sha512-mjJd3PujZMl7j+D395WTIO5tU5RIDBfVSRtRR4VOJou3H66E38UjbjvDGh3slJzPuolsb+yQFqwHNNdyp5jg3w=="], - "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], "is-typedarray": ["is-typedarray@1.0.0", "", {}, "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="], @@ -2247,8 +2242,6 @@ "tree-dump": ["tree-dump@1.1.0", "", { "peerDependencies": { "tslib": "2" } }, "sha512-rMuvhU4MCDbcbnleZTFezWsaZXRFemSqAM+7jPnzUl1fo9w3YEKOxAeui0fz3OI4EU4hf23iyA7uQRVko+UaBA=="], - "tree-kill": ["tree-kill@1.2.2", "", { "bin": "cli.js" }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="], - "ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="], "ts-graphviz": ["ts-graphviz@2.1.6", "", { "dependencies": { "@ts-graphviz/adapter": "^2.0.6", "@ts-graphviz/ast": "^2.0.7", "@ts-graphviz/common": "^2.1.5", "@ts-graphviz/core": "^2.0.7" } }, "sha512-XyLVuhBVvdJTJr2FJJV2L1pc4MwSjMhcunRVgDE9k4wbb2ee7ORYnPewxMWUav12vxyfUM686MSGsqnVRIInuw=="], @@ -2637,8 +2630,6 @@ "browserslist/baseline-browser-mapping": ["baseline-browser-mapping@2.11.21", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-uh8vpY/1/YyFkunIDFH/12p7/7VdPKA1hejMVEbdkEaWnUz0Hesvx5EbiU6XxjyHZIOju+ZMbQJkRh+es3/spQ=="], - "browserstack-local/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], - "buffer-image-size/@types/node": ["@types/node@24.2.1", "", { "dependencies": { "undici-types": "~7.10.0" } }, "sha512-DRh5K+ka5eJic8CjH7td8QpYEV6Zo10gfRkjHCO3weqZHWDtAaSTFtl4+VMqOJ4N5jcuhZ9/l+yy8rVgw7BQeQ=="], "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], @@ -2703,8 +2694,6 @@ "htmlparser2/entities": ["entities@8.0.0", "", {}, "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA=="], - "https-proxy-agent/agent-base": ["agent-base@9.0.0", "", {}, "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA=="], - "is-core-module/hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], "istanbul-lib-instrument/@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" } }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="], diff --git a/package.json b/package.json index 1339861842..f17b2b98fe 100644 --- a/package.json +++ b/package.json @@ -196,7 +196,6 @@ "adm-zip": "0.6.1", "angular-eslint": "22.5.0", "baseline-browser-mapping": "^2.11.27", - "browserstack-local": "1.5.15", "copy-webpack-plugin": "14.0.0", "eslint": "^10.11.0", "fs-extra": "11.4.1", From da4e571212380c123ccf73fb80a91775ee585dfd Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 18:13:21 -0700 Subject: [PATCH 13/18] chore: run the bootstrap helpers with bun bootstrap ran extension-generator.mjs and dev-setup.cjs with node; the postinstall step already runs both with bun. The devkit steps keep npm, because the devkit has its own package-lock.json. --- bootstrap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap b/bootstrap index 9d4fba245c..6a8915baef 100755 --- a/bootstrap +++ b/bootstrap @@ -91,7 +91,7 @@ if [ ! -f "build/extension-generator.mjs" ]; then exit 1 fi -node build/extension-generator.mjs +bun build/extension-generator.mjs if [ -f "src/frontend/packages/core/src/_custom-import.module.ts" ]; then print_success "Extension module generated" @@ -107,7 +107,7 @@ if [ ! -f "build/dev-setup.cjs" ]; then exit 1 fi -node build/dev-setup.cjs +bun build/dev-setup.cjs if [ -f "proxy.conf.js" ]; then print_success "Development configuration created" From e06c338ad196d3c063c4ecafe03cbc15dc7828dc Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 18:15:52 -0700 Subject: [PATCH 14/18] docs(extensions): correct how packages are removed The guide said frontend packages declare their backend plugins in package.json (none do; src/jetstream/plugin-config.yaml is the list), that removing a package drops its plugins, that prepare-backend and npm install in the buildpack handle it, and that STRATOS_BUILD_REMOVE works from manifest.yml. A release push uses binary_buildpack and builds nothing during staging. Describe the stratos.yaml packages.exclude list, STRATOS_YAML, STRATOS_BUILD_REMOVE at build time and plugin-config.yaml for backend plugins. Checked with the extension generator: both stratos.yaml and STRATOS_BUILD_REMOVE drop @stratosui/kubernetes from the generated _custom-import.module.ts. --- docs/extensions/disable-packages.md | 52 ++++++++++++++--------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/extensions/disable-packages.md b/docs/extensions/disable-packages.md index 9d494eb524..7fe423e631 100644 --- a/docs/extensions/disable-packages.md +++ b/docs/extensions/disable-packages.md @@ -4,24 +4,18 @@ title: Remove Stratos Packages sidebar_label: Remove Packages --- -Frontend packages and their associated backend plugins can be removed at build time via configuration. +Frontend packages and backend plugins can be removed at build time. They are configured separately: removing a frontend package does +not remove the backend plugins it uses. -## Frontend Package to Backend Plugin Dependencies +All of the methods below act when Stratos is built. A Cloud Foundry push of a release package (`binary_buildpack`) builds nothing +during staging, so set them before running `make build release cf`, not in `manifest.yml`. -Stratos NPM packages define a list of backend plugins that they require in order to function. These are found in the package's `package.json` in -the `stratos` section `backend` property. For instance the [Stratos Cloud Foundry](https://github.com/cloudfoundry/stratos/blob/main/src/frontend/packages/cloud-foundry/package.json) - package depends on multiple backend plugins. +## Remove frontend packages -If a backend package is not referenced by a package that is built and is not in the 'default' plugins [list](https://github.com/cloudfoundry/stratos/blob/main/src/jetstream/default_plugins.go) - then it will not be included in the backend build. Therefore omitting a frontend package will also most likely remove it's dependent plugins. +### Via stratos.yaml -> [!IMPORTANT] -> To ensure backend plugins are excluded correctly the npm target `prepare-backend` should run before building the backend the usual way with -> `build-backend`. If pushing Stratos to Cloud Foundry this step will be completed automatically after `npm install` runs within the buildpack. - -## Remove via stratos.yaml -Frontend packages can be removed from the build by adding them to the `excludes` section of `./stratos.yaml`. For example, to exclude -kubernetes and associated features add the kubernetes package to the excludes section before Stratos builds. +Frontend packages can be removed from the build by listing them under `packages.exclude` in `./stratos.yaml` at the repository root. +For example, to exclude Kubernetes and its features: ``` packages: @@ -29,18 +23,24 @@ packages: - '@stratosui/kubernetes' ``` -## Remove via environment variable -Similarly to adding to the exclude section in stratos.yaml, added a frontend package to the `STRATOS_BUILD_REMOVE` environment variable will - achieve the same outcome but easier to use when pushing Stratos to Cloud Foundry. For instance updating the env section of your `manifest.yml` - file as follows will exclude kubernetes and associated features from the build. +To keep the file elsewhere, point `STRATOS_YAML` at it. + +### Via environment variable + +Listing a frontend package in the `STRATOS_BUILD_REMOVE` environment variable has the same effect. Separate several packages with +commas. For example: ``` -applications: - - name: console - - env: - STRATOS_BUILD_REMOVE: "@stratosui/kubernetes" +STRATOS_BUILD_REMOVE=@stratosui/kubernetes make build release cf ``` -## Remove by deletion -Functionality can be removed by simply deleting the package from the folder structure. This should have the same effect as both methods above, - including automatically excluding any unreferences backend plugins. + +### By deletion + +Deleting a package from `src/frontend/packages` also removes it from the build. + +## Remove backend plugins + +The backend plugins compiled into Jetstream are listed in [`src/jetstream/plugin-config.yaml`](https://github.com/cloudfoundry/stratos/blob/develop/src/jetstream/plugin-config.yaml). +The plugins in the default [list](https://github.com/cloudfoundry/stratos/blob/develop/src/jetstream/default_plugins.go) are always +included. To remove a plugin, delete its entry from `plugin-config.yaml` before building the backend; `make build backend` regenerates +`extra_plugins.go` from that file. See [Plugin Architecture](../plugin-architecture.md) for details. From 5f2f4061d6b06a35a2da857ff4a15d43088b487e Mon Sep 17 00:00:00 2001 From: Norman Abramovitz Date: Wed, 7 Oct 2026 18:16:52 -0700 Subject: [PATCH 15/18] docs: describe the post-NgRx list architecture pagination-architecture.md still described NgRx selectors, reducers, LocalListController and the global page-size session, all removed with NgRx. Rewrite it from the current code: client-side page draining (drainCfPages and CnsiEntitySource), per-endpoint sources, the EndpointDataService registry and its caching and staleness rules, MergeOrchestrator, ViewPipeline paging/sorting/filtering, list state, signal-list rendering and the app wall's stats polling. --- docs/pagination-architecture.md | 845 ++++++++++++++------------------ 1 file changed, 370 insertions(+), 475 deletions(-) diff --git a/docs/pagination-architecture.md b/docs/pagination-architecture.md index 5e282fdbd2..668b6d4c27 100644 --- a/docs/pagination-architecture.md +++ b/docs/pagination-architecture.md @@ -1,484 +1,379 @@ # Pagination Architecture -Developer guide to the Stratos list pagination system. This covers the data flow from store to UI, the view toggle mechanism, the "All" page size handling, and common pitfalls. - -## Component Overview - -``` -ListComponent (list.component.ts) - ├── view$ ─── controls card/table toggle - ├── paginatorSettings ─── plain object bridging store → paginator - ├── PageSizeSessionService ─── in-memory per-view page size memory - │ - ├── AppPaginatorComponent (app-paginator.component.ts) - │ ├── pageSize @Input ─── setter resolves PAGE_SIZE_ALL - │ ├── selectValue getter ─── drives ` uses `[selected]` per-option rather than `[value]` on the select element: - -```html -