mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 14:27:32 +00:00
chore: fix login integration (#10318)
# Which Problems Are Solved Login integration tests are not executed in the pipeline # How the Problems Are Solved The login integration tests are fixed and added as a pipeline workflow. It tests against the built login docker image. On pipeline failures, developers are guided on how to fix them using a dev container configured for this purpose. # Additional Changes - email domains are replaced by example.com. In case the tests were accidentally run against a cloud instance, it wouldn't cause bounces. - pnpm is upgraded, because the --filter argument doesn't work for the install command on the old version. - The login Dockerfile is optimized for docker image builds # Additional Changes From Review for https://github.com/zitadel/zitadel/pull/10305 These changes were requested from @peintnermax - The base dev container starts without any services besides the database and the dev container itself - CONTRIBUTING.md is restructured - To reproduce pipeline checks, only the devcontainer CLI and Docker are needed. This is described in the CONTRIBUTING.md - The convenience npm script "generate" is added # Additional Context - Follow-up for PR https://github.com/zitadel/zitadel/pull/10305 - Base for https://github.com/zitadel/zitadel/issues/10277
This commit is contained in:
@@ -8,9 +8,13 @@ ENV SHELL=/bin/bash \
|
|||||||
PNPM_HOME=/home/node/.local/share/pnpm \
|
PNPM_HOME=/home/node/.local/share/pnpm \
|
||||||
PATH=/home/node/.local/share/pnpm:$PATH
|
PATH=/home/node/.local/share/pnpm:$PATH
|
||||||
|
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get --no-install-recommends install -y \
|
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 && \
|
libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb && \
|
||||||
apt-get clean && \
|
apt-get clean && \
|
||||||
corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@9.1.2 --activate
|
corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@10.13.1 --activate
|
||||||
|
|
||||||
|
COPY --chown=node:node commands /commands
|
||||||
|
|
||||||
|
USER node
|
||||||
|
2
.devcontainer/base/Dockerfile.dockerignore
Normal file
2
.devcontainer/base/Dockerfile.dockerignore
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!commands
|
39
.devcontainer/base/commands/login-integration.post-attach.sh
Executable file
39
.devcontainer/base/commands/login-integration.post-attach.sh
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
#!/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
|
18
.devcontainer/base/commands/login-integration.update-content.sh
Executable file
18
.devcontainer/base/commands/login-integration.update-content.sh
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/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
|
30
.devcontainer/base/commands/turbo-lint-unit.post-attach.sh
Executable file
30
.devcontainer/base/commands/turbo-lint-unit.post-attach.sh
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
#!/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
|
12
.devcontainer/base/commands/turbo-lint-unit.update-content.sh
Executable file
12
.devcontainer/base/commands/turbo-lint-unit.update-content.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/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
|
@@ -1,15 +1,15 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
||||||
"name": "devcontainer",
|
"name": "Base: Build and Run the Components you need",
|
||||||
"dockerComposeFile": "docker-compose.yml",
|
"dockerComposeFile": "docker-compose.yaml",
|
||||||
"service": "devcontainer",
|
"service": "devcontainer",
|
||||||
|
"runServices": [
|
||||||
|
"devContainer",
|
||||||
|
"db"
|
||||||
|
],
|
||||||
"workspaceFolder": "/workspaces",
|
"workspaceFolder": "/workspaces",
|
||||||
"features": {
|
"remoteEnv": {
|
||||||
"ghcr.io/devcontainers/features/go:1": {
|
"DISPLAY": ""
|
||||||
"version": "1.24"
|
|
||||||
},
|
|
||||||
"ghcr.io/guiyomh/features/golangci-lint:0": {},
|
|
||||||
"ghcr.io/jungaretti/features/make:1": {}
|
|
||||||
},
|
},
|
||||||
"forwardPorts": [
|
"forwardPorts": [
|
||||||
3000,
|
3000,
|
||||||
@@ -17,12 +17,13 @@
|
|||||||
4200,
|
4200,
|
||||||
8080
|
8080
|
||||||
],
|
],
|
||||||
"onCreateCommand": "pnpm install -g sass@1.64.1",
|
"onCreateCommand": "pnpm install --frozen-lockfile --recursive --prefer-offline",
|
||||||
"customizations": {
|
"features": {
|
||||||
"jetbrains": {
|
"ghcr.io/devcontainers/features/go:1": {
|
||||||
"settings": {
|
"version": "1.24"
|
||||||
"com.intellij:app:HttpConfigurable.use_proxy_pac": true
|
},
|
||||||
}
|
"ghcr.io/guiyomh/features/golangci-lint:0": {},
|
||||||
}
|
"ghcr.io/jungaretti/features/make:1": {},
|
||||||
|
"ghcr.io/devcontainers/features/docker-outside-of-docker": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,20 +1,11 @@
|
|||||||
x-build-cache: &build-cache
|
|
||||||
cache_from:
|
|
||||||
- type=gha
|
|
||||||
cache_to:
|
|
||||||
- type=gha,mode=max
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
devcontainer:
|
devcontainer:
|
||||||
container_name: devcontainer
|
container_name: devcontainer
|
||||||
build:
|
build:
|
||||||
context: .
|
context: ../base
|
||||||
<<: *build-cache
|
|
||||||
volumes:
|
volumes:
|
||||||
- ../../:/workspaces:cached
|
- ../../:/workspaces:cached
|
||||||
- /tmp/.X11-unix:/tmp/.X11-unix:cached
|
|
||||||
- home-dir:/home/node:delegated
|
|
||||||
command: sleep infinity
|
command: sleep infinity
|
||||||
working_dir: /workspaces
|
working_dir: /workspaces
|
||||||
environment:
|
environment:
|
||||||
@@ -39,34 +30,9 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "5432:5432"
|
- "5432:5432"
|
||||||
|
|
||||||
mock-zitadel:
|
|
||||||
container_name: mock-zitadel
|
|
||||||
build:
|
|
||||||
context: ../../apps/login/integration/core-mock
|
|
||||||
<<: *build-cache
|
|
||||||
ports:
|
|
||||||
- 22220:22220
|
|
||||||
- 22222:22222
|
|
||||||
|
|
||||||
login-integration:
|
|
||||||
container_name: login-integration
|
|
||||||
build:
|
|
||||||
context: ../..
|
|
||||||
dockerfile: build/login/Dockerfile
|
|
||||||
<<: *build-cache
|
|
||||||
image: "${LOGIN_TAG:-zitadel-login:local}"
|
|
||||||
env_file: ../../apps/login/.env.test
|
|
||||||
network_mode: service:devcontainer
|
|
||||||
environment:
|
|
||||||
NODE_ENV: test
|
|
||||||
PORT: 3001
|
|
||||||
depends_on:
|
|
||||||
mock-zitadel:
|
|
||||||
condition: service_started
|
|
||||||
|
|
||||||
zitadel:
|
zitadel:
|
||||||
image: "${ZITADEL_TAG:-ghcr.io/zitadel/zitadel:v4.0.0-rc.2}"
|
|
||||||
container_name: zitadel
|
container_name: zitadel
|
||||||
|
image: "${ZITADEL_TAG:-ghcr.io/zitadel/zitadel:latest}"
|
||||||
command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --config /zitadel.yaml --steps /zitadel.yaml'
|
command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --config /zitadel.yaml --steps /zitadel.yaml'
|
||||||
volumes:
|
volumes:
|
||||||
- ../../apps/login/acceptance/pat:/pat:delegated
|
- ../../apps/login/acceptance/pat:/pat:delegated
|
||||||
@@ -89,7 +55,6 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ../../apps/login/acceptance/setup
|
context: ../../apps/login/acceptance/setup
|
||||||
dockerfile: ../go-command.Dockerfile
|
dockerfile: ../go-command.Dockerfile
|
||||||
<<: *build-cache
|
|
||||||
entrypoint: "./setup.sh"
|
entrypoint: "./setup.sh"
|
||||||
network_mode: service:devcontainer
|
network_mode: service:devcontainer
|
||||||
environment:
|
environment:
|
||||||
@@ -111,7 +76,7 @@ services:
|
|||||||
|
|
||||||
login-acceptance:
|
login-acceptance:
|
||||||
container_name: login
|
container_name: login
|
||||||
image: "${LOGIN_TAG:-ghcr.io/zitadel/zitadel-login:v4.0.0-rc.2}"
|
image: "${LOGIN_TAG:-ghcr.io/zitadel/zitadel-login:latest}"
|
||||||
network_mode: service:devcontainer
|
network_mode: service:devcontainer
|
||||||
volumes:
|
volumes:
|
||||||
- ../../apps/login/.env.test.local:/env-files/.env:cached
|
- ../../apps/login/.env.test.local:/env-files/.env:cached
|
||||||
@@ -126,7 +91,6 @@ services:
|
|||||||
dockerfile: ../go-command.Dockerfile
|
dockerfile: ../go-command.Dockerfile
|
||||||
args:
|
args:
|
||||||
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
||||||
<<: *build-cache
|
|
||||||
environment:
|
environment:
|
||||||
PORT: '3333'
|
PORT: '3333'
|
||||||
command:
|
command:
|
||||||
@@ -151,7 +115,6 @@ services:
|
|||||||
dockerfile: ../go-command.Dockerfile
|
dockerfile: ../go-command.Dockerfile
|
||||||
args:
|
args:
|
||||||
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
||||||
<<: *build-cache
|
|
||||||
network_mode: service:devcontainer
|
network_mode: service:devcontainer
|
||||||
environment:
|
environment:
|
||||||
API_URL: 'http://localhost:8080'
|
API_URL: 'http://localhost:8080'
|
||||||
@@ -175,7 +138,6 @@ services:
|
|||||||
# dockerfile: ../../go-command.Dockerfile
|
# dockerfile: ../../go-command.Dockerfile
|
||||||
# args:
|
# args:
|
||||||
# - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
# - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
||||||
# <<: *build-cache
|
|
||||||
# network_mode: service:devcontainer
|
# network_mode: service:devcontainer
|
||||||
# environment:
|
# environment:
|
||||||
# API_URL: 'http://localhost:8080'
|
# API_URL: 'http://localhost:8080'
|
||||||
@@ -197,7 +159,6 @@ services:
|
|||||||
dockerfile: ../go-command.Dockerfile
|
dockerfile: ../go-command.Dockerfile
|
||||||
args:
|
args:
|
||||||
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
||||||
<<: *build-cache
|
|
||||||
network_mode: service:devcontainer
|
network_mode: service:devcontainer
|
||||||
environment:
|
environment:
|
||||||
API_URL: 'http://localhost:8080'
|
API_URL: 'http://localhost:8080'
|
||||||
@@ -219,7 +180,6 @@ services:
|
|||||||
# dockerfile: ../../go-command.Dockerfile
|
# dockerfile: ../../go-command.Dockerfile
|
||||||
# args:
|
# args:
|
||||||
# - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
# - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
|
||||||
# <<: *build-cache
|
|
||||||
# network_mode: service:devcontainer
|
# network_mode: service:devcontainer
|
||||||
# environment:
|
# environment:
|
||||||
# API_URL: 'http://localhost:8080'
|
# API_URL: 'http://localhost:8080'
|
||||||
@@ -236,4 +196,3 @@ services:
|
|||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
postgres-data:
|
postgres-data:
|
||||||
home-dir:
|
|
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
|
||||||
"name": "login-integration-debug",
|
|
||||||
"dockerComposeFile": [
|
|
||||||
"../base/docker-compose.yml",
|
|
||||||
"docker-compose.yml"
|
|
||||||
],
|
|
||||||
"service": "login-integration-debug",
|
|
||||||
"runServices": ["login-integration-debug"],
|
|
||||||
"workspaceFolder": "/workspaces",
|
|
||||||
"forwardPorts": [3001],
|
|
||||||
"onCreateCommand": "pnpm install --recursive",
|
|
||||||
"postAttachCommand": "pnpm turbo daemon clean; pnpm turbo @zitadel/login#dev test:integration:login:debug",
|
|
||||||
"customizations": {
|
|
||||||
"jetbrains": {
|
|
||||||
"settings": {
|
|
||||||
"com.intellij:app:HttpConfigurable.use_proxy_pac": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,9 +0,0 @@
|
|||||||
services:
|
|
||||||
login-integration-debug:
|
|
||||||
extends:
|
|
||||||
file: ../base/docker-compose.yml
|
|
||||||
service: devcontainer
|
|
||||||
container_name: login-integration-debug
|
|
||||||
depends_on:
|
|
||||||
mock-zitadel:
|
|
||||||
condition: service_started
|
|
@@ -1,19 +1,26 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
||||||
"name": "login-integration",
|
"name": "Login Integration",
|
||||||
"dockerComposeFile": [
|
"dockerComposeFile": [
|
||||||
"../base/docker-compose.yml"
|
"./docker-compose.yaml"
|
||||||
],
|
],
|
||||||
"service": "devcontainer",
|
"service": "login-integration-dev",
|
||||||
"runServices": ["login-integration"],
|
"runServices": [
|
||||||
"workspaceFolder": "/workspaces",
|
"login-integration"
|
||||||
"forwardPorts": [3001],
|
],
|
||||||
"onCreateCommand": "pnpm install --frozen-lockfile --recursive && cd apps/login/packages/integration && pnpm cypress install && pnpm test:integration:login",
|
"workspaceFolder": "/workspaces/apps/login",
|
||||||
"customizations": {
|
"forwardPorts": [
|
||||||
"jetbrains": {
|
22220,
|
||||||
"settings": {
|
22222,
|
||||||
"com.intellij:app:HttpConfigurable.use_proxy_pac": true
|
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": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
35
.devcontainer/login-integration/docker-compose.yaml
Normal file
35
.devcontainer/login-integration/docker-compose.yaml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
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
|
22
.devcontainer/login-subtree/devcontainer.json
Normal file
22
.devcontainer/login-subtree/devcontainer.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"$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": {}
|
||||||
|
}
|
||||||
|
}
|
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
|
||||||
"name": "turbo-lint-unit-debug",
|
|
||||||
"dockerComposeFile": [
|
|
||||||
"../base/docker-compose.yml",
|
|
||||||
"docker-compose.yml"
|
|
||||||
],
|
|
||||||
"service": "turbo-lint-unit-debug",
|
|
||||||
"runServices": ["turbo-lint-unit-debug"],
|
|
||||||
"workspaceFolder": "/workspaces",
|
|
||||||
"forwardPorts": [3001],
|
|
||||||
"onCreateCommand": "pnpm install --recursive",
|
|
||||||
"postAttachCommand": "pnpm turbo daemon clean; pnpm turbo watch lint test:unit",
|
|
||||||
"customizations": {
|
|
||||||
"jetbrains": {
|
|
||||||
"settings": {
|
|
||||||
"com.intellij:app:HttpConfigurable.use_proxy_pac": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,6 +0,0 @@
|
|||||||
services:
|
|
||||||
turbo-lint-unit-debug:
|
|
||||||
extends:
|
|
||||||
file: ../base/docker-compose.yml
|
|
||||||
service: devcontainer
|
|
||||||
container_name: turbo-lint-unit-debug
|
|
@@ -1,18 +1,20 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
|
||||||
"name": "turbo-lint-unit",
|
"name": "Turbo Lint and Unit Tests",
|
||||||
"dockerComposeFile": [
|
"dockerComposeFile": [
|
||||||
"../base/docker-compose.yml"
|
"../base/docker-compose.yaml"
|
||||||
],
|
],
|
||||||
"service": "devcontainer",
|
"service": "devcontainer",
|
||||||
"runServices": ["devcontainer"],
|
"runServices": [
|
||||||
|
"devcontainer"
|
||||||
|
],
|
||||||
"workspaceFolder": "/workspaces",
|
"workspaceFolder": "/workspaces",
|
||||||
"postStartCommand": "pnpm install --frozen-lockfile --recursive && pnpm turbo lint test:unit",
|
"forwardPorts": [
|
||||||
"customizations": {
|
3001
|
||||||
"jetbrains": {
|
],
|
||||||
"settings": {
|
"remoteEnv": {
|
||||||
"com.intellij:app:HttpConfigurable.use_proxy_pac": true
|
"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"
|
||||||
}
|
}
|
@@ -1,11 +1,14 @@
|
|||||||
|
|
||||||
# .git
|
# .git
|
||||||
.codecov
|
.codecov
|
||||||
.github
|
.github
|
||||||
.gitignore
|
.gitignore
|
||||||
.dockerignore
|
.dockerignore
|
||||||
**/Dockerfile
|
**/Dockerfile
|
||||||
/k8s/
|
**/node_modules
|
||||||
/node_modules/
|
**/.pnpm-store
|
||||||
|
**/.turbo
|
||||||
|
**/.next
|
||||||
/console/src/app/proto/generated/
|
/console/src/app/proto/generated/
|
||||||
/console/.angular
|
/console/.angular
|
||||||
/console/tmp/
|
/console/tmp/
|
||||||
@@ -24,5 +27,5 @@ console/.angular
|
|||||||
console/node_modules
|
console/node_modules
|
||||||
console/src/app/proto/generated/
|
console/src/app/proto/generated/
|
||||||
console/tmp/
|
console/tmp/
|
||||||
.vscode
|
|
||||||
build/*.Dockerfile
|
build/*.Dockerfile
|
||||||
|
|
||||||
|
7
.github/workflows/build.yml
vendored
7
.github/workflows/build.yml
vendored
@@ -102,6 +102,12 @@ jobs:
|
|||||||
login_build_image_name: "ghcr.io/zitadel/zitadel-login-build"
|
login_build_image_name: "ghcr.io/zitadel/zitadel-login-build"
|
||||||
node_version: "20"
|
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:
|
e2e:
|
||||||
uses: ./.github/workflows/e2e.yml
|
uses: ./.github/workflows/e2e.yml
|
||||||
needs: [compile]
|
needs: [compile]
|
||||||
@@ -121,6 +127,7 @@ jobs:
|
|||||||
lint,
|
lint,
|
||||||
container,
|
container,
|
||||||
login-container,
|
login-container,
|
||||||
|
login-integration-test,
|
||||||
e2e,
|
e2e,
|
||||||
]
|
]
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
19
.github/workflows/lint.yml
vendored
19
.github/workflows/lint.yml
vendored
@@ -53,14 +53,21 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
- name: Install Dev Container CLI
|
||||||
|
run: npm install -g @devcontainers/cli@0.80.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Run lint and unit tests in dev container
|
- name: Lint and Unit Test All JavaScript Code
|
||||||
uses: devcontainers/ci@v0.3
|
run: npm run devcontainer:lint-unit
|
||||||
with:
|
- name: Fix Failures
|
||||||
push: never
|
if: failure()
|
||||||
configFile: .devcontainer/turbo-lint-unit/devcontainer.json
|
run: |
|
||||||
runCmd: echo "Successfully ran lint and unit tests in dev container postStartCommand"
|
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:
|
core:
|
||||||
name: core
|
name: core
|
||||||
|
15
.github/workflows/login-container.yml
vendored
15
.github/workflows/login-container.yml
vendored
@@ -12,8 +12,8 @@ on:
|
|||||||
type: string
|
type: string
|
||||||
outputs:
|
outputs:
|
||||||
login_build_image:
|
login_build_image:
|
||||||
description: 'The full image tag of the standalone login image'
|
description: 'The full image tag of the standalone login image'
|
||||||
value: '${{ inputs.login_build_image_name }}:${{ github.sha }}'
|
value: ${{ inputs.login_build_image_name }}:${{ github.sha }}
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
packages: write
|
packages: write
|
||||||
@@ -30,6 +30,8 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
packages: write
|
packages: write
|
||||||
|
outputs:
|
||||||
|
login_build_image: ${{ steps.short-sha.outputs.login_build_image }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Login meta
|
- name: Login meta
|
||||||
@@ -41,7 +43,7 @@ jobs:
|
|||||||
annotations: |
|
annotations: |
|
||||||
manifest:org.opencontainers.image.licenses=MIT
|
manifest:org.opencontainers.image.licenses=MIT
|
||||||
tags: |
|
tags: |
|
||||||
type=sha,prefix=,suffix=,format=long
|
type=sha,prefix=,format=long
|
||||||
- name: Login to Docker registry
|
- name: Login to Docker registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
@@ -49,6 +51,7 @@ jobs:
|
|||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
|
id: setup-buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: Bake login multi-arch
|
- name: Bake login multi-arch
|
||||||
uses: docker/bake-action@v6
|
uses: docker/bake-action@v6
|
||||||
@@ -58,13 +61,9 @@ jobs:
|
|||||||
source: .
|
source: .
|
||||||
push: true
|
push: true
|
||||||
provenance: true
|
provenance: true
|
||||||
sbom: true
|
|
||||||
targets: login-standalone
|
targets: login-standalone
|
||||||
set: |
|
|
||||||
*.cache-from=type=gha
|
|
||||||
*.cache-to=type=gha,mode=max
|
|
||||||
files: |
|
files: |
|
||||||
./apps/login/docker-bake.hcl
|
./apps/login/docker-bake.hcl
|
||||||
./apps/login/docker-bake-release.hcl
|
${{ github.event_name == 'workflow_dispatch' && './apps/login/docker-bake-release.hcl' || '' }}
|
||||||
./docker-bake.hcl
|
./docker-bake.hcl
|
||||||
cwd://${{ steps.login-meta.outputs.bake-file }}
|
cwd://${{ steps.login-meta.outputs.bake-file }}
|
||||||
|
58
.github/workflows/login-integration-test.yml
vendored
Normal file
58
.github/workflows/login-integration-test.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
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-ci/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-ci/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-ci/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
|
102
CONTRIBUTING.md
102
CONTRIBUTING.md
@@ -1,6 +1,5 @@
|
|||||||
# Contributing to Zitadel
|
# Contributing to Zitadel
|
||||||
|
|
||||||
|
|
||||||
## Introduction
|
## 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 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.
|
||||||
@@ -150,51 +149,19 @@ 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.
|
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.
|
Please check out the dedicated [API guidelines](./API_DESIGN.md) page when contributing to the API.
|
||||||
|
|
||||||
|
|
||||||
#### <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`. 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="backend"></a>Contribute Backend Code
|
## <a name="backend"></a>Contribute Backend Code
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### <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.
|
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.
|
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).
|
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.
|
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.
|
||||||
@@ -208,6 +175,8 @@ The commands in this section are tested against the following software versions:
|
|||||||
- [Go version 1.22](https://go.dev/doc/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)
|
- [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.
|
Make some changes to the source code, then run the database locally.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -588,6 +557,48 @@ For the turbo commands, check your options with `pnpm turbo --help`
|
|||||||
| `pnpm turbo down` | Remove containers and volumes | Shut down containers from the integration test setup `pnpm turbo down` |
|
| `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` |
|
| `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
|
## <a name="contribute-translations"></a>Contribute Translations
|
||||||
|
|
||||||
Zitadel loads translations from four files:
|
Zitadel loads translations from four files:
|
||||||
@@ -608,11 +619,6 @@ You also have to add some changes to the following files:
|
|||||||
- [Customized Text Docs](./docs/docs/guides/manage/customize/texts.md)
|
- [Customized Text Docs](./docs/docs/guides/manage/customize/texts.md)
|
||||||
- [Add language option](./internal/api/ui/login/static/templates/external_not_found_option.html)
|
- [Add language option](./internal/api/ui/login/static/templates/external_not_found_option.html)
|
||||||
|
|
||||||
## Want to start Zitadel?
|
|
||||||
|
|
||||||
You can find an installation guide for all the different environments here:
|
|
||||||
[https://zitadel.com/docs/self-hosting/deploy/overview](https://zitadel.com/docs/self-hosting/deploy/overview)
|
|
||||||
|
|
||||||
## **Did you find a security flaw?**
|
## **Did you find a security flaw?**
|
||||||
|
|
||||||
- Please read [Security Policy](./SECURITY.md).
|
- Please read [Security Policy](./SECURITY.md).
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
NEXT_PUBLIC_BASE_PATH="/ui/v2/login"
|
ZITADEL_API_URL=http://localhost:22222
|
||||||
ZITADEL_API_URL=http://mock-zitadel:22222
|
|
||||||
ZITADEL_SERVICE_USER_TOKEN="yolo"
|
ZITADEL_SERVICE_USER_TOKEN="yolo"
|
||||||
EMAIL_VERIFICATION=true
|
EMAIL_VERIFICATION=true
|
||||||
DEBUG=true
|
DEBUG=true
|
||||||
|
PORT=3001
|
||||||
|
NEXT_PUBLIC_BASE_PATH=/ui/v2/login
|
||||||
|
2
apps/login/.gitignore
vendored
2
apps/login/.gitignore
vendored
@@ -2,6 +2,7 @@ custom-config.js
|
|||||||
.env*.local
|
.env*.local
|
||||||
standalone
|
standalone
|
||||||
tsconfig.tsbuildinfo
|
tsconfig.tsbuildinfo
|
||||||
|
cypress
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
node_modules
|
node_modules
|
||||||
@@ -11,6 +12,5 @@ node_modules
|
|||||||
dist
|
dist
|
||||||
dist-ssr
|
dist-ssr
|
||||||
*.local
|
*.local
|
||||||
.env
|
|
||||||
.vscode
|
.vscode
|
||||||
/blob-report/
|
/blob-report/
|
||||||
|
@@ -3,21 +3,21 @@ FROM node:20-alpine AS base
|
|||||||
FROM base AS build
|
FROM base AS build
|
||||||
ENV PNPM_HOME="/pnpm"
|
ENV PNPM_HOME="/pnpm"
|
||||||
ENV PATH="$PNPM_HOME:$PATH"
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
RUN corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@9.1.2 --activate && \
|
RUN corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@10.13.1 --activate && \
|
||||||
apk update && apk add --no-cache && \
|
apk update && \
|
||||||
rm -rf /var/cache/apk/*
|
rm -rf /var/cache/apk/*
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY pnpm-lock.yaml ./
|
COPY pnpm-lock.yaml ./
|
||||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm fetch --frozen-lockfile
|
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm fetch --frozen-lockfile
|
||||||
COPY package.json ./
|
COPY package.json ./
|
||||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile --prod
|
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN pnpm build:login:standalone
|
RUN pnpm build:login:standalone
|
||||||
|
|
||||||
FROM scratch AS build-out
|
FROM scratch AS build-out
|
||||||
COPY --from=build /app/.next/standalone /
|
COPY --from=build /app/.next/standalone /
|
||||||
COPY --from=build /app/.next/static /.next/static
|
COPY --from=build /app/.next/static /.next/static
|
||||||
COPY --from=build /app/public /public
|
COPY public public
|
||||||
|
|
||||||
FROM base AS login-standalone
|
FROM base AS login-standalone
|
||||||
WORKDIR /runtime
|
WORKDIR /runtime
|
||||||
@@ -25,12 +25,13 @@ RUN addgroup --system --gid 1001 nodejs && \
|
|||||||
adduser --system --uid 1001 nextjs
|
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.
|
# 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
|
RUN mkdir -p /.env-file && touch /.env-file/.env && chown -R nextjs:nodejs /.env-file
|
||||||
COPY ./scripts/ ./
|
COPY --chown=nextjs:nodejs ./scripts/ ./
|
||||||
COPY --chown=nextjs:nodejs --from=build-out / ./
|
COPY --chown=nextjs:nodejs --from=build-out / ./
|
||||||
USER nextjs
|
USER nextjs
|
||||||
ENV HOSTNAME="0.0.0.0"
|
ENV HOSTNAME="0.0.0.0" \
|
||||||
ENV PORT=3000
|
NEXT_PUBLIC_BASE_PATH="/ui/v2/login" \
|
||||||
|
PORT=3000
|
||||||
# TODO: Check healthy, not ready
|
# TODO: Check healthy, not ready
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
CMD ["/bin/sh", "-c", "node ./healthcheck.js http://localhost:${PORT}/ui/v2/login/healthy"]
|
CMD ["/bin/sh", "-c", "node /runtime/healthcheck.js http://localhost:${PORT}/ui/v2/login/healthy"]
|
||||||
ENTRYPOINT ["./entrypoint.sh"]
|
ENTRYPOINT ["/runtime/entrypoint.sh"]
|
||||||
|
@@ -8,7 +8,8 @@
|
|||||||
!next.config.mjs
|
!next.config.mjs
|
||||||
!next-env-vars.d.ts
|
!next-env-vars.d.ts
|
||||||
!next-env.d.ts
|
!next-env.d.ts
|
||||||
!tailwind.config.js
|
!tailwind.config.mjs
|
||||||
|
!postcss.config.cjs
|
||||||
!tsconfig.json
|
!tsconfig.json
|
||||||
!package.json
|
!package.json
|
||||||
!pnpm-lock.yaml
|
!pnpm-lock.yaml
|
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "login-test-acceptance",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"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 .turbo node_modules"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@faker-js/faker": "^9.7.0",
|
|
||||||
"@otplib/core": "^12.0.0",
|
|
||||||
"@otplib/plugin-crypto": "^12.0.0",
|
|
||||||
"@otplib/plugin-thirty-two": "^12.0.0",
|
|
||||||
"@playwright/test": "^1.52.0",
|
|
||||||
"dotenv-cli": "^8.0.0",
|
|
||||||
"gaxios": "^7.1.0",
|
|
||||||
"typescript": "^5.8.3"
|
|
||||||
}
|
|
||||||
}
|
|
@@ -2,11 +2,11 @@ import { defineConfig } from "cypress";
|
|||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
reporter: "list",
|
reporter: "list",
|
||||||
|
video: true,
|
||||||
e2e: {
|
e2e: {
|
||||||
baseUrl: process.env.LOGIN_BASE_URL || "http://localhost:3001/ui/v2/login",
|
baseUrl: process.env.LOGIN_BASE_URL || "http://localhost:3001/ui/v2/login",
|
||||||
specPattern: "integration/**/*.cy.{js,jsx,ts,tsx}",
|
specPattern: "integration/integration/**/*.cy.{js,jsx,ts,tsx}",
|
||||||
supportFile: "support/e2e.{js,jsx,ts,tsx}",
|
supportFile: "integration/support/e2e.{js,jsx,ts,tsx}",
|
||||||
setupNodeEvents(on, config) {
|
setupNodeEvents(on, config) {
|
||||||
// implement node event listeners here
|
// implement node event listeners here
|
||||||
},
|
},
|
@@ -1,8 +1,10 @@
|
|||||||
FROM bufbuild/buf:1.54.0 AS proto-files
|
FROM bufbuild/buf:1.54.0 AS dependencies
|
||||||
RUN buf export https://github.com/envoyproxy/protoc-gen-validate.git --path validate --output /proto-files && \
|
RUN buf export https://github.com/envoyproxy/protoc-gen-validate.git --path validate --output /proto && \
|
||||||
buf export https://github.com/grpc-ecosystem/grpc-gateway.git --path protoc-gen-openapiv2 --output /proto-files && \
|
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 protos/zitadelgoogle/api/annotations.proto --path google/api/http.proto --path google/api/field_behavior.proto --output /proto-files && \
|
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
|
||||||
buf export https://github.com/zitadel/zitadel.git --path ./proto/zitadel --output /proto-files
|
|
||||||
|
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
|
FROM golang:1.20.5-alpine3.18 AS mock-zitadel
|
||||||
|
|
||||||
@@ -10,6 +12,7 @@ RUN go install github.com/eliobischof/grpc-mock/cmd/grpc-mock@01b09f60db1b501178
|
|||||||
|
|
||||||
COPY mocked-services.cfg .
|
COPY mocked-services.cfg .
|
||||||
COPY initial-stubs initial-stubs
|
COPY initial-stubs initial-stubs
|
||||||
COPY --from=proto-files /proto-files/ ./
|
COPY --from=dependencies /proto/ ./
|
||||||
|
COPY --from=zitadel-protos /zitadel/ ./zitadel/
|
||||||
|
|
||||||
ENTRYPOINT [ "sh", "-c", "grpc-mock -v 1 -proto $(tr '\n' ',' < ./mocked-services.cfg) -stub-dir ./initial-stubs -mock-addr :22222" ]
|
ENTRYPOINT [ "sh", "-c", "grpc-mock -v 1 -proto $(tr '\n' ',' < ./mocked-services.cfg) -stub-dir ./initial-stubs -mock-addr :22222" ]
|
||||||
|
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Using fixtures to represent data",
|
|
||||||
"email": "hello@cypress.io",
|
|
||||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
|
||||||
}
|
|
@@ -22,22 +22,22 @@ describe("verify invite", () => {
|
|||||||
user: {
|
user: {
|
||||||
userId: "221394658884845598",
|
userId: "221394658884845598",
|
||||||
state: 1,
|
state: 1,
|
||||||
username: "john@zitadel.com",
|
username: "john@example.com",
|
||||||
loginNames: ["john@zitadel.com"],
|
loginNames: ["john@example.com"],
|
||||||
preferredLoginName: "john@zitadel.com",
|
preferredLoginName: "john@example.com",
|
||||||
human: {
|
human: {
|
||||||
userId: "221394658884845598",
|
userId: "221394658884845598",
|
||||||
state: 1,
|
state: 1,
|
||||||
username: "john@zitadel.com",
|
username: "john@example.com",
|
||||||
loginNames: ["john@zitadel.com"],
|
loginNames: ["john@example.com"],
|
||||||
preferredLoginName: "john@zitadel.com",
|
preferredLoginName: "john@example.com",
|
||||||
profile: {
|
profile: {
|
||||||
givenName: "John",
|
givenName: "John",
|
||||||
familyName: "Doe",
|
familyName: "Doe",
|
||||||
avatarUrl: "https://zitadel.com/avatar.jpg",
|
avatarUrl: "https://example.com/avatar.jpg",
|
||||||
},
|
},
|
||||||
email: {
|
email: {
|
||||||
email: "john@zitadel.com",
|
email: "john@example.com",
|
||||||
isVerified: false,
|
isVerified: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -68,7 +68,7 @@ describe("verify invite", () => {
|
|||||||
factors: {
|
factors: {
|
||||||
user: {
|
user: {
|
||||||
id: "221394658884845598",
|
id: "221394658884845598",
|
||||||
loginName: "john@zitadel.com",
|
loginName: "john@example.com",
|
||||||
},
|
},
|
||||||
password: undefined,
|
password: undefined,
|
||||||
webAuthN: undefined,
|
webAuthN: undefined,
|
||||||
@@ -93,7 +93,7 @@ describe("verify invite", () => {
|
|||||||
stub("zitadel.user.v2.UserService", "VerifyInviteCode");
|
stub("zitadel.user.v2.UserService", "VerifyInviteCode");
|
||||||
|
|
||||||
cy.visit("/verify?userId=221394658884845598&code=abc&invite=true");
|
cy.visit("/verify?userId=221394658884845598&code=abc&invite=true");
|
||||||
cy.url({ timeout: 10_000 }).should("include", Cypress.config().baseUrl + "/authenticator/set");
|
cy.url().should("include", Cypress.config().baseUrl + "/authenticator/set");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows an error if invite code validation failed", () => {
|
it("shows an error if invite code validation failed", () => {
|
||||||
|
@@ -33,7 +33,7 @@ describe("login", () => {
|
|||||||
factors: {
|
factors: {
|
||||||
user: {
|
user: {
|
||||||
id: "221394658884845598",
|
id: "221394658884845598",
|
||||||
loginName: "john@zitadel.com",
|
loginName: "john@example.com",
|
||||||
},
|
},
|
||||||
password: undefined,
|
password: undefined,
|
||||||
webAuthN: undefined,
|
webAuthN: undefined,
|
||||||
@@ -64,22 +64,22 @@ describe("login", () => {
|
|||||||
{
|
{
|
||||||
userId: "221394658884845598",
|
userId: "221394658884845598",
|
||||||
state: 1,
|
state: 1,
|
||||||
username: "john@zitadel.com",
|
username: "john@example.com",
|
||||||
loginNames: ["john@zitadel.com"],
|
loginNames: ["john@example.com"],
|
||||||
preferredLoginName: "john@zitadel.com",
|
preferredLoginName: "john@example.com",
|
||||||
human: {
|
human: {
|
||||||
userId: "221394658884845598",
|
userId: "221394658884845598",
|
||||||
state: 1,
|
state: 1,
|
||||||
username: "john@zitadel.com",
|
username: "john@example.com",
|
||||||
loginNames: ["john@zitadel.com"],
|
loginNames: ["john@example.com"],
|
||||||
preferredLoginName: "john@zitadel.com",
|
preferredLoginName: "john@example.com",
|
||||||
profile: {
|
profile: {
|
||||||
givenName: "John",
|
givenName: "John",
|
||||||
familyName: "Doe",
|
familyName: "Doe",
|
||||||
avatarUrl: "https://zitadel.com/avatar.jpg",
|
avatarUrl: "https://example.com/avatar.jpg",
|
||||||
},
|
},
|
||||||
email: {
|
email: {
|
||||||
email: "john@zitadel.com",
|
email: "john@example.com",
|
||||||
isVerified: true,
|
isVerified: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -94,8 +94,8 @@ describe("login", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
it("should redirect a user with password authentication to /password", () => {
|
it("should redirect a user with password authentication to /password", () => {
|
||||||
cy.visit("/loginname?loginName=john%40zitadel.com&submit=true");
|
cy.visit("/loginname?loginName=john%40example.com&submit=true");
|
||||||
cy.url({ timeout: 10_000 }).should("include", Cypress.config().baseUrl + "/password");
|
cy.url({ timeout: 5 * 60_000 }).should("include", Cypress.config().baseUrl + "/password");
|
||||||
});
|
});
|
||||||
describe("with passkey prompt", () => {
|
describe("with passkey prompt", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
@@ -112,8 +112,8 @@ describe("login", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
// it("should prompt a user to setup passwordless authentication if passkey is allowed in the login settings", () => {
|
// it("should prompt a user to setup passwordless authentication if passkey is allowed in the login settings", () => {
|
||||||
// cy.visit("/loginname?loginName=john%40zitadel.com&submit=true");
|
// cy.visit("/loginname?loginName=john%40example.com&submit=true");
|
||||||
// cy.location("pathname", { timeout: 10_000 }).should("eq", "/password");
|
// cy.location("pathname", { timeout: 5 * 60_000 }).should("eq", "/password");
|
||||||
// cy.get('input[type="password"]').focus().type("MyStrongPassword!1");
|
// cy.get('input[type="password"]').focus().type("MyStrongPassword!1");
|
||||||
// cy.get('button[type="submit"]').click();
|
// cy.get('button[type="submit"]').click();
|
||||||
// cy.location("pathname", { timeout: 10_000 }).should(
|
// cy.location("pathname", { timeout: 10_000 }).should(
|
||||||
@@ -134,22 +134,22 @@ describe("login", () => {
|
|||||||
{
|
{
|
||||||
userId: "221394658884845598",
|
userId: "221394658884845598",
|
||||||
state: 1,
|
state: 1,
|
||||||
username: "john@zitadel.com",
|
username: "john@example.com",
|
||||||
loginNames: ["john@zitadel.com"],
|
loginNames: ["john@example.com"],
|
||||||
preferredLoginName: "john@zitadel.com",
|
preferredLoginName: "john@example.com",
|
||||||
human: {
|
human: {
|
||||||
userId: "221394658884845598",
|
userId: "221394658884845598",
|
||||||
state: 1,
|
state: 1,
|
||||||
username: "john@zitadel.com",
|
username: "john@example.com",
|
||||||
loginNames: ["john@zitadel.com"],
|
loginNames: ["john@example.com"],
|
||||||
preferredLoginName: "john@zitadel.com",
|
preferredLoginName: "john@example.com",
|
||||||
profile: {
|
profile: {
|
||||||
givenName: "John",
|
givenName: "John",
|
||||||
familyName: "Doe",
|
familyName: "Doe",
|
||||||
avatarUrl: "https://zitadel.com/avatar.jpg",
|
avatarUrl: "https://example.com/avatar.jpg",
|
||||||
},
|
},
|
||||||
email: {
|
email: {
|
||||||
email: "john@zitadel.com",
|
email: "john@example.com",
|
||||||
isVerified: true,
|
isVerified: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -165,8 +165,8 @@ describe("login", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should redirect a user with passwordless authentication to /passkey", () => {
|
it("should redirect a user with passwordless authentication to /passkey", () => {
|
||||||
cy.visit("/loginname?loginName=john%40zitadel.com&submit=true");
|
cy.visit("/loginname?loginName=john%40example.com&submit=true");
|
||||||
cy.url({ timeout: 10_000 }).should("include", Cypress.config().baseUrl + "/passkey");
|
cy.url().should("include", Cypress.config().baseUrl + "/passkey");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -15,7 +15,7 @@ describe("register idps", () => {
|
|||||||
cy.visit("/idp");
|
cy.visit("/idp");
|
||||||
cy.get('button[e2e="google"]').click();
|
cy.get('button[e2e="google"]').click();
|
||||||
cy.origin(IDP_URL, { args: IDP_URL }, (url) => {
|
cy.origin(IDP_URL, { args: IDP_URL }, (url) => {
|
||||||
cy.location("href", { timeout: 10_000 }).should("eq", url);
|
cy.location("href").should("eq", url);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -48,7 +48,7 @@ describe("register", () => {
|
|||||||
factors: {
|
factors: {
|
||||||
user: {
|
user: {
|
||||||
id: "221394658884845598",
|
id: "221394658884845598",
|
||||||
loginName: "john@zitadel.com",
|
loginName: "john@example.com",
|
||||||
},
|
},
|
||||||
password: undefined,
|
password: undefined,
|
||||||
webAuthN: undefined,
|
webAuthN: undefined,
|
||||||
@@ -64,10 +64,10 @@ describe("register", () => {
|
|||||||
cy.visit("/register");
|
cy.visit("/register");
|
||||||
cy.get('input[data-testid="firstname-text-input"]').focus().type("John");
|
cy.get('input[data-testid="firstname-text-input"]').focus().type("John");
|
||||||
cy.get('input[data-testid="lastname-text-input"]').focus().type("Doe");
|
cy.get('input[data-testid="lastname-text-input"]').focus().type("Doe");
|
||||||
cy.get('input[data-testid="email-text-input"]').focus().type("john@zitadel.com");
|
cy.get('input[data-testid="email-text-input"]').focus().type("john@example.com");
|
||||||
cy.get('input[type="checkbox"][value="privacypolicy"]').check();
|
cy.get('input[type="checkbox"][value="privacypolicy"]').check();
|
||||||
cy.get('input[type="checkbox"][value="tos"]').check();
|
cy.get('input[type="checkbox"][value="tos"]').check();
|
||||||
cy.get('button[type="submit"]').click();
|
cy.get('button[type="submit"]').click();
|
||||||
cy.url({ timeout: 10_000 }).should("include", Cypress.config().baseUrl + "/passkey/set");
|
cy.url().should("include", Cypress.config().baseUrl + "/passkey/set");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -24,22 +24,22 @@ describe("verify email", () => {
|
|||||||
user: {
|
user: {
|
||||||
userId: "221394658884845598",
|
userId: "221394658884845598",
|
||||||
state: 1,
|
state: 1,
|
||||||
username: "john@zitadel.com",
|
username: "john@example.com",
|
||||||
loginNames: ["john@zitadel.com"],
|
loginNames: ["john@example.com"],
|
||||||
preferredLoginName: "john@zitadel.com",
|
preferredLoginName: "john@example.com",
|
||||||
human: {
|
human: {
|
||||||
userId: "221394658884845598",
|
userId: "221394658884845598",
|
||||||
state: 1,
|
state: 1,
|
||||||
username: "john@zitadel.com",
|
username: "john@example.com",
|
||||||
loginNames: ["john@zitadel.com"],
|
loginNames: ["john@example.com"],
|
||||||
preferredLoginName: "john@zitadel.com",
|
preferredLoginName: "john@example.com",
|
||||||
profile: {
|
profile: {
|
||||||
givenName: "John",
|
givenName: "John",
|
||||||
familyName: "Doe",
|
familyName: "Doe",
|
||||||
avatarUrl: "https://zitadel.com/avatar.jpg",
|
avatarUrl: "https://example.com/avatar.jpg",
|
||||||
},
|
},
|
||||||
email: {
|
email: {
|
||||||
email: "john@zitadel.com",
|
email: "john@example.com",
|
||||||
isVerified: false, // email is not verified yet
|
isVerified: false, // email is not verified yet
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -70,7 +70,7 @@ describe("verify email", () => {
|
|||||||
factors: {
|
factors: {
|
||||||
user: {
|
user: {
|
||||||
id: "221394658884845598",
|
id: "221394658884845598",
|
||||||
loginName: "john@zitadel.com",
|
loginName: "john@example.com",
|
||||||
},
|
},
|
||||||
password: undefined,
|
password: undefined,
|
||||||
webAuthN: undefined,
|
webAuthN: undefined,
|
||||||
@@ -90,6 +90,6 @@ describe("verify email", () => {
|
|||||||
// TODO: Avoid uncaught exception in application
|
// TODO: Avoid uncaught exception in application
|
||||||
cy.once("uncaught:exception", () => false);
|
cy.once("uncaught:exception", () => false);
|
||||||
cy.visit("/verify?userId=221394658884845598&code=abc");
|
cy.visit("/verify?userId=221394658884845598&code=abc");
|
||||||
cy.contains("Could not verify email", { timeout: 10_000 });
|
cy.contains("Could not verify email");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
const url = Cypress.env("CORE_MOCK_STUBS_URL") || "http://mock-zitadel:22220/v1/stubs";
|
const url = Cypress.env("CORE_MOCK_STUBS_URL") || "http://localhost:22220/v1/stubs";
|
||||||
|
|
||||||
function removeStub(service: string, method: string) {
|
function removeStub(service: string, method: string) {
|
||||||
return cy.request({
|
return cy.request({
|
||||||
|
@@ -4,5 +4,5 @@
|
|||||||
"lib": ["es5", "dom"],
|
"lib": ["es5", "dom"],
|
||||||
"types": ["cypress", "node"]
|
"types": ["cypress", "node"]
|
||||||
},
|
},
|
||||||
"include": ["**/*.ts"]
|
"include": ["**/*.ts", "../cypress.config.ts"]
|
||||||
}
|
}
|
||||||
|
2
apps/login/next-env-vars.d.ts
vendored
2
apps/login/next-env-vars.d.ts
vendored
@@ -27,6 +27,8 @@ declare namespace NodeJS {
|
|||||||
/**
|
/**
|
||||||
* Optional: custom request headers to be added to every request
|
* Optional: custom request headers to be added to every request
|
||||||
* Split by comma, key value pairs separated by colon
|
* Split by comma, key value pairs separated by colon
|
||||||
|
* For example: to call the Zitadel API at an internal address, you can set:
|
||||||
|
* `CUSTOM_REQUEST_HEADERS=Host:http://zitadel-internal:8080`
|
||||||
*/
|
*/
|
||||||
CUSTOM_REQUEST_HEADERS?: string;
|
CUSTOM_REQUEST_HEADERS?: string;
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"packageManager": "pnpm@9.1.2+sha256.19c17528f9ca20bd442e4ca42f00f1b9808a9cb419383cd04ba32ef19322aba7",
|
"packageManager": "pnpm@10.13.1",
|
||||||
"name": "@zitadel/login",
|
"name": "@zitadel/login",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -15,8 +15,7 @@
|
|||||||
"test:unit": "vitest --run",
|
"test:unit": "vitest --run",
|
||||||
"lint-staged": "lint-staged",
|
"lint-staged": "lint-staged",
|
||||||
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next",
|
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next",
|
||||||
"test:integration:login": "cypress run",
|
"test:integration:login": "wait-on --simultaneous 1 http://localhost:3001/ui/v2/login/verify?userId=221394658884845598&code=abc && cypress run",
|
||||||
"test:integration:login:debug": "cypress open",
|
|
||||||
"test:acceptance": "dotenv -e ../login/.env.test.local playwright",
|
"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": "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"
|
"test:acceptance:setup:dev": "cd ../.. && make login_test_acceptance_setup_dev"
|
||||||
@@ -54,6 +53,11 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/eslint-parser": "^7.23.0",
|
"@babel/eslint-parser": "^7.23.0",
|
||||||
"@bufbuild/buf": "^1.53.0",
|
"@bufbuild/buf": "^1.53.0",
|
||||||
|
"@faker-js/faker": "^9.7.0",
|
||||||
|
"@otplib/core": "^12.0.0",
|
||||||
|
"@otplib/plugin-crypto": "^12.0.0",
|
||||||
|
"@otplib/plugin-thirty-two": "^12.0.0",
|
||||||
|
"@playwright/test": "^1.52.0",
|
||||||
"@testing-library/jest-dom": "^6.6.3",
|
"@testing-library/jest-dom": "^6.6.3",
|
||||||
"@testing-library/react": "^16.3.0",
|
"@testing-library/react": "^16.3.0",
|
||||||
"@types/ms": "2.1.0",
|
"@types/ms": "2.1.0",
|
||||||
@@ -67,34 +71,30 @@
|
|||||||
"@vercel/git-hooks": "1.0.0",
|
"@vercel/git-hooks": "1.0.0",
|
||||||
"@vitejs/plugin-react": "^4.4.1",
|
"@vitejs/plugin-react": "^4.4.1",
|
||||||
"autoprefixer": "10.4.21",
|
"autoprefixer": "10.4.21",
|
||||||
|
"concurrently": "^9.1.2",
|
||||||
|
"cypress": "^14.5.2",
|
||||||
|
"dotenv-cli": "^8.0.0",
|
||||||
|
"env-cmd": "^10.0.0",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-config-next": "15.4.0-canary.86",
|
"eslint-config-next": "15.4.0-canary.86",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
|
"gaxios": "^7.1.0",
|
||||||
"grpc-tools": "1.13.0",
|
"grpc-tools": "1.13.0",
|
||||||
"jsdom": "^26.1.0",
|
"jsdom": "^26.1.0",
|
||||||
"lint-staged": "15.5.1",
|
"lint-staged": "15.5.1",
|
||||||
"make-dir-cli": "4.0.0",
|
"make-dir-cli": "4.0.0",
|
||||||
|
"nodemon": "^3.1.9",
|
||||||
"postcss": "8.5.3",
|
"postcss": "8.5.3",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"prettier-plugin-organize-imports": "^3.2.0",
|
"prettier-plugin-organize-imports": "^3.2.0",
|
||||||
"prettier-plugin-tailwindcss": "0.6.11",
|
"prettier-plugin-tailwindcss": "0.6.11",
|
||||||
"sass": "^1.87.0",
|
"sass": "^1.87.0",
|
||||||
|
"start-server-and-test": "^2.0.11",
|
||||||
"tailwindcss": "3.4.14",
|
"tailwindcss": "3.4.14",
|
||||||
"ts-proto": "^2.7.0",
|
"ts-proto": "^2.7.0",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"vite-tsconfig-paths": "^5.1.4",
|
"vite-tsconfig-paths": "^5.1.4",
|
||||||
"vitest": "^2.0.0",
|
"vitest": "^2.0.0",
|
||||||
"concurrently": "^9.1.2",
|
"wait-on": "^7.2.0"
|
||||||
"cypress": "^14.5.2",
|
|
||||||
"dotenv-cli": "^8.0.0",
|
|
||||||
"env-cmd": "^10.0.0",
|
|
||||||
"nodemon": "^3.1.9",
|
|
||||||
"start-server-and-test": "^2.0.11",
|
|
||||||
"@faker-js/faker": "^9.7.0",
|
|
||||||
"@otplib/core": "^12.0.0",
|
|
||||||
"@otplib/plugin-crypto": "^12.0.0",
|
|
||||||
"@otplib/plugin-thirty-two": "^12.0.0",
|
|
||||||
"@playwright/test": "^1.52.0",
|
|
||||||
"gaxios": "^7.1.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
9151
apps/login/pnpm-lock.yaml
generated
Normal file
9151
apps/login/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,22 +1,57 @@
|
|||||||
{
|
{
|
||||||
"extends": ["//"],
|
"extends": [
|
||||||
|
"//"
|
||||||
|
],
|
||||||
"tasks": {
|
"tasks": {
|
||||||
"build": {
|
"build": {
|
||||||
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
|
"outputs": [
|
||||||
"dependsOn": ["@zitadel/client#build"]
|
"dist/**",
|
||||||
|
".next/**",
|
||||||
|
"!.next/cache/**"
|
||||||
|
],
|
||||||
|
"dependsOn": [
|
||||||
|
"@zitadel/client#build"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"build:login:standalone": {
|
"build:login:standalone": {
|
||||||
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
|
"outputs": [
|
||||||
"dependsOn": ["@zitadel/client#build"]
|
"dist/**",
|
||||||
|
".next/**",
|
||||||
|
"!.next/cache/**"
|
||||||
|
],
|
||||||
|
"dependsOn": [
|
||||||
|
"@zitadel/client#build"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"dev": {
|
"dev": {
|
||||||
"dependsOn": ["@zitadel/client#build"]
|
"persistent": true,
|
||||||
|
"cache": false,
|
||||||
|
"dependsOn": [
|
||||||
|
"@zitadel/client#build"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"test": {
|
"test": {
|
||||||
"dependsOn": ["@zitadel/client#build"]
|
"dependsOn": [
|
||||||
|
"@zitadel/client#build"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"test:unit": {
|
"test:unit": {
|
||||||
"dependsOn": ["@zitadel/client#build"]
|
"dependsOn": [
|
||||||
|
"@zitadel/client#build"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"test:integration:login": {
|
||||||
|
"inputs": [
|
||||||
|
".next/**",
|
||||||
|
"!.next/cache/**",
|
||||||
|
"integration/integration/**",
|
||||||
|
"integration/support/**",
|
||||||
|
"cypress.config.ts"
|
||||||
|
],
|
||||||
|
"outputs": [
|
||||||
|
"cypress/videos/**",
|
||||||
|
"cypress/screenshots/**"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,34 +1,43 @@
|
|||||||
FROM node:20-alpine AS base
|
FROM node:20-alpine AS runtime
|
||||||
|
|
||||||
FROM base AS build
|
FROM runtime AS pnpm-base
|
||||||
|
RUN apk add --no-cache libc6-compat
|
||||||
ENV PNPM_HOME="/pnpm"
|
ENV PNPM_HOME="/pnpm"
|
||||||
ENV PATH="$PNPM_HOME:$PATH"
|
ENV PATH="$PNPM_HOME:$PATH"
|
||||||
RUN corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@9.1.2 --activate && \
|
RUN corepack enable && corepack prepare pnpm@10.13.1 --activate
|
||||||
apk update && apk add --no-cache && \
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
rm -rf /var/cache/apk/*
|
pnpm add -g turbo@2.5.5
|
||||||
WORKDIR /app
|
|
||||||
COPY pnpm-lock.yaml pnpm-workspace.yaml ./
|
FROM pnpm-base AS pruner
|
||||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm fetch --frozen-lockfile \
|
WORKDIR /prune
|
||||||
--filter @zitadel/login \
|
|
||||||
--filter @zitadel/client \
|
|
||||||
--filter @zitadel/proto
|
|
||||||
COPY package.json ./
|
|
||||||
COPY apps/login/package.json ./apps/login/package.json
|
|
||||||
COPY packages/zitadel-proto/package.json ./packages/zitadel-proto/package.json
|
|
||||||
COPY packages/zitadel-client/package.json ./packages/zitadel-client/package.json
|
|
||||||
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --frozen-lockfile \
|
|
||||||
--filter @zitadel/login \
|
|
||||||
--filter @zitadel/client \
|
|
||||||
--filter @zitadel/proto
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN pnpm turbo build:login:standalone
|
RUN pnpm turbo prune @zitadel/login @zitadel/client @zitadel/proto --docker
|
||||||
|
|
||||||
|
FROM pnpm-base AS installer
|
||||||
|
WORKDIR /install
|
||||||
|
COPY --from=pruner /prune/out/pnpm-lock.yaml ./
|
||||||
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
|
pnpm fetch --frozen-lockfile
|
||||||
|
COPY --from=pruner /prune/out/json/ .
|
||||||
|
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||||
|
pnpm install --frozen-lockfile --ignore-scripts
|
||||||
|
|
||||||
|
FROM pnpm-base AS builder
|
||||||
|
WORKDIR /build
|
||||||
|
COPY --from=installer /install/ .
|
||||||
|
COPY --from=pruner /prune/out/full/ .
|
||||||
|
COPY proto ./proto
|
||||||
|
ENV CI=true
|
||||||
|
RUN --mount=type=cache,id=turbo,target=/build/.turbo/cache \
|
||||||
|
--mount=type=cache,id=next,target=/build/apps/login/.next/cache \
|
||||||
|
pnpm turbo build:login:standalone --cache-dir=/build/.turbo/cache
|
||||||
|
|
||||||
FROM scratch AS build-out
|
FROM scratch AS build-out
|
||||||
COPY /apps/login/public ./apps/login/public
|
COPY /apps/login/public ./apps/login/public
|
||||||
COPY --from=build /app/apps/login/.next/standalone ./
|
COPY --from=builder /build/apps/login/.next/standalone ./
|
||||||
COPY --from=build /app/apps/login/.next/static ./apps/login/.next/static
|
COPY --from=builder /build/apps/login/.next/static ./apps/login/.next/static
|
||||||
|
|
||||||
FROM base AS login-standalone
|
FROM runtime AS login-standalone
|
||||||
WORKDIR /runtime
|
WORKDIR /runtime
|
||||||
RUN addgroup --system --gid 1001 nodejs && \
|
RUN addgroup --system --gid 1001 nodejs && \
|
||||||
adduser --system --uid 1001 nextjs
|
adduser --system --uid 1001 nextjs
|
||||||
@@ -36,10 +45,11 @@ RUN addgroup --system --gid 1001 nodejs && \
|
|||||||
RUN mkdir -p /.env-file && touch /.env-file/.env && chown -R nextjs:nodejs /.env-file
|
RUN mkdir -p /.env-file && touch /.env-file/.env && chown -R nextjs:nodejs /.env-file
|
||||||
COPY --chown=nextjs:nodejs apps/login/scripts ./
|
COPY --chown=nextjs:nodejs apps/login/scripts ./
|
||||||
COPY --chown=nextjs:nodejs --from=build-out . .
|
COPY --chown=nextjs:nodejs --from=build-out . .
|
||||||
|
# Debug the final structure
|
||||||
USER nextjs
|
USER nextjs
|
||||||
ENV HOSTNAME="0.0.0.0"
|
ENV HOSTNAME="0.0.0.0"
|
||||||
ENV PORT=3000
|
ENV PORT=3000
|
||||||
# TODO: Check healthy, not ready
|
# TODO: Check healthy, not ready
|
||||||
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
CMD ["/bin/sh", "-c", "node ./healthcheck.js http://localhost:${PORT}/ui/v2/login/healthy"]
|
CMD ["/bin/sh", "-c", "node /runtime/healthcheck.js http://localhost:${PORT}/ui/v2/login/healthy"]
|
||||||
ENTRYPOINT ["./entrypoint.sh"]
|
ENTRYPOINT ["/runtime/entrypoint.sh"]
|
||||||
|
@@ -6,8 +6,6 @@ target "login-standalone" {
|
|||||||
target "login-standalone-out" {
|
target "login-standalone-out" {
|
||||||
inherits = ["login-standalone"]
|
inherits = ["login-standalone"]
|
||||||
target = "build-out"
|
target = "build-out"
|
||||||
output = [
|
output = ["type=local,dest=.artifacts/login"]
|
||||||
"type=local,dest=.artifacts/login"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
@@ -67,6 +67,5 @@
|
|||||||
"@docusaurus/module-type-aliases": "^3.8.1",
|
"@docusaurus/module-type-aliases": "^3.8.1",
|
||||||
"@docusaurus/types": "^3.8.1",
|
"@docusaurus/types": "^3.8.1",
|
||||||
"tailwindcss": "^3.2.4"
|
"tailwindcss": "^3.2.4"
|
||||||
},
|
}
|
||||||
"packageManager": "pnpm@9.1.2+sha256.19c17528f9ca20bd442e4ca42f00f1b9808a9cb419383cd04ba32ef19322aba7"
|
|
||||||
}
|
}
|
@@ -17,7 +17,7 @@
|
|||||||
"clean": "rm -rf .turbo node_modules"
|
"clean": "rm -rf .turbo node_modules"
|
||||||
},
|
},
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"devDependencies": {
|
||||||
"@types/pg": "^8.11.6",
|
"@types/pg": "^8.11.6",
|
||||||
"cypress-wait-until": "^3.0.2",
|
"cypress-wait-until": "^3.0.2",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
@@ -26,9 +26,7 @@
|
|||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"typescript": "^5.5.4",
|
"typescript": "^5.5.4",
|
||||||
"uuid": "^10.0.0",
|
"uuid": "^10.0.0",
|
||||||
"wait-on": "^7.2.0"
|
"wait-on": "^7.2.0",
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^22.3.0",
|
"@types/node": "^22.3.0",
|
||||||
"cypress": "^14.5.3"
|
"cypress": "^14.5.3"
|
||||||
}
|
}
|
||||||
|
12
package.json
12
package.json
@@ -1,15 +1,14 @@
|
|||||||
{
|
{
|
||||||
"packageManager": "pnpm@9.1.2+sha256.19c17528f9ca20bd442e4ca42f00f1b9808a9cb419383cd04ba32ef19322aba7",
|
"packageManager": "pnpm@10.13.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "zitadel-monorepo",
|
"name": "zitadel-monorepo",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"generate": "turbo run generate",
|
||||||
"changeset": "changeset",
|
"changeset": "changeset",
|
||||||
"devcontainer": "devcontainer",
|
"devcontainer:lint-unit": "FAIL_COMMANDS_ON_ERRORS=true devcontainer up --prebuild --config .devcontainer/turbo-lint-unit/devcontainer.json --workspace-folder .",
|
||||||
"devcontainer:lint-unit": "pnpm devcontainer up --config .devcontainer/turbo-lint-unit/devcontainer.json --workspace-folder . --remove-existing-container",
|
"devcontainer:integration:login": "FAIL_COMMANDS_ON_ERRORS=true devcontainer up --prebuild --config .devcontainer/login-integration/devcontainer.json --workspace-folder .",
|
||||||
"devcontainer:integration:login": "pnpm devcontainer up --config .devcontainer/login-integration/devcontainer.json --workspace-folder . --remove-existing-container",
|
|
||||||
"clean": "turbo run clean",
|
"clean": "turbo run clean",
|
||||||
"clean:all": "pnpm run clean && rm -rf .turbo node_modules",
|
"clean:all": "pnpm run clean && rm -rf .turbo node_modules"
|
||||||
"generate": "turbo run generate"
|
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"overrides": {
|
"overrides": {
|
||||||
@@ -21,6 +20,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@changesets/cli": "^2.29.5",
|
"@changesets/cli": "^2.29.5",
|
||||||
"@devcontainers/cli": "^0.80.0",
|
"@devcontainers/cli": "^0.80.0",
|
||||||
|
"sass": "^1.64.1",
|
||||||
"turbo": "2.5.5"
|
"turbo": "2.5.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"packageManager": "pnpm@10.13.1",
|
||||||
"name": "@zitadel/client",
|
"name": "@zitadel/client",
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"packageManager": "pnpm@10.13.1",
|
||||||
"name": "@zitadel/proto",
|
"name": "@zitadel/proto",
|
||||||
"version": "1.3.1",
|
"version": "1.3.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -77,7 +78,7 @@
|
|||||||
},
|
},
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"generate": "pnpm exec buf generate ../../proto",
|
"generate": "buf generate ../../proto",
|
||||||
"clean": "rm -rf zitadel .turbo node_modules google protoc-gen-openapiv2 validate cjs types es"
|
"clean": "rm -rf zitadel .turbo node_modules google protoc-gen-openapiv2 validate cjs types es"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
2672
pnpm-lock.yaml
generated
2672
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,9 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://turbo.build/schema.json",
|
"$schema": "https://turbo.build/schema.json",
|
||||||
"ui": "tui",
|
"ui": "tui",
|
||||||
"globalDependencies": ["**/.env.*local"],
|
"globalDependencies": [
|
||||||
|
"**/.env.*local"
|
||||||
|
],
|
||||||
"globalEnv": [
|
"globalEnv": [
|
||||||
"DEBUG",
|
"DEBUG",
|
||||||
"VERCEL_URL",
|
"VERCEL_URL",
|
||||||
@@ -36,6 +38,7 @@
|
|||||||
},
|
},
|
||||||
"start": {},
|
"start": {},
|
||||||
"test:unit": {},
|
"test:unit": {},
|
||||||
|
"test:integration:login": {},
|
||||||
"test:acceptance": {},
|
"test:acceptance": {},
|
||||||
"test:e2e": {},
|
"test:e2e": {},
|
||||||
"lint": {},
|
"lint": {},
|
||||||
|
Reference in New Issue
Block a user