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 <florian@zitadel.com>
Co-authored-by: Tim Möhlmann <tim+github@zitadel.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
(cherry picked from commit f69a6ed4f3)

# Conflicts:
#	.github/workflows/build.yml
#	.github/workflows/console.yml
#	.github/workflows/core.yml
#	CONTRIBUTING.md
#	Makefile
#	backend/v3/storage/database/events_testing/events_test.go
#	backend/v3/storage/database/events_testing/id_provider_instance_test.go
#	backend/v3/storage/database/events_testing/instance_test.go
#	console/README.md
#	console/package.json
#	internal/api/grpc/group/v2/integration_test/query_test.go
#	pnpm-lock.yaml
This commit is contained in:
Elio Bischof
2025-10-08 10:27:02 +02:00
committed by Livio Spring
parent 8a3b5848dc
commit 37acd2a9d9
232 changed files with 2311 additions and 36748 deletions

3
.devcontainer/.env.db Normal file
View File

@@ -0,0 +1,3 @@
PGUSER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_HOST_AUTH_METHOD=trust

View File

@@ -1,20 +0,0 @@
FROM mcr.microsoft.com/devcontainers/typescript-node:20-bookworm
ENV SHELL=/bin/bash \
DEBIAN_FRONTEND=noninteractive \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8 \
CI=1 \
PNPM_HOME=/home/node/.local/share/pnpm \
PATH=/home/node/.local/share/pnpm:$PATH
RUN apt-get update && \
apt-get --no-install-recommends install -y \
# Cypress dependencies
libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb && \
apt-get clean && \
corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@10.13.1 --activate
COPY --chown=node:node commands /commands
USER node

View File

@@ -1,2 +0,0 @@
*
!commands

View File

@@ -1,39 +0,0 @@
#!/bin/bash
if [ "$FAIL_COMMANDS_ON_ERRORS" == "true" ]; then
set -e
fi
echo
echo
echo
echo -e "THANKS FOR CONTRIBUTING TO ZITADEL 🚀"
echo
echo "Your dev container is configured for fixing login integration tests."
echo "The login is running in a separate container with the same configuration."
echo "It calls the mock-zitadel container which provides a mocked Zitadel gRPC API."
echo
echo "Also the test suite is configured correctly."
echo "For example, run a single test file:"
echo "pnpm cypress run --spec integration/integration/login.cy.ts"
echo
echo "You can also run the test interactively."
echo "However, this is only possible from outside the dev container."
echo "On your host machine, run:"
echo "cd apps/login"
echo "pnpm cypress open"
echo
echo "If you want to change the login code, you can replace the login container by a hot reloading dev server."
echo "docker stop login-integration"
echo "pnpm turbo dev"
echo "Navigate to the page you want to fix, for example:"
echo "http://localhost:3001/ui/v2/login/verify?userId=221394658884845598&code=abc"
echo "Change some code and reload the page for instant feedback."
echo
echo "When you are done, make sure all integration tests pass:"
echo "pnpm cypress run"
echo
if [ "$FAIL_COMMANDS_ON_ERRORS" != "true" ]; then
exit 0
fi

View File

@@ -1,18 +0,0 @@
#!/bin/bash
if [ "$FAIL_COMMANDS_ON_ERRORS" == "true" ]; then
echo "Running in fail-on-errors mode"
set -e
fi
pnpm install --frozen-lockfile \
--filter @zitadel/login \
--filter @zitadel/client \
--filter @zitadel/proto \
--filter zitadel-monorepo
pnpm cypress install
pnpm test:integration:login
if [ "$FAIL_COMMANDS_ON_ERRORS" != "true" ]; then
exit 0
fi

View File

@@ -1,30 +0,0 @@
#!/bin/bash
if [ "$FAIL_COMMANDS_ON_ERRORS" == "true" ]; then
set -e
fi
echo
echo
echo
echo -e "THANKS FOR CONTRIBUTING TO ZITADEL 🚀"
echo
echo "Your dev container is configured for fixing linting and unit tests."
echo "No other services are running alongside this container."
echo
echo "To fix all auto-fixable linting errors, run:"
echo "pnpm turbo lint:fix"
echo
echo "To watch console linting errors, run:"
echo "pnpm turbo watch lint --filter console"
echo
echo "To watch @zitadel/client unit test failures, run:"
echo "pnpm turbo watch test:unit --filter @zitadel/client"
echo
echo "To watch @zitadel/login relevant unit tests and linting failures, run:"
echo "pnpm turbo watch lint test:unit --filter @zitadel/login..."
echo
if [ "$FAIL_COMMANDS_ON_ERRORS" != "true" ]; then
exit 0
fi

View File

@@ -1,12 +0,0 @@
#!/bin/bash
if [ "$FAIL_COMMANDS_ON_ERRORS" == "true" ]; then
set -e
fi
pnpm install --frozen-lockfile --recursive
pnpm turbo lint test:unit
if [ "$FAIL_COMMANDS_ON_ERRORS" != "true" ]; then
exit 0
fi

View File

@@ -1,29 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
"name": "Base: Build and Run the Components you need",
"dockerComposeFile": "docker-compose.yaml",
"service": "devcontainer",
"runServices": [
"devContainer",
"db"
],
"workspaceFolder": "/workspaces",
"remoteEnv": {
"DISPLAY": ""
},
"forwardPorts": [
3000,
3001,
4200,
8080
],
"onCreateCommand": "pnpm install --frozen-lockfile --recursive --prefer-offline",
"features": {
"ghcr.io/devcontainers/features/go:1": {
"version": "1.24"
},
"ghcr.io/guiyomh/features/golangci-lint:0": {},
"ghcr.io/jungaretti/features/make:1": {},
"ghcr.io/devcontainers/features/docker-outside-of-docker": {}
}
}

View File

@@ -1,198 +0,0 @@
services:
devcontainer:
container_name: devcontainer
build:
context: ../base
volumes:
- ../../:/workspaces:cached
command: sleep infinity
working_dir: /workspaces
environment:
ZITADEL_DATABASE_POSTGRES_HOST: db
ZITADEL_EXTERNALSECURE: false
db:
container_name: db
image: postgres:17.0-alpine3.19
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
PGUSER: postgres
POSTGRES_PASSWORD: postgres
healthcheck:
test: [ "CMD-SHELL", "pg_isready" ]
interval: "10s"
timeout: "30s"
retries: 5
start_period: "20s"
ports:
- "5432:5432"
zitadel:
container_name: zitadel
image: "${ZITADEL_TAG:-ghcr.io/zitadel/zitadel:latest}"
command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --config /zitadel.yaml --steps /zitadel.yaml'
volumes:
- ../../apps/login/acceptance/pat:/pat:delegated
- ../../apps/login/acceptance/zitadel.yaml:/zitadel.yaml:cached
network_mode: service:devcontainer
healthcheck:
test:
- CMD
- /app/zitadel
- ready
- --config
- /zitadel.yaml
depends_on:
db:
condition: "service_healthy"
configure-login:
container_name: configure-login
restart: no
build:
context: ../../apps/login/acceptance/setup
dockerfile: ../go-command.Dockerfile
entrypoint: "./setup.sh"
network_mode: service:devcontainer
environment:
PAT_FILE: /pat/zitadel-admin-sa.pat
ZITADEL_API_URL: http://localhost:8080
WRITE_ENVIRONMENT_FILE: /login-env/.env.test.local
SINK_EMAIL_INTERNAL_URL: http://sink:3333/email
SINK_SMS_INTERNAL_URL: http://sink:3333/sms
SINK_NOTIFICATION_URL: http://sink:3333/notification
LOGIN_BASE_URL: http://localhost:3000/ui/v2/login/
ZITADEL_API_DOMAIN: localhost
ZITADEL_ADMIN_USER: zitadel-admin@zitadel.localhost
volumes:
- ../../apps/login/acceptance/pat:/pat:cached # Read the PAT file from zitadels setup
- ../../apps/login:/login-env:delegated # Write the environment variables file for the login
depends_on:
zitadel:
condition: "service_healthy"
login-acceptance:
container_name: login
image: "${LOGIN_TAG:-ghcr.io/zitadel/zitadel-login:latest}"
network_mode: service:devcontainer
volumes:
- ../../apps/login/.env.test.local:/env-files/.env:cached
depends_on:
configure-login:
condition: service_completed_successfully
mock-notifications:
container_name: mock-notifications
build:
context: ../../apps/login/acceptance/sink
dockerfile: ../go-command.Dockerfile
args:
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
environment:
PORT: '3333'
command:
- -port
- '3333'
- -email
- '/email'
- -sms
- '/sms'
- -notification
- '/notification'
ports:
- "3333:3333"
depends_on:
configure-login:
condition: "service_completed_successfully"
mock-oidcrp:
container_name: mock-oidcrp
build:
context: ../../apps/login/acceptance/oidcrp
dockerfile: ../go-command.Dockerfile
args:
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
network_mode: service:devcontainer
environment:
API_URL: 'http://localhost:8080'
API_DOMAIN: 'localhost'
PAT_FILE: '/pat/zitadel-admin-sa.pat'
LOGIN_URL: 'http://localhost:3000/ui/v2/login'
ISSUER: 'http://localhost:8000'
HOST: 'localhost'
PORT: '8000'
SCOPES: 'openid profile email'
volumes:
- ../../apps/login/acceptance/pat:/pat:cached
depends_on:
configure-login:
condition: "service_completed_successfully"
# mock-oidcop:
# container_name: mock-oidcop
# build:
# context: ../../apps/login/acceptance/idp/oidc
# dockerfile: ../../go-command.Dockerfile
# args:
# - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
# network_mode: service:devcontainer
# environment:
# API_URL: 'http://localhost:8080'
# API_DOMAIN: 'localhost'
# PAT_FILE: '/pat/zitadel-admin-sa.pat'
# SCHEMA: 'http'
# HOST: 'localhost'
# PORT: "8004"
# volumes:
# - "../apps/login/packages/acceptance/pat:/pat:cached"
# depends_on:
# configure-login:
# condition: "service_completed_successfully"
mock-samlsp:
container_name: mock-samlsp
build:
context: ../../apps/login/acceptance/samlsp
dockerfile: ../go-command.Dockerfile
args:
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
network_mode: service:devcontainer
environment:
API_URL: 'http://localhost:8080'
API_DOMAIN: 'localhost'
PAT_FILE: '/pat/zitadel-admin-sa.pat'
LOGIN_URL: 'http://localhost:3000/ui/v2/login'
IDP_URL: 'http://localhost:8080/saml/v2/metadata'
HOST: 'http://localhost:8001'
PORT: '8001'
volumes:
- "../apps/login/packages/acceptance/pat:/pat:cached"
depends_on:
configure-login:
condition: "service_completed_successfully"
# mock-samlidp:
# container_name: mock-samlidp
# build:
# context: ../../apps/login/acceptance/idp/saml
# dockerfile: ../../go-command.Dockerfile
# args:
# - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
# network_mode: service:devcontainer
# environment:
# API_URL: 'http://localhost:8080'
# API_DOMAIN: 'localhost'
# PAT_FILE: '/pat/zitadel-admin-sa.pat'
# SCHEMA: 'http'
# HOST: 'localhost'
# PORT: "8003"
# volumes:
# - "../apps/login/packages/acceptance/pat:/pat"
# depends_on:
# configure-login:
# condition: "service_completed_successfully"
volumes:
postgres-data:

6
.devcontainer/compose.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
# This script is used to run Docker Compose commands with the appropriate compose project set.
# This makes sure the commands don't break on different workspace_root folder names.
export DEVCONTAINER_LOCAL_WORKSPACE_ROOT=${DEVCONTAINER_LOCAL_WORKSPACE_ROOT:-${NX_WORKSPACE_ROOT:-zitadel}}
docker compose -p ${DEVCONTAINER_LOCAL_WORKSPACE_ROOT##*/}_devcontainer "$@"

View File

@@ -0,0 +1,57 @@
{
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
"name": "Zitadel Devcontainer",
"dockerComposeFile": "docker-compose.yaml",
"service": "devcontainer",
"runServices": [
"devcontainer"
],
"workspaceFolder": "/workspaces/zitadel",
"forwardPorts": [
3000,
4200,
8080,
3100
],
"portsAttributes": {
"3000": {
"label": "Login",
"onAutoForward": "notify"
},
"4200": {
"label": "Console",
"onAutoForward": "notify"
},
"8080": {
"label": "API",
"onAutoForward": "notify"
},
"3100": {
"label": "Docs",
"onAutoForward": "notify"
}
},
"features": {
"ghcr.io/devcontainers/features/go:1": {
"version": "1.24"
},
"ghcr.io/devcontainers/features/docker-outside-of-docker": {},
"ghcr.io/schlich/devcontainer-features/cypress:1": {
"version": "14"
}
},
"containerEnv": {
"DEVCONTAINER_LOCAL_WORKSPACE_ROOT": "${localWorkspaceFolder}"
},
"customizations": {
"vscode": {
"extensions": [
"golang.Go",
"Angular.ng-template",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"nrwl.angular-console"
]
}
}
}

View File

@@ -0,0 +1,88 @@
services:
devcontainer:
image: mcr.microsoft.com/devcontainers/typescript-node:22-bookworm
volumes:
- ../:/workspaces/zitadel:cached
command: sleep infinity
working_dir: /workspaces/zitadel
environment:
SHELL: /bin/bash
DEBIAN_FRONTEND: noninteractive
LANG: C.UTF-8
LC_ALL: C.UTF-8
COREPACK_ENABLE_DOWNLOAD_PROMPT: 0
DEVCONTAINER_DB_HOST: db
DEVCONTAINER_API_HOST: api
DEVCONTAINER_LOGIN_HOST: login
DEVCONTAINER_LOGIN_API_MOCK_HOST: login-api-mock
DEVCONTAINER_DB_API_INTEGRATION_HOST: db-api-integration
DEVCONTAINER_DB_FUNCTIONAL_UI_HOST: db-functional-ui
ports:
- "8080:8080"
- "3000:3000"
- "4200:4200"
db:
image: postgres:17
restart: unless-stopped
env_file:
- ./.env.db
volumes:
- db-data-dev:/var/lib/postgresql/data
healthcheck:
test: [ "CMD-SHELL", "pg_isready", "-U", "postgres" ]
interval: "10s"
timeout: "30s"
retries: 5
start_period: "20s"
ports:
- 5432:5432
db-api-integration:
image: 'postgres:17'
env_file:
- ./.env.db
environment:
PGPORT: 5433
command: postgres -c shared_preload_libraries=pg_stat_statements -c pg_stat_statements.track=all -c shared_buffers=1GB -c work_mem=16MB -c effective_io_concurrency=100 -c wal_level=minimal -c archive_mode=off -c max_wal_senders=0
healthcheck:
test: [ "CMD-SHELL", "pg_isready", "-U", "postgres" ]
interval: '10s'
timeout: '30s'
retries: 5
start_period: '20s'
ports:
- 5433:5433
cache-api-integration:
image: 'redis:8'
ports:
- 6379:6379
db-functional-ui:
image: 'postgres:17'
env_file:
- ./.env.db
environment:
PGPORT: 5434
healthcheck:
test: [ "CMD-SHELL", "pg_isready", "-U", "postgres" ]
interval: '10s'
timeout: '30s'
retries: 5
start_period: '20s'
ports:
- "5434:5434"
login-api-mock:
build:
context: ../apps/login/integration/api-mock
additional_contexts:
zitadel-protos: ../proto
ports:
- 22220:22220
- 22222:22222
volumes:
db-data-dev:

View File

@@ -1,26 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
"name": "Login Integration",
"dockerComposeFile": [
"./docker-compose.yaml"
],
"service": "login-integration-dev",
"runServices": [
"login-integration"
],
"workspaceFolder": "/workspaces/apps/login",
"forwardPorts": [
22220,
22222,
3001
],
"remoteEnv": {
"FAIL_COMMANDS_ON_ERRORS": "${localEnv:FAIL_COMMANDS_ON_ERRORS}",
"DISPLAY": ""
},
"updateContentCommand": "/commands/login-integration.update-content.sh",
"postAttachCommand": "/commands/login-integration.post-attach.sh",
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker": {}
}
}

View File

@@ -1,35 +0,0 @@
services:
login-integration-dev:
extends:
file: ../base/docker-compose.yaml
service: devcontainer
container_name: login-integration-dev
env_file: ../../apps/login/.env.test
environment:
CORE_MOCK_STUBS_URL: http://localhost:22220/v1/stubs
LOGIN_BASE_URL: http://localhost:3001/ui/v2/login
CYPRESS_CACHE_FOLDER: /workspaces/.artifacts/cypress
network_mode: service:mock-zitadel
depends_on:
login-integration:
condition: service_healthy
login-integration:
container_name: login-integration
image: "${LOGIN_TAG:-ghcr.io/zitadel/zitadel-login:latest}"
build:
context: ../..
dockerfile: build/login/Dockerfile
env_file: ../../apps/login/.env.test
network_mode: service:mock-zitadel
mock-zitadel:
container_name: mock-zitadel
build:
context: ../../apps/login/integration/core-mock
additional_contexts:
- zitadel-protos=../../proto
ports:
- 22220:22220
- 22222:22222
- 3001:3001

View File

@@ -1,22 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.base.schema.json",
"image": "mcr.microsoft.com/devcontainers/typescript-node:20-bookworm",
"name": "Login Subtree Container - Use the Login As If You Would Have Forked the Mirror Repo",
"workspaceFolder": "/login",
"workspaceMount": "source=${localWorkspaceFolder}/apps/login,target=/login,type=bind,consistency=cached",
"mounts": [],
"forwardPorts": [
22220,
22222,
3000,
3001
],
"features": {
"ghcr.io/devcontainers/features/go:1": {
"version": "1.24"
},
"ghcr.io/guiyomh/features/golangci-lint:0": {},
"ghcr.io/jungaretti/features/make:1": {},
"ghcr.io/devcontainers/features/docker-outside-of-docker": {}
}
}

View File

@@ -0,0 +1,14 @@
{
"$schema": "../node_modules/nx/schemas/project-schema.json",
"name": "@zitadel/devcontainer",
"targets": {
"compose": {
"description": "Runs arbitrary Docker Compose commands with dev container support. All running services are manageable and addressable from in- and outside the dev container. The services are defined in .devcontainer/docker-compose.yaml.",
"executor": "nx:run-commands",
"options": {
"cwd": "{projectRoot}",
"command": "./compose.sh"
}
}
}
}

View File

@@ -1,20 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
"name": "Turbo Lint and Unit Tests",
"dockerComposeFile": [
"../base/docker-compose.yaml"
],
"service": "devcontainer",
"runServices": [
"devcontainer"
],
"workspaceFolder": "/workspaces",
"forwardPorts": [
3001
],
"remoteEnv": {
"FAIL_COMMANDS_ON_ERRORS": "${localEnv:FAIL_COMMANDS_ON_ERRORS}"
},
"updateContentCommand": "/commands/turbo-lint-unit.update-content.sh",
"postAttachCommand": "/commands/turbo-lint-unit.post-attach.sh"
}

View File

@@ -1,31 +0,0 @@
# .git
.codecov
.github
.gitignore
.dockerignore
**/Dockerfile
**/node_modules
**/.pnpm-store
**/.turbo
**/.next
/console/src/app/proto/generated/
/console/.angular
/console/tmp/
.releaserc.js
changelog.config.js
CONTRIBUTING.md
LICENSE
README.md
SECURITY.md
**/Dockerfile
**/*.Dockerfile
pkg/grpc/*/*.pb.*
pkg/grpc/*/*.swagger.json
**/.artifacts
console/.angular
console/node_modules
console/src/app/proto/generated/
console/tmp/
build/*.Dockerfile

47
.github/instructions/nx.instructions.md vendored Normal file
View File

@@ -0,0 +1,47 @@
---
applyTo: '**'
---
// This file is automatically generated by Nx Console
You are in an nx workspace using Nx 21.6.1 and pnpm as the package manager.
You have access to the Nx MCP server and the tools it provides. Use them. Follow these guidelines in order to best help the user:
# General Guidelines
- When answering questions, use the nx_workspace tool first to gain an understanding of the workspace architecture
- For questions around nx configuration, best practices or if you're unsure, use the nx_docs tool to get relevant, up-to-date docs!! Always use this instead of assuming things about nx configuration
- If the user needs help with an Nx configuration or project graph error, use the 'nx_workspace' tool to get any errors
- To help answer questions about the workspace structure or simply help with demonstrating how tasks depend on each other, use the 'nx_visualize_graph' tool
# Generation Guidelines
If the user wants to generate something, use the following flow:
- learn about the nx workspace and any specifics the user needs by using the 'nx_workspace' tool and the 'nx_project_details' tool if applicable
- get the available generators using the 'nx_generators' tool
- decide which generator to use. If no generators seem relevant, check the 'nx_available_plugins' tool to see if the user could install a plugin to help them
- get generator details using the 'nx_generator_schema' tool
- you may use the 'nx_docs' tool to learn more about a specific generator or technology if you're unsure
- decide which options to provide in order to best complete the user's request. Don't make any assumptions and keep the options minimalistic
- open the generator UI using the 'nx_open_generate_ui' tool
- wait for the user to finish the generator
- read the generator log file using the 'nx_read_generator_log' tool
- use the information provided in the log file to answer the user's question or continue with what they were doing
# Running Tasks Guidelines
If the user wants help with tasks or commands (which include keywords like "test", "build", "lint", or other similar actions), use the following flow:
- Use the 'nx_current_running_tasks_details' tool to get the list of tasks (this can include tasks that were completed, stopped or failed).
- If there are any tasks, ask the user if they would like help with a specific task then use the 'nx_current_running_task_output' tool to get the terminal output for that task/command
- Use the terminal output from 'nx_current_running_task_output' to see what's wrong and help the user fix their problem. Use the appropriate tools if necessary
- If the user would like to rerun the task or command, always use `nx run <taskId>` to rerun in the terminal. This will ensure that the task will run in the nx context and will be run the same way it originally executed
- If the task was marked as "continuous" do not offer to rerun the task. This task is already running and the user can see the output in the terminal. You can use 'nx_current_running_task_output' to get the output of the task to verify the output.
# CI Error Guidelines
If the user wants help with fixing an error in their CI pipeline, use the following flow:
- Retrieve the list of current CI Pipeline Executions (CIPEs) using the 'nx_cloud_cipe_details' tool
- If there are any errors, use the 'nx_cloud_fix_cipe_failure' tool to retrieve the logs for a specific task
- Use the task logs to see what's wrong and help the user fix their problem. Use the appropriate tools if necessary
- Make sure that the problem is fixed by running the task that you passed into the 'nx_cloud_fix_cipe_failure' tool

View File

@@ -1,144 +0,0 @@
name: ZITADEL CI/CD
on:
push:
tags-ignore:
- "*"
branches:
- "main"
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: write
packages: write
issues: write
pull-requests: write
actions: write
jobs:
core:
uses: ./.github/workflows/core.yml
with:
node_version: "20"
buf_version: "latest"
console:
uses: ./.github/workflows/console.yml
with:
node_version: "20"
docs:
uses: ./.github/workflows/docs.yml
with:
node_version: "20"
buf_version: "latest"
version:
uses: ./.github/workflows/version.yml
with:
semantic_version: "23.0.7"
dry_run: true
compile:
needs: [core, console, version]
uses: ./.github/workflows/compile.yml
with:
core_cache_key: ${{ needs.core.outputs.cache_key }}
console_cache_key: ${{ needs.console.outputs.cache_key }}
core_cache_path: ${{ needs.core.outputs.cache_path }}
console_cache_path: ${{ needs.console.outputs.cache_path }}
version: ${{ needs.version.outputs.version }}
node_version: "20"
core-unit-test:
needs: core
uses: ./.github/workflows/core-unit-test.yml
with:
core_cache_key: ${{ needs.core.outputs.cache_key }}
core_cache_path: ${{ needs.core.outputs.cache_path }}
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
core-integration-test:
needs: core
uses: ./.github/workflows/core-integration-test.yml
with:
core_cache_key: ${{ needs.core.outputs.cache_key }}
core_cache_path: ${{ needs.core.outputs.cache_path }}
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
lint:
needs: [core, console]
uses: ./.github/workflows/lint.yml
with:
node_version: "18"
buf_version: "latest"
go_lint_version: "latest"
core_cache_key: ${{ needs.core.outputs.cache_key }}
core_cache_path: ${{ needs.core.outputs.cache_path }}
container:
needs: [compile]
uses: ./.github/workflows/container.yml
secrets: inherit
permissions:
packages: write
if: ${{ github.event_name == 'workflow_dispatch' }}
with:
build_image_name: "ghcr.io/zitadel/zitadel-build"
login-container:
uses: ./.github/workflows/login-container.yml
permissions:
packages: write
id-token: write
with:
login_build_image_name: "ghcr.io/zitadel/zitadel-login-build"
node_version: "20"
login-integration-test:
uses: ./.github/workflows/login-integration-test.yml
needs: [login-container]
with:
login_build_image: ${{ needs.login-container.outputs.login_build_image }}
e2e:
uses: ./.github/workflows/e2e.yml
needs: [compile]
release:
uses: ./.github/workflows/release.yml
permissions:
packages: write
contents: write
issues: write
pull-requests: write
needs:
[
version,
core-unit-test,
core-integration-test,
lint,
container,
login-container,
e2e,
]
if: ${{ github.event_name == 'workflow_dispatch' }}
secrets:
GCR_JSON_KEY_BASE64: ${{ secrets.GCR_JSON_KEY_BASE64 }}
APP_ID: ${{ secrets.APP_ID }}
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
with:
build_image_name: ${{ needs.container.outputs.build_image }}
semantic_version: "23.0.7"
image_name: "ghcr.io/zitadel/zitadel"
google_image_name: "europe-docker.pkg.dev/zitadel-common/zitadel-repo/zitadel"
build_image_name_login: ${{ needs.login-container.outputs.login_build_image }}
image_name_login: "ghcr.io/zitadel/zitadel-login"
google_image_name_login: "europe-docker.pkg.dev/zitadel-common/zitadel-repo/zitadel-login"

67
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,67 @@
name: CI
on:
push:
tags-ignore:
- "*"
branches:
- "main"
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: write
packages: write
issues: write
pull-requests: write
actions: write
jobs:
lint_test_build:
uses: ./.github/workflows/lint_test_build.yml
with:
node_version: "22"
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
NX_CLOUD_ACCESS_TOKEN_READONLY: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
pack:
uses: ./.github/workflows/pack.yml
secrets:
GCR_JSON_KEY_BASE64: ${{ secrets.GCR_JSON_KEY_BASE64 }}
permissions:
packages: write
if: ${{ github.event_name == 'workflow_dispatch' }}
with:
node_version: "22"
semantic_version: "23.0.7"
image_name_github_api: "ghcr.io/zitadel/zitadel"
image_name_google_api: "europe-docker.pkg.dev/zitadel-common/zitadel-repo/zitadel"
image_name_github_login: "ghcr.io/zitadel/zitadel-login"
image_name_google_login: "europe-docker.pkg.dev/zitadel-common/zitadel-repo/zitadel-login"
release:
uses: ./.github/workflows/release.yml
permissions:
packages: write
contents: write
issues: write
pull-requests: write
needs:
- lint_test_build
- pack
if: ${{ github.event_name == 'workflow_dispatch' }}
secrets:
GCR_JSON_KEY_BASE64: ${{ secrets.GCR_JSON_KEY_BASE64 }}
APP_ID: ${{ secrets.APP_ID }}
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
with:
semantic_version: "23.0.7"
image_name_github_api: "ghcr.io/zitadel/zitadel"
image_name_google_api: "europe-docker.pkg.dev/zitadel-common/zitadel-repo/zitadel"
image_name_github_login: "ghcr.io/zitadel/zitadel-login"
image_name_google_login: "europe-docker.pkg.dev/zitadel-common/zitadel-repo/zitadel-login"

View File

@@ -25,21 +25,21 @@ jobs:
matrix:
language: [go,javascript]
steps:
- name: Checkout repository
- name: Checkout Repository
uses: actions/checkout@v4
- if: matrix.language == 'go'
name: Install Go
uses: actions/setup-go@v5
with:
go-version-file: go.mod
# node to install sass for go
- if: matrix.language == 'go'
uses: actions/setup-node@v4
- if: matrix.language == 'go'
name: Set up pnpm
uses: pnpm/action-setup@v4
- name: Generate gRPC Stubs and Static Assets
if: matrix.language == 'go'
run: |
npm install -g sass
make core_build
pnpm install --frozen-lockfile
pnpm nx run-many --nxBail --projects @zitadel/api --targets generate-stubs generate-statik generate-assets
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3

View File

@@ -1,89 +0,0 @@
name: Compile
on:
workflow_call:
inputs:
core_cache_key:
required: true
type: string
core_cache_path:
required: true
type: string
console_cache_key:
required: true
type: string
console_cache_path:
required: true
type: string
version:
required: true
type: string
node_version:
required: true
type: string
jobs:
executable:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
goos: [linux, darwin, windows]
goarch: [amd64, arm64]
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
timeout-minutes: 1
name: restore console
with:
path: ${{ inputs.console_cache_path }}
key: ${{ inputs.console_cache_key }}
fail-on-cache-miss: true
- uses: actions/cache/restore@v4
timeout-minutes: 1
name: restore core
with:
path: ${{ inputs.core_cache_path }}
key: ${{ inputs.core_cache_key }}
fail-on-cache-miss: true
- uses: actions/setup-go@v5
with:
go-version-file: "go.mod"
- name: compile
timeout-minutes: 5
run: |
GOOS="${{matrix.goos}}" \
GOARCH="${{matrix.goarch}}" \
VERSION="${{ inputs.version }}" \
COMMIT_SHA="${{ github.sha }}" \
make compile_pipeline
- name: create folder
run: |
mkdir zitadel-${{ matrix.goos }}-${{ matrix.goarch }}
mv zitadel zitadel-${{ matrix.goos }}-${{ matrix.goarch }}/
cp LICENSE zitadel-${{ matrix.goos }}-${{ matrix.goarch }}/
cp README.md zitadel-${{ matrix.goos }}-${{ matrix.goarch }}/
tar -czvf zitadel-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz zitadel-${{ matrix.goos }}-${{ matrix.goarch }}
- uses: actions/upload-artifact@v4
with:
name: zitadel-${{ matrix.goos }}-${{ matrix.goarch }}
path: zitadel-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz
checksums:
runs-on: ubuntu-latest
needs: [executable]
steps:
- uses: actions/download-artifact@v4
with:
path: executables
pattern: 'zitadel-*-*'
- name: move files one folder up
run: mv */*.tar.gz . && find . -type d -empty -delete
working-directory: executables
- run: sha256sum * > checksums.txt
working-directory: executables
- uses: actions/upload-artifact@v4
with:
name: checksums.txt
path: executables/checksums.txt

View File

@@ -1,52 +0,0 @@
name: Build console
on:
workflow_call:
inputs:
node_version:
required: true
type: string
outputs:
cache_key:
value: ${{ jobs.build.outputs.cache_key }}
cache_path:
value: ${{ jobs.build.outputs.cache_path }}
env:
cache_path: console/dist/console
jobs:
build:
outputs:
cache_key: ${{ steps.cache.outputs.cache-primary-key }}
cache_path: ${{ env.cache_path }}
runs-on:
group: zitadel-public
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
timeout-minutes: 1
continue-on-error: true
id: cache
with:
key: console-${{ hashFiles('console', 'proto', '!console/dist') }}-next
path: ${{ env.cache_path }}
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: pnpm/action-setup@v4
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node_version }}
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
name: Install dependencies
run: pnpm install --frozen-lockfile
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
name: Build console with Turbo
run: pnpm turbo build --filter=./console
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v4
with:
path: ${{ env.cache_path }}
key: ${{ steps.cache.outputs.cache-primary-key }}

View File

@@ -1,173 +0,0 @@
name: Container
on:
workflow_call:
inputs:
build_image_name:
required: true
type: string
outputs:
build_image:
value: '${{ inputs.build_image_name }}:${{ github.sha }}'
permissions:
packages: write
env:
default_labels: |
org.opencontainers.image.documentation=https://zitadel.com/docs
org.opencontainers.image.vendor=CAOS AG
jobs:
build:
name: zitadel
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
arch: [amd64,arm64]
steps:
-
uses: actions/checkout@v4
-
name: Scratch meta
id: scratch-meta
uses: docker/metadata-action@v5
with:
images: ${{ inputs.build_image_name }}
labels: ${{ env.default_labels}}
tags: |
type=sha,prefix=,suffix=,format=long
-
name: Debug meta
id: debug-meta
uses: docker/metadata-action@v5
with:
images: ${{ inputs.build_image_name }}
labels: ${{ env.default_labels}}
tags: |
type=sha,prefix=,suffix=-debug,format=long
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Login to Docker registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
-
uses: actions/download-artifact@v4
with:
path: .artifacts
name: zitadel-linux-${{ matrix.arch }}
-
name: Unpack executable
run: |
tar -xvf .artifacts/zitadel-linux-${{ matrix.arch }}.tar.gz
mv zitadel-linux-${{ matrix.arch }}/zitadel ./zitadel
-
name: Debug
id: build-debug
uses: docker/build-push-action@v6
timeout-minutes: 5
with:
context: .
cache-from: type=gha
cache-to: type=gha,mode=max
file: build/zitadel/Dockerfile
target: artifact
platforms: linux/${{ matrix.arch }}
push: true
labels: ${{ steps.debug-meta.outputs.labels }}
outputs: type=image,name=${{ inputs.build_image_name }},push-by-digest=true,name-canonical=true,push=true
-
name: Scratch
id: build-scratch
uses: docker/build-push-action@v6
timeout-minutes: 3
with:
context: .
cache-from: type=gha
cache-to: type=gha,mode=max
file: build/zitadel/Dockerfile
target: final
platforms: linux/${{ matrix.arch }}
push: true
labels: ${{ steps.scratch-meta.outputs.labels }}
outputs: type=image,name=${{ inputs.build_image_name }},push-by-digest=true,name-canonical=true,push=true
-
name: Export debug digest
run: |
mkdir -p /tmp/digests/debug
digest="${{ steps.build-debug.outputs.digest }}"
touch "/tmp/digests/debug/${digest#sha256:}"
-
name: Export scratch digest
run: |
mkdir -p /tmp/digests/scratch
digest="${{ steps.build-scratch.outputs.digest }}"
touch "/tmp/digests/scratch/${digest#sha256:}"
-
name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests-${{ matrix.arch }}
path: /tmp/digests
if-no-files-found: error
retention-days: 1
merge:
runs-on: ubuntu-latest
needs:
- build
strategy:
fail-fast: false
matrix:
image: [scratch, debug]
include:
- image: scratch
suffix: ''
- image: debug
suffix: '-debug'
steps:
-
name: Download digests
uses: actions/download-artifact@v4
with:
pattern: digests-*
path: /tmp/digests
merge-multiple: true
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Login to Docker registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
-
name: Docker meta
id: build-meta
uses: docker/metadata-action@v5
with:
images: '${{ inputs.build_image_name }}'
tags: |
type=sha,prefix=,suffix=${{ matrix.suffix }},format=long
-
name: Create build manifest list and push
working-directory: /tmp/digests/${{ matrix.image }}
run: |
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< '${{ steps.build-meta.outputs.json }}') \
$(printf '${{ inputs.build_image_name }}@sha256:%s ' *)
-
name: Inspect build image
run: |
docker buildx imagetools inspect ${{ inputs.build_image_name }}:${{ github.sha }}${{ matrix.suffix }}

View File

@@ -1,100 +0,0 @@
name: Integration test core
on:
workflow_call:
inputs:
core_cache_key:
required: true
type: string
core_cache_path:
required: true
type: string
secrets:
CODECOV_TOKEN:
required: true
jobs:
postgres:
runs-on:
group: zitadel-public
services:
postgres:
image: postgres:17
ports:
- 5432:5432
env:
POSTGRES_USER: zitadel
PGUSER: zitadel
POSTGRES_DB: zitadel
POSTGRES_HOST_AUTH_METHOD: trust
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
--health-start-period 10s
cache:
image: redis:latest
ports:
- 6379:6379
steps:
-
uses: actions/checkout@v4
-
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
-
uses: actions/cache/restore@v4
timeout-minutes: 1
name: restore core
id: restore-core
with:
path: ${{ inputs.core_cache_path }}
key: ${{ inputs.core_cache_key }}
fail-on-cache-miss: true
-
id: go-cache-path
name: set cache path
run: echo "GO_CACHE_PATH=$(go env GOCACHE)" >> $GITHUB_OUTPUT
-
uses: actions/cache/restore@v4
id: cache
timeout-minutes: 1
continue-on-error: true
name: restore previous results
with:
key: integration-test-postgres-${{ inputs.core_cache_key }}
restore-keys: |
integration-test-postgres-core-
path: ${{ steps.go-cache-path.outputs.GO_CACHE_PATH }}
-
name: test
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
env:
ZITADEL_MASTERKEY: MasterkeyNeedsToHave32Characters
run: make core_integration_test
-
name: upload server logs
if: always()
uses: actions/upload-artifact@v4
with:
name: integration-test-server-logs
path: |
tmp/zitadel.log
tmp/race.log.*
-
name: publish coverage
uses: codecov/codecov-action@v4.3.0
with:
file: profile.cov
name: core-integration-tests-postgres
flags: core-integration-tests-postgres
token: ${{ secrets.CODECOV_TOKEN }}
-
uses: actions/cache/save@v4
name: cache results
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
with:
key: integration-test-postgres-${{ inputs.core_cache_key }}
path: ${{ steps.go-cache-path.outputs.GO_CACHE_PATH }}

View File

@@ -1,73 +0,0 @@
name: Unit test core
on:
workflow_call:
inputs:
core_cache_key:
required: true
type: string
core_cache_path:
required: true
type: string
crdb_version:
required: false
type: string
secrets:
CODECOV_TOKEN:
required: true
jobs:
test:
runs-on:
group: zitadel-public
steps:
-
uses: actions/checkout@v3
-
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
-
uses: actions/cache/restore@v4
timeout-minutes: 1
name: restore core
id: restore-core
with:
path: ${{ inputs.core_cache_path }}
key: ${{ inputs.core_cache_key }}
fail-on-cache-miss: true
-
id: go-cache-path
name: set cache path
run: echo "GO_CACHE_PATH=$(go env GOCACHE)" >> $GITHUB_OUTPUT
-
uses: actions/cache/restore@v4
id: cache
timeout-minutes: 1
continue-on-error: true
name: restore previous results
with:
key: unit-test-${{ inputs.core_cache_key }}
restore-keys: |
unit-test-core-
path: ${{ steps.go-cache-path.outputs.GO_CACHE_PATH }}
-
name: test
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
run: make core_unit_test
-
name: publish coverage
uses: codecov/codecov-action@v4.3.0
with:
file: profile.cov
name: core-unit-tests
flags: core-unit-tests
token: ${{ secrets.CODECOV_TOKEN }}
-
uses: actions/cache/save@v4
name: cache results
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
with:
key: unit-test-${{ inputs.core_cache_key }}
path: ${{ steps.go-cache-path.outputs.GO_CACHE_PATH }}

View File

@@ -1,79 +0,0 @@
name: Build core
on:
workflow_call:
inputs:
buf_version:
required: true
type: string
node_version:
required: true
type: string
outputs:
cache_key:
value: ${{ jobs.build.outputs.cache_key }}
cache_path:
value: ${{ jobs.build.outputs.cache_path }}
env:
cache_path: |
internal/statik/statik.go
internal/notification/statik/statik.go
internal/api/ui/login/static/resources/themes/zitadel/css/zitadel.css*
internal/api/ui/login/statik/statik.go
internal/api/assets/authz.go
internal/api/assets/router.go
openapi/v2
pkg/grpc/**/*.pb.*
pkg/grpc/**/*.connect.go
jobs:
build:
runs-on:
group: zitadel-public
outputs:
cache_key: ${{ steps.cache.outputs.cache-primary-key }}
cache_path: ${{ env.cache_path }}
steps:
-
uses: actions/checkout@v4
-
uses: actions/cache/restore@v4
timeout-minutes: 1
continue-on-error: true
id: cache
with:
key: core-${{ hashFiles( 'go.*', 'openapi', 'cmd', 'pkg/grpc/**/*.go', 'proto', 'internal') }}-next
path: ${{ env.cache_path }}
-
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: bufbuild/buf-setup-action@v1
with:
github_token: ${{ github.token }}
version: ${{ inputs.buf_version }}
-
# node to install sass
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node_version }}
-
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
run: npm install -g sass
-
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
-
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
run: make core_build
-
if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v4
with:
key: ${{ steps.cache.outputs.cache-primary-key }}
path: ${{ env.cache_path }}

View File

@@ -1,61 +0,0 @@
name: Build docs
on:
workflow_call:
inputs:
node_version:
required: true
type: string
buf_version:
required: true
type: string
outputs:
cache_key:
value: ${{ jobs.build.outputs.cache_key }}
cache_path:
value: ${{ jobs.build.outputs.cache_path }}
env:
cache_path: docs/build
jobs:
build:
outputs:
cache_key: ${{ steps.cache.outputs.cache-primary-key }}
cache_path: ${{ env.cache_path }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/cache/restore@v4
timeout-minutes: 1
continue-on-error: true
id: cache
with:
key: docs-${{ hashFiles('docs', 'proto', '!docs/build', '!docs/node_modules', '!docs/protoc-gen-connect-openapi') }}
restore-keys: |
docs-
path: ${{ env.cache_path }}
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: bufbuild/buf-setup-action@v1
with:
github_token: ${{ github.token }}
version: ${{ inputs.buf_version }}
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: pnpm/action-setup@v4
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node_version }}
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
name: Install dependencies
run: pnpm install
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
name: Build docs with Turbo
run: pnpm turbo build --filter=./docs
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
uses: actions/cache/save@v4
with:
path: ${{ env.cache_path }}
key: ${{ steps.cache.outputs.cache-primary-key }}

View File

@@ -1,64 +0,0 @@
name: "ZITADEL e2e Tests"
on:
workflow_call:
jobs:
test:
timeout-minutes: 10
strategy:
fail-fast: false
matrix:
browser: [firefox, chrome]
runs-on:
group: zitadel-public
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
path: .artifacts
name: zitadel-linux-amd64
- name: Unpack executable
run: |
tar -xvf .artifacts/zitadel-linux-amd64.tar.gz
mv zitadel-linux-amd64/zitadel ./zitadel
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"
cache-dependency-path: pnpm-lock.yaml
- name: Install dependencies
run: pnpm install
- name: Install Cypress binary
run: cd ./e2e && pnpm exec cypress install
- name: Start DB and ZITADEL
run: |
cd ./e2e
ZITADEL_IMAGE=zitadel:local docker compose up --detach --wait
- name: Cypress run
uses: cypress-io/github-action@v6
env:
CYPRESS_BASE_URL: http://localhost:8080/ui/console
CYPRESS_WEBHOOK_HANDLER_HOST: host.docker.internal
CYPRESS_DATABASE_CONNECTION_URL: "postgresql://root@localhost:26257/zitadel"
CYPRESS_BACKEND_URL: http://localhost:8080
with:
working-directory: e2e
browser: ${{ matrix.browser }}
config-file: cypress.config.ts
install: false
- uses: actions/upload-artifact@v4
if: always()
with:
name: production-tests-${{ matrix.browser }}
path: |
e2e/cypress/screenshots
e2e/cypress/videos
e2e/cypress/results
retention-days: 30

View File

@@ -1,93 +0,0 @@
name: Lint
on:
workflow_call:
inputs:
node_version:
required: true
type: string
buf_version:
required: true
type: string
go_lint_version:
required: true
type: string
core_cache_key:
required: true
type: string
core_cache_path:
required: true
type: string
jobs:
lint-skip:
name: lint skip
runs-on: ubuntu-latest
if: ${{ github.event_name != 'pull_request' }}
steps:
- name: Lint skip
run: |
echo "Linting outside of pull requests is skipped"
api:
name: api
runs-on: ubuntu-latest
continue-on-error: true
if: ${{ github.event_name == 'pull_request' }}
steps:
- uses: actions/checkout@v4
- uses: bufbuild/buf-setup-action@v1
with:
version: ${{ inputs.buf_version }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: lint
uses: bufbuild/buf-lint-action@v1
- uses: bufbuild/buf-breaking-action@v1
with:
against: "https://github.com/${{ github.repository }}.git#branch=${{ github.base_ref }}"
turbo-lint-unit:
if: ${{ github.event_name == 'pull_request' }}
name: turbo-lint-unit
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Dev Container CLI
run: npm install -g @devcontainers/cli@0.80.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Lint and Unit Test All JavaScript Code
run: npm run devcontainer:lint-unit
- name: Fix Failures
if: failure()
run: |
echo "Reproduce this check locally:"
echo "npm run devcontainer:lint-unit"
echo "If you have pnpm installed, most linting errors can be fixed automatically:"
echo "pnpm turbo lint:fix"
echo "In other cases, you can open the dev container called \"Turbo Lint and Unit Tests\"."
echo "You will have the same environment as the pipeline check as well as some guidance on how to fix the errors."
core:
name: core
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version-file: "go.mod"
- uses: actions/cache/restore@v4
timeout-minutes: 1
name: restore core
with:
path: ${{ inputs.core_cache_path }}
key: ${{ inputs.core_cache_key }}
fail-on-cache-miss: true
- uses: golangci/golangci-lint-action@v8
with:
version: ${{ inputs.go_lint_version }}
github-token: ${{ github.token }}
only-new-issues: true

98
.github/workflows/lint_test_build.yml vendored Normal file
View File

@@ -0,0 +1,98 @@
name: Lint Test Build
on:
workflow_call:
inputs:
node_version:
required: true
type: string
secrets:
CODECOV_TOKEN:
required: true
NX_CLOUD_ACCESS_TOKEN_READONLY:
required: true
jobs:
lint_test_build:
name: Lint, Test and Build
runs-on: depot-ubuntu-22.04-16
environment: ${{ github.ref_protected == 'true' && 'Protected' || null }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
filter: tree:0
- name: Fetch main branch
run: git fetch origin main:main
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- name: Set up pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node_version }}
cache: "pnpm"
- name: Set up Docker
uses: docker/setup-docker-action@v4
with:
version: v28.3.2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
version: v0.28.0
- name: Set up Docker Compose
uses: docker/setup-compose-action@v1
with:
version: v2.38.2
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Install Cypress binary
run: pnpm cypress install
working-directory: apps/login
- name: Set SHAs for nx affected commands
uses: nrwl/nx-set-shas@v4
- name: Lint, Test and Build
env:
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN || secrets.NX_CLOUD_ACCESS_TOKEN_READONLY }}
run: pnpm nx affected --nxBail --targets lint test build --exclude @zitadel/docs
- name: Suggest Pipeline Fix By Nx Cloud AI
if: failure() || cancelled()
env:
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN || secrets.NX_CLOUD_ACCESS_TOKEN_READONLY }}
run: pnpm nx fix-ci
- name: Publish API Unit Test Coverage
uses: codecov/codecov-action@v4.3.0
with:
file: profile.api.test-unit.cov
name: api-test-unit
flags: api-test-unit
token: ${{ secrets.CODECOV_TOKEN }}
- name: Publish API Integration Test Coverage
uses: codecov/codecov-action@v4.3.0
with:
file: profile.api.test-integration.cov
name: api-test-integration
flags: api-test-integration
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload API Integration Test Race Logs
if: failure() || cancelled()
uses: actions/upload-artifact@v4
with:
name: api-integration-test-race-logs
path: |
.artifacts/api-test-integration/race.log.*
- name: Upload Functional UI Test Artifacts
uses: actions/upload-artifact@v4
if: failure() || cancelled()
with:
name: functional-ui-tests
path: |
tests/functional-ui/cypress/screenshots
tests/functional-ui/cypress/videos
tests/functional-ui/cypress/results

View File

@@ -1,69 +0,0 @@
name: Login Container
on:
workflow_call:
inputs:
login_build_image_name:
description: 'The image repository name of the standalone login image'
type: string
required: true
node_version:
required: true
type: string
outputs:
login_build_image:
description: 'The full image tag of the standalone login image'
value: ${{ inputs.login_build_image_name }}:${{ github.sha }}
permissions:
packages: write
env:
default_labels: |
org.opencontainers.image.documentation=https://zitadel.com/docs
org.opencontainers.image.vendor=CAOS AG
org.opencontainers.image.licenses=MIT
jobs:
login-container:
name: Build Login Container
runs-on: ubuntu-latest
permissions:
packages: write
outputs:
login_build_image: ${{ steps.short-sha.outputs.login_build_image }}
steps:
- uses: actions/checkout@v4
- name: Login meta
id: login-meta
uses: docker/metadata-action@v5
with:
images: ${{ inputs.login_build_image_name }}
labels: ${{ env.default_labels}}
annotations: |
manifest:org.opencontainers.image.licenses=MIT
tags: |
type=sha,prefix=,format=long
- name: Login to Docker registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
id: setup-buildx
uses: docker/setup-buildx-action@v3
- name: Bake login multi-arch
uses: docker/bake-action@v6
env:
NODE_VERSION: ${{ inputs.node_version }}
with:
source: .
push: true
provenance: true
targets: login-standalone
files: |
./apps/login/docker-bake.hcl
${{ github.event_name == 'workflow_dispatch' && './apps/login/docker-bake-release.hcl' || '' }}
./docker-bake.hcl
cwd://${{ steps.login-meta.outputs.bake-file }}

View File

@@ -1,58 +0,0 @@
name: Integration test core
on:
workflow_call:
inputs:
login_build_image:
required: true
type: string
permissions:
packages: write
jobs:
login-integration-test:
name: login-integration-test
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Dev Container CLI
run: npm install -g @devcontainers/cli@0.80.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Pull Login Build Image
run: docker compose --file .devcontainer/login-integration/docker-compose.yaml pull
env:
LOGIN_TAG: ${{ inputs.login_build_image }}
- name: Run Integration Tests against the Login and a Mocked Zitadel API
run: npm run devcontainer:integration:login
env:
LOGIN_TAG: ${{ inputs.login_build_image }}
DOCKER_BUILDKIT: 1
- name: Fix Failures
if: failure()
run: |
echo "Reproduce this check locally:"
echo "LOGIN_TAG=${{ inputs.login_build_image }} npm run devcontainer:integration:login"
echo "To fix the failures, open the dev container called \"Login Integration Tests\"."
echo "You will have the same environment as the pipeline check as well as some guidance on how to fix the errors."
- name: Show Compose Status
if: failure()
run: docker compose --file .devcontainer/base/docker-compose.yaml --file .devcontainer/login-integration/docker-compose.yaml ps
- name: Print Config
if: failure()
run: COMPOSE_BAKE=1 docker compose --file .devcontainer/base/docker-compose.yaml --file .devcontainer/login-integration/docker-compose.yaml config login-integration
env:
LOGIN_TAG: ${{ inputs.login_build_image }}
- name: Show Container Logs
if: failure()
run: docker compose --file .devcontainer/base/docker-compose.yaml --file .devcontainer/login-integration/docker-compose.yaml logs --timestamps --no-color --tail 100 login-integration
- name: Inspect All Failed Containers
if: failure()
run: |
docker ps -a --filter "status=exited" --filter "status=created" --format "table {{.ID}}\t{{.Names}}\t{{.Status}}\t{{.Image}}"
for container in $(docker ps -a --filter "status=exited" --filter "status=created" -q); do
echo "Inspecting container $container"
docker inspect $container || true
done

177
.github/workflows/pack.yml vendored Normal file
View File

@@ -0,0 +1,177 @@
name: Package und Publish Archives and Images
on:
workflow_call:
inputs:
node_version:
required: true
type: string
image_name_github_api:
required: true
type: string
image_name_github_login:
required: true
type: string
image_name_google_api:
required: true
type: string
image_name_google_login:
required: true
type: string
semantic_version:
required: false
type: string
secrets:
GCR_JSON_KEY_BASE64:
description: 'base64 endcrypted key to connect to Google'
required: true
permissions:
packages: write
env:
default_labels: |
org.opencontainers.image.documentation=https://zitadel.com/docs
org.opencontainers.image.vendor=ZITADEL
jobs:
version:
uses: ./.github/workflows/version.yml
with:
semantic_version: ${{ inputs.semantic_version }}
dry_run: true
pack:
runs-on:
group: zitadel-public
environment: ${{ github.ref_protected == 'true' && 'Protected' || null }}
needs: version
steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
fetch-depth: 0
filter: tree:0
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version-file: 'go.mod'
- name: Set up pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ inputs.node_version }}
cache: "pnpm"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
version: v0.28.0
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Pack API and Login
env:
ZITADEL_VERSION: ${{ needs.version.outputs.version }}
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN || secrets.NX_CLOUD_ACCESS_TOKEN_READONLY }}
run: pnpm nx run --nxBail pack
- name: Suggest Pipeline Fix By Nx Cloud AI
if: always()
env:
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN || secrets.NX_CLOUD_ACCESS_TOKEN_READONLY }}
run: pnpm nx fix-ci
- name: Upload all platform archives
uses: actions/upload-artifact@v4
with:
name: zitadel-archives
path: .artifacts/pack
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Google Artifact Registry
uses: docker/login-action@v3
with:
registry: europe-docker.pkg.dev
username: _json_key_base64
password: ${{ secrets.GCR_JSON_KEY_BASE64 }}
- name: Generate Standard Tags and Labels from the GitHub Context for the API Scratch Container Image
id: scratch-meta
uses: docker/metadata-action@v5
with:
images: |
${{ inputs.image_name_github_api }}
${{ inputs.image_name_google_api }}
labels: ${{ env.default_labels}}
tags: |
type=sha,prefix=,suffix=,format=long
- name: Build and Push the SHA-tagged API Scratch Container Image
id: build-scratch
uses: docker/build-push-action@v6
timeout-minutes: 3
with:
context: .
cache-from: type=gha
cache-to: type=gha,mode=max
file: apps/api/Dockerfile
target: final
platforms: linux/amd64,linux/arm64
push: true
labels: ${{ steps.scratch-meta.outputs.labels }}
tags: ${{ steps.scratch-meta.outputs.tags }}
- name: Generate Standard Tags and Labels from the GitHub Context for the API Debug Container Image
id: debug-meta
uses: docker/metadata-action@v5
with:
images: |
${{ inputs.image_name_github_api }}
${{ inputs.image_name_google_api }}
labels: ${{ env.default_labels}}
tags: |
type=sha,prefix=,suffix=-debug,format=long
- name: Build and Push the SHA-tagged API Debug Container Image
id: build-debug
uses: docker/build-push-action@v6
timeout-minutes: 5
with:
context: .
cache-from: type=gha
cache-to: type=gha,mode=max
file: apps/api/Dockerfile
target: builder
platforms: linux/amd64,linux/arm64
push: true
labels: ${{ steps.debug-meta.outputs.labels }}
tags: ${{ steps.debug-meta.outputs.tags }}
outputs: type=image,name=${{ inputs.image_name_github_api }},name-canonical=true
- name: Generate Standard Tags and Labels from the GitHub Context for the Login Container Image
id: login-meta
uses: docker/metadata-action@v5
with:
images: |
${{ inputs.image_name_github_login }}
${{ inputs.image_name_google_login }}
labels: |
org.opencontainers.image.licenses=MIT
${{ env.default_labels}}
tags: |
type=sha,prefix=,suffix=,format=long
- name: Build and Push the SHA-tagged Login Container Image
id: build-login
uses: docker/build-push-action@v6
timeout-minutes: 3
with:
context: apps/login
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
push: true
labels: ${{ steps.login-meta.outputs.labels }}
tags: ${{ steps.login-meta.outputs.tags }}

View File

@@ -6,22 +6,16 @@ on:
semantic_version:
required: true
type: string
build_image_name:
image_name_github_api:
required: true
type: string
image_name:
image_name_google_api:
required: true
type: string
google_image_name:
image_name_github_login:
required: true
type: string
build_image_name_login:
required: true
type: string
image_name_login:
required: true
type: string
google_image_name_login:
image_name_google_login:
required: true
type: string
secrets:
@@ -47,7 +41,8 @@ jobs:
# https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28#create-a-release--parameters
publish:
runs-on: ubuntu-22.04
needs: [ version ]
needs: version
if: needs.version.outputs.published == 'true'
steps:
- id: get_release
uses: cardinalby/git-get-release-action@v1
@@ -72,6 +67,7 @@ jobs:
docker:
runs-on: ubuntu-22.04
needs: [ version ]
if: needs.version.outputs.published == 'true'
steps:
-
name: Set up QEMU
@@ -97,38 +93,38 @@ jobs:
name: Publish ${{ needs.version.outputs.version }}
run: |
docker buildx imagetools create \
--tag ${{ inputs.image_name }}:${{ needs.version.outputs.version }} \
${{ inputs.build_image_name }}
--tag ${{ inputs.image_name_github_api }}:${{ needs.version.outputs.version }} \
${{ inputs.image_name_github_api }}:${{ github.sha }}
docker buildx imagetools create \
--tag ${{ inputs.image_name }}:${{ needs.version.outputs.version }}-debug \
${{ inputs.build_image_name }}-debug
--tag ${{ inputs.image_name_github_api }}:${{ needs.version.outputs.version }}-debug \
${{ inputs.image_name_github_api }}:${{ github.sha }}-debug
docker buildx imagetools create \
--tag ${{ inputs.google_image_name }}:${{ needs.version.outputs.version }} \
${{ inputs.build_image_name }}
--tag ${{ inputs.image_name_google_api }}:${{ needs.version.outputs.version }} \
${{ inputs.image_name_google_api }}:${{ github.sha }}
docker buildx imagetools create \
--tag ${{ inputs.image_name_login }}:${{ needs.version.outputs.version }} \
${{ inputs.build_image_name_login }}
--tag ${{ inputs.image_name_github_login }}:${{ needs.version.outputs.version }} \
${{ inputs.image_name_github_login }}:${{ github.sha }}
docker buildx imagetools create \
--tag ${{ inputs.google_image_name_login }}:${{ needs.version.outputs.version }} \
${{ inputs.build_image_name_login }}
--tag ${{ inputs.image_name_google_login }}:${{ needs.version.outputs.version }} \
${{ inputs.image_name_google_login }}:${{ github.sha }}
-
name: Publish latest
if: ${{ github.ref_name == 'next' }}
run: |
docker buildx imagetools create \
--tag ${{ inputs.image_name }}:latest \
${{ inputs.build_image_name }}
--tag ${{ inputs.image_name_github_api }}:latest \
${{ inputs.image_name_github_api }}:${{ github.sha }}
docker buildx imagetools create \
--tag ${{ inputs.image_name }}:latest-debug \
${{ inputs.build_image_name }}-debug
--tag ${{ inputs.image_name_github_api }}:latest-debug \
${{ inputs.image_name_github_api }}:${{ github.sha }}-debug
docker buildx imagetools create \
--tag ${{ inputs.image_name_login }}:latest \
${{ inputs.build_image_name_login }}
--tag ${{ inputs.image_name_github_login }}:latest \
${{ inputs.image_name_github_login }}:${{ github.sha }}
homebrew-tap:
runs-on: ubuntu-22.04
needs: version
if: ${{ github.ref_name == 'next' }}
if: needs.version.outputs.published == 'true' && github.ref_name == 'next'
continue-on-error: true
steps:
- name: generate token
@@ -148,7 +144,7 @@ jobs:
helm-chart:
runs-on: ubuntu-22.04
needs: version
if: ${{ github.ref_name == 'next' }}
if: needs.version.outputs.published == 'true' && github.ref_name == 'next'
continue-on-error: true
steps:
- name: generate token
@@ -168,7 +164,7 @@ jobs:
npm-packages:
runs-on: ubuntu-latest
needs: version
if: ${{ github.ref_name == 'next' }}
if: needs.version.outputs.published == 'true' && github.ref_name == 'next'
continue-on-error: true
steps:
- name: Checkout code
@@ -194,26 +190,3 @@ jobs:
version: ${{ needs.version.outputs.version }}
cwd: packages
createGithubReleases: false
login-repo:
runs-on: ubuntu-latest
needs: version
if: ${{ github.ref_name == 'next' }}
continue-on-error: true
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Push Subtree
run: make login_push LOGIN_REMOTE_BRANCH=mirror-zitadel-repo
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: 'chore: mirror zitadel repo'
branch: mirror-zitadel-repo
title: 'chore: mirror zitadel repo'
body: 'This PR updates the login repository with the latest changes from the zitadel repository.'
base: main
reviewers: |
@peintnermax
@eliobischof

View File

@@ -11,12 +11,12 @@ on:
type: boolean
outputs:
version:
value: ${{ jobs.generate.outputs.version }}
value: ${{ jobs.semantic.outputs.version }}
published:
value: ${{jobs.generate.outputs.published }}
value: ${{jobs.semantic.outputs.published }}
jobs:
generate:
semantic:
runs-on: ubuntu-22.04
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -25,16 +25,17 @@ jobs:
published: ${{ steps.semantic.outputs.new_release_published }}
steps:
-
name: Source checkout
name: Checkout Repository
uses: actions/checkout@v4
-
name: Download Artifacts
uses: actions/download-artifact@v4
if: ${{ !inputs.dry_run }}
with:
path: .artifacts
pattern: "{checksums.txt,zitadel-*}"
-
name: Semantic Release
name: Run Semantic Release
uses: cycjimmy/semantic-release-action@v4
id: semantic
env:
@@ -46,7 +47,7 @@ jobs:
@semantic-release/exec@6.0.3
@semantic-release/github@10.0.2
-
name: output
name: Output Version For Dependent Workflows
id: output
run:
if [[ ! -z "${{ steps.semantic.outputs.new_release_version }}" ]]; then echo "VERSION=v${{ steps.semantic.outputs.new_release_version }}" >> "$GITHUB_OUTPUT"; else echo "VERSION=${{ github.sha }}" >> "$GITHUB_OUTPUT";fi

24
.gitignore vendored
View File

@@ -11,7 +11,7 @@
# Coverage
coverage.txt
profile.cov
profile*.cov
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
@@ -24,9 +24,9 @@ sandbox.go
# IDE
.idea
.vscode
.DS_STORE
.run
.vscode
# credential
google-credentials
@@ -47,7 +47,6 @@ cmd/zitadel/zitadel
/zitadel
# buildfolders and generated files
tmp/
console/src/app/proto/generated/
**.pb.go
!pkg/grpc/protoc/v2/options.pb.go
@@ -79,21 +78,22 @@ build/local/*.env
/zitadel
node_modules/
.kreya
login-client.pat
admin.pat
.env.*local
go.work
go.work.sum
# Local Netlify folder
.netlify
load-test/node_modules
load-test/pnpm-debug.log
load-test/dist
load-test/output/*
dist
.vercel
# Turbo
.turbo/
**/.turbo/
# PNPM
.pnpm-store
.pnpm-store
# Nx
.nx/cache
.nx/workspace-data
.cursor/rules/nx-rules.mdc

View File

@@ -99,6 +99,7 @@ linters:
- .github
- .keys
- .vscode
- .devcontainer
- build
- deploy
- guides
@@ -113,12 +114,13 @@ linters:
- packages
- console
- docs
- load-test
- benchmark
- tests
issues:
max-issues-per-linter: 0
max-same-issues: 0
new-from-rev: main
new-from-rev: origin/main
formatters:
enable:
- gci
@@ -138,6 +140,7 @@ formatters:
- .github
- .keys
- .vscode
- .devcontainer
- build
- deploy
- guides
@@ -152,4 +155,5 @@ formatters:
- packages
- console
- docs
- load-test
- benchmark
- tests

View File

@@ -1,10 +1,83 @@
# Contributing to Zitadel
Zitadel is an open-source identity and access management platform built with a modern tech stack including Go (API), Next.js/React (Login), Angular (Console), and Docusaurus (Docs) - all orchestrated through an Nx monorepo with pnpm for efficient development workflows.
## Quick Start
1. Clone the repository: `git clone https://github.com/zitadel/zitadel` or [open it in a local Dev Container](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/zitadel/zitadel) or [create a GitHub Codespace](https://codespaces.new/zitadel/zitadel)
2. If you cloned the repository to your local machine, install the required development dependencies
- [Node.js v22.x](https://nodejs.org/en/download/) - Required for UI development and to run development commands `pnpm nx ...`
- [Go 1.24.x](https://go.dev/doc/install) - Required for API development
- [Docker](https://docs.docker.com/engine/install/) - Required for supporting services like the development database and for tests.
- [Cypress runtime dependencies](https://docs.cypress.io/guides/continuous-integration/introduction#Dependencies) - Required for Browser UI tests
<details>
<summary>WSL2 on Windows 10 users (click to expand)</summary>
For Cypress tests on WSL2, you may need to configure X11 forwarding. Following suggestions [here](https://stackoverflow.com/questions/62641553/setup-cypress-on-wsl-ubuntu-for-windows-10) and [here](https://github.com/microsoft/WSL/issues/4106). Use at your own risk.
1. Install `VcXsrv Windows X Server`
2. Set shortcut target to `"C:\Program Files\VcXsrv\xlaunch.exe" -ac`
3. In WSL2: `export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0`
4. Disable access control when starting XLaunch
</details>
3. Use [Corepack](https://pnpm.io/installation#using-corepack) to make sure you have [pnpm](https://pnpm.io/) installed in the correct version: `corepack enable`.
4. Install node module dependencies: `pnpm install`
5. Generate code `pnpm nx run-many --target generate`
6. Optionally, install the following VSCode plugins:
- [Go](https://marketplace.visualstudio.com/items?itemName=golang.Go) - For API development. Use golangci-lint v2 as linter.
- [Angular Language Service](https://marketplace.visualstudio.com/items?itemName=Angular.ng-template) - For Console development
- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - Code linting
- [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) - Code formatting
- [Nx Console](https://marketplace.visualstudio.com/items?itemName=nrwl.angular-console) - Nx task runner tooling
Jump to the dedicated sections for developing a specific project:
- [Contributing to the API](#contribute-to-api)
- [Contributing to the Login](#contribute-to-login)
- [Contributing to the Console](#contribute-to-console)
- [Contributing to the Docs](#contribute-to-docs)
- [Contributing translations](#contribute-translations)
## Development Commands Cheat Sheet
This repository contains multiple interconnected projects.
You can build and start any project with Nx commands.
| Task | Command | Notes | Details |
| ----------------------------- | ------------------------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Production** | `pnpm nx run PROJECT:prod` | Production server | |
| **Develop** | `pnpm nx run PROJECT:dev` | Development server | |
| **Generate** | `pnpm nx run PROJECT:generate` | Generate .gitignored files | |
| **Generate Go Files** | `pnpm nx run @zitadel/api:generate-go` | Regenerate checked-in files | This is needed to generate files using [Stringer](https://pkg.go.dev/golang.org/x/tools/cmd/stringer), [Enumer](https://github.com/dmarkham/enumer) or [gomock](https://github.com/uber-go/mock) |
| **Test - Unit** | `pnpm nx run PROJECT:test-unit` | Run unit tests | |
| **Test - Integration** | `pnpm nx run PROJECT:test-integration` | Run integration tests | Learn mnore about how to [debug API integration tests](#run-api-integration-tests) |
| **Test - Integration Stop** | `pnpm nx run PROJECT:test-integration-stop` | Stop integration containers | |
| **Test - Functional UI** | `pnpm nx run @zitadel/functional-ui:test` | Run functional UI tests | Learn more about how to [develop the Console and opening the interactive Test Suite](#pass-console-quality-checks) |
| **Test - Functional UI Stop** | `pnpm nx run @zitadel/functional-ui:stop` | Run functional UI containers | |
| **Test** | `pnpm nx run PROJECT:test` | Run all tests | |
| **Lint** | `pnpm nx run PROJECT:lint` | Check code style | |
| **Lint Fix** | `pnpm nx run PROJECT:lint-fix` | Auto-fix style issues | |
Replace `PROJECT` with one of the following:
- `@zitadel/zitadel` (you can omit this root level project when using `pnpm nx run`, like `pnpm nx run db`)
- `@zitadel/api`
- `@zitadel/login`
- `@zitadel/console`
- `@zitadel/docs`
- `@zitadel/client`
- `@zitadel/proto`
Instead of the project names, you can also use their directory names for `PROJECT`, like `pnpm nx run login:dev`.
Alternatively, you can use the infix-notation, like `pnpm nx dev @zitadel/login` or `pnpm nx dev login`.
To stream all logs instead of opening the interactive terminal, disable the TUI with `pnpm nx --tui false ...`.
If a command is stuck because a process is already running, stop the Nx daemon and try again: `pnpm nx daemon --stop`.
## Introduction
Thank you for your interest about how to contribute! As you might know there is more than code to contribute. You can find all information needed to start contributing here.
Thank you for your interest in contributing! As you might know there is more than code to contribute. You can find all information needed to start contributing here.
Please give us and our community the chance to get rid of security vulnerabilities by responsibly disclose this kind of issues by contacting [security@zitadel.com](mailto:security@zitadel.com).
Please give us and our community the chance to get rid of security vulnerabilities by responsibly disclosing these issues to [security@zitadel.com](mailto:security@zitadel.com).
The strongest part of a community is the possibility to share thoughts. That's why we try to react as soon as possible to your ideas, thoughts and feedback. We love to discuss as much as possible in an open space like in the [issues](https://github.com/zitadel/zitadel/issues) and [discussions](https://github.com/zitadel/zitadel/discussions) section here or in our [chat](https://zitadel.com/chat), but we understand your doubts and provide further contact options [here](https://zitadel.com/contact).
@@ -13,13 +86,13 @@ If you want to give an answer or be part of discussions please be kind. Treat ot
## What can I contribute?
For people who are new to Zitadel: We flag issues which are a good starting point to start contributing.
You find them [here](https://github.com/zitadel/zitadel/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
You can find them [here](https://github.com/zitadel/zitadel/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22).
We add the label "good first issue" for problems we think are a good starting point to contribute to Zitadel.
- [Issues for first time contributors](https://github.com/zitadel/zitadel/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
- [All issues](https://github.com/zitadel/zitadel/issues)
Help shaping the future of Zitadel:
Help shape the future of Zitadel:
- Join our [chat](https://zitadel.com/chat) and discuss with us or others.
- Ask or answer questions in the [issues section](https://github.com/zitadel/zitadel/issues)
@@ -31,13 +104,14 @@ Follow [@zitadel](https://twitter.com/zitadel) on twitter
[Contribute](#how-to-contribute)
- [Contribute code](#contribute)
- If you found a mistake on our [docs page](https://zitadel.com/docs) or something is missing please read [the docs section](contribute-docs)
- [Translate](#contribute-internationalization) and improve texts
- [Contribute API code](#contribute-to-api)
- [Contribute frontend code](#contribute-to-frontend)
- If you found a mistake on our [Docs page](https://zitadel.com/docs) or something is missing please read [the Docs section](#contribute-to-docs)
- [Translate](#contribute-translations) and improve texts
## How to contribute
We strongly recommend to [talk to us](https://zitadel.com/contact) before you start contributing to streamline our and your work.
We strongly recommend [talking to us](https://zitadel.com/contact) before you start contributing to streamline your work with ours.
We accept contributions through pull requests.
You need a github account for that.
@@ -49,25 +123,25 @@ Go through the following checklist before you submit the final pull request:
The code consists of the following parts:
| name | description | language | where to find | Development Guide |
| --------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------- |
| backend | Service that serves the grpc(-web) and RESTful API | [go](https://go.dev) | [API implementation](./internal/api/grpc) | [Contribute to Backend](contribute-backend) |
| API definitions | Specifications of the API | [Protobuf](https://developers.google.com/protocol-buffers) | [./proto/zitadel](./proto/zitadel) | [Contribute to Backend](contribute-backend) |
| console | Frontend the user interacts with after log in | [Angular](https://angular.io), [Typescript](https://www.typescriptlang.org) | [./console](./console) | [Contribute to Frontend](contribute-frontend) |
| login | Modern authentication UI built with Next.js | [Next.js](https://nextjs.org), [React](https://reactjs.org), [TypeScript](https://www.typescriptlang.org) | [./login](./login) | [Contribute to Frontend](contribute-frontend) |
| docs | Project documentation made with docusaurus | [Docusaurus](https://docusaurus.io/) | [./docs](./docs) | [Contribute to Frontend](contribute-frontend) |
| translations | Internationalization files for default languages | YAML | [./console](./console) and [./internal](./internal) | [Contribute Translations](contribute-translations) |
| name | description | language | where to find | Development Guide |
| ------------------ | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------- |
| API implementation | Service that serves the grpc(-web) and RESTful API | [go](https://go.dev) | [API implementation](./internal/api/grpc) | [Contribute to API](#contribute-to-api) |
| API definitions | Specifications of the API | [Protobuf](https://developers.google.com/protocol-buffers) | [./proto/zitadel](./proto/zitadel) | [Contribute to API](#contribute-to-api) |
| Console | Frontend the user interacts with after log in | [Angular](https://angular.io), [Typescript](https://www.typescriptlang.org) | [./console](./console) | [Contribute to Frontend](#contribute-to-frontend) |
| Login | Modern authentication UI built with Next.js | [Next.js](https://nextjs.org), [React](https://reactjs.org), [TypeScript](https://www.typescriptlang.org) | [./apps/login](./apps/login) | [Contribute to Frontend](#contribute-to-frontend) |
| Docs | Project documentation made with docusaurus | [Docusaurus](https://docusaurus.io/) | [./docs](./docs) | [Contribute to Frontend](#contribute-to-frontend) |
| translations | Internationalization files for default languages | YAML | [./console](./console) and [./internal](./internal) | [Contribute Translations](#contribute-translations) |
Please follow the guides to validate and test the code before you contribute.
### Submit a pull request (PR)
### Submitting a pull request (PR)
1. [Fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) the [zitadel/zitadel](https://github.com/zitadel/zitadel) repository on GitHub
2. On your fork, commit your changes to a new branch
`git checkout -b my-fix-branch main`
3. Make your changes following the [guidelines](#contribute) in this guide. Make sure that all tests pass.
3. Make your changes following the [guidelines](#how-to-contribute) in this guide. Make sure that all tests pass.
4. Commit the changes on the new branch
@@ -107,7 +181,7 @@ Must be one of the following:
#### Scope
This is optional to indicate which component is affected. In doubt, leave blank (`<type>: <short summary>`)
This is optional to indicate which component is affected. If in doubt, leave blank (`<type>: <short summary>`)
#### Short summary
@@ -149,80 +223,91 @@ The API is designed to be used by different clients, such as web applications, m
Therefore, the API is designed to be easy to use, consistent, and reliable.
Please check out the dedicated [API guidelines](./API_DESIGN.md) page when contributing to the API.
## <a name="backend"></a>Contribute Backend Code
## Contribute to API
To start developing, make sure you followed the [quick start](#quick-start) steps.
### Develop the API
### <a name="backend-requirements"></a> Backend Requirements
By executing the commands from this section, you run everything you need to develop the Zitadel backend locally.
> [!INFO]
> Some [dev containers are available](dev-containers) for remote development with docker and pipeline debugging in isolated environments.
> If you don't want to use one of the dev containers, you can develop the backend components directly on your local machine.
> To do so, proceed with installing the necessary dependencies.
Using [Docker Compose](https://docs.docker.com/compose/), you run a [PostgreSQL](https://www.postgresql.org/download/) on your local machine.
With [make](https://www.gnu.org/software/make/), you build a debuggable Zitadel binary and run it using [delve](https://github.com/go-delve/delve).
Then, you test your changes via the console your binary is serving at http://<span because="breaks the link"></span>localhost:8080 and by verifying the database.
Once you are happy with your changes, you run end-to-end tests and tear everything down.
Zitadel uses [golangci-lint v2](https://golangci-lint.run) for code quality checks. Please use [this configuration](.golangci.yaml) when running `golangci-lint`. We recommend to set golangci-lint as linter in your IDE.
The commands in this section are tested against the following software versions:
- [Docker version 20.10.17](https://docs.docker.com/engine/install/)
- [Go version 1.22](https://go.dev/doc/install)
- [Delve 1.9.1](https://github.com/go-delve/delve/tree/v1.9.1/Documentation/installation)
### <a name="build-and-run-zitadel"></a>Build and Run Zitadel
Make some changes to the source code, then run the database locally.
Optionally build the Console
```bash
# You just need the db service to develop the backend against.
docker compose --file ./e2e/docker-compose.yaml up --detach db
pnpm nx run @zitadel/api:build-console
```
Build the binary. This takes some minutes, but you can speed up rebuilds.
Optionally start the Login in another terminal
```bash
make compile
pnpm nx run @zitadel/login:prod
```
> Note: With this command, several steps are executed.
> For speeding up rebuilds, you can reexecute only specific steps you think are necessary based on your changes.
> Generating gRPC stubs: `make core_api`
> Running unit tests: `make core_unit_test`
> Generating the console: `make console_build console_move`
> Build the binary: `make compile`
Run the local development database.
You can now run and debug the binary in .artifacts/zitadel/zitadel using your favourite IDE, for example GoLand.
You can test if Zitadel does what you expect by using the UI at http://localhost:8080/ui/console.
Also, you can verify the data by running `psql "host=localhost dbname=zitadel sslmode=disable"` and running SQL queries.
```bash
pnpm nx db
```
### Run Local Unit Tests
Start a debug session in your IDE.
For example, in VSCode, you can use a `launch.json` configuration like this.
```json
{
"name": "Debug Zitadel API",
"type": "go",
"request": "launch",
"mode": "debug",
"env": {
"ZITADEL_DATABASE_POSTGRES_HOST": "${env:DEVCONTAINER_DB_HOST}"
},
"program": "main.go",
"args": [
"start-from-init",
"--config",
"${workspaceFolder}/apps/api/prod-default.yaml",
"--steps",
"${workspaceFolder}/apps/api/prod-default.yaml",
"--masterkey",
"MasterkeyNeedsToHave32Characters"
]
}
```
If you have built the Console and started the Login, visit http://localhost:8080/ui/console?login_hint=zitadel-admin@zitadel.localhost and enter `Password1!` to log in.
Call the API using the generated [](./admin.pat) with [grpcurl](https://github.com/fullstorydev/grpcurl) or [grpcui](https://github.com/fullstorydev/grpcui), for example:
```bash
grpcurl -plaintext -H "Authorization: Bearer $(cat admin.pat)" localhost:8080 zitadel.user.v2.UserService.ListUsers
```
To connect to the database and explore Zitadel data, run `psql "host=${DEVCONTAINER_DB_HOST:-localhost} dbname=zitadel sslmode=disable"`.
### Run API Unit Tests
To test the code without dependencies, run the unit tests:
```bash
make core_unit_test
pnpm nx run @zitadel/api:test-unit
```
### Run Local Integration Tests
### Run API Integration Tests
Integration tests are run as gRPC clients against a running Zitadel server binary.
The server binary is typically [build with coverage enabled](https://go.dev/doc/build-cover).
It is also possible to run a Zitadel sever in a debugger and run the integrations tests like that. In order to run the server, a database is required.
In order to prepare the local system, the following will bring up the database, builds a coverage binary, initializes the database and starts the sever.
API tests are run as gRPC clients against a running Zitadel server binary.
The server binary is [built with coverage enabled](https://go.dev/doc/build-cover).
```bash
make core_integration_db_up core_integration_server_start
pnpm nx run @zitadel/api:test-integration
```
When this job is finished, you can run individual package integration test through your IDE or command-line. The actual integration test clients reside in the `integration_test` subdirectory of the package they aim to test. Integration test files use the `integration` build tag, in order to be excluded from regular unit tests.
Because of the server-client split, Go is usually unaware of changes in server code and tends to cache test results. Pas `-count 1` to disable test caching.
To develop and run the test cases from within your IDE or by the command line, start only the API.
The actual integration test clients reside in the `integration_test` subdirectory of the package they aim to test.
Integration test files use the `integration` build tag, in order to be excluded from regular unit tests.
Because of the server-client split, Go is usually unaware of changes in server code and tends to cache test results.
Pass `-count 1` to disable test caching.
```bash
pnpm nx run @zitadel/api:test-integration-run-api
```
Example command to run a single package integration test:
@@ -233,258 +318,270 @@ go test -count 1 -tags integration ./internal/api/grpc/management/integration_te
To run all available integration tests:
```bash
make core_integration_test_packages
go test -count 1 -tags integration -parallel 1 $(go list -tags integration ./... | grep -e \"integration_test\" -e \"events_testing\")
```
When you change any Zitadel server code, be sure to rebuild and restart the server before the next test run.
It is also possible to run the API in a debugger and run the integrations tests against it.
In order to run the server, a database with correctly set up data is required.
When starting the debugger, make sure the Zitadel binary starts with `start-from-init --config=./apps/api/test-integration-api.yaml --steps=./apps/api/test-integration-api.yaml --masterkey=MasterkeyNeedsToHave32Characters"`
To cleanup after testing (deletes the ephemeral database!):
```bash
make core_integration_server_stop core_integration_server_start
pnpm nx run @zitadel/devcontainer:compose down db-api-integration cache-api-integration
```
To cleanup after testing (deletes the database!):
### Run Functional UI Tests
To test the whole system, including the Console UI and the Login UI, run the Functional UI tests.
```bash
make core_integration_server_stop core_integration_db_down
```
The test binary has the race detector enabled. `core_core_integration_server_stop` checks for any race logs reported by Go and will print them along a `66` exit code when found. Note that the actual race condition may have happened anywhere during the server lifetime, including start, stop or serving gRPC requests during tests.
### Run Local End-to-End Tests
To test the whole system, including the console UI and the login UI, run the E2E tests.
```bash
# Build the production docker image
export Zitadel_IMAGE=zitadel:local GOOS=linux
make docker_image
# If you made changes in the e2e directory, make sure you reformat the files
pnpm turbo lint:fix --filter=e2e
# If you made changes in the tests/functional-ui directory, make sure you reformat the files
pnpm nx run @zitadel/functional-ui:lint-fix
# Run the tests
docker compose --file ./e2e/docker-compose.yaml run --service-ports e2e
```
When you are happy with your changes, you can cleanup your environment.
```bash
# Stop and remove the docker containers for zitadel and the database
docker compose --file ./e2e/docker-compose.yaml down
```
### Run Local End-to-End Tests Against Your Dev Server Console
If you also make [changes to the console](#console), you can run the test suite against your locally built backend code and frontend server.
```bash
# Install dependencies (from repository root)
pnpm install
# Run the tests interactively
pnpm run open:golangangular
# Run the tests non-interactively
pnpm run e2e:golangangular
```
When you are happy with your changes, you can cleanup your environment.
```bash
# Stop and remove the docker containers for zitadel and the database
docker compose --file ./e2e/docker-compose.yaml down
pnpm nx run @zitadel/functional-ui:test
```
## Contribute Frontend Code
This repository uses **pnpm** as package manager and **Turbo** for build orchestration.
All frontend packages are managed as a monorepo with shared dependencies and optimized builds:
This repository uses **pnpm** as package manager and **Nx** for build orchestration.
- [apps/login](contribute-login) (depends on packages/zitadel-client and packages/zitadel-proto)
- apps/login/integration
- apps/login/acceptance
- [console](contribute-console) (depends on packages/zitadel-client)
- packages/zitadel-client
- packages/zitadel-proto
- [docs](contribute-docs)
### Project Overview
### <a name="frontend-dev-requirements"></a>Frontend Development Requirements
Choose your contribution area:
The frontend components are run in a [Node](https://nodejs.org/en/about/) environment and are managed using the pnpm package manager and the Turborepo orchestrator.
- **[Login App](#contribute-to-login)** (Next.js/React) - Modern authentication flows
- **[Console](#contribute-to-console)** (Angular) - Admin dashboard and user management
- **[Docs](#contribute-to-docs)** (Docusaurus) - Project documentation
- **[Client Packages](#client-packages)** - Shared libraries for API communication
> [!INFO]
> Some [dev containers are available](dev-containers) for remote development with docker and pipeline debugging in isolated environments.
> If you don't want to use one of the dev containers, you can develop the frontend components directly on your local machine.
> To do so, proceed with installing the necessary dependencies.
### Project Dependencies
We use **pnpm** as package manager and **Turbo** for build orchestration. Use angular-eslint/Prettier for linting/formatting.
VSCode users, check out [this ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) and [this Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) to fix lint and formatting issues during development.
The commands in this section are tested against the following software versions:
- [Docker version 20.10.17](https://docs.docker.com/engine/install/)
- [Node version v20.x](https://nodejs.org/en/download/)
- [pnpm version 9.x](https://pnpm.io/installation)
To run tests with Cypress, ensure you have installed the required [Cypress runtime dependencies](https://docs.cypress.io/guides/continuous-integration/introduction#Dependencies)
<details>
<summary>Note for WSL2 on Windows 10</summary>
Following the suggestions <a href="https://stackoverflow.com/questions/62641553/setup-cypress-on-wsl-ubuntu-for-windows-10">here </a> subsequently <a href="https://github.com/microsoft/WSL/issues/4106">here </a> may need to XLaunch and configure your DISPLAY variable. Use at your own risk.
1. Install `VcXsrv Windows X Server`
2. Set the target of your shortcut to `"C:\Program Files\VcXsrv\xlaunch.exe" -ac`
3. In WSL2 run `export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0` to set your DISPLAY variable
4. When starting XLaunch, make sure to disable access control
</details>
### <a name="contribute-login"></a>Contribute to Login
The Login UI is a Next.js application that provides the user interface for authentication flows.
It's located in the `apps/login` directory and uses pnpm and Turbo for development.
To start developing the login, make sure your system has the [required system dependencies](frontend-dev-requirements) installed.
#### Development Setup
```bash
# Start from the root of the repository
# Start the database and Zitadel backend
docker compose --file ./apps/login/acceptance/docker-compose.yaml up --detach zitadel
# Install dependencies
pnpm install
# Option 1: Run login development server with Turbo (recommended)
pnpm turbo dev --filter=@zitadel/login
# Option 2: Build and serve login (production build)
pnpm turbo build --filter=@zitadel/login
cd ./login && pnpm start
```
apps/login → packages/zitadel-client → packages/zitadel-proto
console → packages/zitadel-client → packages/zitadel-proto
docs → (independent)
```
The login UI is available at http://localhost:3000.
**Nx handles this automatically** - when you change `zitadel-proto`, Nx rebuilds dependent projects.
### Contribute to Login
The Login UI is a Next.js application that provides the user interface for authentication flows.
It is MIT-licensed, so you are free to change and deploy it as you like.
It's located in the `apps/login` directory and uses pnpm and Nx for development.
Get familiar with the [Login ui docs](https://zitadel.com/docs/guides/integrate/login-ui).
To start developing, make sure you followed the [quick start](#quick-start) steps.
#### Develop the Login against a local API
Run the local development database.
```bash
pnpm nx db
```
In another terminal, start the API
```bash
pnpm nx run @zitadel/api:prod
```
In another terminal, start the Login development server
```bash
pnpm nx run @zitadel/login:dev
```
Visit http://localhost:8080/ui/console?login_hint=zitadel-admin@zitadel.localhost and enter `Password1!` to log in.
Make some changes to the source code and see how the browser is automatically updated.
#### Develop against a Cloud instance
If you don't want to build and run a local API, you can just run the Login development server and point it to a cloud instance.
1. Create a personal access token and point your instance to your local Login, [as described in the Docs](https://zitadel.com/docs/self-hosting/manage/login-client).
2. Save the following file to `apps/login/.env.dev.local`
```env
ZITADEL_API_URL=https://[your-cloud-instance-domain]
ZITADEL_SERVICE_USER_TOKEN=[personal access token for an IAM Login Client]
```
3. Start the development server.
```bash
pnpm nx run @zitadel/login:dev
```
Visit http://localhost:8080/ui/console?login_hint=zitadel-admin@zitadel.localhost and enter `Password1!` to log in.
#### Login Architecture
The login application consists of multiple packages:
The Login application consists of multiple packages:
- `@zitadel/login` - Main Next.js application
- `@zitadel/client` - TypeScript client library for Zitadel APIs
- `@zitadel/proto` - Protocol buffer definitions and generated code
The build process uses Turbo to orchestrate dependencies:
The build process uses Nx and pnpm to orchestrate dependencies:
1. Proto generation (`@zitadel/proto#generate`)
2. Client library build (`@zitadel/client#build`)
3. Login application build (`@zitadel/login#build`)
#### Pass Login Quality Checks
#### Pass Quality Checks
Reproduce the pipelines linting and testing for the login.
Reproduce the pipeline quality checks for the code you changed.
```bash
pnpm turbo quality --filter=./apps/login/* --filter=./packages/*
# Run Login-related linting builds and unit tests
pnpm nx run-many --projects @zitadel/login @zitadel/client @zitadel/proto --targets lint build test
```
Fix the [quality checks](troubleshoot-frontend), add new checks that cover your changes and mark your pull request as ready for review when the pipeline checks pass.
Fix the quality checks, add new checks that cover your changes and mark your pull request as ready for review when the pipeline checks pass.
### <a name="contribute-console"></a>Contribute to Console
#### <a name="login-deploy"></a>Deploy
To start developing the console, make sure your system has the [required system dependencies](frontend-dev-requirements) installed.
Then, you need to decide which Zitadel instance you would like to target.
- The easiest starting point is to [configure your environment](console-dev-existing-zitadel) to use a [Zitadel cloud](https://zitadel.com) instance.
- Alternatively, you can [start a local Zitadel instance from scratch and develop against it](console-dev-local-zitadel).
- [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fzitadel%2Fzitadel&env=ZITADEL_API_URL,ZITADEL_SERVICE_USER_ID,ZITADEL_SERVICE_USER_TOKEN&root-directory=apps/login&envDescription=Setup%20a%20service%20account%20with%20IAM_LOGIN_CLIENT%20membership%20on%20your%20instance%20and%20provide%20its%20id%20and%20personal%20access%20token.&project-name=zitadel-login&repository-name=zitadel-login)
- Build and deploy with Docker: `pnpm nx run @zitadel/login:build && docker build -t my-zitadel-login apps/login`
- Build and deploy with NodeJS: `pnpm nx run @zitadel/login:prod`
#### <a name="console-dev-existing-zitadel"></a>Develop against an already running Zitadel instance
### Contribute to Console
By default, `pnpm dev --filter=console` targets a Zitadel API running at http://localhost:8080.
To change this, export the link to your environment.json in your environment variables.
To learn more about the Console, go to the Consoles [README.md](./console/README.md).
To start developing, make sure you followed the [quick start](#quick-start) steps.
#### Develop the Console against a local API
Run the local development database.
```bash
export ENVIRONMENT_JSON_URL=https://my-cloud-instance-abcdef.us1.zitadel.cloud/ui/console/assets/environment.json
pnpm nx db
```
Proceed [with configuring your console redirect URIs](console-redirect).
#### <a name="console-dev-local-zitadel"></a>Develop against a local Zitadel instance from scratch
By executing the commands from this section, you run everything you need to develop the console locally.
Using [Docker Compose](https://docs.docker.com/compose/), you run [PostgreSQL](https://www.postgresql.org/download/) and the [latest release of Zitadel](https://github.com/zitadel/zitadel/releases/latest) on your local machine.
You use the Zitadel container as backend for your console.
Run the database and the latest backend locally.
In another terminal, start the API
```bash
# Start from the root of the repository
# You just need the db and the zitadel services to develop the console against.
docker compose --file ./e2e/docker-compose.yaml up --detach zitadel
pnpm nx run @zitadel/api:prod
```
When Zitadel accepts traffic, navigate to http://localhost:8080/ui/console/projects?login_hint=zitadel-admin@zitadel.localhost and log in with _Password1!_.
Proceed [with configuring your console redirect URIs](console-redirect).
#### <a name="console-redirect"></a> Configure Console redirect URI
To allow console access via http://localhost:4200, you have to configure the Zitadel backend.
1. Navigate to /ui/console/projects in your target Zitadel instance.
3. Select the _Zitadel_ project.
4. Select the _Console_ application.
5. Select _Redirect Settings_
6. Add _http://<span because="breaks the link"></span>localhost:4200/auth/callback_ to the _Redirect URIs_
7. Add _http://<span because="breaks the link"></span>localhost:4200/signedout_ to the _Post Logout URIs_
8. Select the _Save_ button
#### Develop
Run the local console development server.
In another terminal, start the Login
```bash
# Install dependencies (from repository root)
pnpm install
# Option 1: Run console development server with live reloading and dependency rebuilds
pnpm turbo dev --filter=console
# Option 2: Build and serve console (production build)
pnpm turbo build --filter=console
pnpm turbo serve --filter=console
pnpm nx run @zitadel/login:prod
```
Navigate to http://localhost:4200/.
Allow the API [to redirect to your dev server](#configure-console-dev-server-redirects).
In another terminal, start the Console development server
```bash
pnpm nx run @zitadel/console:dev
```
Visit http://localhost:4200/?login_hint=zitadel-admin@zitadel.localhost and enter `Password1!` to log in.
Make some changes to the source code and see how the browser is automatically updated.
#### Pass Quality Checks
#### Develop against a Cloud instance
Reproduce the pipelines linting and testing for the console.
If you don't want to build and run a local API, you can just run the console development server and point it to a cloud instance.
```bash
pnpm turbo quality --filter=console --filter=e2e
Save the following file to console/.env.local
```env
ENVIRONMENT_JSON_URL=https://[your-cloud-instance-domain]/ui/console/assets/environment.json
```
Fix the [quality checks](troubleshoot-frontend), add new checks that cover your changes and mark your pull request as ready for review when the pipeline checks pass.
Start the development server.
### <a name="contribute-docs"></a>Contribute to Docs
```bash
pnpm nx run @zitadel/console:dev
```
Project documentation is made with Docusaurus and is located under [./docs](./docs). The documentation uses **pnpm** and **Turbo** for development and build processes.
Allow the API [to redirect to your dev server](#configure-console-dev-server-redirects).
Visit http://localhost:4200/?login_hint=zitadel-admin@zitadel.localhost and enter `Password1!` to log in.
#### Configure Console Dev Server Redirects
To allow Console access via http://localhost:4200, you have to configure the Zitadel API.
1. Navigate to http://localhost:8080/ui/console/projects.
2. Select the _ZITADEL_ project.
3. Select the _Console_ application.
4. Select _Redirect Settings_
5. Add _http://<span because="breaks the link"></span>localhost:4200/auth/callback_ to the _Redirect URIs_
6. Add _http://<span because="breaks the link"></span>localhost:4200/signedout_ to the _Post Logout URIs_
7. Select the _Save_ button
#### Pass Console Quality Checks
Run the quality checks for the code you changed.
```bash
# Run console-related linting builds and unit tests
pnpm nx run-many --projects @zitadel/console @zitadel/client @zitadel/proto @zitadel/functional-ui --targets lint build test
```
Run functional UI tests against a locally built API and a dev server Console.
Allow the API [to redirect to your dev server](#configure-console-dev-server-redirects).
Alternatively, create the file `tests/functional-ui/.env.open.local` with the following content:
```conf
CYPRESS_BASE_URL=http://localhost:8080/ui/console
```
```bash
# Run the API and the Console dev server
# Beware this doesn't work from within a dev container.
pnpm nx run @zitadel/functional-ui:open
```
Or run all tests to completion.
```bash
# Run the tests
pnpm nx run @zitadel/functional-ui:test
```
Fix the quality checks, add new checks that cover your changes and mark your pull request as ready for review when the pipeline checks pass.
### Contribute to Client Packages
To start developing, make sure you followed the [quick start](#quick-start) steps.
**`@zitadel/proto`**: Protocol buffer definitions and generated TypeScript/JavaScript clients.
```bash
pnpm nx run @zitadel/proto:generate # Regenerate after proto changes
```
**`@zitadel/client`**: High-level TypeScript client library with utilities for API interaction.
```bash
pnpm nx run @zitadel/client:build # Build after changes
```
### Contribute to Docs
Project documentation is made with Docusaurus and is located under [./docs](./docs). The documentation uses **pnpm** and **Nx** for development and build processes.
To start developing, make sure you followed the [quick start](#quick-start) steps.
#### Local Development
```bash
# Install dependencies (from repository root)
pnpm install
# Start development server (recommended)
pnpm nx run @zitadel/docs:dev
# Option 1: Run docs development server with Turbo (recommended)
pnpm turbo dev --filter=zitadel-docs
# Option 2: Build and serve docs (production build)
pnpm turbo build --filter=zitadel-docs
cd ./docs && pnpm serve
# Or start production server
pnpm nx run @zitadel/docs:prod
```
The docs build process automatically:
The Docs build process automatically:
1. Downloads required protoc plugins
2. Generates gRPC documentation from proto files
@@ -519,87 +616,15 @@ Scope can be left empty (omit the brackets) or refer to the top navigation secti
#### Pass Quality Checks
Reproduce the pipelines linting checks for the docs.
Verify the Docs build correctly.
```bash
pnpm turbo quality --filter=docs
pnpm nx run @zitadel/docs:build
```
Fix the [quality checks](troubleshoot-frontend), add new checks that cover your changes and mark your pull request as ready for review when the pipeline checks pass.
Fix the quality checks, add new checks that cover your changes and mark your pull request as ready for review when the pipeline checks pass.
### <a name="troubleshoot-frontend"></a>Troubleshoot Frontend Quality Checks
To debug and fix failing tasks, execute them individually using the `--filter` flag.
We recommend to use [one of the dev containers](dev-containers) to reproduce pipeline issues.
```bash
# to reproduce linting error in the console:
pnpm lint --filter=console
# To fix them:
pnpm lint:fix --filter=console
```
More tasks that are runnable on-demand.
Some tasks have variants like `pnpm test:e2e:angulargolang`,
others support arguments and flags like `pnpm test:integration run --spec apps/login/integration/integration/login.cy.ts`.
For the turbo commands, check your options with `pnpm turbo --help`
| Command | Description | Example |
| ------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pnpm turbo run generate` | Generate stubs from Proto files | Generate API docs: `pnpm turbo run generate --filter zitadel-docs` |
| `pnpm turbo build` | Build runnable JavaScript code | Regenerate the proto stubs and build the @zitadel/client package: `pnpm turbo build --filter @zitadel/client` |
| `pnpm turbo quality` | Reproduce the pipeline quality checks | Run login-related quality checks `pnpm turbo quality --filter './apps/login/*' --filter './packages/*'` |
| `pnpm turbo lint` | Check linting issues | Check login-related linting issues for differences with main `pnpm turbo lint --filter=[main...HEAD] --filter .'/apps/login/**/*' --filter './packages/*'` |
| `pnpm turbo lint:fix` | Fix linting issues | Fix console-relevant linting issues `pnpm turbo lint:fix --filter console --filter './packages/*' --filter zitadel-e2e` |
| `pnpm turbo test:unit` | Run unit tests. Rerun on file changes | Run unit tests in all packages in and watch for file changes `pnpm turbo watch test:unit` |
| `pnpm turbo test:e2e` | Run the Cypress CLI for console e2e tests | Test interactively against the console in a local dev server and Zitadel in a container: `pnpm turbo test:e2e:angular open` |
| `pnpm turbo down` | Remove containers and volumes | Shut down containers from the integration test setup `pnpm turbo down` |
| `pnpm turbo clean` | Remove downloaded dependencies and other generated files | Remove generated docs `pnpm turbo clean --filter zitadel-docs` |
## <a name="dev-containers"></>Developing Zitadel with Dev Containers
You can use dev containers if you'd like to make sure you have the same development environment like the corresponding GitHub PR checks use.
The following dev containers are available:
- **.devcontainer/base/devcontainer.json**: Contains everything you need to run whatever you want.
- **.devcontainer/turbo-lint-unit/devcontainer.json**: Runs a dev container that executes frontent linting and unit tests and then exits. This is useful to reproduce the corresponding GitHub PR check.
- **.devcontainer/turbo-lint-unit-debug/devcontainer.json**: Runs a dev container that executes frontent linting and unit tests in watch mode. You can fix the errors right away and have immediate feedback.
- **.devcontainer/login-integration/devcontainer.json**: Runs a dev container that executes login integration tests and then exits. This is useful to reproduce the corresponding GitHub PR check.
- **.devcontainer/login-integration-debug/devcontainer.json**: Runs a dev container that spins up the login in a hot-reloading dev server and executes login integration tests interactively. You can fix the errors right away and have immediate feedback.
You can also run the GitHub PR checks locally in dev containers without having to connect to a dev container.
The following pnpm commands use the [devcontainer CLI](https://github.com/devcontainers/cli/) and exit when the checks are done.
The minimal system requirements are having Docker and the devcontainers CLI installed.
If you don't have the node_modules installed already, you need to install the devcontainers CLI manually. Run `npm i -g @devcontainers/cli@0.80.0`. Alternatively, the [official Microsoft VS Code extension for Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) offers a command `Dev Containers: Install devcontainer CLI`
```bash
npm run devcontainer:lint-unit
npm run devcontainer:integration:login
```
If you don't have NPM installed, copy and execute the scripts from the package.json directly.
To connect to a dev container to have full IDE support, follow the instructions provided by your code editor/IDE to initiate the dev container.
This typically involves opening the "Command Palette" or similar functionality and searching for commands related to "Dev Containers" or "Remote Containers".
The quick start guide for VS Code can found [here](https://code.visualstudio.com/docs/devcontainers/containers#_quick-start-open-an-existing-folder-in-a-container)
For example, to build and run the Zitadel binary in a dev container, connect your IDE to the dev container described in .devcontainer/base/devcontainer.json.
Run the following commands inside the container to start Zitadel.
```bash
make compile && ./zitadel start-from-init --masterkey MasterkeyNeedsToHave32Characters --tlsMode disabled
```
Zitadel serves traffic as soon as you can see the following log line:
`INFO[0001] server is listening on [::]:8080`
## <a name="contribute-translations"></a>Contribute Translations
## Contribute Translations
Zitadel loads translations from four files:
@@ -684,10 +709,10 @@ There are a few general labels that don't belong to a specific category.
The category shows which part of Zitadel is affected.
- **category: backend**: The backend includes the APIs, event store, command and query side. This is developed in golang.
- **category: ci**: ci is all about continues integration and pipelines.
- **category: ci**: ci is all about continuous integration and pipelines.
- **category: design**: All about the ux/ui of Zitadel
- **category: docs**: Adjustments or new documentations, this can be found in the docs folder.
- **category: frontend**: The frontend concerns on the one hand the Zitadel management console (Angular) and on the other hand the login (gohtml)
- **category: frontend**: The frontend concerns on the one hand the Zitadel management Console (Angular) and on the other hand the Login (gohtml)
- **category: infra**: Infrastructure does include many different parts. E.g Terraform-provider, docker, metrics, etc.
- **category: translation**: Everything concerning translations or new languages

View File

@@ -22,8 +22,9 @@ proto/
The following files and directories, including their subdirectories, are licensed under the [MIT License](https://opensource.org/license/mit/):
```
login/
clients/
apps/login/
packages/zitadel-client/
packages/zitadel-proto/
```
## Community Contributions

196
Makefile
View File

@@ -1,196 +0,0 @@
go_bin := "$$(go env GOPATH)/bin"
gen_authopt_path := "$(go_bin)/protoc-gen-authoption"
gen_zitadel_path := "$(go_bin)/protoc-gen-zitadel"
now := $(shell date '+%Y-%m-%dT%T%z' | sed -E 's/.([0-9]{2})([0-9]{2})$$/-\1:\2/')
VERSION ?= development-$(now)
COMMIT_SHA ?= $(shell git rev-parse HEAD)
ZITADEL_IMAGE ?= zitadel:local
GOCOVERDIR = tmp/coverage
ZITADEL_MASTERKEY ?= MasterkeyNeedsToHave32Characters
export GOCOVERDIR ZITADEL_MASTERKEY
LOGIN_REMOTE_NAME := login
LOGIN_REMOTE_URL ?= https://github.com/zitadel/typescript.git
LOGIN_REMOTE_BRANCH ?= main
.PHONY: compile
compile: core_build console_build compile_pipeline
.PHONY: docker_image
docker_image:
@if [ ! -f ./zitadel ]; then \
echo "Compiling zitadel binary"; \
$(MAKE) compile; \
else \
echo "Reusing precompiled zitadel binary"; \
fi
DOCKER_BUILDKIT=1 docker build -f build/zitadel/Dockerfile -t $(ZITADEL_IMAGE) .
.PHONY: compile_pipeline
compile_pipeline: console_move
CGO_ENABLED=0 go build -o zitadel -v -ldflags="-s -w -X 'github.com/zitadel/zitadel/cmd/build.commit=$(COMMIT_SHA)' -X 'github.com/zitadel/zitadel/cmd/build.date=$(now)' -X 'github.com/zitadel/zitadel/cmd/build.version=$(VERSION)' "
chmod +x zitadel
.PHONY: core_dependencies
core_dependencies:
go mod download
.PHONY: core_static
core_static:
go install github.com/rakyll/statik@v0.1.7
go generate internal/api/ui/login/static/resources/generate.go
go generate internal/api/ui/login/statik/generate.go
go generate internal/notification/statik/generate.go
go generate internal/statik/generate.go
.PHONY: core_generate_all
core_generate_all:
go install github.com/dmarkham/enumer@v1.5.11 # https://pkg.go.dev/github.com/dmarkham/enumer?tab=versions
go install github.com/rakyll/statik@v0.1.7 # https://pkg.go.dev/github.com/rakyll/statik?tab=versions
go install go.uber.org/mock/mockgen@v0.4.0 # https://pkg.go.dev/go.uber.org/mock/mockgen?tab=versions
go install golang.org/x/tools/cmd/stringer@v0.36.0 # https://pkg.go.dev/golang.org/x/tools/cmd/stringer?tab=versions
go generate ./...
.PHONY: core_assets
core_assets:
mkdir -p docs/apis/assets
go run internal/api/assets/generator/asset_generator.go -directory=internal/api/assets/generator/ -assets=docs/apis/assets/assets.md
.PHONY: core_api_generator
core_api_generator:
ifeq (,$(wildcard $(gen_authopt_path)))
go install internal/protoc/protoc-gen-authoption/main.go \
&& mv $$(go env GOPATH)/bin/main $(gen_authopt_path)
endif
ifeq (,$(wildcard $(gen_zitadel_path)))
go install internal/protoc/protoc-gen-zitadel/main.go \
&& mv $$(go env GOPATH)/bin/main $(gen_zitadel_path)
endif
.PHONY: core_grpc_dependencies
core_grpc_dependencies:
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.35.1 # https://pkg.go.dev/google.golang.org/protobuf/cmd/protoc-gen-go?tab=versions
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.5.1 # https://pkg.go.dev/google.golang.org/grpc/cmd/protoc-gen-go-grpc?tab=versions
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.22.0 # https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway?tab=versions
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@v2.22.0 # https://pkg.go.dev/github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2?tab=versions
go install github.com/envoyproxy/protoc-gen-validate@v1.1.0 # https://pkg.go.dev/github.com/envoyproxy/protoc-gen-validate?tab=versions
go install github.com/bufbuild/buf/cmd/buf@v1.45.0 # https://pkg.go.dev/github.com/bufbuild/buf/cmd/buf?tab=versions
go install connectrpc.com/connect/cmd/protoc-gen-connect-go@v1.18.1 # https://pkg.go.dev/connectrpc.com/connect/cmd/protoc-gen-connect-go?tab=versions
.PHONY: core_api
core_api: core_api_generator core_grpc_dependencies
buf generate
mkdir -p pkg/grpc
cp -r .artifacts/grpc/github.com/zitadel/zitadel/pkg/grpc/** pkg/grpc/
mkdir -p openapi/v2/zitadel
cp -r .artifacts/grpc/zitadel/ openapi/v2/zitadel
.PHONY: core_build
core_build: core_dependencies core_api core_static core_assets
.PHONY: console_move
console_move:
cp -r console/dist/console/* internal/api/ui/console/static
.PHONY: console_dependencies
console_dependencies:
npx pnpm install --frozen-lockfile --filter=console...
.PHONY: console_build
console_build: console_dependencies
npx pnpm turbo build --filter=./console
.PHONY: clean
clean:
$(RM) -r .artifacts/grpc
$(RM) $(gen_authopt_path)
$(RM) $(gen_zitadel_path)
$(RM) -r tmp/
.PHONY: core_unit_test
core_unit_test:
go test -race -coverprofile=profile.cov -coverpkg=./internal/... ./...
.PHONY: core_integration_db_up
core_integration_db_up:
docker compose -f internal/integration/config/docker-compose.yaml up --pull always --wait cache postgres
.PHONY: core_integration_db_down
core_integration_db_down:
docker compose -f internal/integration/config/docker-compose.yaml down -v
.PHONY: core_integration_setup
core_integration_setup:
go build -cover -race -tags integration -o zitadel.test main.go
mkdir -p $${GOCOVERDIR}
GORACE="halt_on_error=1" ./zitadel.test init --config internal/integration/config/zitadel.yaml --config internal/integration/config/postgres.yaml
GORACE="halt_on_error=1" ./zitadel.test setup --masterkeyFromEnv --init-projections --config internal/integration/config/zitadel.yaml --config internal/integration/config/postgres.yaml --steps internal/integration/config/steps.yaml
.PHONY: core_integration_server_start
core_integration_server_start: core_integration_setup
GORACE="log_path=tmp/race.log" \
./zitadel.test start --masterkeyFromEnv --config internal/integration/config/zitadel.yaml --config internal/integration/config/postgres.yaml \
> tmp/zitadel.log 2>&1 \
& printf $$! > tmp/zitadel.pid
.PHONY: core_integration_test_packages
core_integration_test_packages:
go test -race -count 1 -tags integration -timeout 60m -parallel 1 $$(go list -tags integration ./... | grep "integration_test")
.PHONY: core_integration_server_stop
core_integration_server_stop:
pid=$$(cat tmp/zitadel.pid); \
$(RM) tmp/zitadel.pid; \
kill $$pid; \
if [ -s tmp/race.log.$$pid ]; then \
cat tmp/race.log.$$pid; \
exit 66; \
fi
.PHONY: core_integration_reports
core_integration_reports:
go tool covdata textfmt -i=tmp/coverage -pkg=github.com/zitadel/zitadel/internal/...,github.com/zitadel/zitadel/cmd/... -o profile.cov
.PHONY: core_integration_test
core_integration_test: core_integration_server_start core_integration_test_packages core_integration_server_stop core_integration_reports
.PHONY: console_lint
console_lint:
npx pnpm turbo lint --filter=./console
.PHONY: core_lint
core_lint:
golangci-lint run \
--timeout 10m \
--config ./.golangci.yaml \
--out-format=github-actions \
--concurrency=$$(getconf _NPROCESSORS_ONLN)
.PHONY: login_pull
login_pull: login_ensure_remote
@echo "Pulling changes from the 'apps/login' subtree on remote $(LOGIN_REMOTE_NAME) branch $(LOGIN_REMOTE_BRANCH)"
git fetch $(LOGIN_REMOTE_NAME) $(LOGIN_REMOTE_BRANCH)
git merge -s ours --allow-unrelated-histories $(LOGIN_REMOTE_NAME)/$(LOGIN_REMOTE_BRANCH) -m "Synthetic merge to align histories"
git push
.PHONY: login_push
login_push: login_ensure_remote
@echo "Pushing changes to the 'apps/login' subtree on remote $(LOGIN_REMOTE_NAME) branch $(LOGIN_REMOTE_BRANCH)"
git subtree split --prefix=apps/login -b login-sync-tmp
git checkout login-sync-tmp
git fetch $(LOGIN_REMOTE_NAME) main
git merge -s ours --allow-unrelated-histories $(LOGIN_REMOTE_NAME)/main -m "Synthetic merge to align histories"
git push $(LOGIN_REMOTE_NAME) login-sync-tmp:$(LOGIN_REMOTE_BRANCH)
git checkout -
git branch -D login-sync-tmp
login_ensure_remote:
@if ! git remote get-url $(LOGIN_REMOTE_NAME) > /dev/null 2>&1; then \
echo "Adding remote $(LOGIN_REMOTE_NAME)"; \
git remote add $(LOGIN_REMOTE_NAME) $(LOGIN_REMOTE_URL); \
else \
echo "Remote $(LOGIN_REMOTE_NAME) already exists."; \
fi

View File

@@ -4,6 +4,8 @@
</p>
<p align="center">
<a href="https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/zitadel/zitadel" alt="Open in Dev Container">
<img src="https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue" /> </a>
<a href="https://github.com/zitadel/zitadel/blob/main/LICENSE" alt="License">
<img src="https://badgen.net/github/license/zitadel/zitadel/" /></a>
<a href="https://bestpractices.coreinfrastructure.org/projects/6662"><img src="https://bestpractices.coreinfrastructure.org/projects/6662/badge"></a>
@@ -117,14 +119,14 @@ Authentication
- Username / Password
- Multifactor authentication with OTP, U2F, Email OTP, SMS OTP
- [LDAP](https://zitadel.com/docs/guides/integrate/identity-providers/ldap)
- [External enterprise identity providers and social logins](https://zitadel.com/docs/guides/integrate/identity-providers/introduction)
- [External enterprise identity providers and social logins](https://zitadel.com/docs/guides/integrate/identity-providers/introduction)
- [Device authorization](https://zitadel.com/docs/guides/solution-scenarios/device-authorization)
- [OpenID Connect certified](https://openid.net/certification/#OPs) => [OIDC Endpoints](https://zitadel.com/docs/apis/openidoauth/endpoints)
- [SAML 2.0](http://docs.oasis-open.org/security/saml/Post2.0/sstc-saml-tech-overview-2.0.html) => [SAML Endpoints](https://zitadel.com/docs/apis/saml/endpoints)
- [Custom sessions](https://zitadel.com/docs/guides/integrate/login-ui/username-password) if you need to go beyond OIDC or SAML
- [Machine-to-machine](https://zitadel.com/docs/guides/integrate/service-users/authenticate-service-users) with JWT profile, Personal Access Tokens (PAT), and Client Credentials
- [Token exchange and impersonation](https://zitadel.com/docs/guides/integrate/token-exchange)
- [Beta: Hosted Login V2](https://zitadel.com/docs/guides/integrate/login/hosted-login#hosted-login-version-2-beta) our new login version 2.0
- [Beta: Hosted Login V2](https://zitadel.com/docs/guides/integrate/login/hosted-login#hosted-login-version-2-beta) our new Login version 2.0
Multi-Tenancy
@@ -142,7 +144,7 @@ Integration
- [Examples and SDKs](https://zitadel.com/docs/sdk-examples/introduction)
- [Audit Log and SOC/SIEM](https://zitadel.com/docs/guides/integrate/external-audit-log)
- [User registration and onboarding](https://zitadel.com/docs/guides/integrate/onboarding)
- [Hosted and custom login user interface](https://zitadel.com/docs/guides/integrate/login/login-users)
- [Hosted and custom Login user interface](https://zitadel.com/docs/guides/integrate/login/login-users)
Self-Service
- [Self-registration](https://zitadel.com/docs/concepts/features/selfservice#registration) including verification
@@ -179,7 +181,7 @@ Secure a React Application using OpenID Connect Authorization Code with PKCE
### Login with Passkeys
Use our login widget to allow easy and secure access to your applications and enjoy all the benefits of Passkeys (FIDO 2 / WebAuthN):
Use our Login widget to allow easy and secure access to your applications and enjoy all the benefits of Passkeys (FIDO 2 / WebAuthN):
[![Passkeys](https://user-images.githubusercontent.com/1366906/223664178-4132faef-4832-4014-b9ab-90c2a8d15436.gif)](https://www.youtube.com/watch?v=cZjHQYurSjw&list=PLTDa7jTlOyRLdABgD2zL0LGM7rx5GZ1IR&index=2 "Passkeys")
@@ -191,7 +193,7 @@ Use [Console](https://zitadel.com/docs/guides/manage/console/overview) or our [A
### Login V2
Check out our new Login V2 version in our [typescript repository](https://github.com/zitadel/typescript) or in our [documentation](https://zitadel.com/docs/guides/integrate/login/hosted-login#hosted-login-version-2-beta)
Check out our new Login V2 version in our [documentation](https://zitadel.com/docs/guides/integrate/login/hosted-login#hosted-login-version-2-beta)
![New Login Showcase](https://github.com/user-attachments/assets/cb5c5212-128b-4dc9-b11d-cabfd3f73e26)
## Security

5
apps/api/.env Normal file
View File

@@ -0,0 +1,5 @@
ZITADEL_DATABASE_POSTGRES_HOST=${DEVCONTAINER_DB_API_HOST:-localhost}
ZITADEL_DATABASE_POSTGRES_PORT=5432
ZITADEL_PORT=8080
ZITADEL_EXTERNALPORT=8080
API_AWAIT_DB_SERVICE=db

View File

@@ -0,0 +1,5 @@
ZITADEL_DATABASE_POSTGRES_HOST=${DEVCONTAINER_DB_FUNCTIONAL_UI_HOST:-localhost}
ZITADEL_DATABASE_POSTGRES_PORT=5434
ZITADEL_PORT=8083
ZITADEL_EXTERNALPORT=8083
API_AWAIT_DB_SERVICE=db-functional-ui

View File

@@ -0,0 +1,3 @@
ZITADEL_DATABASE_POSTGRES_HOST=${DEVCONTAINER_DB_API_INTEGRATION_HOST:-localhost}
ZITADEL_DATABASE_POSTGRES_PORT=5433
ZITADEL_API_URL=http://localhost:8082

View File

@@ -0,0 +1,5 @@
ZITADEL_DATABASE_POSTGRES_HOST=${DEVCONTAINER_DB_API_INTEGRATION_HOST:-localhost}
ZITADEL_DATABASE_POSTGRES_PORT=5433
ZITADEL_PORT=8082
ZITADEL_EXTERNALPORT=8082
API_AWAIT_DB_SERVICE=db-api-integration

34
apps/api/Dockerfile Normal file
View File

@@ -0,0 +1,34 @@
# Builder stage: Sets up the environment, installs dependencies, copies the Zitadel binary, and configures permissions for the application.
# This stage produces a runnable image that can be used for debugging.
FROM debian:latest AS builder
ARG TARGETPLATFORM
RUN apt-get update && apt-get install ca-certificates -y
COPY apps/api/entrypoint.sh /app/entrypoint.sh
COPY ./.artifacts/bin/${TARGETPLATFORM}/zitadel /app/zitadel
RUN useradd -s "" --home / zitadel && \
chown zitadel /app/zitadel && \
chmod +x /app/zitadel && \
chown zitadel /app/entrypoint.sh && \
chmod +x /app/entrypoint.sh
WORKDIR /app
ENV PATH="/app:${PATH}"
USER zitadel
ENTRYPOINT ["/app/entrypoint.sh"]
# Final stage: Creates a minimal container image with just the Zitadel binary and necessary files
FROM scratch AS final
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /etc/ssl/certs /etc/ssl/certs
COPY --from=builder /app/zitadel /app/zitadel
HEALTHCHECK NONE
EXPOSE 8080
USER zitadel
ENTRYPOINT ["/app/zitadel"]

View File

@@ -0,0 +1,25 @@
ExternalSecure: false
TLS.Enabled: false
Database.Postgres:
Database: zitadel
MaxOpenConns: 20
MaxIdleConns: 20
ConnMaxLifetime: 60m
ConnMaxIdleTime: 10m
FirstInstance:
LoginClientPatPath: login-client.pat
PatPath: admin.pat
InstanceName: ZITADEL
DefaultLanguage: en
Org:
LoginClient:
Machine:
Username: login-client
Name: Automatically Initialized IAM Login Client
Pat.ExpirationDate: 2099-01-01T00:00:00Z
Machine:
Machine:
Username: admin
Name: Automatically Initialized IAM admin Client
Pat.ExpirationDate: 2099-01-01T00:00:00Z
DefaultInstance.Features.LoginV2.BaseURI: http://localhost:3000/ui/v2/login

470
apps/api/project.json Normal file
View File

@@ -0,0 +1,470 @@
{
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"name": "@zitadel/api",
"projectType": "application",
"namedInputs": {
"sources": [
"{workspaceRoot}/cmd/**/*.go",
"{workspaceRoot}/internal/**/*.go",
"{workspaceRoot}/proto/**/*.go",
"{workspaceRoot}/pkg/**/*.go",
"{workspaceRoot}/main.go"
],
"runtime": [
"sources",
"{workspaceRoot}/go*",
"!{workspaceRoot}/internal/integration/**/*",
"!{workspaceRoot}/**/*_test.go",
"!{workspaceRoot}/**/integration_test/**/*"
],
"pack": [
{ "env": "VERSION" },
"runtime"
]
},
"targets": {
"prod": {
"description": "Runs the Go-based API backend in production mode",
"continuous": true,
"dependsOn": [
"build"
],
"executor": "nx:run-commands",
"options": {
"parallel": false,
"commands": [
"timeout 300 bash -c 'until nx run @zitadel/devcontainer:compose exec ${API_AWAIT_DB_SERVICE} pg_isready -U postgres -h localhost; do echo \"Awaiting DB\"; sleep 2; done' || (echo \"Database readiness check timed out after 5 minutes\" && exit 1)",
"./.artifacts/bin/$(go env GOOS)/$(go env GOARCH)/${ZITADEL_BINARY:-zitadel.local} start-from-init --config ${API_CONFIG_FILE} --steps ${API_CONFIG_FILE} --masterkey MasterkeyNeedsToHave32Characters"
]
},
"defaultConfiguration": "default",
"configurations": {
"default": {
"env": {
"API_CONFIG_FILE": "{projectRoot}/prod-default.yaml"
}
},
"test-integration-api": {
"env": {
"API_CONFIG_FILE": "{projectRoot}/test-integration-api.yaml"
}
},
"test-functional-ui": {
"env": {
"API_CONFIG_FILE": "{projectRoot}/test-functional-ui.yaml"
}
}
}
},
"build": {
"description": "Compiles the Go-based API backend into an executable binary.",
"dependsOn": [
"generate",
"build-console"
],
"command": "bash -c 'CGO_ENABLED=0 go build -o .artifacts/bin/$(go env GOOS)/$(go env GOARCH)/zitadel.local -v -ldflags=\"-s -w\"'",
"inputs": [
{ "runtime": "go env GOOS" },
{ "runtime": "go env GOARCH" },
"runtime"
],
"outputs": [
"{workspaceRoot}/.artifacts/bin/*/*/zitadel.local"
]
},
"generate": {
"description": "Generates the code needed to start a full-featured API: gRPC and OpenAPI stubs, static files for the embedded login v1, asset routes and documentation.",
"dependsOn": [
"generate-stubs",
"generate-assets",
"generate-statik"
]
},
"lint-install":{
"description": "Installs golangci-lint binary for linting. Using go install is not recommended in the official docs, because this can produce non-deterministic results.",
"cache": true,
"command": "curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b .artifacts/bin/$(go env GOOS)/$(go env GOARCH) v2.5.0",
"inputs": [
{ "runtime": "go env GOOS" },
{ "runtime": "go env GOARCH" }
],
"outputs": [
"{workspaceRoot}/.artifacts/bin/*/*/golangci-lint"
]
},
"lint": {
"description": "Lints the Go code with golangci-lint using the configuration in .golangci.yaml",
"dependsOn": [
"lint-install",
"generate-stubs",
"generate-assets"
],
"command": "PATH=\"${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH):$PATH\" golangci-lint run --timeout 15m --config ./.golangci.yaml --verbose",
"cache": true,
"inputs": [
"sources",
"{workspaceRoot}/.golangci.yaml"
]
},
"test": {
"description": "Runs all tests (unit and integration)",
"dependsOn": [
"test-unit",
"test-integration"
]
},
"test-unit": {
"description": "Runs the unit tests with coverage",
"dependsOn": [
"generate-stubs",
"generate-assets",
"generate-statik"
],
"command": "go test -race -coverprofile=profile.api.test-unit.cov -coverpkg=./internal/... ./...",
"inputs": [
"sources",
"{workspaceRoot}/go*"
],
"outputs": [
"{workspaceRoot}/profile.api.test-unit.cov"
]
},
"test-integration-build": {
"description": "Builds the test binary for integration tests.",
"dependsOn": [
"generate-stubs",
"generate-assets",
"generate-statik"
],
"command": "go build -cover -race -tags integration -o .artifacts/bin/$(go env GOOS)/$(go env GOARCH)/zitadel.test main.go",
"cache": true,
"inputs": [
{ "runtime": "go env GOOS" },
{ "runtime": "go env GOARCH" },
"sources",
"{workspaceRoot}/internal/integration/**",
"{workspaceRoot}/go*"
],
"outputs": [
"{workspaceRoot}/.artifacts/bin/*/*/zitadel.test"
]
},
"test-integration-run-db": {
"description": "Runs the database and cache for integration tests.",
"continuous": true,
"command": "nx run @zitadel/devcontainer:compose up --force-recreate --renew-anon-volumes db-api-integration cache-api-integration"
},
"test-integration-run-api": {
"description": "Runs the API server for the integration tests.",
"continuous": true,
"dependsOn": [
"test-integration-build"
],
"executor": "nx:run-commands",
"options": {
"env": {
"ZITADEL_BINARY": "zitadel.test",
"GOCOVERDIR": "{workspaceRoot}/.artifacts/api-test-integration/coverage",
"GORACE": "log_path=.artifacts/api-test-integration/race.log"
},
"parallel": false,
"commands": [
"rm -rf .artifacts/api-test-integration",
"mkdir -p ${GOCOVERDIR}",
"nx run @zitadel/api:prod:test-integration-api --excludeTaskDependencies"
]
}
},
"test-integration": {
"description": "Runs the integration tests sequentially with coverage and race condition detection. Go test caching is disabled, because the tests run against an out-of-process API.",
"dependsOn": [
"test-integration-run-db",
"test-integration-run-api"
],
"executor": "nx:run-commands",
"options": {
"parallel": false,
"env": {
"GOCOVERDIR": "{workspaceRoot}/.artifacts/api-test-integration/coverage"
},
"commands": [
"wait-on --verbose --interval 2000 --simultaneous 1 --timeout 30m \"${ZITADEL_API_URL}/debug/ready\"",
"bash -c 'go test -race -count 1 -tags integration -timeout 60m -parallel 1 $(go list -tags integration ./... | grep -e \"integration_test\" -e \"events_testing\")'",
"go tool covdata textfmt -i=$GOCOVERDIR -pkg=github.com/zitadel/zitadel/internal/...,github.com/zitadel/zitadel/cmd/...,github.com/zitadel/zitadel/backend/... -o profile.api.test-integration.cov",
"nx run @zitadel/api:test-integration-stop"
]
},
"inputs": [
{ "runtime": "go env GOOS" },
{ "runtime": "go env GOARCH" },
"sources",
"{workspaceRoot}/internal/integration/**",
"{workspaceRoot}/go*"
],
"outputs": [
"{workspaceRoot}/profile.api.test-integration.cov"
]
},
"test-integration-stop": {
"description": "Stops the database and cache containers used for integration tests.",
"command": "nx run @zitadel/devcontainer:compose down --volumes db-api-integration cache-api-integration"
},
"build-console": {
"description": "Builds the Console and copies its static files to the API.",
"dependsOn": [
"@zitadel/console:build"
],
"command": "cp -r console/dist/console/* internal/api/ui/console/static",
"cache": true,
"outputs": [
"{workspaceRoot}/internal/api/ui/console/static"
]
},
"generate-install": {
"description": "Installs the binaries needed for generating code. We avoid using go tools so the dev tool dependencies don't interfere with the prod dependencies.",
"executor": "nx:run-commands",
"options": {
"commands": [
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install github.com/dmarkham/enumer@v1.5.11",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install go.uber.org/mock/mockgen@v0.4.0",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install golang.org/x/tools/cmd/stringer@v0.36.0",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install github.com/rakyll/statik@v0.1.7",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install github.com/bufbuild/buf/cmd/buf@v1.45.0",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.35.1",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.5.1",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.22.0",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@v2.22.0",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install github.com/envoyproxy/protoc-gen-validate@v1.1.0",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install connectrpc.com/connect/cmd/protoc-gen-connect-go@v1.18.1",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.35.1",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install ./internal/protoc/protoc-gen-authoption",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install ./internal/protoc/protoc-gen-zitadel"
]
},
"cache": true,
"inputs": [
{ "runtime": "go env GOOS" },
{ "runtime": "go env GOARCH" },
"{workspaceRoot}/internal/protoc/protoc-gen-authoption/**/*",
"{workspaceRoot}/internal/protoc/protoc-gen-zitadel/**/*"
],
"outputs": [
"{workspaceRoot}/.artifacts/bin/*/*/enumer",
"{workspaceRoot}/.artifacts/bin/*/*/mockgen",
"{workspaceRoot}/.artifacts/bin/*/*/stringer",
"{workspaceRoot}/.artifacts/bin/*/*/statik",
"{workspaceRoot}/.artifacts/bin/*/*/buf",
"{workspaceRoot}/.artifacts/bin/*/*/protoc-gen-go",
"{workspaceRoot}/.artifacts/bin/*/*/protoc-gen-go-grpc",
"{workspaceRoot}/.artifacts/bin/*/*/protoc-gen-grpc-gateway",
"{workspaceRoot}/.artifacts/bin/*/*/protoc-gen-openapiv2",
"{workspaceRoot}/.artifacts/bin/*/*/protoc-gen-validate",
"{workspaceRoot}/.artifacts/bin/*/*/protoc-gen-connect-go",
"{workspaceRoot}/.artifacts/bin/*/*/protoc-gen-authoption",
"{workspaceRoot}/.artifacts/bin/*/*/protoc-gen-zitadel"
]
},
"generate-stubs": {
"description": "Generates the gRPC and OpenAPI stubs from the proto files.",
"dependsOn": [
"generate-install"
],
"executor": "nx:run-commands",
"options": {
"parallel": false,
"commands": [
"bash -c 'PATH=\"${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH):$PATH\" buf generate'",
"mkdir -p pkg/grpc openapi/v2/zitadel",
"cp -r .artifacts/grpc/github.com/zitadel/zitadel/pkg/grpc/** pkg/grpc/",
"cp -r .artifacts/grpc/zitadel/ openapi/v2/zitadel"
]
},
"cache": true,
"inputs": [
"{workspaceRoot}/proto/**/*",
"{workspaceRoot}/buf.gen.yaml",
"{workspaceRoot}/buf.yaml"
],
"outputs": [
"{workspaceRoot}/pkg/grpc/**/*",
"{workspaceRoot}/openapi/v2/zitadel/**/*"
]
},
"generate-statik": {
"description": "Generates statik files for embedding static resources",
"dependsOn": [
"generate-install"
],
"executor": "nx:run-commands",
"options": {
"commands": [
"PATH=\"${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH):$PATH\" go generate internal/api/ui/login/static/resources/generate.go",
"PATH=\"${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH):$PATH\" go generate internal/api/ui/login/statik/generate.go",
"PATH=\"${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH):$PATH\" go generate internal/notification/statik/generate.go",
"PATH=\"${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH):$PATH\" go generate internal/statik/generate.go"
]
},
"cache": true,
"inputs": [
{ "runtime": "go env GOOS" },
{ "runtime": "go env GOARCH" },
"{workspaceRoot}/internal/statik/generate.go",
"{workspaceRoot}/internal/notification/statik/generate.go",
"{workspaceRoot}/internal/api/ui/login/static/resources/generate.go",
"{workspaceRoot}/internal/api/ui/login/statik/generate.go"
],
"outputs": [
"{workspaceRoot}/internal/statik/statik.go",
"{workspaceRoot}/internal/notification/statik/statik.go",
"{workspaceRoot}/internal/api/ui/login/static/resources/themes/zitadel/css/zitadel.css*",
"{workspaceRoot}/internal/api/ui/login/statik/statik.go"
]
},
"generate-assets": {
"description": "Generates asset routes and documentation",
"dependsOn": [
"generate-install"
],
"command": "mkdir -p docs/apis/assets && go run internal/api/assets/generator/asset_generator.go -directory=internal/api/assets/generator/ -assets=docs/apis/assets/assets.md",
"cache": true,
"inputs": [
"{workspaceRoot}/internal/api/assets/generator/asset_generator.go"
],
"outputs": [
"{workspaceRoot}/internal/api/assets/authz.go",
"{workspaceRoot}/internal/api/assets/router.go",
"{workspaceRoot}/docs/apis/assets/assets.md"
]
},
"generate-go": {
"description": "Generates Go using Go native generation tools. This only needs to be run if sources for //go:generate files change, like for Stringer, Enumer, Mockgen etc.",
"dependsOn": [
"generate-install"
],
"command": "PATH=\"${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH):$PATH\" go generate ./..."
},
"pack-platform": {
"description": "Cross-compiles the binary and packages it for the platform defined by GOOS and GOARCH environment variables. The version is taken from the ZITADEL_VERSION environment variable.",
"executor": "nx:run-commands",
"options": {
"commands": [
"mkdir -p .artifacts/pack .artifacts/bin/$GOOS/$GOARCH",
"bash -c 'EXT=\"\"; if [ \"$GOOS\" = \"windows\" ]; then EXT=\".exe\"; fi; echo \"Building for $GOOS-$GOARCH...\"; CGO_ENABLED=0 go build -o .artifacts/bin/$GOOS/$GOARCH/zitadel$EXT -v -ldflags=\"-s -w -X github.com/zitadel/zitadel/cmd/build.commit=$(git rev-parse --short HEAD) -X github.com/zitadel/zitadel/cmd/build.date=$(date \"+%Y-%m-%dT%T%z\" | sed -E \"s/.([0-9]{2})([0-9]{2})$/-\\1:\\2/\") -X github.com/zitadel/zitadel/cmd/build.version=${ZITADEL_VERSION}\"'",
"bash -c 'EXT=\"\"; if [ \"$GOOS\" = \"windows\" ]; then EXT=\".exe\"; fi; FOLDER=\".artifacts/pack/zitadel-$GOOS-$GOARCH\"; mkdir -p \"$FOLDER\"; cp \".artifacts/bin/$GOOS/$GOARCH/zitadel$EXT\" \"$FOLDER/\"; cp LICENSE \"$FOLDER/\"; cp README.md \"$FOLDER/\"; tar -czvf \"$FOLDER.tar.gz\" \"$FOLDER\"; rm -rf \"$FOLDER\"'"
]
}
},
"pack-darwin-amd64": {
"description": "Packages the API for Darwin AMD64 (Intel) architecture",
"dependsOn": [
"generate-stubs",
"generate-assets",
"generate-statik"
],
"command": "GOOS=darwin GOARCH=amd64 nx run @zitadel/api:pack-platform",
"cache": true,
"inputs": [
"pack",
{ "env": "ZITADEL_VERSION" }
],
"outputs": [
"{workspaceRoot}/.artifacts/pack/zitadel-darwin-amd64.tar.gz",
"{workspaceRoot}/.artifacts/bin/darwin/amd64/zitadel"
]
},
"pack-darwin-arm64": {
"description": "Packages the API for Darwin ARM64 (Apple Silicon) architecture",
"dependsOn": [
"generate-stubs",
"generate-assets",
"generate-statik"
],
"command": "GOOS=darwin GOARCH=arm64 nx run @zitadel/api:pack-platform",
"cache": true,
"inputs": [
"pack",
{ "env": "ZITADEL_VERSION" }
],
"outputs": [
"{workspaceRoot}/.artifacts/pack/zitadel-darwin-arm64.tar.gz",
"{workspaceRoot}/.artifacts/bin/darwin/arm64/zitadel"
]
},
"pack-linux-amd64": {
"description": "Packages the API for Linux AMD64 architecture",
"dependsOn": [
"generate-stubs",
"generate-assets",
"generate-statik"
],
"command": "GOOS=linux GOARCH=amd64 nx run @zitadel/api:pack-platform",
"cache": true,
"inputs": [
"pack",
{ "env": "ZITADEL_VERSION" }
],
"outputs": [
"{workspaceRoot}/.artifacts/pack/zitadel-linux-amd64.tar.gz",
"{workspaceRoot}/.artifacts/bin/linux/amd64/zitadel"
]
},
"pack-linux-arm64": {
"description": "Packages the API for Linux ARM64 architecture",
"dependsOn": [
"generate-stubs",
"generate-assets",
"generate-statik"
],
"command": "GOOS=linux GOARCH=arm64 nx run @zitadel/api:pack-platform",
"cache": true,
"inputs": [
"pack",
{ "env": "ZITADEL_VERSION" }
],
"outputs": [
"{workspaceRoot}/.artifacts/pack/zitadel-linux-arm64.tar.gz",
"{workspaceRoot}/.artifacts/bin/linux/arm64/zitadel"
]
},
"pack-windows-amd64": {
"description": "Packages the API for Windows AMD64 architecture",
"dependsOn": [
"generate-stubs",
"generate-assets",
"generate-statik"
],
"command": "GOOS=windows GOARCH=amd64 nx run @zitadel/api:pack-platform",
"cache": true,
"inputs": [
"pack",
{ "env": "ZITADEL_VERSION" }
],
"outputs": [
"{workspaceRoot}/.artifacts/pack/zitadel-windows-amd64.tar.gz",
"{workspaceRoot}/.artifacts/bin/windows/amd64/zitadel.exe"
]
},
"pack-windows-arm64": {
"description": "Packages the API for Windows ARM64 architecture",
"dependsOn": [
"generate-stubs",
"generate-assets",
"generate-statik"
],
"command": "GOOS=windows GOARCH=arm64 nx run @zitadel/api:pack-platform",
"cache": true,
"inputs": [
"pack",
{ "env": "ZITADEL_VERSION" }
],
"outputs": [
"{workspaceRoot}/.artifacts/pack/zitadel-windows-arm64.tar.gz",
"{workspaceRoot}/.artifacts/bin/windows/arm64/zitadel.exe"
]
}
}
}

View File

@@ -1,14 +1,11 @@
Log:
Level: info
ExternalDomain: localhost
ExternalSecure: false
Database:
postgres:
# This makes the e2e config reusable with an out-of-docker zitadel process and an /etc/hosts entry
Host: host.docker.internal
Port: 5432
database: zitadel
MaxOpenConns: 15
MaxIdleConns: 10

View File

@@ -1,3 +1,26 @@
Database:
Postgres:
MaxOpenConns: 20
MaxIdleConns: 20
MaxConnLifetime: 1h
MaxConnIdleTime: 5m
Database: zitadel
FirstInstance:
Skip: false
PatPath: .artifacts/api-test-integration/admin-pat.txt
InstanceName: ZITADEL
DefaultLanguage: en
Org:
Name: ZITADEL
Machine:
Machine:
Username: boss
Name: boss
Pat:
ExpirationDate: 2099-01-01T00:00:00Z
Human:
PasswordChangeRequired: false
Log:
Level: info
@@ -47,11 +70,6 @@ Telemetry:
- "multi-value-1"
- "multi-value-2"
FirstInstance:
Org:
Human:
PasswordChangeRequired: false
LogStore:
Execution:
Stdout:
@@ -107,4 +125,4 @@ OIDC:
DefaultLogoutURLV2: "/logout?post_logout_redirect=" # ZITADEL_OIDC_DEFAULTLOGOUTURLV2
SAML:
DefaultLoginURLV2: "/login?authRequest=" # ZITADEL_SAML_DEFAULTLOGINURLV2
DefaultLoginURLV2: "/login?authRequest=" # ZITADEL_SAML_DEFAULTLOGINURLV2

5
apps/login/.env Normal file
View File

@@ -0,0 +1,5 @@
NEXT_PUBLIC_BASE_PATH=/ui/v2/login
EMAIL_VERIFICATION=false
DEBUG=true
ZITADEL_API_URL=http://localhost:8080
ZITADEL_SERVICE_USER_TOKEN_FILE=../../login-client.pat

1
apps/login/.env.prod Normal file
View File

@@ -0,0 +1 @@
ZITADEL_SERVICE_USER_TOKEN_FILE=../../../../login-client.pat

View File

@@ -1,6 +0,0 @@
ZITADEL_API_URL=http://localhost:22222
ZITADEL_SERVICE_USER_TOKEN="yolo"
EMAIL_VERIFICATION=true
DEBUG=true
PORT=3001
NEXT_PUBLIC_BASE_PATH=/ui/v2/login

View File

@@ -0,0 +1,2 @@
API_MOCK_STUBS_HOST=${DEVCONTAINER_LOGIN_API_MOCK_HOST:-localhost}
API_MOCK_STUBS_URL=http://${API_MOCK_STUBS_HOST}:22220/v1/stubs

View File

@@ -0,0 +1,4 @@
ZITADEL_API_URL=http://${DEVCONTAINER_LOGIN_API_MOCK_HOST:-localhost}:22222
ZITADEL_SERVICE_USER_TOKEN=none
ZITADEL_SERVICE_USER_TOKEN_FILE=""
PORT=3001

View File

@@ -1,63 +0,0 @@
name: 🐛 Bug Report
description: "Create a bug report to help us improve ZITADEL Typescript Library."
title: "[Bug]: "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: checkboxes
id: preflight
attributes:
label: Preflight Checklist
options:
- label:
I could not find a solution in the documentation, the existing issues or discussions
required: true
- label:
I have joined the [ZITADEL chat](https://zitadel.com/chat)
validations:
required: true
- type: input
id: version
attributes:
label: Version
description: Which version of ZITADEL Typescript Library are you using.
- type: textarea
id: impact
attributes:
label: Describe the problem caused by this bug
description: A clear and concise description of the problem you have and what the bug is.
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: To reproduce
description: Steps to reproduce the behaviour
placeholder: |
Steps to reproduce the behavior:
1. ...
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: If applicable, add screenshots to help explain your problem.
- type: textarea
id: expected
attributes:
label: Expected behavior
description: A clear and concise description of what you expected to happen.
- type: textarea
id: config
attributes:
label: Relevant Configuration
description: Add any relevant configurations that could help us. Make sure to redact any sensitive information.
- type: textarea
id: additional
attributes:
label: Additional Context
description: Please add any other infos that could be useful.

View File

@@ -1,4 +0,0 @@
blank_issues_enabled: true
contact_links:
- name: 💬 ZITADEL Community Chat
url: https://zitadel.com/chat

View File

@@ -1,30 +0,0 @@
name: 📄 Documentation
description: Create an issue for missing or wrong documentation.
labels: ["docs"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this issue.
- type: checkboxes
id: preflight
attributes:
label: Preflight Checklist
options:
- label:
I could not find a solution in the existing issues, docs, nor discussions
required: true
- label:
I have joined the [ZITADEL chat](https://zitadel.com/chat)
- type: textarea
id: docs
attributes:
label: Describe the docs your are missing or that are wrong
placeholder: As a [type of user], I want [some goal] so that [some reason].
validations:
required: true
- type: textarea
id: additional
attributes:
label: Additional Context
description: Please add any other infos that could be useful.

View File

@@ -1,54 +0,0 @@
name: 🛠️ Improvement
description: "Create an new issue for an improvment in ZITADEL"
labels: ["improvement"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this improvement request
- type: checkboxes
id: preflight
attributes:
label: Preflight Checklist
options:
- label:
I could not find a solution in the existing issues, docs, nor discussions
required: true
- label:
I have joined the [ZITADEL chat](https://zitadel.com/chat)
- type: textarea
id: problem
attributes:
label: Describe your problem
description: Please describe your problem this improvement is supposed to solve.
placeholder: Describe the problem you have
validations:
required: true
- type: textarea
id: solution
attributes:
label: Describe your ideal solution
description: Which solution do you propose?
placeholder: As a [type of user], I want [some goal] so that [some reason].
validations:
required: true
- type: input
id: version
attributes:
label: Version
description: Which version of the typescript library are you using.
- type: dropdown
id: environment
attributes:
label: Environment
description: How do you use ZITADEL?
options:
- ZITADEL Cloud
- Self-hosted
validations:
required: true
- type: textarea
id: additional
attributes:
label: Additional Context
description: Please add any other infos that could be useful.

View File

@@ -1,54 +0,0 @@
name: 💡 Proposal / Feature request
description: "Create an issue for a feature request/proposal."
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this proposal / feature reqeust
- type: checkboxes
id: preflight
attributes:
label: Preflight Checklist
options:
- label:
I could not find a solution in the existing issues, docs, nor discussions
required: true
- label:
I have joined the [ZITADEL chat](https://zitadel.com/chat)
- type: textarea
id: problem
attributes:
label: Describe your problem
description: Please describe your problem this proposal / feature is supposed to solve.
placeholder: Describe the problem you have.
validations:
required: true
- type: textarea
id: solution
attributes:
label: Describe your ideal solution
description: Which solution do you propose?
placeholder: As a [type of user], I want [some goal] so that [some reason].
validations:
required: true
- type: input
id: version
attributes:
label: Version
description: Which version of the Typescript Library are you using.
- type: dropdown
id: environment
attributes:
label: Environment
description: How do you use ZITADEL?
options:
- ZITADEL Cloud
- Self-hosted
validations:
required: true
- type: textarea
id: additional
attributes:
label: Additional Context
description: Please add any other infos that could be useful.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

View File

@@ -1,21 +0,0 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: '/'
open-pull-requests-limit: 1
schedule:
interval: 'daily'
- package-ecosystem: npm
directory: '/'
open-pull-requests-limit: 3
schedule:
interval: daily
groups:
prod:
dependency-type: production
dev:
dependency-type: development
ignore:
- dependency-name: "eslint"
versions: [ "9.x" ]

View File

@@ -1,13 +0,0 @@
### Definition of Ready
- [ ] I am happy with the code
- [ ] Short description of the feature/issue is added in the pr description
- [ ] PR is linked to the corresponding user story
- [ ] Acceptance criteria are met
- [ ] All open todos and follow ups are defined in a new ticket and justified
- [ ] Deviations from the acceptance criteria and design are agreed with the PO and documented.
- [ ] Vitest unit tests ensure that components produce expected outputs on different inputs.
- [ ] Cypress integration tests ensure that login app pages work as expected on good and bad user inputs, ZITADEL responses or IDP redirects. The ZITADEL API is mocked, IDP redirects are simulated.
- [ ] Playwright acceptances tests ensure that the happy paths of common user journeys work as expected. The ZITADEL API is not mocked but IDP redirects are simulated.
- [ ] No debug or dead code
- [ ] My code has no repetitions

View File

@@ -1,39 +0,0 @@
name: Auto-close PRs and guide to correct repo
on:
workflow_dispatch:
pull_request_target:
types: [opened]
jobs:
auto-close:
runs-on: ubuntu-latest
if: github.repository_id == '622995060' && github.ref_name != 'mirror-zitadel-repo'
steps:
- name: Comment and close PR
uses: actions/github-script@v7
with:
script: |
const message = `
👋 **Thanks for your contribution @${{ github.event.pull_request.user.login }}!**
This repository \`${{ github.repository }}\` is a read-only mirror of the git subtree at [\`zitadel/zitadel/login\`](https://github.com/zitadel/zitadel).
Therefore, we close this pull request automatically.
Your changes are not lost. Submitting them to the main repository is easy:
1. [Fork zitadel/zitadel](https://github.com/zitadel/zitadel/fork)
2. Clone your Zitadel fork \`git clone https://github.com/<your-owner>/zitadel.git\`
3. Change directory to your Zitadel forks root.
4. Pull your changes into the Zitadel fork by running \`make login_pull LOGIN_REMOTE_URL=https://github.com/<your-owner>/typescript.git LOGIN_REMOTE_BRANCH=<your-typescript-fork-branch>\`.
5. Push your changes and [open a pull request to zitadel/zitadel](https://github.com/zitadel/zitadel/compare)
`.trim();
await github.rest.issues.createComment({
...context.repo,
issue_number: context.issue.number,
body: message
});
await github.rest.pulls.update({
...context.repo,
pull_number: context.issue.number,
state: "closed"
});

View File

@@ -1,41 +0,0 @@
name: Add new issues to product management project
on:
issues:
types:
- opened
jobs:
add-to-project:
name: Add issue and community pr to project
runs-on: ubuntu-latest
if: github.repository_id == '622995060'
steps:
- name: add issue
uses: actions/add-to-project@v1.0.2
if: ${{ github.event_name == 'issues' }}
with:
# You can target a repository in a different organization
# to the issue
project-url: https://github.com/orgs/zitadel/projects/2
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
- uses: tspascoal/get-user-teams-membership@v3
id: checkUserMember
if: github.actor != 'dependabot[bot]'
with:
username: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.ADD_TO_PROJECT_PAT }}
- name: add pr
uses: actions/add-to-project@v1.0.2
if: ${{ github.event_name == 'pull_request_target' && github.actor != 'dependabot[bot]' && !contains(steps.checkUserMember.outputs.teams, 'engineers')}}
with:
# You can target a repository in a different organization
# to the issue
project-url: https://github.com/orgs/zitadel/projects/2
github-token: ${{ secrets.ADD_TO_PROJECT_PAT }}
- uses: actions-ecosystem/action-add-labels@v1.1.3
if: ${{ github.event_name == 'pull_request_target' && github.actor != 'dependabot[bot]' && !contains(steps.checkUserMember.outputs.teams, 'staff')}}
with:
github_token: ${{ secrets.ADD_TO_PROJECT_PAT }}
labels: |
os-contribution

View File

@@ -1,32 +0,0 @@
name: Release
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
runs-on: ubuntu-latest
if: github.repository_id != '622995060'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install dependencies
run: pnpm install
- name: Create Release Pull Request
uses: changesets/action@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,67 +0,0 @@
name: Quality
on:
pull_request:
workflow_dispatch:
inputs:
ignore-run-cache:
description: 'Whether to ignore the run cache'
required: false
default: true
ref-tag:
description: 'overwrite the DOCKER_METADATA_OUTPUT_VERSION environment variable used by the make file'
required: false
default: ''
jobs:
quality:
name: Ensure Quality
if: github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' && github.repository_id != '622995060')
runs-on: ubuntu-22.04
timeout-minutes: 30
permissions:
contents: read # We only need read access to the repository contents
actions: write # We need write access to the actions cache
env:
CACHE_DIR: /tmp/login-run-caches
# Only run this job on workflow_dispatch or pushes to forks
steps:
- uses: actions/checkout@v4
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/zitadel/login
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}
- name: Set up Buildx
uses: docker/setup-buildx-action@v3
# Only with correctly restored build cache layers, the run caches work as expected.
# To restore docker build layer caches, extend the docker-bake.hcl to use the cache-from and cache-to options.
# https://docs.docker.com/build/ci/github-actions/cache/
# Alternatively, you can use a self-hosted runner or a third-party builder that restores build layer caches out-of-the-box, like https://depot.dev/
- name: Restore Run Caches
uses: actions/cache/restore@v4
id: run-caches-restore
with:
path: ${{ env.CACHE_DIR }}
key: ${{ runner.os }}-login-run-caches-${{github.ref_name}}-${{ github.sha }}-${{github.run_attempt}}
restore-keys: |
${{ runner.os }}-login-run-caches-${{github.ref_name}}-${{ github.sha }}-
${{ runner.os }}-login-run-caches-${{github.ref_name}}-
${{ runner.os }}-login-run-caches-
- run: make login_quality
env:
IGNORE_RUN_CACHE: ${{ github.event.inputs.ignore-run-cache == 'true' }}
DOCKER_METADATA_OUTPUT_VERSION: ${{ github.event.inputs.ref-tag || env.DOCKER_METADATA_OUTPUT_VERSION || steps.meta.outputs.version }}
- name: Save Run Caches
uses: actions/cache/save@v4
with:
path: ${{ env.CACHE_DIR }}
key: ${{ steps.run-caches-restore.outputs.cache-primary-key }}
if: always()

View File

@@ -6,7 +6,6 @@ cypress
.DS_Store
node_modules
.turbo
*.log
.next
dist

View File

@@ -1,128 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
legal@zitadel.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@@ -1,218 +0,0 @@
# Contributing
:attention: In this CONTRIBUTING.md you read about contributing to this very repository.
If you want to develop your own login UI, please refer [to the README.md](./README.md).
## Introduction
Thank you for your interest about how to contribute!
:attention: If you notice a possible **security vulnerability**, please don't hesitate to disclose any concern by contacting [security@zitadel.com](mailto:security@zitadel.com).
You don't have to be perfectly sure about the nature of the vulnerability.
We will give them a high priority and figure them out.
We also appreciate all your other ideas, thoughts and feedback and will take care of them as soon as possible.
We love to discuss in an open space using [GitHub issues](https://github.com/zitadel/typescript/issues),
[GitHub discussions in the core repo](https://github.com/zitadel/zitadel/discussions)
or in our [chat on Discord](https://zitadel.com/chat).
For private discussions,
you have [more contact options on our Website](https://zitadel.com/contact).
## Pull Requests
The repository zitadel/typescript is a read-only mirror of the git subtree at zitadel/zitadel/login.
To submit changes, please open a Pull Request [in the zitadel/zitadel repository](https://github.com/zitadel/zitadel/compare).
If you already made changes based on the zitadel/typescript repository, these changes are not lost.
Submitting them to the main repository is easy:
1. [Fork zitadel/zitadel](https://github.com/zitadel/zitadel/fork)
1. Clone your Zitadel fork git clone https://github.com/<your-owner>/zitadel.git
1. Change directory to your Zitadel forks root.
1. Pull your changes into the Zitadel fork by running make login_pull LOGIN_REMOTE_URL=https://github.com/<your-owner>/typescript.git LOGIN_REMOTE_BRANCH=<your-typescript-fork-branch>.
1. Push your changes and [open a pull request to zitadel/zitadel](https://github.com/zitadel/zitadel/compare)
Please consider the following guidelines when creating a pull request.
- The latest changes are always in `main`, so please make your pull request against that branch.
- pull requests should be raised for any change
- Pull requests need approval of a Zitadel core engineer @zitadel/engineers before merging
- We use ESLint/Prettier for linting/formatting, so please run `pnpm lint:fix` before committing to make resolving conflicts easier (VSCode users, check out [this ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) and [this Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) to fix lint and formatting issues in development)
- If you add new functionality, please provide the corresponding documentation as well and make it part of the pull request
### Setting up local environment
```sh
# Install dependencies. Developing requires Node.js v20
pnpm install
# Generate gRPC stubs
pnpm generate
# Start a local development server for the login and manually configure apps/login/.env.local
pnpm dev
```
The application is now available at `http://localhost:3000`
Configure apps/login/.env.local to target the Zitadel instance of your choice.
The login app live-reloads on changes, so you can start developing right away.
### <a name="latest"></a>Developing Against A Local Latest Zitadel Release
The following command uses Docker to run a local Zitadel instance and the login application in live-reloading dev mode.
Additionally, it runs a Traefik reverse proxy that exposes the login with a self-signed certificate at https://127.0.0.1.sslip.io
127.0.0.1.sslip.io is a special domain that resolves to your localhost, so it's safe to allow your browser to proceed with loading the page.
```sh
# Install dependencies. Developing requires Node.js v20
pnpm install
# Generate gRPC stubs
pnpm generate
# Start a local development server and have apps/login/.env.test.local configured for you to target the local Zitadel instance.
pnpm dev:local
```
Log in at https://127.0.0.1.sslip.io/ui/v2/login/loginname and use the following credentials:
**Loginname**: *zitadel-admin@zitadel.127.0.0.1.sslip.io*
**Password**: _Password1!_.
The login app live-reloads on changes, so you can start developing right away.
### <a name="local"></a>Developing Against A Locally Compiled Zitadel
To develop against a locally compiled version of Zitadel, you need to build the Zitadel docker image first.
Clone the [Zitadel repository](https://github.com/zitadel/zitadel.git) and run the following command from its root:
```sh
# This compiles a Zitadel binary if it does not exist at ./zitadel already and copies it into a Docker image.
# If you want to recompile the binary, run `make compile` first
make login_dev
```
Open another terminal session at zitadel/zitadel/login and run the following commands to start the dev server.
```bash
# Install dependencies. Developing requires Node.js v20
pnpm install
# Start a local development server and have apps/login/.env.test.local configured for you to target the local Zitadel instance.
NODE_ENV=test pnpm dev
```
Log in at https://127.0.0.1.sslip.io/ui/v2/login/loginname and use the following credentials:
**Loginname**: *zitadel-admin@zitadel.127.0.0.1.sslip.io*
**Password**: _Password1!_.
The login app live-reloads on changes, so you can start developing right away.
### Quality Assurance
Use `make` commands to test the quality of your code against a production build without installing any dependencies besides Docker.
Using `make` commands, you can reproduce and debug the CI pipelines locally.
```sh
# Reproduce the whole CI pipeline in docker
make login_quality
# Show other options with make
make help
```
Use `pnpm` commands to run the tests in dev mode with live reloading and debugging capabilities.
#### Linting and formatting
Check the formatting and linting of the code in docker
```sh
make login_lint
```
Check the linting of the code using pnpm
```sh
pnpm lint
pnpm format
```
Fix the linting of your code
```sh
pnpm lint:fix
pnpm format:fix
```
#### Running Unit Tests
Run the tests in docker
```sh
make login_test_unit
```
Run unit tests with live-reloading
```sh
pnpm test:unit
```
#### Running Integration Tests
Run the test in docker
```sh
make login_test_integration
```
Alternatively, run a live-reloading development server with an interactive Cypress test suite.
First, set up your local test environment.
```sh
# Install dependencies. Developing requires Node.js v20
pnpm install
# Generate gRPC stubs
pnpm generate
# Start a local development server and use apps/login/.env.test to use the locally mocked Zitadel API.
pnpm test:integration:setup
```
Now, in another terminal session, open the interactive Cypress integration test suite.
```sh
pnpm test:integration open
```
Show more options with Cypress
```sh
pnpm test:integration help
```
#### Running Acceptance Tests
To run the tests in docker against the latest release of Zitadel, use the following command:
:warning: The acceptance tests are not reliable at the moment :construction:
```sh
make login_test_acceptance
```
Alternatively, run can use a live-reloading development server with an interactive Playwright test suite.
Set up your local environment by running the commands either for [developing against a local latest Zitadel release](latest) or for [developing against a locally compiled Zitadel](compiled).
Now, in another terminal session, open the interactive Playwright acceptance test suite.
```sh
pnpm test:acceptance open
```
Show more options with Playwright
```sh
pnpm test:acceptance help
```

View File

@@ -1,37 +1,18 @@
FROM node:20-alpine AS base
FROM base AS build
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@10.13.1 --activate && \
apk update && \
rm -rf /var/cache/apk/*
FROM node:22-alpine
WORKDIR /app
COPY pnpm-lock.yaml ./
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm fetch --frozen-lockfile
COPY package.json ./
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile
COPY . .
RUN pnpm build:login:standalone
FROM scratch AS build-out
COPY --from=build /app/.next/standalone /
COPY --from=build /app/.next/static /.next/static
COPY public public
FROM base AS login-standalone
WORKDIR /runtime
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
# If /.env-file/.env is mounted into the container, its variables are made available to the server before it starts up.
RUN mkdir -p /.env-file && touch /.env-file/.env && chown -R nextjs:nodejs /.env-file
COPY --chown=nextjs:nodejs ./scripts/ ./
COPY --chown=nextjs:nodejs --from=build-out / ./
COPY --chown=nextjs:nodejs .next/standalone ./
USER nextjs
ENV HOSTNAME="0.0.0.0" \
NEXT_PUBLIC_BASE_PATH="/ui/v2/login" \
PORT=3000
PORT="3000" \
NODE_ENV="production"
# TODO: Check healthy, not ready
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD ["/bin/sh", "-c", "node /runtime/healthcheck.js http://localhost:${PORT}/ui/v2/login/healthy"]
ENTRYPOINT ["/runtime/entrypoint.sh"]
CMD ["/bin/sh", "-c", "node /app/healthcheck.js http://localhost:${PORT}/ui/v2/login/healthy"]
ENTRYPOINT ["/app/entrypoint.sh", "node", "apps/login/server.js" ]

View File

@@ -1,22 +0,0 @@
*
!constants
!scripts
!src
!public
!locales
!next.config.mjs
!next-env-vars.d.ts
!next-env.d.ts
!tailwind.config.mjs
!postcss.config.cjs
!tsconfig.json
!package.json
!pnpm-lock.yaml
**/*.md
**/*.png
**/node_modules
**/.turbo
**/*.test.ts
**/*.test.tsx

View File

@@ -1,5 +1,4 @@
import { defineConfig } from "cypress";
export default defineConfig({
reporter: "list",
video: true,
@@ -7,11 +6,12 @@ export default defineConfig({
runMode: 2
},
e2e: {
baseUrl: process.env.LOGIN_BASE_URL || "http://localhost:3001/ui/v2/login",
baseUrl: `http://localhost:3001${process.env.NEXT_PUBLIC_BASE_PATH || ""}`,
specPattern: "integration/integration/**/*.cy.{js,jsx,ts,tsx}",
supportFile: "integration/support/e2e.{js,jsx,ts,tsx}",
setupNodeEvents(on, config) {
// implement node event listeners here
},
pageLoadTimeout: 120_0000,
env: {
API_MOCK_STUBS_URL: process.env.API_MOCK_STUBS_URL || "http://localhost:22220/v1/stubs"
}
},
});

View File

@@ -1,3 +0,0 @@
target "release" {
platforms = ["linux/amd64", "linux/arm64"]
}

View File

@@ -1,25 +0,0 @@
variable "LOGIN_TAG" {
default = "zitadel-login:local"
}
group "default" {
targets = ["login-standalone"]
}
# The release target is overwritten in docker-bake-release.hcl
# It makes sure the image is built for multiple platforms.
# By default the platforms property is empty, so images are only built for the current bake runtime platform.
target "release" {}
target "docker-metadata-action" {
# In the pipeline, this target is overwritten by the docker metadata action.
tags = ["${LOGIN_TAG}"]
}
# We run integration and acceptance tests against the next standalone server for docker.
target "login-standalone" {
inherits = [
"docker-metadata-action",
"release",
]
}

View File

@@ -3,9 +3,7 @@ RUN buf export https://github.com/envoyproxy/protoc-gen-validate.git --path vali
buf export https://github.com/grpc-ecosystem/grpc-gateway.git --path protoc-gen-openapiv2 --output /proto && \
buf export https://github.com/googleapis/googleapis.git --path google/api/annotations.proto --path google/api/http.proto --path google/api/field_behavior.proto --output /proto
FROM bufbuild/buf:1.54.0 AS zitadel-protos
RUN buf export https://github.com/zitadel/zitadel.git --path ./proto/zitadel --output /zitadel
FROM golang:1.20.5-alpine3.18 AS mock-zitadel
RUN go install github.com/eliobischof/grpc-mock/cmd/grpc-mock@01b09f60db1b501178af59bed03b2c22661df48c

View File

@@ -0,0 +1,19 @@
{
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
"name": "@zitadel/login-api-mock",
"targets": {
"build": {
"description": "Builds the API mock server",
"command": "nx run @zitadel/devcontainer:compose build login-api-mock"
},
"serve": {
"description": "Starts the API mock server",
"continuous": true,
"command": "nx run @zitadel/devcontainer:compose up --force-recreate --renew-anon-volumes login-api-mock"
},
"down": {
"description": "Stops the API mock server",
"command": "nx run @zitadel/devcontainer:compose down login-api-mock"
}
}
}

View File

@@ -18,7 +18,7 @@ Cypress.on('uncaught:exception', (err, runnable) => {
return true;
});
const url = Cypress.env("CORE_MOCK_STUBS_URL") || "http://localhost:22220/v1/stubs";
const url = Cypress.env("API_MOCK_STUBS_URL");
function removeStub(service: string, method: string) {
return cy.request({

View File

@@ -16,6 +16,9 @@ declare namespace NodeJS {
/**
* The service user token
* If ZITADEL_SERVICE_USER_TOKEN is set, its value is used.
* If ZITADEL_SERVICE_USER_TOKEN is not set but ZITADEL_SERVICE_USER_TOKEN_FILE is set, the application blocks until the file is created.
* As soon as the file exists, its content is read and ZITADEL_SERVICE_USER_TOKEN is set.
*/
ZITADEL_SERVICE_USER_TOKEN: string;

View File

@@ -3,8 +3,6 @@ import { DEFAULT_CSP } from "./constants/csp.js";
const withNextIntl = createNextIntlPlugin();
/** @type {import('next').NextConfig} */
const secureHeaders = [
{
key: "Strict-Transport-Security",
@@ -33,6 +31,7 @@ const secureHeaders = [
{ key: "X-Frame-Options", value: "deny" },
];
/** @type {import('next').NextConfig} */
const nextConfig = {
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
output: process.env.NEXT_OUTPUT_MODE || undefined,

View File

@@ -4,21 +4,16 @@
"private": true,
"type": "module",
"scripts": {
"dev": "next dev",
"build": "next build",
"build:login:standalone": "NEXT_PUBLIC_BASE_PATH=/ui/v2/login NEXT_OUTPUT_MODE=standalone next build",
"start": "next start",
"lint": "pnpm run '/^lint:check:.*$/'",
"lint:check:next": "next lint",
"lint:check:prettier": "prettier --check .",
"lint:fix": "prettier --write .",
"test:unit": "vitest --run",
"build": "NEXT_OUTPUT_MODE=standalone next build && cp -r public scripts/* .next/standalone/ && cp -r .next/static .next/standalone/apps/login/.next/ && rm .next/standalone/apps/login/.env",
"build-vercel": "next build",
"dev": "HOSTNAME=127.0.0.1 ./scripts/entrypoint.sh next dev",
"prod": "cd ./.next/standalone && HOSTNAME=127.0.0.1 ./entrypoint.sh node apps/login/server.js",
"lint-check-next": "next lint",
"lint-check-prettier": "prettier --check .",
"lint-fix": "prettier --write .",
"test-unit": "vitest --run",
"lint-staged": "lint-staged",
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next",
"test:integration:login": "wait-on --simultaneous 1 http://localhost:3001/ui/v2/login/verify?userId=221394658884845598&code=abc && cypress run",
"test:acceptance": "dotenv -e ../login/.env.test.local playwright",
"test:acceptance:setup": "cd ../.. && make login_test_acceptance_setup_env && NODE_ENV=test turbo run test:acceptance:setup:dev",
"test:acceptance:setup:dev": "cd ../.. && make login_test_acceptance_setup_dev"
"clean": "rm -rf node_modules .next cypress"
},
"pnpm": {
"overrides": {
@@ -36,8 +31,6 @@
"@heroicons/react": "2.1.3",
"@radix-ui/react-tooltip": "^1.2.7",
"@tailwindcss/forms": "0.5.7",
"@zitadel/client": "latest",
"@zitadel/proto": "latest",
"clsx": "1.2.1",
"copy-to-clipboard": "^3.3.3",
"deepmerge": "^4.3.1",
@@ -74,11 +67,13 @@
"@typescript-eslint/parser": "^7.0.0",
"@vercel/git-hooks": "1.0.0",
"@vitejs/plugin-react": "^4.4.1",
"@zitadel/client": "workspace:*",
"@zitadel/proto": "workspace:*",
"autoprefixer": "10.4.21",
"concurrently": "^9.1.2",
"cypress": "^14.5.2",
"cypress": "^14.5.4",
"dotenv-cli": "^8.0.0",
"env-cmd": "^10.0.0",
"env-cmd": "^10.1.0",
"eslint": "^8.57.0",
"eslint-config-next": "15.4.0-canary.86",
"eslint-config-prettier": "^9.1.0",
@@ -98,7 +93,6 @@
"ts-proto": "^2.7.0",
"typescript": "^5.8.3",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^2.0.0",
"wait-on": "^7.2.0"
"vitest": "^2.0.0"
}
}
}

156
apps/login/project.json Normal file
View File

@@ -0,0 +1,156 @@
{
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"targets": {
"prod": {
"description": "Runs the Next.js Login application in production mode from the standalone build",
"continuous": true,
"dependsOn": [
"build"
],
"defaultConfiguration": "default",
"configurations": {
"default": {},
"test-login-integration": {}
}
},
"dev": {
"description": "Runs the Next.js Login application in development mode with hot-reloading",
"continuous": true,
"dependsOn": [
"^build"
]
},
"build": {
"description": "Builds the Next.js Login application in standalone mode for production",
"cache": true,
"dependsOn": [
"^build"
],
"inputs": [
"default",
"{workspaceRoot}/pnpm-lock.yaml",
"!{projectRoot}/.env.*",
"!{projectRoot}/.local.env",
"!{projectRoot}/integration/**/*",
"!{projectRoot}/acceptance/**/*",
"!{projectRoot}/cypress.config.ts"
],
"outputs": [
"{projectRoot}/.next/standalone"
]
},
"build-vercel": {
"description": "Builds the Next.js Login application for Vercel deployment",
"cache": true,
"dependsOn": [
"^build"
],
"inputs": [
"default",
"{workspaceRoot}/pnpm-lock.yaml",
"!{projectRoot}/.env.*",
"!{projectRoot}/.local.env",
"!{projectRoot}/integration/**/*",
"!{projectRoot}/acceptance/**/*",
"!{projectRoot}/cypress.config.ts"
],
"outputs": [
"{projectRoot}/.next",
"!{projectRoot}/.next/cache",
"!{projectRoot}/.next/standalone"
]
},
"lint": {
"description": "Runs all linters",
"dependsOn": [
"lint-check-*"
]
},
"lint-check-prettier": {
"description": "Checks code formatting with Prettier",
"cache": true,
"inputs": [
"default"
]
},
"lint-check-next": {
"description": "Runs Next.js specific lint checks",
"cache": true,
"inputs": [
"default"
]
},
"test": {
"description": "Runs all tests (unit and integration)",
"dependsOn": [
"test-unit",
"test-integration"
]
},
"test-unit": {
"description": "Runs unit tests using Vitest",
"dependsOn": [
"^build"
]
},
"test-integration-run-login": {
"description": "Runs the Login application under test. It has its own target, separate from test-integration, because it's a continuous task.",
"dependsOn": [
"build"
],
"continuous": true,
"command": "nx run @zitadel/login:prod:test-login-integration --excludeTaskDependencies"
},
"test-integration": {
"description": "Runs integration tests using Cypress against a running Login and a mocked API",
"dependsOn": [
"test-integration-run-login",
"@zitadel/login-api-mock:build",
"@zitadel/login-api-mock:serve"
],
"executor": "nx:run-commands",
"options": {
"cwd": "{projectRoot}",
"parallel": false,
"commands": [
"pnpm cypress install",
"pnpm wait-on --verbose --interval 2000 --simultaneous 1 --timeout 30m \"tcp:${API_MOCK_STUBS_HOST}:22220\" \"http-get://localhost:3001/ui/v2/login/verify?userId=221394658884845598&code=abc\"",
"DISPLAY='' pnpm cypress run --headless",
"nx run @zitadel/login:test-integration-stop"
]
},
"inputs": [
"default",
"{workspaceRoot}/pnpm-lock.yaml",
"!{projectRoot}/acceptance/**/*",
{ "env": "LOGIN_BASE_URL" }
]
},
"test-integration-stop": {
"description": "Stops the gRPC mock container used for integration tests.",
"command": "nx run @zitadel/login-api-mock:down"
},
"pack": {
"description": "Packages the standalone Login application build into an archive",
"dependsOn": [
"build"
],
"executor": "nx:run-commands",
"options": {
"parallel": false,
"env": {
"STANDALONE_DIR": "{projectRoot}/.next/standalone",
"PACK_DIR": "{workspaceRoot}/.artifacts/pack"
},
"commands": [
"mkdir -p ${PACK_DIR}",
"tar -czvf ${PACK_DIR}/zitadel-login-standalone.tar.gz -C ${STANDALONE_DIR} ."
]
},
"cache": true,
"outputs": [
"{workspaceRoot}/.artifacts/pack/zitadel-login-*.tar.gz"
]
}
}
}

View File

@@ -1,11 +1,18 @@
#!/bin/sh
set -o allexport
. /.env-file/.env
set +o allexport
if [ -n "${ZITADEL_SERVICE_USER_TOKEN_FILE}" ] && [ -f "${ZITADEL_SERVICE_USER_TOKEN_FILE}" ]; then
echo "ZITADEL_SERVICE_USER_TOKEN_FILE=${ZITADEL_SERVICE_USER_TOKEN_FILE} is set and file exists, setting ZITADEL_SERVICE_USER_TOKEN to the files content"
export ZITADEL_SERVICE_USER_TOKEN=$(cat "${ZITADEL_SERVICE_USER_TOKEN_FILE}")
if [ -f /.env-file/.env ]; then
set -o allexport
. /.env-file/.env
set +o allexport
fi
exec node /runtime/apps/login/server.js
if [ -n "${ZITADEL_SERVICE_USER_TOKEN_FILE}" ]; then
echo "ZITADEL_SERVICE_USER_TOKEN_FILE=${ZITADEL_SERVICE_USER_TOKEN_FILE} is set. Awaiting file and reading token."
while [ ! -f "${ZITADEL_SERVICE_USER_TOKEN_FILE}" ]; do
sleep 2
done
echo "token file found, reading token"
export ZITADEL_SERVICE_USER_TOKEN=$(cat "${ZITADEL_SERVICE_USER_TOKEN_FILE}")
fi
exec $@

View File

@@ -1,7 +1,11 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -19,7 +23,9 @@
}
],
"paths": {
"@/*": ["./src/*"]
"@/*": [
"./src/*"
]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],

View File

@@ -1,57 +0,0 @@
{
"extends": [
"//"
],
"tasks": {
"build": {
"outputs": [
"dist/**",
".next/**",
"!.next/cache/**"
],
"dependsOn": [
"@zitadel/client#build"
]
},
"build:login:standalone": {
"outputs": [
"dist/**",
".next/**",
"!.next/cache/**"
],
"dependsOn": [
"@zitadel/client#build"
]
},
"dev": {
"persistent": true,
"cache": false,
"dependsOn": [
"@zitadel/client#build"
]
},
"test": {
"dependsOn": [
"@zitadel/client#build"
]
},
"test:unit": {
"dependsOn": [
"@zitadel/client#build"
]
},
"test:integration:login": {
"inputs": [
".next/**",
"!.next/cache/**",
"integration/integration/**",
"integration/support/**",
"cypress.config.ts"
],
"outputs": [
"cypress/videos/**",
"cypress/screenshots/**"
]
}
}
}

4
apps/login/vercel.json Normal file
View File

@@ -0,0 +1,4 @@
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"buildCommand": "pnpm nx run @zitadel/login:build-vercel"
}

View File

@@ -1,13 +1,13 @@
# Load Tests
# Benchmarks
This package contains code for load testing specific endpoints of ZITADEL using [k6](https://k6.io).
This package contains code for benchmarking specific endpoints of the API using [k6](https://k6.io).
## Prerequisite
* [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
* [k6](https://k6.io/docs/get-started/installation/)
* [go](https://go.dev/doc/install)
* running ZITADEL
* running the API
## Structure

View File

@@ -1,6 +1,5 @@
{
"name": "typescript",
"version": "1.0.0",
"name": "@zitadel/benchmark",
"repository": "ssh://git@github.com/zitadel/zitadel.git",
"author": "ZITADEL Authors <hi@zitadel.com>",
"engines": {
@@ -29,6 +28,6 @@
"bundle": "webpack",
"lint": "prettier --check src/**",
"lint:fix": "prettier --write src",
"clean": "rm -rf dist .turbo node_modules"
"clean": "rm -rf dist node_modules"
}
}

Some files were not shown because too many files have changed in this diff Show More