chore: rehaul DevX (#10571)

# Which Problems Are Solved

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

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

The following values can be used for PROJECT:

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

The project names and folders are streamlined:

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

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

# How the Problems Are Solved

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

# Additional Changes

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

# Additional Context

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

---------

Co-authored-by: Florian Forster <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
Co-authored-by: Copilot <[email protected]>
This commit is contained in:
Elio Bischof
2025-10-08 10:27:02 +02:00
committed by GitHub
co-authored by Florian Forster Tim Möhlmann Copilot
parent e47acaeef2
commit f69a6ed4f3
236 changed files with 5708 additions and 6549 deletions
+5
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
+5
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
+3
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
+5
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
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"]
+17
View File
@@ -0,0 +1,17 @@
#!/bin/bash
case $@ in
sh*)
${@:3}
;;
bash*)
${@:5}
;;
*)
if [[ ! -z "$@" ]]
then
ZITADEL_ARGS="$@"
fi
/app/zitadel ${ZITADEL_ARGS}
;;
esac
+25
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
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/[email protected]",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install go.uber.org/mock/[email protected]",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install golang.org/x/tools/cmd/[email protected]",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install github.com/rakyll/[email protected]",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install github.com/bufbuild/buf/cmd/[email protected]",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install google.golang.org/protobuf/cmd/[email protected]",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install google.golang.org/grpc/cmd/[email protected]",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install github.com/grpc-ecosystem/grpc-gateway/v2/[email protected]",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install github.com/grpc-ecosystem/grpc-gateway/v2/[email protected]",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install github.com/envoyproxy/[email protected]",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install connectrpc.com/connect/cmd/[email protected]",
"GOBIN=${PWD}/.artifacts/bin/$(go env GOOS)/$(go env GOARCH) go install google.golang.org/protobuf/cmd/[email protected]",
"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"
]
}
}
}
+59
View File
@@ -0,0 +1,59 @@
Log:
Level: info
ExternalSecure: false
Database:
postgres:
# This makes the e2e config reusable with an out-of-docker zitadel process and an /etc/hosts entry
database: zitadel
MaxOpenConns: 15
MaxIdleConns: 10
Database: zitadel
User:
Username: zitadel
Password: zitadel
SSL:
Mode: disable
Admin:
Username: postgres
Password: postgres
SSL:
Mode: disable
TLS:
Enabled: false
FirstInstance:
Org:
Human:
PasswordChangeRequired: false
Console:
InstanceManagementURL: "https://example.com/instances/{{.InstanceID}}"
Projections:
Customizations:
NotificationsQuotas:
RequeueEvery: 1s
Quotas:
Access:
Enabled: true
Debounce:
MinFrequency: 0s
MaxBulkSize: 0
ExhaustedCookieKey: "zitadel.quota.limiting"
ExhaustedCookieMaxAge: "600s"
DefaultInstance:
LoginPolicy:
MfaInitSkipLifetime: "0"
Features:
LoginV2:
Required: false
SystemAPIUsers:
- cypress:
KeyData: "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF6aStGRlNKTDdmNXl3NEtUd3pnTQpQMzRlUEd5Y20vTStrVDBNN1Y0Q2d4NVYzRWFESXZUUUtUTGZCYUVCNDV6YjlMdGpJWHpEdzByWFJvUzJoTzZ0CmgrQ1lRQ3ozS0N2aDA5QzBJenhaaUIySVMzSC9hVCs1Qng5RUZZK3ZuQWtaamNjYnlHNVlOUnZtdE9sbnZJZUkKSDdxWjB0RXdrUGZGNUdFWk5QSlB0bXkzVUdWN2lvZmRWUVMxeFJqNzMrYU13NXJ2SDREOElkeWlBQzNWZWtJYgpwdDBWajBTVVgzRHdLdG9nMzM3QnpUaVBrM2FYUkYwc2JGaFFvcWRKUkk4TnFnWmpDd2pxOXlmSTV0eXhZc3duCitKR3pIR2RIdlczaWRPRGxtd0V0NUsycGFzaVJJV0syT0dmcSt3MEVjbHRRSGFidXFFUGdabG1oQ2tSZE5maXgKQndJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=="
+128
View File
@@ -0,0 +1,128 @@
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
ExternalSecure: false
TLS:
Enabled: false
Caches:
Connectors:
Memory:
Enabled: true
Postgres:
Enabled: true
Redis:
Enabled: true
Instance:
Connector: "memory"
MaxAge: 5m
LastUsage: 1m
Log:
Level: info
Milestones:
Connector: "postgres"
MaxAge: 5m
LastUsage: 1m
Log:
Level: info
Organization:
Connector: "redis"
MaxAge: 5m
LastUsage: 1m
Log:
Level: info
Quotas:
Access:
Enabled: true
Telemetry:
Enabled: true
Endpoints:
- http://localhost:8081/milestone
Headers:
single-value: "single-value"
multi-value:
- "multi-value-1"
- "multi-value-2"
LogStore:
Execution:
Stdout:
Enabled: true
Projections:
HandleActiveInstances: 30m
RequeueEvery: 20s
Customizations:
NotificationsQuotas:
RequeueEvery: 5s
telemetry:
HandleActiveInstances: 60s
RequeueEvery: 5s
DefaultInstance:
LoginPolicy:
MfaInitSkipLifetime: "0"
SystemAPIUsers:
- tester:
KeyData: "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF6aStGRlNKTDdmNXl3NEtUd3pnTQpQMzRlUEd5Y20vTStrVDBNN1Y0Q2d4NVYzRWFESXZUUUtUTGZCYUVCNDV6YjlMdGpJWHpEdzByWFJvUzJoTzZ0CmgrQ1lRQ3ozS0N2aDA5QzBJenhaaUIySVMzSC9hVCs1Qng5RUZZK3ZuQWtaamNjYnlHNVlOUnZtdE9sbnZJZUkKSDdxWjB0RXdrUGZGNUdFWk5QSlB0bXkzVUdWN2lvZmRWUVMxeFJqNzMrYU13NXJ2SDREOElkeWlBQzNWZWtJYgpwdDBWajBTVVgzRHdLdG9nMzM3QnpUaVBrM2FYUkYwc2JGaFFvcWRKUkk4TnFnWmpDd2pxOXlmSTV0eXhZc3duCitKR3pIR2RIdlczaWRPRGxtd0V0NUsycGFzaVJJV0syT0dmcSt3MEVjbHRRSGFidXFFUGdabG1oQ2tSZE5maXgKQndJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=="
Memberships:
- MemberType: System
Roles:
- "SYSTEM_OWNER"
- "IAM_OWNER"
- "ORG_OWNER"
- cypress:
KeyData: "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF6aStGRlNKTDdmNXl3NEtUd3pnTQpQMzRlUEd5Y20vTStrVDBNN1Y0Q2d4NVYzRWFESXZUUUtUTGZCYUVCNDV6YjlMdGpJWHpEdzByWFJvUzJoTzZ0CmgrQ1lRQ3ozS0N2aDA5QzBJenhaaUIySVMzSC9hVCs1Qng5RUZZK3ZuQWtaamNjYnlHNVlOUnZtdE9sbnZJZUkKSDdxWjB0RXdrUGZGNUdFWk5QSlB0bXkzVUdWN2lvZmRWUVMxeFJqNzMrYU13NXJ2SDREOElkeWlBQzNWZWtJYgpwdDBWajBTVVgzRHdLdG9nMzM3QnpUaVBrM2FYUkYwc2JGaFFvcWRKUkk4TnFnWmpDd2pxOXlmSTV0eXhZc3duCitKR3pIR2RIdlczaWRPRGxtd0V0NUsycGFzaVJJV0syT0dmcSt3MEVjbHRRSGFidXFFUGdabG1oQ2tSZE5maXgKQndJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=="
- system-user-with-no-permissions:
KeyData: "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFqTVdFWDZtK0gzWndaV1ptTUhxbApHbVoxa0wvRVlWZzJCb24yQm5wOU5LTXdoVTlpK29CcUwrR0FzVVZYdnBkMmhVTy9ZK1VpVzlRdnJ4K3ZBeVpNCmdrNjRRNlFFNm5ZMWJncnV3aEJDUC85ZWlMMzVvOTRHelhiS2RDSEF5bFNBQmRHemZaTDN1YUgwVndvRk9neU0KZkJveTdGMHFLRXA0bVp5ZUhmMFo3ZXZacVVyRDVNcEZMTjBhUnRqVWpwOTFpd0tGU29kYXY1S25sYW4vSGtQaQpzN3NnLzBmVURRRDRzZ2ZvcndManJWYnI1aUtxSTBHQ3VhUEwzazRQOEdnY1haczVJcHUzb1BDZXdWUTBvd1hoCjJvRXVTdlNDYS8wTmxYanRLMlRqbmlYeTVSL2NaVXF3NzNOd0NFdjl4N1pLaU51dkpEWkw2UnM5Q0xJT3RhVkUKTFFJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg=="
Memberships:
# MemberType System allows the user to access all APIs for all instances or organizations
- MemberType: IAM
Roles:
- "NO_ROLES"
InitProjections:
Enabled: true
# Extend key lifetimes so we do not see more legacy keys when
# integration tests are rerun on the same DB with more than 6 hours apart.
# The test counts the amount of keys returned from the JWKS endpoint and fails
# with 2 or more legacy public keys,
SystemDefaults:
KeyConfig:
PrivateKeyLifetime: 7200h
PublicKeyLifetime: 14400h
OIDC:
DefaultLoginURLV2: "/login?authRequest=" # ZITADEL_OIDC_DEFAULTLOGINURLV2
DefaultLogoutURLV2: "/logout?post_logout_redirect=" # ZITADEL_OIDC_DEFAULTLOGOUTURLV2
SAML:
DefaultLoginURLV2: "/login?authRequest=" # ZITADEL_SAML_DEFAULTLOGINURLV2
+5
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
View File
@@ -0,0 +1 @@
ZITADEL_SERVICE_USER_TOKEN_FILE=../../../../login-client.pat
-6
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
+2
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
@@ -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
-63
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.
-4
View File
@@ -1,4 +0,0 @@
blank_issues_enabled: true
contact_links:
- name: 💬 ZITADEL Community Chat
url: https://zitadel.com/chat
-30
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.
-54
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.
-54
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

-21
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" ]
-13
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
-39
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"
});
-41
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/[email protected]
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/[email protected]
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/[email protected]
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
-32
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 }}
-67
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()
-1
View File
@@ -6,7 +6,6 @@ cypress
.DS_Store
node_modules
.turbo
*.log
.next
dist
-128
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.
-218
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 [[email protected]](mailto:[email protected]).
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**: *[email protected]*
**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**: *[email protected]*
**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
```
+9 -28
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 [email protected] --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" ]
-22
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
+5 -5
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"
}
},
});
-3
View File
@@ -1,3 +0,0 @@
target "release" {
platforms = ["linux/amd64", "linux/arm64"]
}
-25
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",
]
}
@@ -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
@@ -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"
}
}
}
+1 -1
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({
+3
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;
+1 -2
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,
+15 -21
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
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"
]
}
}
}
+14 -7
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 $@
+8 -2
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"],
-57
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
View File
@@ -0,0 +1,4 @@
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"buildCommand": "pnpm nx run @zitadel/login:build-vercel"
}