Skip to content

Commit 6003308

Browse files
committed
List supported frameworks in CLI scaffold flow
1 parent 637914f commit 6003308

28 files changed

Lines changed: 1003 additions & 324 deletions
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@zitadel/cli": patch
3+
"@zitadel/sdk-nuxt": patch
4+
---
5+
6+
Allow fresh app scaffolding after `zitadel start` creates local runtime ignore files, and load Nuxt runtime config through the Nuxt virtual imports module.

.github/instructions/consumer-journey.instructions.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ gate, not as a demo-app e2e suite.
1010
- CI must consume the current workflow's GoReleaser image and npm package
1111
tarballs. Do not replace this with public npm packages for Zitadel packages.
1212
- The journey must exercise the customer local runtime flow through `npx`:
13-
`doctor`, `start`, then `setup --framework next --server local` with
13+
`doctor`, `start`, then
14+
`setup --framework <next|nuxt|react|vue|angular> --server local` with
1415
`--non-interactive --json`.
1516
- Produce package artifacts with `corepack pnpm --dir <package> pack` and keep
1617
tarball verification for required package presence plus unresolved
@@ -19,14 +20,14 @@ gate, not as a demo-app e2e suite.
1920
design tokens must not be uploaded or published to Verdaccio.
2021
- Keep Verdaccio proxying npmjs for third-party dependencies while publishing
2122
Zitadel tarballs under both `alpha` and `latest`.
22-
- Keep generated Next.js apps outside the repo and use `npm` inside the
23-
generated app to match the documented consumer path.
23+
- Keep generated apps outside the repo and use `npm` inside the generated app to
24+
match the documented consumer path.
2425
- Preserve the CLI setup JSON contract: `--non-interactive --json` must parse
2526
from stdout and return `status: "ok"`.
2627
- Browser tests should run serially with one worker, use `localhost` for
2728
WebAuthn, and require passkey coverage in CI. `JOURNEY_ENABLE_PASSKEY=0` is
2829
only a local debugging escape hatch.
2930
- Failure artifacts should include Playwright output/report, doctor/start/setup
3031
JSON and stderr, local runtime metadata/logs, metadata, generated app package
31-
manifests, Verdaccio logs, and Next logs. Do not upload generated
32+
manifests, Verdaccio logs, and generated app logs. Do not upload generated
3233
`node_modules` or `.next`.

.github/workflows/ci.yml

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -548,9 +548,14 @@ jobs:
548548
retention-days: 7
549549

550550
consumer-journey-e2e:
551+
name: consumer-journey-e2e (${{ matrix.framework }})
551552
runs-on: depot-ubuntu-24.04-4
552553
timeout-minutes: 35
553554
needs: [goreleaser-snapshot, npm-pack-smoke]
555+
strategy:
556+
fail-fast: false
557+
matrix:
558+
framework: [next, nuxt, react, vue, angular]
554559
steps:
555560
- uses: actions/checkout@v6
556561

@@ -667,38 +672,52 @@ jobs:
667672
docker image inspect -f '{{.Os}}/{{.Architecture}}' "$(cat goreleaser-dist/nextgen-image.tag)" | grep -q '^linux/amd64$'
668673
echo "ZITADEL_LOCAL_IMAGE=$(cat goreleaser-dist/nextgen-image.tag)" >> "$GITHUB_ENV"
669674
670-
- name: Prepare fresh Next.js app
675+
- name: Prepare fresh ${{ matrix.framework }} app
671676
id: prepare-app
672677
env:
678+
JOURNEY_APP_URL: http://localhost:3000
679+
JOURNEY_FRAMEWORK: ${{ matrix.framework }}
673680
JOURNEY_REGISTRY_URL: http://127.0.0.1:4873
674-
JOURNEY_WORK_DIR: ${{ runner.temp }}/zitadel-cli-journey
675-
run: node apps/cli-journey-e2e/scripts/prepare-next-app.mjs
681+
JOURNEY_WORK_DIR: ${{ runner.temp }}/zitadel-cli-journey-${{ matrix.framework }}
682+
run: node apps/cli-journey-e2e/scripts/prepare-app.mjs
676683

677-
- name: Start generated Next.js app
684+
- name: Start generated ${{ matrix.framework }} app
678685
run: |
679686
cd "$JOURNEY_APP_DIR"
680-
npm run dev -- --hostname localhost --port 3000 > "$RUNNER_TEMP/next-app.log" 2>&1 &
681-
echo "NEXT_APP_PID=$!" >> "$GITHUB_ENV"
687+
APP_LOG="$RUNNER_TEMP/${{ matrix.framework }}-app.log"
688+
case "${{ matrix.framework }}" in
689+
next)
690+
npm run dev -- --hostname localhost --port 3000 > "$APP_LOG" 2>&1 &
691+
;;
692+
*)
693+
npm run dev -- --host localhost --port 3000 > "$APP_LOG" 2>&1 &
694+
;;
695+
esac
696+
echo "JOURNEY_APP_PID=$!" >> "$GITHUB_ENV"
682697
for _ in $(seq 1 90); do
683698
if curl -fsS http://localhost:3000/login >/dev/null; then
684699
exit 0
685700
fi
686701
sleep 1
687702
done
688-
echo "::error::timed out waiting for generated Next.js app"
689-
cat "$RUNNER_TEMP/next-app.log"
703+
echo "::error::timed out waiting for generated ${{ matrix.framework }} app"
704+
cat "$APP_LOG"
690705
exit 1
691706
692707
- name: Run consumer journey Playwright tests
708+
env:
709+
JOURNEY_FRAMEWORK: ${{ matrix.framework }}
710+
JOURNEY_PLAYWRIGHT_OUTPUT_DIR: apps/cli-journey-e2e/test-output/playwright/${{ matrix.framework }}/output
711+
JOURNEY_PLAYWRIGHT_REPORT_DIR: apps/cli-journey-e2e/test-output/playwright/${{ matrix.framework }}/report
693712
run: >-
694713
corepack pnpm --filter @zitadel/cli-journey-e2e
695714
exec playwright test --config playwright.config.mts
696715
697716
- name: Collect diagnostics
698717
if: failure()
699718
run: |
700-
DIAG_DIR="$RUNNER_TEMP/consumer-journey-diagnostics"
701-
APP_DIR="$RUNNER_TEMP/zitadel-cli-journey/myapp"
719+
DIAG_DIR="$RUNNER_TEMP/consumer-journey-diagnostics-${{ matrix.framework }}"
720+
APP_DIR="$RUNNER_TEMP/zitadel-cli-journey-${{ matrix.framework }}/myapp"
702721
mkdir -p "$DIAG_DIR/generated-app"
703722
if [ -d "$APP_DIR" ]; then
704723
(
@@ -711,15 +730,15 @@ jobs:
711730
> "$DIAG_DIR/logs.json" 2> "$DIAG_DIR/logs.stderr.log"
712731
) || true
713732
fi
714-
cp "$RUNNER_TEMP/next-app.log" "$DIAG_DIR/" 2>/dev/null || true
733+
cp "$RUNNER_TEMP/${{ matrix.framework }}-app.log" "$DIAG_DIR/" 2>/dev/null || true
715734
cp "$RUNNER_TEMP/verdaccio.log" "$DIAG_DIR/" 2>/dev/null || true
716-
cp "$RUNNER_TEMP/zitadel-cli-journey/doctor.json" "$DIAG_DIR/" 2>/dev/null || true
717-
cp "$RUNNER_TEMP/zitadel-cli-journey/doctor.stderr.log" "$DIAG_DIR/" 2>/dev/null || true
718-
cp "$RUNNER_TEMP/zitadel-cli-journey/start.json" "$DIAG_DIR/" 2>/dev/null || true
719-
cp "$RUNNER_TEMP/zitadel-cli-journey/start.stderr.log" "$DIAG_DIR/" 2>/dev/null || true
720-
cp "$RUNNER_TEMP/zitadel-cli-journey/setup.json" "$DIAG_DIR/" 2>/dev/null || true
721-
cp "$RUNNER_TEMP/zitadel-cli-journey/setup.stderr.log" "$DIAG_DIR/" 2>/dev/null || true
722-
cp "$RUNNER_TEMP/zitadel-cli-journey/metadata.json" "$DIAG_DIR/" 2>/dev/null || true
735+
cp "$RUNNER_TEMP/zitadel-cli-journey-${{ matrix.framework }}/doctor.json" "$DIAG_DIR/" 2>/dev/null || true
736+
cp "$RUNNER_TEMP/zitadel-cli-journey-${{ matrix.framework }}/doctor.stderr.log" "$DIAG_DIR/" 2>/dev/null || true
737+
cp "$RUNNER_TEMP/zitadel-cli-journey-${{ matrix.framework }}/start.json" "$DIAG_DIR/" 2>/dev/null || true
738+
cp "$RUNNER_TEMP/zitadel-cli-journey-${{ matrix.framework }}/start.stderr.log" "$DIAG_DIR/" 2>/dev/null || true
739+
cp "$RUNNER_TEMP/zitadel-cli-journey-${{ matrix.framework }}/setup.json" "$DIAG_DIR/" 2>/dev/null || true
740+
cp "$RUNNER_TEMP/zitadel-cli-journey-${{ matrix.framework }}/setup.stderr.log" "$DIAG_DIR/" 2>/dev/null || true
741+
cp "$RUNNER_TEMP/zitadel-cli-journey-${{ matrix.framework }}/metadata.json" "$DIAG_DIR/" 2>/dev/null || true
723742
cp "$APP_DIR/.zitadel/local/runtime.json" "$DIAG_DIR/runtime.json" 2>/dev/null || true
724743
cp "$APP_DIR/package.json" "$DIAG_DIR/generated-app/" 2>/dev/null || true
725744
cp "$APP_DIR/package-lock.json" "$DIAG_DIR/generated-app/" 2>/dev/null || true
@@ -728,19 +747,19 @@ jobs:
728747
if: failure()
729748
uses: actions/upload-artifact@v7
730749
with:
731-
name: consumer-journey-diagnostics
750+
name: consumer-journey-diagnostics-${{ matrix.framework }}
732751
path: |
733-
apps/cli-journey-e2e/test-output/playwright/report/**
734-
apps/cli-journey-e2e/test-output/playwright/output/**
735-
${{ runner.temp }}/consumer-journey-diagnostics/**
752+
apps/cli-journey-e2e/test-output/playwright/${{ matrix.framework }}/report/**
753+
apps/cli-journey-e2e/test-output/playwright/${{ matrix.framework }}/output/**
754+
${{ runner.temp }}/consumer-journey-diagnostics-${{ matrix.framework }}/**
736755
if-no-files-found: ignore
737756
retention-days: 7
738757

739758
- name: Tear down consumer journey services
740759
if: always()
741760
run: |
742-
if [ -n "${NEXT_APP_PID:-}" ]; then kill "$NEXT_APP_PID" 2>/dev/null || true; fi
743-
APP_DIR="$RUNNER_TEMP/zitadel-cli-journey/myapp"
761+
if [ -n "${JOURNEY_APP_PID:-}" ]; then kill "$JOURNEY_APP_PID" 2>/dev/null || true; fi
762+
APP_DIR="$RUNNER_TEMP/zitadel-cli-journey-${{ matrix.framework }}/myapp"
744763
if [ -d "$APP_DIR" ]; then
745764
(
746765
cd "$APP_DIR"

AGENTS.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,10 @@ Secrets").
4545
- `apps/demo-next-e2e/` and `apps/demo-nuxt-e2e/` are the Playwright projects
4646
that exercise each demo through real framework middleware against the
4747
api-mock TCP server.
48-
- `apps/cli-journey-e2e/` contains the fresh Next.js consumer journey
49-
Playwright project. It installs local package tarballs through a temporary
50-
registry and verifies CLI setup plus real registration/login flows.
48+
- `apps/cli-journey-e2e/` contains the fresh consumer journey Playwright
49+
project for every CLI-supported framework. It installs local package tarballs
50+
through a temporary registry and verifies CLI setup plus real
51+
registration/login flows.
5152
- `packages/components/` contains shared Lit components.
5253
- `packages/sdk-core/`, `packages/sdk-next/`, `packages/sdk-nuxt/`,
5354
`packages/sdk-react/`, `packages/sdk-vue/`, and `packages/sdk-angular/`
@@ -148,10 +149,11 @@ corepack pnpm run journey
148149
This runner requires Docker for Verdaccio and the CLI-managed local runtime. By
149150
default it builds a local runtime image, ensures the Playwright Chromium
150151
browsers are installed, builds and packs local npm packages with pnpm, creates
151-
an empty app directory outside the repo, runs `npx @zitadel/cli@alpha doctor`,
152-
`start`, and `setup --framework next --server local`, starts the generated app
153-
on `localhost`, and runs Playwright with one worker. Use
154-
`-- --image <docker-tag>` to reuse an existing local runtime image.
152+
empty app directories outside the repo, runs `npx @zitadel/cli@alpha doctor`,
153+
`start`, and `setup --framework <id> --server local`, starts the generated apps
154+
on `localhost`, and runs Playwright with one worker per framework journey. Use
155+
`-- --framework next` to run one framework and `-- --image <docker-tag>` to
156+
reuse an existing local runtime image.
155157

156158
Use `corepack pnpm run journey` for deterministic CI-style proof of the
157159
fresh-app path. Use `corepack pnpm run cli -- ...` for manual browser or agent

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,10 @@ corepack pnpm run journey
153153
This opt-in check ensures the Playwright Chromium browsers are installed, builds
154154
the local npm packages, publishes them to a temporary Verdaccio registry, runs
155155
`npx @zitadel/cli@alpha doctor`, `start`, and
156-
`setup --framework next --server local` in an empty app directory, starts the
157-
generated app, and verifies registration/login journeys.
156+
`setup --framework <id> --server local` in fresh app directories for every
157+
supported framework, starts the generated apps, and verifies registration/login
158+
journeys. Use `corepack pnpm run journey -- --framework next` to run only the
159+
Next.js journey.
158160

159161
Use `corepack pnpm run journey` for deterministic CI-style proof. Use
160162
`corepack pnpm run cli -- ...` when you want to drive the same local package

apps/cli-journey-e2e/AGENTS.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ These instructions apply to `apps/cli-journey-e2e/**`. Defer to the root
55

66
## Purpose
77

8-
This project protects the customer local setup journey. Tests must exercise a
9-
fresh app directory that runs the CLI local runtime path (`doctor`, `start`,
10-
`setup --server local`) before starting the generated Next.js app. It must not
11-
test the checked-in demo apps.
8+
This project protects the customer local setup journey across every supported
9+
CLI framework. Tests must exercise a fresh app directory that runs the CLI local
10+
runtime path (`doctor`, `start`, `setup --server local`) before starting the
11+
generated app. It must not test the checked-in demo apps.
1212

1313
## Maintenance Rules
1414

@@ -20,8 +20,8 @@ test the checked-in demo apps.
2020
- CI must install Zitadel packages from current workflow tarballs through the
2121
temporary Verdaccio registry, not from public npm.
2222
- CI must run `npx @zitadel/cli@alpha doctor`, `start`, and
23-
`setup --framework next --server local` from the fresh app directory with
24-
`--non-interactive --json`.
23+
`setup --framework <next|nuxt|react|vue|angular> --server local` from the
24+
fresh app directory with `--non-interactive --json`.
2525
- Pack and upload only the public packages:
2626
`@zitadel/cli`, `@zitadel/api`, `@zitadel/components`,
2727
`@zitadel/sdk-core`, `@zitadel/sdk-next`, `@zitadel/sdk-nuxt`,

apps/cli-journey-e2e/README.md

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,20 @@ Fresh-app Playwright coverage for the customer local setup journey.
44

55
This project is private test infrastructure. It does not test the checked-in
66
demo apps. Instead, it builds the current workspace packages, publishes packed
7-
tarballs to a temporary registry, creates an empty app directory outside the
8-
repo, runs the customer local CLI flow through `npx`, starts the generated app,
9-
and verifies that a real user can register, log out, and log in again.
7+
tarballs to a temporary registry, creates empty app directories outside the
8+
repo, runs the customer local CLI flow through `npx`, starts the generated apps,
9+
and verifies that real users can register, log out, and log in again across
10+
Next, Nuxt, React, Vue, and Angular.
1011

1112
## Local runner
1213

1314
```sh
1415
corepack pnpm run journey
1516
```
1617

17-
The default mode uses Docker for Verdaccio and for the CLI-managed local
18-
runtime. It builds a local runtime image unless `--image` is provided:
18+
The default mode runs the full framework matrix in parallel. It uses Docker for
19+
Verdaccio and for the CLI-managed local runtimes, and builds a local runtime
20+
image unless `--image` is provided:
1921

2022
1. Ensure the Playwright Chromium browsers are installed.
2123
2. Build the public workspace packages.
@@ -25,21 +27,26 @@ runtime. It builds a local runtime image unless `--image` is provided:
2527
5. Start Verdaccio with npmjs proxying enabled.
2628
6. Publish tarballs to Verdaccio with `alpha` and `latest` tags.
2729
7. Build or use a local runtime Docker image for `zitadel start`.
28-
8. Create an empty app directory in a temporary directory.
30+
8. Create one empty app directory per selected framework in a temporary directory.
2931
9. Run `npx <cli-package>@alpha doctor --non-interactive --json`.
3032
10. Run `npx <cli-package>@alpha start --non-interactive --json`.
31-
11. Run `npx <cli-package>@alpha setup --framework next --server local --non-interactive --json`.
32-
12. Start the generated app on `localhost`.
33-
13. Run the Playwright tests with one worker.
33+
11. Run `npx <cli-package>@alpha setup --framework <id> --server local --non-interactive --json`.
34+
12. Start each generated app on `localhost`.
35+
13. Run the Playwright tests with one worker per framework journey.
3436

3537
### Options
3638

3739
```sh
3840
corepack pnpm run journey -- --keep
3941
corepack pnpm run journey -- --work-dir /tmp/zitadel-journey
4042
corepack pnpm run journey -- --image nextgen:local
43+
corepack pnpm run journey -- --framework next
44+
corepack pnpm run journey -- --concurrency 2
4145
```
4246

47+
- `--framework <id>` runs one framework (`next`, `nuxt`, `react`, `vue`, or
48+
`angular`) instead of the full matrix.
49+
- `--concurrency <n>` controls local framework parallelism. The default is `5`.
4350
- `--image <docker-tag>` uses an existing local runtime image instead of
4451
building one.
4552
- `--keep` keeps the temporary work directory after success.
@@ -48,29 +55,33 @@ corepack pnpm run journey -- --image nextgen:local
4855
Useful environment overrides:
4956

5057
- `JOURNEY_REGISTRY_PORT`
51-
- `JOURNEY_APP_PORT`
58+
- `JOURNEY_APP_PORT` for single-framework runs only
59+
- `JOURNEY_ZITADEL_PORT` for single-framework runs only
5260
- `JOURNEY_ENABLE_PASSKEY=0` as a local-only escape hatch while debugging
5361
passkey setup. CI must run passkey coverage.
5462

5563
## CI gate
5664

57-
The `consumer-journey-e2e` workflow job does not use public Zitadel packages or
58-
GHCR images. It downloads the GoReleaser snapshot image and the public npm
59-
package tarballs produced by the same workflow, publishes those tarballs to
60-
Verdaccio, points `ZITADEL_LOCAL_IMAGE` at the loaded image, runs the same
61-
`npx` local setup flow, and runs the same Playwright project against the
62-
generated app. Private support packages such as design tokens are bundled into
63-
the public packages that need them and must not be uploaded or published.
65+
The `consumer-journey-e2e` workflow job runs as a framework matrix. Each matrix
66+
leg does not use public Zitadel packages or GHCR images. It downloads the
67+
GoReleaser snapshot image and the public npm package tarballs produced by the
68+
same workflow, publishes those tarballs to Verdaccio, points
69+
`ZITADEL_LOCAL_IMAGE` at the loaded image, runs the same `npx` local setup flow,
70+
and runs the same Playwright project against the generated app. Private support
71+
packages such as design tokens are bundled into the public packages that need
72+
them and must not be uploaded or published.
6473

6574
Failure diagnostics intentionally stay small: Playwright report/output,
6675
doctor/start/setup JSON and stderr, local runtime metadata/logs, metadata,
67-
generated app `package.json` and `package-lock.json`, Verdaccio logs, and Next
68-
logs. Do not upload generated app `node_modules` or `.next` directories.
76+
generated app `package.json` and `package-lock.json`, Verdaccio logs, and
77+
generated app logs. Do not upload generated app `node_modules` or framework
78+
build directories.
6979

7080
## Coverage
7181

72-
The suite is serial and one-worker because every test shares the same fresh
73-
backend and generated app instance.
82+
Each framework suite is serial and one-worker because every test in that suite
83+
shares the same fresh backend and generated app instance. Local all-framework
84+
runs execute framework suites in parallel.
7485

7586
- CLI local setup contract: doctor, start, and setup exit successfully, stdout
7687
parses as JSON, `status` is `ok`, the generated app depends on the local SDK
@@ -79,5 +90,3 @@ backend and generated app instance.
7990
out, and log in again with password.
8091
- Passkey-only account: register with email/passkey, log out, and log in again
8192
with passkey.
82-
- Password-plus-passkey account: register with password, accept passkey setup,
83-
log out, log in with password, log out, and log in with passkey.

apps/cli-journey-e2e/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"private": true,
55
"scripts": {
66
"test": "node --test scripts/*.test.mjs",
7-
"prepare-app": "node scripts/prepare-next-app.mjs",
7+
"prepare-app": "node scripts/prepare-app.mjs",
88
"publish-tarballs": "node scripts/publish-tarballs.mjs",
99
"verify-tarballs": "node scripts/verify-tarballs.mjs",
1010
"e2e-local": "node scripts/run-local.mjs",

apps/cli-journey-e2e/playwright.config.mts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,22 @@ import { nxE2EPreset } from "@nx/playwright/preset";
22
import { defineConfig, devices } from "@playwright/test";
33

44
const baseURL = process.env.JOURNEY_APP_URL ?? "http://localhost:3000";
5+
const outputDir =
6+
process.env.JOURNEY_PLAYWRIGHT_OUTPUT_DIR ?? "./test-output/playwright/output";
7+
const reportDir =
8+
process.env.JOURNEY_PLAYWRIGHT_REPORT_DIR ?? "./test-output/playwright/report";
59

610
export default defineConfig({
711
...nxE2EPreset(import.meta.filename, { testDir: "./src" }),
812
fullyParallel: false,
913
workers: 1,
10-
reporter: [["html", { outputFolder: "./test-output/playwright/report", open: "never" }]],
14+
reporter: [["html", { outputFolder: reportDir, open: "never" }]],
1115
use: {
1216
baseURL,
1317
trace: "retain-on-failure",
1418
video: "retain-on-failure",
1519
},
16-
outputDir: "./test-output/playwright/output",
20+
outputDir,
1721
projects: [
1822
{
1923
name: "chromium",

0 commit comments

Comments
 (0)