feat: build, publish, and deploy the compute workloads plugin bundle - #215
Merged
Merged
Conversation
Nothing built, published, or hosted ui/consumer/workloads's static assets anywhere — service-catalog's fan-out needs a real HTTPS assets.baseURL to create a ConsumerPortalPlugin, and there wasn't one. - New Dockerfile: bun build stage -> nginx-unprivileged serving dist/. Verified locally (docker build + run, plugin-manifest.json and remoteEntry.js both serve 200) including under the hardened securityContext the Deployment uses (read-only rootfs, non-root, dropped capabilities, emptyDir mounts for nginx's writable dirs). - New ui/consumer/workloads/config/: Deployment+Service+HTTPRoute, published as its own kustomize bundle (mirrors datum-storybook's pattern — the platform's dominant convention for "app repo publishes its own deployable static frontend bundle" — not echo's inline-in-infra pattern). HTTPRoute attaches to the shared external-gateway per environment, same as cloud-portal/datum-storybook; no dedicated Gateway. - .github/workflows/publish.yaml: two new jobs (image + kustomize bundle) using the same reusable workflows compute's apiserver already calls — publish-docker.yaml already supports context/dockerfile-path inputs. - service-configuration.yaml: sets spec.userInterface.consumer.assets.baseURL to the new staging-only hostname, entitlement None for now. Flagged inline: this component applies identically to every environment's milo control plane today (no per-env patch exists), so this also lands in production's control plane — low-risk short-term since production's cloud-portal has no platform registry source wired up yet, but real per-environment parametrization is still owed. Companion infra PR wires the environment-side (Gateway listener, Kustomization, staging-only for the same reason the credential rollout was staging-only).
Matches the established split (see cloud-portal's config/base, which has no namespace.yaml either): the app repo's bundle only carries workload resources; the namespace itself is infra's responsibility (apps/compute-workloads-plugin/base/namespace.yaml, companion infra PR).
scotwells
requested changes
Aug 10, 2026
Per review on #215: - No reason to expose this plugin publicly — the browser never talks to a plugin origin directly (cloud-portal's server fetches the manifest/ assets and proxies them via /api/plugins/<slug>/...). Drops the HTTPRoute entirely; the Deployment now terminates TLS itself via a cert-manager CSI server cert (key-usages: server auth, datum-control-plane ClusterIssuer) — the same pattern milo's own apiserver, ClickHouse, and the OTel collector already use for internal-only TLS. Verified locally: docker build/run with a temporary self-signed cert mounted the same way the CSI volume will be, curl -k and openssl s_client both confirm the server block and cert subject are correct. - Move config/components/consumer-ui-plugin (was ui/consumer/workloads/config) so it lives alongside compute's other kustomize components (matches config/components/service-catalog's kind: Component convention) and gets folded into compute-manager's own Deployment set via its existing components: list (companion infra change) — same cluster, same compute-system namespace, no new Flux Kustomization or OCIRepository. - Bump the reusable workflow pin to v1.20.0 per review (matches cloud-portal's own pin). Drop the separate kustomize-bundle publish job entirely: once the Deployment is folded into compute-manager, a separate bundle publish never actually gets read by anything, so it can't pin an image tag that matters. Accept a floating :latest tag with imagePullPolicy: Always instead — this is a static asset server, not a GitOps-tracked control-plane binary. - service-configuration.yaml: assets.baseURL is now the internal Service DNS name (compute-workloads-plugin.compute-system.svc.cluster.local), not a public hostname. Cluster-local DNS resolves correctly in whatever environment compute-manager deploys to, so (unlike the previous public-hostname draft) this needs no per-environment override. Sets assets.caBundle to datum-control-plane-ca's public cert (fetched from the live datum-control-plane-trust-bundle ConfigMap, non-sensitive) so cloud-portal trusts the CSI-issued cert without disabling verification. Verified: kustomize build config/components/consumer-ui-plugin standalone, and the full compute-manager composition (base/manager + all its components including this new one) — both images present with no cross-contamination, no build errors.
scotwells
reviewed
Aug 10, 2026
- Rename compute-workloads-plugin -> compute-consumer-ui-plugin throughout (Deployment/Service/labels/image/CSI dns-names/baseURL). "Workloads" is one page within compute's consumer plugin, not the plugin's identity — and this leaves room for a symmetric compute-provider-ui-plugin later. - Replace nginx with Bun's own static file server (serve.ts): drops an entire second runtime/technology for what's a few lines of fetch handling, and this project is already Bun-based end to end. Verified locally the same way as before — docker build/run with a temporary self-signed cert, curl -k for real assets (200), unknown paths (404), and a path-traversal attempt (404, confirms the path normalization actually blocks it). - Drop assets.caBundle entirely. Checked plugin-fetch.ts: withCaBundle() is a no-op when caBundle is unset, falling through to Bun's default TLS trust — and cloud-portal's own Deployment already sets NODE_EXTRA_CA_CERTS platform-wide (both staging and production) pointing at the same datum-control-plane-trust-bundle the plugin's CSI cert chains to. The explicit caBundle was redundant with trust cloud-portal already has. - CI pin: plain `@v1.20.0` instead of the SHA-pinned form.
scotwells
approved these changes
Aug 10, 2026
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Targets #198 (plugin source, still draft), not main —
ui/consumer/workloadslives only there.No build, publish, or hosting existed for the plugin's static assets. service-catalog's fan-out needs a real HTTPS
assets.baseURLto create aConsumerPortalPlugin. This adds it.Revised per review:
key-usages: server auth,datum-control-planeClusterIssuer) — same pattern milo's own apiserver, ClickHouse, and the OTel collector use for internal TLS.assets.baseURLis the internal Service DNS name;assets.caBundlecarries the CA so cloud-portal trusts it without disabling verification.config/components/consumer-ui-plugin(kind: Component), folded intocompute-manager's existingcomponents:list (companion infra PR) — same namespace, same cluster, no new Flux resources.compute-workloads-pluginimage stays a floating:latestwithimagePullPolicy: Always— a separate bundle to pin its tag would never actually get read once the Deployment moved intocompute-manager's own bundle.v1.20.0.Test plan
docker build/runlocally with a temporary self-signed cert mounted the same way the CSI volume will be —curl -kandopenssl s_clientboth confirm the TLS server block and cert subjectkustomize build config/components/consumer-ui-pluginrenders cleanly standalonecompute-managercomposition (base/manager+ all its components including this one) renders cleanly, both images present, no cross-contaminationkubectl get consumerportalpluginsshows acomputeentry, cloud-portal logs showlisted 1 ConsumerPortalPlugin(s)