chore: rehaul DevX (#10571)

# Which Problems Are Solved

Replaces Turbo by Nx and lays the foundation for the next CI
improvements. It enables using Nx Cloud to speed the up the pipelines
that affect any node package.
It streamlines the dev experience for frontend and backend developers by
providing the following commands:

| Task | Command | Notes |
|------|---------|--------|
| **Production** | `nx run PROJECT:prod` | Production server |
| **Develop** | `nx run PROJECT:dev` | Hot reloading development server
|
| **Test** | `nx run PROJECT:test` | Run all tests |
| **Lint** | `nx run PROJECT:lint` | Check code style |
| **Lint Fix** | `nx run PROJECT:lint-fix` | Auto-fix style issues |

The following values can be used for PROJECT:

- @zitadel/zitadel (root commands)
- @zitadel/api,
- @zitadel/login,
- @zitadel/console,
- @zitadel/docs,
- @zitadel/client
- @zitadel/proto

The project names and folders are streamlined:

| Old Folder | New Folder |
| --- | --- |
| ./e2e | ./tests/functional-ui |
| ./load-test | ./benchmark |
| ./build/zitadel | ./apps/api |
| ./console | ./apps/console (postponed so the PR is reviewable) |  

Also, all references to the TypeScript repo are removed so we can
archive it.

# How the Problems Are Solved

- Ran `npx nx@latest init`
- Replaced all turbo.json by project.json and fixed the target configs
- Removed Turbo dependency
- All JavaScript related code affected by a PRs changes is
quality-checked using the `nx affected` command
- We move PR checks that are runnable using Nx into the `check`
workflow. For workflows where we don't use Nx, yet, we restore
previously built dependency artifacts from Nx.
- We only use a single and easy to understand dev container
- The CONTRIBUTING.md is streamlined
- The setup with a generated client pat is orchestrated with Nx
- Everything related to the TypeScript repo is updated or removed. A
**Deploy with Vercel** button is added to the docs and the
CONTRIBUTING.md.

# Additional Changes

- NPM package names have a consistent pattern.
- Docker bake is removed. The login container is built and released like
the core container.
- The integration tests build the login container before running, so
they don't rely on the login container action anymore. This fixes
consistently failing checks on PRs from forks.
- The docs build in GitHub actions is removed, as we already build on
Vercel.

# Additional Context

- Internal discussion:
https://zitadel.slack.com/archives/C087ADF8LRX/p1756277884928169
- Workflow dispatch test:
https://github.com/zitadel/zitadel/actions/runs/17760122959

---------

Co-authored-by: Florian Forster <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
Co-authored-by: Copilot <[email protected]>
This commit is contained in:
Elio Bischof
2025-10-08 10:27:02 +02:00
committed by GitHub
co-authored by Florian Forster Tim Möhlmann Copilot
parent e47acaeef2
commit f69a6ed4f3
236 changed files with 5708 additions and 6549 deletions
+1
View File
@@ -0,0 +1 @@
ENVIRONMENT_JSON_URL=http://localhost:8080/ui/console/assets/environment.json
+28 -72
View File
@@ -1,68 +1,17 @@
# Console Angular App
# Zitadel Console
This is the ZITADEL Console Angular application.
The Console is Zitadels management UI.
## Development
It is built using [Angular](https://angular.dev/) and part of the Zitadel monorepo.
### Prerequisites
- Node.js 18 or later
- pnpm (latest)
### Installation
```bash
pnpm install
```
### Proto Generation
The Console app uses **dual proto generation** with Turbo dependency management:
1. **`@zitadel/proto` generation**: Modern ES modules with `@bufbuild/protobuf` for v2 APIs
2. **Local `buf.gen.yaml` generation**: Traditional protobuf JavaScript classes for v1 APIs
The Console app's `turbo.json` ensures that `@zitadel/proto#generate` runs before the Console's own generation, providing both:
- Modern schemas from `@zitadel/proto` (e.g., `UserSchema`, `DetailsSchema`)
- Legacy classes from `src/app/proto/generated` (e.g., `User`, `Project`)
Generated files:
- **`@zitadel/proto`**: Modern ES modules in `login/packages/zitadel-proto/`
- **Local generation**: Traditional protobuf files in `src/app/proto/generated/`
- TypeScript definition files (`.d.ts`)
- JavaScript files (`.js`)
- gRPC client files (`*ServiceClientPb.ts`)
- OpenAPI/Swagger JSON files (`.swagger.json`)
To generate proto files:
```bash
pnpm turbo generate --filter=./console
```
This automatically runs both generations in the correct order via Turbo dependencies.
### Development Server
To start the development server:
```bash
pnpm turbo start --filter=./console
```
This will:
1. Fetch the environment configuration from the server
2. Serve the app on the default port
To get started follow the [contributing quick start](../CONTRIBUTING.md#console).
### Building
To build for production:
```bash
pnpm turbo build --filter=./console
pnpm nx run @zitadel/console:build
```
This will:
@@ -75,38 +24,45 @@ This will:
To run linting and formatting checks:
```bash
pnpm turbo lint --filter=./console
pnpm nx @zitadel/console:lint
```
To auto-fix formatting issues:
```bash
pnpm turbo lint:fix --filter=./console
pnpm nx @zitadel/console:lint-fix
```
## Project Structure
- `src/app/proto/generated/` - Generated proto files (Angular-specific format)
- `buf.gen.yaml` - Local proto generation configuration
- `turbo.json` - Turbo dependency configuration for proto generation
- `project.json` - Nx orchestration and caching for builds and tests
- `prebuild.development.js` - Development environment configuration script
## Proto Generation Details
The Console app uses **dual proto generation** managed by Turbo dependencies:
### Dependency Chain
The Console app has the following build dependencies managed by Turbo:
The Console app has the following build dependencies managed by Nx:
1. `@zitadel/proto#generate` - Generates modern protobuf files
2. `@zitadel/client#build` - Builds the TypeScript gRPC client library
3. `console#generate` - Generates Console-specific protobuf files
4. `console#build` - Builds the Angular application
1. `@zitadel/proto:generate` - Generates the protobuf stubs
2. `@zitadel/client:build` - Builds the TypeScript gRPC client library
3. `@zitadel/console:generate` - Generates Console-specific protobuf stubs
4. `@zitadel/console:build` - Creates a production build from Console
This ensures that the Console always has access to the latest client library and protobuf definitions.
### Legacy v1 API (Traditional Protobuf)
### Proto Generation Details
1. **`@zitadel/proto` generation**: Modern ES modules with `@bufbuild/protobuf` for v2 APIs
2. **Local `buf.gen.yaml` generation**: Traditional protobuf JavaScript classes for v1 APIs
The Console app calls Zitadel v1 and v2 APIs.
As long as the Console still calls v1 APIs, it needs to import client stubs from separate sources:
- [Source outputs from direct buf generation for v1 APIs](#v1-stubs)
- [@zitadel/client for v2 APIs](#v2-stubs)
### <a name="v1-stubs"></a>Legacy v1 API (Traditional Protobuf)
- Uses local `buf.gen.yaml` configuration
- Generates traditional Google protobuf JavaScript classes extending `jspb.Message`
@@ -114,7 +70,7 @@ This ensures that the Console always has access to the latest client library and
- Output: `src/app/proto/generated/`
- Used for: Most existing Console functionality
### Modern v2 API (ES Modules)
### <a name="v2-stubs"></a>Modern v2 API (ES Modules)
- Uses `@zitadel/proto` package generation
- Generates modern ES modules with `@bufbuild/protobuf`
@@ -124,9 +80,9 @@ This ensures that the Console always has access to the latest client library and
### Dependency Management
The Console's `turbo.json` ensures proper execution order:
The Console's `project.json` ensures proper execution order:
1. `@zitadel/proto#generate` runs first (modern ES modules)
1. `@zitadel/proto:generate` runs first (modern ES modules)
2. Console's local generation runs second (traditional protobuf)
3. Build/lint/start tasks depend on both generations being complete
+8 -11
View File
@@ -1,17 +1,14 @@
{
"name": "console",
"version": "0.0.0",
"name": "@zitadel/console",
"scripts": {
"ng": "ng",
"dev": "node prebuild.development.js && ng serve",
"start": "node prebuild.development.js && ng serve",
"dev": "wait-on --verbose --interval 2000 --simultaneous 1 --timeout 30m ${ENVIRONMENT_JSON_URL} && node prebuild.development.js && ng serve --host=${DEVCONTAINER_LISTEN_HOST:-127.0.0.1}",
"build": "ng build --configuration production --base-href=/ui/console/",
"lint": "pnpm run '/^lint:check:.*$/'",
"lint:check:ng": "ng lint",
"lint:check:prettier": "prettier --check src",
"lint:fix": "prettier --write src",
"lint-check-ng": "ng lint",
"lint-check-prettier": "prettier --check src",
"lint-fix": "prettier --write src",
"generate": "pnpm exec buf generate ../proto --include-imports --include-wkt",
"clean": "rm -rf dist .angular .turbo node_modules src/app/proto/generated"
"clean": "rm -rf dist .angular node_modules src/app/proto/generated"
},
"private": true,
"dependencies": {
@@ -39,8 +36,6 @@
"@ng-icons/heroicons": "^32.1.0",
"@ngx-translate/core": "^17.0.0",
"@tanstack/angular-query-experimental": "^5.85.6",
"@zitadel/client": "workspace:*",
"@zitadel/proto": "workspace:*",
"angular-oauth2-oidc": "^20.0.2",
"angularx-qrcode": "^20.0.0",
"buffer": "^6.0.3",
@@ -84,6 +79,8 @@
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^5.62.0",
"@typescript-eslint/parser": "^5.62.0",
"@zitadel/client": "workspace:*",
"@zitadel/proto": "workspace:*",
"eslint": "^8.57.1",
"jasmine-core": "~5.6.0",
"jasmine-spec-reporter": "~7.0.0",
+56
View File
@@ -0,0 +1,56 @@
{
"$schema": "../node_modules/nx/schemas/project-schema.json",
"targets": {
"lint": {
"description": "Runs all linters",
"dependsOn": [
"lint-check-*"
]
},
"lint-check-prettier": {
"description": "Checks code formatting with Prettier",
"cache": true,
"inputs": [
"default"
]
},
"lint-check-ng": {
"description": "Runs Angular specific lint checks",
"cache": true,
"inputs": [
"default"
]
},
"generate": {
"description": "Generates code from protobuf definitions for API v1 endpoints",
"inputs": [
"{workspaceRoot}/proto/**/*",
"{projectRoot}/buf.gen.yaml",
"{projectRoot}/package.json",
"{workspaceRoot}/pnpm-lock.yaml"
],
"outputs": [
"{projectRoot}/src/app/proto/generated"
]
},
"build": {
"description": "Builds the Console for production",
"inputs": [
"default",
"{workspaceRoot}/pnpm-lock.yaml",
"{workspaceRoot}/docs/frameworks.json"
],
"outputs": [
"{projectRoot}/dist"
]
},
"dev": {
"description": "Runs the Console in development mode with hot-reloading",
"continuous": true,
"dependsOn": [
"generate",
"^build"
]
}
}
}
-24
View File
@@ -1,24 +0,0 @@
{
"$schema": "https://turbo.build/schema.json",
"extends": ["//"],
"tasks": {
"generate": {
"dependsOn": ["@zitadel/proto#generate"],
"outputs": ["src/app/proto/generated/**"]
},
"build": {
"dependsOn": ["generate", "@zitadel/client#build"],
"outputs": ["dist/**"]
},
"dev": {
"dependsOn": ["generate", "@zitadel/client#build"],
"cache": false,
"persistent": true
},
"start": {
"dependsOn": ["generate", "@zitadel/client#build"],
"cache": false,
"persistent": true
}
}
}