Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions .github/workflows/ui-plugins.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: UI Plugins

# Typechecks and unit-tests the portal plugins under ui/. Each is its own npm
# Typechecks and unit-tests the portal plugins under ui/. Each is its own pnpm
# project with its own lockfile, so this runs per plugin. Their images are
# built by publish.yaml, which never ran either check.
#
Expand Down Expand Up @@ -45,19 +45,26 @@ jobs:
- name: Clone the code
uses: actions/checkout@v7

# Installs the version the plugin's packageManager pins. There is no
# package.json at the repository root, so point at the plugin's.
- name: Setup pnpm
uses: pnpm/action-setup@v6
with:
package_json_file: ui/${{ matrix.plugin }}/package.json

- name: Setup Node
uses: actions/setup-node@v7
with:
node-version-file: ui/${{ matrix.plugin }}/.nvmrc
cache: npm
cache-dependency-path: ui/${{ matrix.plugin }}/package-lock.json
cache: pnpm
cache-dependency-path: ui/${{ matrix.plugin }}/pnpm-lock.yaml

- name: Install dependencies
run: npm ci --ignore-scripts --no-audit --no-fund
run: pnpm install --frozen-lockfile --ignore-scripts

- name: Typecheck
run: npm run typecheck
run: pnpm typecheck

- name: Unit tests
if: matrix.test
run: npm test
run: pnpm test
14 changes: 8 additions & 6 deletions ui/consumer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,25 +36,27 @@ RUN --mount=type=bind,target=/src \

FROM node:26.13.0-alpine3.24@sha256:c6ad9e9c1d80f6eb607c26b4b0a132ff7a2344fad1c78ea3baa2a7d4c8de6d94 AS build
WORKDIR /app
COPY ui/consumer/package.json ui/consumer/package-lock.json ./
RUN npm ci --ignore-scripts --no-audit --no-fund
# Node 26 ships no corepack, so install the pnpm that package.json's
# packageManager pins; it stays in this stage only.
COPY ui/consumer/package.json ui/consumer/pnpm-lock.yaml ui/consumer/pnpm-workspace.yaml ./
RUN npm install -g "$(node -p 'require("./package.json").packageManager')" --no-audit --no-fund && \
pnpm install --frozen-lockfile --ignore-scripts
COPY ui/consumer/ .
COPY --from=console-wasm /out/ /console-wasm/
ENV CONSOLE_WASM_DIR=/console-wasm
RUN npm run build
RUN pnpm build

FROM node:26.13.0-alpine3.24@sha256:c6ad9e9c1d80f6eb607c26b4b0a132ff7a2344fad1c78ea3baa2a7d4c8de6d94
# Node keeps its own copy of the CA roots apart from Alpine's bundle. Fail the
# build if either still trusts the compromised eMudhra root (emSign ECC Root
# CA - G3), which Bun's built-in roots kept until 1.4.4 with no way to drop it.
# CA - G3).
RUN apk add --no-cache --upgrade 'ca-certificates>=20261020-r0'
RUN ! grep -q MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG /etc/ssl/certs/ca-certificates.crt
RUN node -e 'const { rootCertificates } = require("node:tls"); const { X509Certificate } = require("node:crypto"); const compromised = rootCertificates.some((pem) => new X509Certificate(pem).subject.split("\n").includes("CN=emSign ECC Root CA - G3")); if (compromised) { console.error("refusing to build: Node trusts emSign ECC Root CA - G3"); process.exit(1); }'
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY ui/consumer/serve.ts ./
# uid/gid 1000, as the Bun image's bun user was and the Deployment's
# securityContext expects.
# uid/gid 1000, as the Deployment's securityContext expects.
USER 1000:1000
EXPOSE 8443
CMD ["node", "serve.ts"]
14 changes: 7 additions & 7 deletions ui/consumer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,12 @@ warns and the Shell tab stays hidden. Install and run it in isolation:

```bash
cd ui/consumer
npm install
npm run dev # Vite dev server (:7778, HMR) — standalone/direct
npm run preview # built dist/ served (:7778) — proxy-safe
npm run build # static dist/ (remoteEntry.js + plugin-manifest.json + chunks)
npm run typecheck # tsc --noEmit
npm test # vitest unit tests
pnpm install
pnpm dev # Vite dev server (:7778, HMR) — standalone/direct
pnpm preview # built dist/ served (:7778) — proxy-safe
pnpm build # static dist/ (remoteEntry.js + plugin-manifest.json + chunks)
pnpm typecheck # tsc --noEmit
pnpm test # vitest unit tests
```

### Serve `dev` or `preview`? (it matters for the portal proxy)
Expand Down Expand Up @@ -209,7 +209,7 @@ listed in this plugin's `shared` config resolve to the host's copy, and any
other datum-ui subpath the plugin imports is bundled into the remote.

Keep the plugin's versions of these packages at the host's resolved versions
(cloud-portal's `package-lock.json`), not npm's latest: the host's copy is
(cloud-portal's lockfile), not the registry's latest: the host's copy is
what runs, so a newer local version only lets the plugin type-check against
APIs the host doesn't have.

Expand Down
Loading
Loading