diff --git a/docs/platform-engineer-guide/backstage-plugins/custom-portal.mdx b/docs/platform-engineer-guide/backstage-plugins/custom-portal.mdx new file mode 100644 index 00000000..a5915095 --- /dev/null +++ b/docs/platform-engineer-guide/backstage-plugins/custom-portal.mdx @@ -0,0 +1,170 @@ +--- +title: Building a custom portal +description: Scaffold your own copy of the OpenChoreo portal with create-portal, add plugins and re-brand it, deploy it in place of the stock image, and merge in each new release. +sidebar_position: 4 +--- + +# Building a custom portal + +There are three ways to run a Backstage portal for OpenChoreo: + +| Path | Choose it when | +| ----------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| **The stock portal** | The portal the control-plane Helm chart deploys is enough, and you only need [configuration](../backstage-configuration.mdx). | +| **A custom portal** (this page) | You want the full OpenChoreo portal, plus your own plugins, pages or branding, as a repository you own and build. | +| **[Plugins in your own Backstage](./installing-into-existing-backstage.mdx)** | You already run a Backstage app and want to add OpenChoreo to it. | + +A custom portal starts as a copy of the stock portal, generated by `@openchoreo/create-portal`. It is a thin Backstage app: the portal itself comes from the published `@openchoreo/backstage-portal-app` and `@openchoreo/backstage-portal-backend` packages, so the repository holds only configuration and whatever you add. You do not fork `openchoreo/backstage-plugins`. + +:::info Available from 1.4.0 + +`@openchoreo/create-portal` and `@openchoreo/backstage-portal-app` are first published with `1.4.0`. Earlier releases have no custom-portal path; fork the upstream repository instead. + +::: + +## Prerequisites + +- Node.js 20 or 22, and Yarn through `corepack enable`. The generated repository pins its own Yarn release. +- `git`, so the CLI can create the initial commit that upgrades build on. +- An OpenChoreo control plane on the same release, for the portal to connect to. +- Docker and access to a container registry, to build and ship the image. + +## Create the portal + +```bash +npx @openchoreo/create-portal +``` + +`npm init @openchoreo/portal` runs the same CLI. It asks for a name, then: + +1. Writes the template into `./`, with every `@openchoreo/*` package pinned to the CLI's own release. +2. Creates `app-config.local.yaml` from the bundled example. +3. Commits the untouched template. +4. Runs `yarn install` and `yarn tsc`. + +The template ships inside the CLI package, so creating a portal needs only the npm registry. + +| Flag | Meaning | +| ----------------------- | --------------------------------------------------------------------------------------------------------------- | +| `--name ` | Portal name (lowercase letters, digits, dashes). Skips the prompt. | +| `--path ` | Write into this directory instead of `./`. | +| `--registry ` | Registry to install `@openchoreo/*` from. Defaults to the registry npm uses for `@openchoreo`, otherwise npmjs. | +| `--skip-install` | Skip `yarn install` and `yarn tsc`. | +| `--template-path ` | Use a template directory instead of the bundled one. | + +To pin a specific release, run that version of the CLI: `npx @openchoreo/create-portal@1.4.0`. + +### Using a registry mirror + +Without `--registry`, the CLI uses the registry npm resolves `@openchoreo/*` from: `@openchoreo:registry` in your `.npmrc`, otherwise npm's `registry`. A mirror configured once in `.npmrc` therefore carries over without a flag, and so does `npm init @openchoreo/portal --registry `. + +The registry is written to the portal's `.yarnrc.yml`. If it needs authentication, add an `npmAuthToken` for the `openchoreo` scope to your user-level `~/.yarnrc.yml` rather than committing it. A plain `http://` registry is added to `unsafeHttpWhitelist` automatically, because Yarn otherwise refuses it. + +## What you get + +```text +my-portal/ +├── packages/app/ # the frontend: feature discovery installs the portal +├── packages/backend/ # the backend: portalBackendFeatures plus your plugins +│ └── Dockerfile # the same image build as the stock portal +├── plugins/ # your own plugins (`yarn new`) +├── app-config*.yaml # the stock portal's configuration, now yours +├── templates/, examples/ # the OpenChoreo scaffolder templates +└── .openchoreo-portal.json # the release this repository started from +``` + +The frontend is `createApp()` with no feature list. `app.packages: all` in both app-configs turns on Backstage [feature discovery](./feature-discovery.mdx), which installs the portal from the `@openchoreo/backstage-portal-app` dependency. A `discovery.test.ts` fails if that ever stops happening, which would otherwise show up only as an empty page. + +The backend adds `portalBackendFeatures`, the stock portal's complete backend. + +The Portal Assistant is not included. It ships only in the stock portal image. + +## Run it locally + +```bash +cd my-portal +yarn start # frontend on :3000, backend on :7007 +``` + +Local settings live in `app-config.local.yaml`, which git ignores. The defaults target a local k3d install on `*.openchoreo.localhost:8080`. For any other control plane, point `openchoreo.baseUrl`, `thunder.baseUrl` and the `auth.providers.openchoreo-auth` URLs at it. + +The sign-in client must accept the local redirect URL `http://localhost:7007/api/auth/openchoreo-auth/handler/frame`. See [Authentication](../backstage-configuration.mdx#authentication). + +## Add plugins + +Optional OpenChoreo plugins, community plugins and your own plugins all install the same way: as dependencies of the portal. + +- **Frontend.** `yarn workspace app add ` is the whole installation. Discovery picks up any dependency that default-exports a frontend feature from its root or `./alpha` entry point. A plugin with only named exports goes into `createApp({ features: [...] })` in `packages/app/src/App.tsx`. +- **Backend.** `yarn workspace backend add `, then add `backend.add(import(''))` to `packages/backend/src/index.ts`. +- **Your own.** `yarn new` scaffolds a plugin into `plugins/`. + +## Customize + +Everything the portal contributes is a Backstage New Frontend System extension, so most changes are configuration: + +```yaml title="app-config.yaml" +app: + extensions: + # Hide a tab or page you don't use + - entity-content:openchoreo-observability/wirelogs: false + # Move a tab into another group + - entity-content:openchoreo-ci/workflows: + config: + group: development +``` + +To replace a piece outright, contribute an extension with the same ID from a feature you pass to `createApp({ features })`. Features listed there install after discovered ones, so yours win. See [Feature discovery](./feature-discovery.mdx#turning-extensions-off) for switching extensions off. + +Logo, product name and brand color are runtime configuration under `app.branding`; see [Theming and branding](./theming.mdx). Favicons and the web manifest live in `packages/app/public/`. + +Optional capabilities are switched with `openchoreo.features.*.enabled`. Keep them matching what your control plane actually runs; the Helm chart sets them for you in production. + +## Build and deploy + +The template ships a `yarn.lock` seeded with the dependency set the release was tested with. The first `yarn install` trims it to what your portal uses; commit the result. Then build the image: + +```bash +docker build . -f packages/backend/Dockerfile \ + -t registry.example.com/acme/portal:0.1.0 +docker push registry.example.com/acme/portal:0.1.0 +``` + +The image replaces the stock `openchoreo-ui` image, and reads the same configuration from the chart. Point the control-plane chart at it: + +```bash +helm upgrade openchoreo-control-plane \ + oci://ghcr.io/openchoreo/helm-charts/openchoreo-control-plane \ + --version \ + --namespace openchoreo-control-plane \ + --reuse-values \ + --set backstage.image.repository=registry.example.com/acme/portal \ + --set backstage.image.tag=0.1.0 +``` + +Use a new tag for every build. With an unchanged tag, nodes that already have the image keep running the old one. + +## Upgrade to a new release + +All `@openchoreo/*` packages version in lockstep, so an upgrade is one version bump in `packages/app/package.json` and `packages/backend/package.json`, plus whatever skeleton changes the release made to configuration, the Dockerfile or the scaffolder templates. + +Each release's template is published as a tag of [`openchoreo/portal-template`](https://github.com/openchoreo/portal-template), so git can merge those changes into your customizations. + +Once, right after creating the portal, record the release you started from as the merge base. This merge changes no files: + +```bash +git remote add portal-template https://github.com/openchoreo/portal-template +git fetch portal-template --tags +git merge -s ours --allow-unrelated-histories v1.4.0 \ + -m "chore: record portal-template v1.4.0 as the upgrade base" +``` + +Use the release in `.openchoreo-portal.json`. Then, for each upgrade: + +```bash +git fetch portal-template --tags +git merge v1.5.0 +``` + +Conflicts appear only where you changed the same lines as the release. For `yarn.lock`, take the release's copy (`git checkout --theirs yarn.lock`) and let `yarn install` add your dependencies back. Then run `yarn install && yarn tsc && yarn test:all`, update `release` in `.openchoreo-portal.json`, and rebuild the image. + +Upgrade the portal together with the control plane, since a portal expects the API of its own release. diff --git a/docs/platform-engineer-guide/backstage-plugins/overview.mdx b/docs/platform-engineer-guide/backstage-plugins/overview.mdx index 3401c7b2..344d39c3 100644 --- a/docs/platform-engineer-guide/backstage-plugins/overview.mdx +++ b/docs/platform-engineer-guide/backstage-plugins/overview.mdx @@ -10,6 +10,8 @@ OpenChoreo ships its own Backstage portal preconfigured for the platform. If you This is an alternative to forking the [`openchoreo/backstage-plugins`](https://github.com/openchoreo/backstage-plugins) repository. You install a small set of npm packages into your own Backstage workspace and wire them up. +If you want the full OpenChoreo portal with your own plugins and branding, rather than OpenChoreo inside an existing app, see [Building a custom portal](./custom-portal.mdx). + ## What you get **Core** (required) — delivered by a single install path: @@ -59,9 +61,10 @@ If you are upgrading from a plugin version `^1.1.x` install, see the [1.1.x to 1 ## Where to start 1. [Installing into an existing Backstage app](./installing-into-existing-backstage.mdx) — the canonical step-by-step. Core first; opt-in tab packs follow. -2. [Catalog sync](./catalog-sync.mdx) — what gets synced and how to tune it. -3. [Entity views](./entity-views.mdx) — the full tab matrix and per-tab package mapping. -4. [Permission policy](./permission-policy.mdx) — composing OpenChoreo authorization with your existing policy. -5. [Troubleshooting](./troubleshooting.mdx) — failure-mode index keyed by exact error message. +2. [Building a custom portal](./custom-portal.mdx) — scaffold your own copy of the OpenChoreo portal instead. +3. [Catalog sync](./catalog-sync.mdx) — what gets synced and how to tune it. +4. [Entity views](./entity-views.mdx) — the full tab matrix and per-tab package mapping. +5. [Permission policy](./permission-policy.mdx) — composing OpenChoreo authorization with your existing policy. +6. [Troubleshooting](./troubleshooting.mdx) — failure-mode index keyed by exact error message. To author your own scaffolder templates that reuse the OpenChoreo scaffolder actions, see [Custom Backstage Scaffolder Templates](../backstage-scaffolder-templates.mdx) under Platform Setup. diff --git a/sidebars.ts b/sidebars.ts index 63478367..75f123cc 100644 --- a/sidebars.ts +++ b/sidebars.ts @@ -123,6 +123,7 @@ const sidebars: SidebarsConfig = { items: [ "platform-engineer-guide/backstage-plugins/migration-1.1-to-1.2", "platform-engineer-guide/backstage-plugins/installing-into-existing-backstage", + "platform-engineer-guide/backstage-plugins/custom-portal", "platform-engineer-guide/backstage-plugins/feature-discovery", "platform-engineer-guide/backstage-plugins/catalog-sync", "platform-engineer-guide/backstage-plugins/entity-views",