diff --git a/.devcontainer/base/Dockerfile b/.devcontainer/base/Dockerfile
new file mode 100644
index 0000000000..119594bc6f
--- /dev/null
+++ b/.devcontainer/base/Dockerfile
@@ -0,0 +1,16 @@
+FROM mcr.microsoft.com/devcontainers/typescript-node:20-bookworm
+
+ENV SHELL=/bin/bash \
+ DEBIAN_FRONTEND=noninteractive \
+ LANG=C.UTF-8 \
+ LC_ALL=C.UTF-8 \
+ CI=1 \
+ PNPM_HOME=/home/node/.local/share/pnpm \
+ PATH=/home/node/.local/share/pnpm:$PATH
+
+
+RUN apt-get update && \
+ apt-get --no-install-recommends install -y \
+ libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb && \
+ apt-get clean && \
+ corepack enable && COREPACK_ENABLE_DOWNLOAD_PROMPT=0 corepack prepare pnpm@9.1.2 --activate
diff --git a/.devcontainer/base/devcontainer.json b/.devcontainer/base/devcontainer.json
new file mode 100644
index 0000000000..187e012e67
--- /dev/null
+++ b/.devcontainer/base/devcontainer.json
@@ -0,0 +1,28 @@
+{
+ "$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
+ "name": "devcontainer",
+ "dockerComposeFile": "docker-compose.yml",
+ "service": "devcontainer",
+ "workspaceFolder": "/workspaces",
+ "features": {
+ "ghcr.io/devcontainers/features/go:1": {
+ "version": "1.24"
+ },
+ "ghcr.io/guiyomh/features/golangci-lint:0": {},
+ "ghcr.io/jungaretti/features/make:1": {}
+ },
+ "forwardPorts": [
+ 3000,
+ 3001,
+ 4200,
+ 8080
+ ],
+ "onCreateCommand": "pnpm install -g sass@1.64.1",
+ "customizations": {
+ "jetbrains": {
+ "settings": {
+ "com.intellij:app:HttpConfigurable.use_proxy_pac": true
+ }
+ }
+ }
+}
diff --git a/.devcontainer/base/docker-compose.yml b/.devcontainer/base/docker-compose.yml
new file mode 100644
index 0000000000..d1b26f1a7b
--- /dev/null
+++ b/.devcontainer/base/docker-compose.yml
@@ -0,0 +1,225 @@
+services:
+
+ devcontainer:
+ container_name: devcontainer
+ build:
+ context: .
+ volumes:
+ - ../../:/workspaces:cached
+ - /tmp/.X11-unix:/tmp/.X11-unix:cached
+ - home-dir:/home/node:delegated
+ command: sleep infinity
+ working_dir: /workspaces
+ environment:
+ ZITADEL_DATABASE_POSTGRES_HOST: db
+ ZITADEL_EXTERNALSECURE: false
+
+ db:
+ container_name: db
+ image: postgres:17.0-alpine3.19
+ restart: unless-stopped
+ volumes:
+ - postgres-data:/var/lib/postgresql/data
+ environment:
+ PGUSER: postgres
+ POSTGRES_PASSWORD: postgres
+ healthcheck:
+ test: [ "CMD-SHELL", "pg_isready" ]
+ interval: "10s"
+ timeout: "30s"
+ retries: 5
+ start_period: "20s"
+ ports:
+ - "5432:5432"
+
+ mock-zitadel:
+ container_name: mock-zitadel
+ build:
+ context: ../../apps/login/integration/core-mock
+ ports:
+ - 22220:22220
+ - 22222:22222
+
+ login-integration:
+ container_name: login-integration
+ build:
+ context: ../..
+ dockerfile: build/login/Dockerfile
+ 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:
+ image: "${ZITADEL_TAG:-ghcr.io/zitadel/zitadel:v4.0.0-rc.2}"
+ container_name: zitadel
+ command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --config /zitadel.yaml --steps /zitadel.yaml'
+ volumes:
+ - ../../apps/login/acceptance/pat:/pat:delegated
+ - ../../apps/login/acceptance/zitadel.yaml:/zitadel.yaml:cached
+ network_mode: service:devcontainer
+ healthcheck:
+ test:
+ - CMD
+ - /app/zitadel
+ - ready
+ - --config
+ - /zitadel.yaml
+ depends_on:
+ db:
+ condition: "service_healthy"
+
+ configure-login:
+ container_name: configure-login
+ restart: no
+ build:
+ context: ../../apps/login/acceptance/setup
+ dockerfile: ../go-command.Dockerfile
+ entrypoint: "./setup.sh"
+ network_mode: service:devcontainer
+ environment:
+ PAT_FILE: /pat/zitadel-admin-sa.pat
+ ZITADEL_API_URL: http://localhost:8080
+ WRITE_ENVIRONMENT_FILE: /login-env/.env.test.local
+ SINK_EMAIL_INTERNAL_URL: http://sink:3333/email
+ SINK_SMS_INTERNAL_URL: http://sink:3333/sms
+ SINK_NOTIFICATION_URL: http://sink:3333/notification
+ LOGIN_BASE_URL: http://localhost:3000/ui/v2/login/
+ ZITADEL_API_DOMAIN: localhost
+ ZITADEL_ADMIN_USER: zitadel-admin@zitadel.localhost
+ volumes:
+ - ../../apps/login/acceptance/pat:/pat:cached # Read the PAT file from zitadels setup
+ - ../../apps/login:/login-env:delegated # Write the environment variables file for the login
+ depends_on:
+ zitadel:
+ condition: "service_healthy"
+
+ login-acceptance:
+ container_name: login
+ image: "${LOGIN_TAG:-ghcr.io/zitadel/zitadel-login:v4.0.0-rc.2}"
+ network_mode: service:devcontainer
+ volumes:
+ - ../../apps/login/.env.test.local:/env-files/.env:cached
+ depends_on:
+ configure-login:
+ condition: service_completed_successfully
+
+ mock-notifications:
+ container_name: mock-notifications
+ build:
+ context: ../../apps/login/acceptance/sink
+ dockerfile: ../go-command.Dockerfile
+ args:
+ - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
+ environment:
+ PORT: '3333'
+ command:
+ - -port
+ - '3333'
+ - -email
+ - '/email'
+ - -sms
+ - '/sms'
+ - -notification
+ - '/notification'
+ ports:
+ - "3333:3333"
+ depends_on:
+ configure-login:
+ condition: "service_completed_successfully"
+
+ mock-oidcrp:
+ container_name: mock-oidcrp
+ build:
+ context: ../../apps/login/acceptance/oidcrp
+ dockerfile: ../go-command.Dockerfile
+ args:
+ - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
+ network_mode: service:devcontainer
+ environment:
+ API_URL: 'http://localhost:8080'
+ API_DOMAIN: 'localhost'
+ PAT_FILE: '/pat/zitadel-admin-sa.pat'
+ LOGIN_URL: 'http://localhost:3000/ui/v2/login'
+ ISSUER: 'http://localhost:8000'
+ HOST: 'localhost'
+ PORT: '8000'
+ SCOPES: 'openid profile email'
+ volumes:
+ - ../../apps/login/acceptance/pat:/pat:cached
+ depends_on:
+ configure-login:
+ condition: "service_completed_successfully"
+
+ # mock-oidcop:
+ # container_name: mock-oidcop
+ # build:
+ # context: ../../apps/login/acceptance/idp/oidc
+ # dockerfile: ../../go-command.Dockerfile
+ # args:
+ # - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
+ # network_mode: service:devcontainer
+ # environment:
+ # API_URL: 'http://localhost:8080'
+ # API_DOMAIN: 'localhost'
+ # PAT_FILE: '/pat/zitadel-admin-sa.pat'
+ # SCHEMA: 'http'
+ # HOST: 'localhost'
+ # PORT: "8004"
+ # volumes:
+ # - "../apps/login/packages/acceptance/pat:/pat:cached"
+ # depends_on:
+ # configure-login:
+ # condition: "service_completed_successfully"
+
+ mock-samlsp:
+ container_name: mock-samlsp
+ build:
+ context: ../../apps/login/acceptance/samlsp
+ dockerfile: ../go-command.Dockerfile
+ args:
+ - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
+ network_mode: service:devcontainer
+ environment:
+ API_URL: 'http://localhost:8080'
+ API_DOMAIN: 'localhost'
+ PAT_FILE: '/pat/zitadel-admin-sa.pat'
+ LOGIN_URL: 'http://localhost:3000/ui/v2/login'
+ IDP_URL: 'http://localhost:8080/saml/v2/metadata'
+ HOST: 'http://localhost:8001'
+ PORT: '8001'
+ volumes:
+ - "../apps/login/packages/acceptance/pat:/pat:cached"
+ depends_on:
+ configure-login:
+ condition: "service_completed_successfully"
+
+# mock-samlidp:
+# container_name: mock-samlidp
+# build:
+# context: ../../apps/login/acceptance/idp/saml
+# dockerfile: ../../go-command.Dockerfile
+# args:
+# - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
+# network_mode: service:devcontainer
+# environment:
+# API_URL: 'http://localhost:8080'
+# API_DOMAIN: 'localhost'
+# PAT_FILE: '/pat/zitadel-admin-sa.pat'
+# SCHEMA: 'http'
+# HOST: 'localhost'
+# PORT: "8003"
+# volumes:
+# - "../apps/login/packages/acceptance/pat:/pat"
+# depends_on:
+# configure-login:
+# condition: "service_completed_successfully"
+
+volumes:
+ postgres-data:
+ home-dir:
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
deleted file mode 100644
index 5d49f92cf4..0000000000
--- a/.devcontainer/devcontainer.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "name": "zitadel",
- "dockerComposeFile": "docker-compose.yml",
- "service": "devcontainer",
- "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
- "features": {
- "ghcr.io/devcontainers/features/go:1": {
- "version": "1.22"
- },
- "ghcr.io/devcontainers/features/node:1": {},
- "ghcr.io/guiyomh/features/golangci-lint:0": {},
- "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {},
- "ghcr.io/devcontainers/features/github-cli:1": {},
- "ghcr.io/jungaretti/features/make:1": {}
- },
- "forwardPorts": [
- 3000,
- 4200,
- 8080
- ],
- "onCreateCommand": "npm install -g sass@1.64.1"
-}
diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml
deleted file mode 100644
index cece28632b..0000000000
--- a/.devcontainer/docker-compose.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-version: '3.8'
-services:
- devcontainer:
- image: mcr.microsoft.com/devcontainers/base:ubuntu
- volumes:
- - ../..:/workspaces:cached
- - /var/run/docker.sock:/var/run/docker.sock
- network_mode: service:db
- command: sleep infinity
- environment:
- ZITADEL_DATABASE_POSTGRES_HOST: db
- ZITADEL_DATABASE_POSTGRES_PORT: 5432
- ZITADEL_DATABASE_POSTGRES_DATABASE: zitadel
- ZITADEL_DATABASE_POSTGRES_USER_USERNAME: zitadel
- ZITADEL_DATABASE_POSTGRES_USER_PASSWORD: zitadel
- ZITADEL_DATABASE_POSTGRES_USER_SSL_MODE: disable
- ZITADEL_DATABASE_POSTGRES_ADMIN_USERNAME: postgres
- ZITADEL_DATABASE_POSTGRES_ADMIN_PASSWORD: postgres
- ZITADEL_DATABASE_POSTGRES_ADMIN_SSL_MODE: disable
- ZITADEL_EXTERNALSECURE: false
- db:
- image: postgres:latest
- restart: unless-stopped
- volumes:
- - postgres-data:/var/lib/postgresql/data
- environment:
- PGUSER: postgres
- POSTGRES_PASSWORD: postgres
-
-volumes:
- postgres-data:
diff --git a/.devcontainer/login-integration-debug/devcontainer.json b/.devcontainer/login-integration-debug/devcontainer.json
new file mode 100644
index 0000000000..525b04788e
--- /dev/null
+++ b/.devcontainer/login-integration-debug/devcontainer.json
@@ -0,0 +1,21 @@
+{
+ "$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
+ }
+ }
+ }
+}
diff --git a/.devcontainer/login-integration-debug/docker-compose.yml b/.devcontainer/login-integration-debug/docker-compose.yml
new file mode 100644
index 0000000000..11ce02ee7d
--- /dev/null
+++ b/.devcontainer/login-integration-debug/docker-compose.yml
@@ -0,0 +1,9 @@
+services:
+ login-integration-debug:
+ extends:
+ file: ../base/docker-compose.yml
+ service: devcontainer
+ container_name: login-integration-debug
+ depends_on:
+ mock-zitadel:
+ condition: service_started
diff --git a/.devcontainer/login-integration/devcontainer.json b/.devcontainer/login-integration/devcontainer.json
new file mode 100644
index 0000000000..1b7e02df43
--- /dev/null
+++ b/.devcontainer/login-integration/devcontainer.json
@@ -0,0 +1,19 @@
+{
+ "$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
+ "name": "login-integration",
+ "dockerComposeFile": [
+ "../base/docker-compose.yml"
+ ],
+ "service": "devcontainer",
+ "runServices": ["login-integration"],
+ "workspaceFolder": "/workspaces",
+ "forwardPorts": [3001],
+ "onCreateCommand": "pnpm install --frozen-lockfile --recursive && cd apps/login/packages/integration && pnpm cypress install && pnpm test:integration:login",
+ "customizations": {
+ "jetbrains": {
+ "settings": {
+ "com.intellij:app:HttpConfigurable.use_proxy_pac": true
+ }
+ }
+ }
+}
diff --git a/.devcontainer/turbo-lint-unit-debug/devcontainer.json b/.devcontainer/turbo-lint-unit-debug/devcontainer.json
new file mode 100644
index 0000000000..19446687a1
--- /dev/null
+++ b/.devcontainer/turbo-lint-unit-debug/devcontainer.json
@@ -0,0 +1,21 @@
+{
+ "$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
+ }
+ }
+ }
+}
diff --git a/.devcontainer/turbo-lint-unit-debug/docker-compose.yml b/.devcontainer/turbo-lint-unit-debug/docker-compose.yml
new file mode 100644
index 0000000000..a19a0211e5
--- /dev/null
+++ b/.devcontainer/turbo-lint-unit-debug/docker-compose.yml
@@ -0,0 +1,6 @@
+services:
+ turbo-lint-unit-debug:
+ extends:
+ file: ../base/docker-compose.yml
+ service: devcontainer
+ container_name: turbo-lint-unit-debug
diff --git a/.devcontainer/turbo-lint-unit/devcontainer.json b/.devcontainer/turbo-lint-unit/devcontainer.json
new file mode 100644
index 0000000000..f3c4f64355
--- /dev/null
+++ b/.devcontainer/turbo-lint-unit/devcontainer.json
@@ -0,0 +1,18 @@
+{
+ "$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
+ "name": "turbo-lint-unit",
+ "dockerComposeFile": [
+ "../base/docker-compose.yml"
+ ],
+ "service": "devcontainer",
+ "runServices": ["devcontainer"],
+ "workspaceFolder": "/workspaces",
+ "postStartCommand": "pnpm install --frozen-lockfile --recursive && pnpm turbo lint test:unit",
+ "customizations": {
+ "jetbrains": {
+ "settings": {
+ "com.intellij:app:HttpConfigurable.use_proxy_pac": true
+ }
+ }
+ }
+}
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 81f3104065..e501eb169b 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -19,7 +19,6 @@ permissions:
issues: write
pull-requests: write
actions: write
- id-token: write
jobs:
core:
@@ -32,6 +31,11 @@ jobs:
uses: ./.github/workflows/console.yml
with:
node_version: "20"
+
+ docs:
+ uses: ./.github/workflows/docs.yml
+ with:
+ node_version: "20"
buf_version: "latest"
version:
@@ -50,6 +54,8 @@ jobs:
console_cache_path: ${{ needs.console.outputs.cache_path }}
version: ${{ needs.version.outputs.version }}
node_version: "20"
+ secrets:
+ DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
core-unit-test:
needs: core
@@ -79,16 +85,6 @@ jobs:
core_cache_key: ${{ needs.core.outputs.cache_key }}
core_cache_path: ${{ needs.core.outputs.cache_path }}
- login-quality:
- needs: [compile]
- uses: ./.github/workflows/login-quality.yml
- permissions:
- actions: write
- id-token: write
- with:
- ignore-run-cache: ${{ github.event_name == 'workflow_dispatch' || fromJSON(github.run_attempt) > 1 }}
- node_version: "20"
-
container:
needs: [compile]
uses: ./.github/workflows/container.yml
@@ -101,13 +97,14 @@ jobs:
login-container:
uses: ./.github/workflows/login-container.yml
- if: ${{ github.event_name == 'workflow_dispatch' }}
permissions:
packages: write
id-token: write
with:
login_build_image_name: "ghcr.io/zitadel/zitadel-login-build"
node_version: "20"
+ secrets:
+ DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
e2e:
uses: ./.github/workflows/e2e.yml
@@ -121,7 +118,15 @@ jobs:
issues: write
pull-requests: write
needs:
- [version, core-unit-test, core-integration-test, lint, container, login-container, login-quality, e2e]
+ [
+ version,
+ core-unit-test,
+ core-integration-test,
+ lint,
+ container,
+ login-container,
+ e2e,
+ ]
if: ${{ github.event_name == 'workflow_dispatch' }}
secrets:
GCR_JSON_KEY_BASE64: ${{ secrets.GCR_JSON_KEY_BASE64 }}
diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml
index 7b64427a18..65e7851d48 100644
--- a/.github/workflows/compile.yml
+++ b/.github/workflows/compile.yml
@@ -21,6 +21,10 @@ on:
node_version:
required: true
type: string
+ secrets:
+ DEPOT_TOKEN:
+ required: true
+
jobs:
executable:
runs-on: ubuntu-latest
@@ -29,98 +33,59 @@ jobs:
matrix:
goos: [linux, darwin, windows]
goarch: [amd64, arm64]
-
- steps:
- -
- uses: actions/checkout@v4
- -
- uses: actions/cache/restore@v4
- timeout-minutes: 1
- name: restore console
- with:
- path: ${{ inputs.console_cache_path }}
- key: ${{ inputs.console_cache_key }}
- fail-on-cache-miss: true
- -
- uses: actions/cache/restore@v4
- timeout-minutes: 1
- name: restore core
- with:
- path: ${{ inputs.core_cache_path }}
- key: ${{ inputs.core_cache_key }}
- fail-on-cache-miss: true
- -
- uses: actions/setup-go@v5
- with:
- go-version-file: 'go.mod'
- -
- name: compile
- timeout-minutes: 5
- run: |
- GOOS="${{matrix.goos}}" \
- GOARCH="${{matrix.goarch}}" \
- VERSION="${{ inputs.version }}" \
- COMMIT_SHA="${{ github.sha }}" \
- make compile_pipeline
- -
- name: create folder
- run: |
- mkdir zitadel-${{ matrix.goos }}-${{ matrix.goarch }}
- mv zitadel zitadel-${{ matrix.goos }}-${{ matrix.goarch }}/
- cp LICENSE zitadel-${{ matrix.goos }}-${{ matrix.goarch }}/
- cp README.md zitadel-${{ matrix.goos }}-${{ matrix.goarch }}/
- tar -czvf zitadel-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz zitadel-${{ matrix.goos }}-${{ matrix.goarch }}
- -
- uses: actions/upload-artifact@v4
- with:
- name: zitadel-${{ matrix.goos }}-${{ matrix.goarch }}
- path: zitadel-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz
- login:
- runs-on: ubuntu-latest
steps:
- -
- uses: actions/checkout@v4
- -
- uses: depot/setup-action@v1
- with:
- oidc: true
- -
- run: make login_standalone_out
- env:
- # latest if branch is main, otherwise image version which is the pull request number
- LOGIN_BAKE_CLI: depot bake
- DEPOT_PROJECT_ID: w47wkxzdtw
- NODE_VERSION: ${{ inputs.node_version }}
- -
- name: move files
- run: |
- cp login/LICENSE login/apps/login/standalone/
- cp login/README.md login/apps/login/standalone/
- tar -czvf login.tar.gz -C login/apps/login/standalone .
- -
- uses: actions/upload-artifact@v4
- with:
- name: login
- path: login.tar.gz
+ - uses: actions/checkout@v4
+ - uses: actions/cache/restore@v4
+ timeout-minutes: 1
+ name: restore console
+ with:
+ path: ${{ inputs.console_cache_path }}
+ key: ${{ inputs.console_cache_key }}
+ fail-on-cache-miss: true
+ - uses: actions/cache/restore@v4
+ timeout-minutes: 1
+ name: restore core
+ with:
+ path: ${{ inputs.core_cache_path }}
+ key: ${{ inputs.core_cache_key }}
+ fail-on-cache-miss: true
+ - uses: actions/setup-go@v5
+ with:
+ go-version-file: "go.mod"
+ - name: compile
+ timeout-minutes: 5
+ run: |
+ GOOS="${{matrix.goos}}" \
+ GOARCH="${{matrix.goarch}}" \
+ VERSION="${{ inputs.version }}" \
+ COMMIT_SHA="${{ github.sha }}" \
+ make compile_pipeline
+ - name: create folder
+ run: |
+ mkdir zitadel-${{ matrix.goos }}-${{ matrix.goarch }}
+ mv zitadel zitadel-${{ matrix.goos }}-${{ matrix.goarch }}/
+ cp LICENSE zitadel-${{ matrix.goos }}-${{ matrix.goarch }}/
+ cp README.md zitadel-${{ matrix.goos }}-${{ matrix.goarch }}/
+ tar -czvf zitadel-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz zitadel-${{ matrix.goos }}-${{ matrix.goarch }}
+ - uses: actions/upload-artifact@v4
+ with:
+ name: zitadel-${{ matrix.goos }}-${{ matrix.goarch }}
+ path: zitadel-${{ matrix.goos }}-${{ matrix.goarch }}.tar.gz
checksums:
runs-on: ubuntu-latest
- needs: [executable, login]
+ needs: [executable]
steps:
- -
- uses: actions/download-artifact@v4
- with:
- path: executables
- -
- name: move files one folder up
- run: mv */*.tar.gz . && find . -type d -empty -delete
- working-directory: executables
- -
- run: sha256sum * > checksums.txt
- working-directory: executables
- -
- uses: actions/upload-artifact@v4
- with:
- name: checksums.txt
- path: executables/checksums.txt
+ - uses: actions/download-artifact@v4
+ with:
+ path: executables
+ - name: move files one folder up
+ run: mv */*.tar.gz . && find . -type d -empty -delete
+ working-directory: executables
+ - run: sha256sum * > checksums.txt
+ working-directory: executables
+ - uses: actions/upload-artifact@v4
+ with:
+ name: checksums.txt
+ path: executables/checksums.txt
diff --git a/.github/workflows/console.yml b/.github/workflows/console.yml
index 3e77757129..b2f8119190 100644
--- a/.github/workflows/console.yml
+++ b/.github/workflows/console.yml
@@ -1,19 +1,16 @@
name: Build console
-on:
+on:
workflow_call:
inputs:
node_version:
required: true
type: string
- buf_version:
- required: true
- type: string
outputs:
cache_key:
value: ${{ jobs.build.outputs.cache_key }}
cache_path:
- value: ${{ jobs.build.outputs.cache_path }}
+ value: ${{ jobs.build.outputs.cache_path }}
env:
cache_path: console/dist/console
@@ -25,38 +22,32 @@ jobs:
cache_path: ${{ env.cache_path }}
runs-on: ubuntu-latest
steps:
- -
- uses: actions/checkout@v4
- -
- uses: actions/cache/restore@v4
- timeout-minutes: 1
- continue-on-error: true
- id: cache
- with:
- key: console-${{ hashFiles('console', 'proto', '!console/dist') }}
- restore-keys: |
- console-
- path: ${{ env.cache_path }}
- -
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
- uses: bufbuild/buf-setup-action@v1
- with:
- github_token: ${{ github.token }}
- version: ${{ inputs.buf_version }}
- -
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
- uses: actions/setup-node@v4
- with:
- node-version: ${{ inputs.node_version }}
- cache: 'yarn'
- cache-dependency-path: console/yarn.lock
- -
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
- run: make console_build
- -
- if: ${{ steps.cache.outputs.cache-hit != 'true' }}
- uses: actions/cache/save@v4
- with:
- path: ${{ env.cache_path }}
- key: ${{ steps.cache.outputs.cache-primary-key }}
-
\ No newline at end of file
+ - uses: actions/checkout@v4
+ - uses: actions/cache/restore@v4
+ timeout-minutes: 1
+ continue-on-error: true
+ id: cache
+ with:
+ key: console-${{ hashFiles('console', 'proto', '!console/dist') }}
+ restore-keys: |
+ console-
+ path: ${{ env.cache_path }}
+ - if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+ uses: pnpm/action-setup@v4
+ - if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ inputs.node_version }}
+ cache: "pnpm"
+ cache-dependency-path: pnpm-lock.yaml
+ - if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+ name: Install dependencies
+ run: pnpm install --frozen-lockfile
+ - if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+ name: Build console with Turbo
+ run: pnpm turbo build --filter=./console
+ - if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+ uses: actions/cache/save@v4
+ with:
+ path: ${{ env.cache_path }}
+ key: ${{ steps.cache.outputs.cache-primary-key }}
diff --git a/.github/workflows/container.yml b/.github/workflows/container.yml
index 33ffd4f6af..f762124e00 100644
--- a/.github/workflows/container.yml
+++ b/.github/workflows/container.yml
@@ -79,7 +79,7 @@ jobs:
context: .
cache-from: type=gha
cache-to: type=gha,mode=max
- file: build/Dockerfile
+ file: build/zitadel/Dockerfile
target: artifact
platforms: linux/${{ matrix.arch }}
push: true
@@ -94,7 +94,7 @@ jobs:
context: .
cache-from: type=gha
cache-to: type=gha,mode=max
- file: build/Dockerfile
+ file: build/zitadel/Dockerfile
target: final
platforms: linux/${{ matrix.arch }}
push: true
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 0000000000..2f0ac3d7af
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,61 @@
+name: Build docs
+
+on:
+ workflow_call:
+ inputs:
+ node_version:
+ required: true
+ type: string
+ buf_version:
+ required: true
+ type: string
+ outputs:
+ cache_key:
+ value: ${{ jobs.build.outputs.cache_key }}
+ cache_path:
+ value: ${{ jobs.build.outputs.cache_path }}
+
+env:
+ cache_path: docs/build
+
+jobs:
+ build:
+ outputs:
+ cache_key: ${{ steps.cache.outputs.cache-primary-key }}
+ cache_path: ${{ env.cache_path }}
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/cache/restore@v4
+ timeout-minutes: 1
+ continue-on-error: true
+ id: cache
+ with:
+ key: docs-${{ hashFiles('docs', 'proto', '!docs/build', '!docs/node_modules', '!docs/protoc-gen-connect-openapi') }}
+ restore-keys: |
+ docs-
+ path: ${{ env.cache_path }}
+ - if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+ uses: bufbuild/buf-setup-action@v1
+ with:
+ github_token: ${{ github.token }}
+ version: ${{ inputs.buf_version }}
+ - if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+ uses: pnpm/action-setup@v4
+ - if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+ uses: actions/setup-node@v4
+ with:
+ node-version: ${{ inputs.node_version }}
+ cache: "pnpm"
+ cache-dependency-path: pnpm-lock.yaml
+ - if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+ name: Install dependencies
+ run: pnpm install
+ - if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+ name: Build docs with Turbo
+ run: pnpm turbo build --filter=./docs
+ - if: ${{ steps.cache.outputs.cache-hit != 'true' }}
+ uses: actions/cache/save@v4
+ with:
+ path: ${{ env.cache_path }}
+ key: ${{ steps.cache.outputs.cache-primary-key }}
diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml
index e717163507..b9c2159e1c 100644
--- a/.github/workflows/e2e.yml
+++ b/.github/workflows/e2e.yml
@@ -12,44 +12,47 @@ jobs:
browser: [firefox, chrome]
runs-on: ubuntu-latest
steps:
- -
- name: Checkout Repository
+ - name: Checkout Repository
uses: actions/checkout@v4
- -
- uses: actions/download-artifact@v4
+ - uses: actions/download-artifact@v4
with:
path: .artifacts
name: zitadel-linux-amd64
- -
- name: Unpack executable
+ - name: Unpack executable
run: |
tar -xvf .artifacts/zitadel-linux-amd64.tar.gz
mv zitadel-linux-amd64/zitadel ./zitadel
- -
- name: Set up QEMU
+ - name: Set up QEMU
uses: docker/setup-qemu-action@v3
- -
- name: Set up Docker Buildx
+ - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- -
- name: Start DB and ZITADEL
+ - uses: pnpm/action-setup@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: "pnpm"
+ cache-dependency-path: pnpm-lock.yaml
+ - name: Install dependencies
+ run: pnpm install
+ - name: Install Cypress binary
+ run: cd ./e2e && pnpm exec cypress install
+ - name: Start DB and ZITADEL
run: |
cd ./e2e
ZITADEL_IMAGE=zitadel:local docker compose up --detach --wait
- -
- name: Cypress run
+ - name: Cypress run
uses: cypress-io/github-action@v6
env:
CYPRESS_BASE_URL: http://localhost:8080/ui/console
CYPRESS_WEBHOOK_HANDLER_HOST: host.docker.internal
- CYPRESS_DATABASE_CONNECTION_URL: 'postgresql://root@localhost:26257/zitadel'
+ CYPRESS_DATABASE_CONNECTION_URL: "postgresql://root@localhost:26257/zitadel"
CYPRESS_BACKEND_URL: http://localhost:8080
with:
working-directory: e2e
browser: ${{ matrix.browser }}
config-file: cypress.config.ts
- -
- uses: actions/upload-artifact@v4
+ install: false
+ - uses: actions/upload-artifact@v4
if: always()
with:
name: production-tests-${{ matrix.browser }}
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index e704bdb146..b8c7486f1f 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -20,7 +20,6 @@ on:
type: string
jobs:
-
lint-skip:
name: lint skip
runs-on: ubuntu-latest
@@ -36,64 +35,50 @@ jobs:
continue-on-error: true
if: ${{ github.event_name == 'pull_request' }}
steps:
- -
- uses: actions/checkout@v4
- -
- uses: bufbuild/buf-setup-action@v1
- with:
- version: ${{ inputs.buf_version }}
- github_token: ${{ secrets.GITHUB_TOKEN }}
- -
- name: lint
- uses: bufbuild/buf-lint-action@v1
- -
- uses: bufbuild/buf-breaking-action@v1
- with:
- against: "https://github.com/${{ github.repository }}.git#branch=${{ github.base_ref }}"
+ - uses: actions/checkout@v4
+ - uses: bufbuild/buf-setup-action@v1
+ with:
+ version: ${{ inputs.buf_version }}
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ - name: lint
+ uses: bufbuild/buf-lint-action@v1
+ - uses: bufbuild/buf-breaking-action@v1
+ with:
+ against: "https://github.com/${{ github.repository }}.git#branch=${{ github.base_ref }}"
- console:
+ turbo-lint-unit:
if: ${{ github.event_name == 'pull_request' }}
- name: console
+ name: turbo-lint-unit
runs-on: ubuntu-latest
steps:
- -
- name: Checkout
- uses: actions/checkout@v4
- -
- uses: actions/setup-node@v4
- with:
- node-version: ${{ inputs.node_version }}
- cache: 'yarn'
- cache-dependency-path: console/yarn.lock
- -
- run: cd console && yarn install
- -
- name: lint
- run: make console_lint
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Run lint and unit tests in dev container
+ uses: devcontainers/ci@v0.3
+ with:
+ push: never
+ configFile: .devcontainer/turbo-lint-unit/devcontainer.json
+ runCmd: echo "Successfully ran lint and unit tests in dev container postStartCommand"
core:
name: core
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request' }}
steps:
- -
- name: Checkout
- uses: actions/checkout@v4
- -
- uses: actions/setup-go@v5
- with:
- go-version-file: 'go.mod'
- -
- uses: actions/cache/restore@v4
- timeout-minutes: 1
- name: restore core
- with:
- path: ${{ inputs.core_cache_path }}
- key: ${{ inputs.core_cache_key }}
- fail-on-cache-miss: true
- -
- uses: golangci/golangci-lint-action@v6
- with:
- version: ${{ inputs.go_lint_version }}
- github-token: ${{ github.token }}
- only-new-issues: true
+ - name: Checkout
+ uses: actions/checkout@v4
+ - uses: actions/setup-go@v5
+ with:
+ go-version-file: "go.mod"
+ - uses: actions/cache/restore@v4
+ timeout-minutes: 1
+ name: restore core
+ with:
+ path: ${{ inputs.core_cache_path }}
+ key: ${{ inputs.core_cache_key }}
+ fail-on-cache-miss: true
+ - uses: golangci/golangci-lint-action@v6
+ with:
+ version: ${{ inputs.go_lint_version }}
+ github-token: ${{ github.token }}
+ only-new-issues: true
diff --git a/.github/workflows/login-container.yml b/.github/workflows/login-container.yml
index 5cc841bff4..5137213cc4 100644
--- a/.github/workflows/login-container.yml
+++ b/.github/workflows/login-container.yml
@@ -14,6 +14,9 @@ on:
login_build_image:
description: 'The full image tag of the standalone login image'
value: '${{ inputs.login_build_image_name }}:${{ github.sha }}'
+ secrets:
+ DEPOT_TOKEN:
+ required: true
permissions:
packages: write
@@ -27,15 +30,12 @@ env:
jobs:
login-container:
name: Build Login Container
- runs-on: depot-ubuntu-22.04-8
+ runs-on: ubuntu-latest
permissions:
- id-token: write
packages: write
steps:
- uses: actions/checkout@v4
- uses: depot/setup-action@v1
- with:
- oidc: true
- name: Login meta
id: login-meta
uses: docker/metadata-action@v5
@@ -55,16 +55,16 @@ jobs:
- name: Bake login multi-arch
uses: depot/bake-action@v1
env:
+ DEPOT_TOKEN: ${{ secrets.DEPOT_TOKEN }}
NODE_VERSION: ${{ inputs.node_version }}
with:
push: true
provenance: true
sbom: true
targets: login-standalone
- set: login-*.context=./login/
project: w47wkxzdtw
files: |
- ./login/docker-bake.hcl
- ./login/docker-bake-release.hcl
+ ./apps/login/docker-bake.hcl
+ ./apps/login/docker-bake-release.hcl
./docker-bake.hcl
cwd://${{ steps.login-meta.outputs.bake-file }}
diff --git a/.github/workflows/login-quality.yml b/.github/workflows/login-quality.yml
deleted file mode 100644
index 0b4fea73f4..0000000000
--- a/.github/workflows/login-quality.yml
+++ /dev/null
@@ -1,59 +0,0 @@
-name: Login Quality
-
-on:
- workflow_call:
- inputs:
- ignore-run-cache:
- description: 'Ignore run caches'
- type: boolean
- required: true
- node_version:
- required: true
- type: string
-jobs:
- quality:
- name: Ensure Quality
- runs-on: depot-ubuntu-22.04-8
- timeout-minutes: 30
- permissions:
- id-token: write
- actions: write
- env:
- CACHE_DIR: /tmp/login-run-caches
- steps:
- - uses: actions/checkout@v4
- - uses: depot/setup-action@v1
- with:
- oidc: true
- - 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-
- - uses: actions/download-artifact@v4
- with:
- path: .artifacts
- name: zitadel-linux-amd64
- - name: Unpack executable
- run: |
- tar -xvf .artifacts/zitadel-linux-amd64.tar.gz
- mv zitadel-linux-amd64/zitadel ./zitadel
- - run: make login_quality
- env:
- # latest if branch is main, otherwise image version which is the pull request number
- LOGIN_BAKE_CLI: depot bake
- DEPOT_PROJECT_ID: w47wkxzdtw
- IGNORE_RUN_CACHE: ${{ github.event.inputs.ignore-run-cache }}
- NODE_VERSION: ${{ inputs.node_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()
diff --git a/.github/workflows/ready_for_review.yml b/.github/workflows/ready_for_review.yml
index 2ead263dc9..db756633f4 100644
--- a/.github/workflows/ready_for_review.yml
+++ b/.github/workflows/ready_for_review.yml
@@ -13,7 +13,7 @@ jobs:
Please make sure you tick the following checkboxes before marking this Pull Request (PR) as ready for review:
- - [ ] I am happy with the code
+ - [ ] I have reviewed my changes and would approve it
- [ ] Documentations and examples are up-to-date
- [ ] Logical behavior changes are tested automatically
- [ ] No debug or dead code
@@ -28,4 +28,4 @@ jobs:
owner: context.repo.owner,
repo: context.repo.repo,
body: content
- })
\ No newline at end of file
+ })
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index e23c8869c5..bfbc3d6934 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -165,7 +165,7 @@ jobs:
run: |
gh workflow -R zitadel/zitadel-charts run bump.yml
- typescript-packages:
+ npm-packages:
runs-on: ubuntu-latest
needs: version
if: ${{ github.ref_name == 'next' }}
@@ -184,7 +184,7 @@ jobs:
- name: Install dependencies
working-directory: login
- run: pnpm install
+ run: pnpm install --frozen-lockfile
- name: Create Release Pull Request
uses: changesets/action@v1
@@ -192,9 +192,10 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
version: ${{ needs.version.outputs.version }}
- cwd: login
+ cwd: packages
+ createGithubReleases: false
- typescript-repo:
+ login-repo:
runs-on: ubuntu-latest
needs: version
if: ${{ github.ref_name == 'next' }}
diff --git a/.gitignore b/.gitignore
index 0aa6cc1976..4c3c877a18 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
# Test binary, build with `go test -c`
*.test
+!/**/.env.test
# Coverage
coverage.txt
@@ -68,6 +69,7 @@ docs/docs/apis/proto
/internal/api/ui/login/static/resources/themes/zitadel/css/zitadel.css
/internal/api/ui/login/static/resources/themes/zitadel/css/zitadel.css.map
zitadel-*-*
+!apps/**/zitadel-*-*
# local
build/local/*.env
@@ -84,7 +86,14 @@ go.work.sum
.netlify
load-test/node_modules
-load-test/yarn-error.log
+load-test/pnpm-debug.log
load-test/dist
load-test/output/*
.vercel
+
+# Turbo
+.turbo/
+**/.turbo/
+
+# PNPM
+.pnpm-store
\ No newline at end of file
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000000..7bd51097f9
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1,2 @@
+auto-install-peers = true
+ignore-scripts = "postman-code-generators"
diff --git a/login/.nvmrc b/.nvmrc
similarity index 100%
rename from login/.nvmrc
rename to .nvmrc
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ce8b9aff89..4c1ae53072 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,4 +1,5 @@
-# Contributing to ZITADEL
+# Contributing to Zitadel
+
## Introduction
@@ -12,24 +13,29 @@ If you want to give an answer or be part of discussions please be kind. Treat ot
## What can I contribute?
-For people who are new to ZITADEL: We flag issues which are a good starting point to start contributing. You find them [here](https://github.com/zitadel/zitadel/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
+For people who are new to Zitadel: We flag issues which are a good starting point to start contributing.
+You find them [here](https://github.com/zitadel/zitadel/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
+We add the label "good first issue" for problems we think are a good starting point to contribute to Zitadel.
-Make ZITADEL more popular and give it a ⭐
+- [Issues for first time contributors](https://github.com/zitadel/zitadel/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
+- [All issues](https://github.com/zitadel/zitadel/issues)
-Help shaping the future of ZITADEL:
+Help shaping the future of Zitadel:
- Join our [chat](https://zitadel.com/chat) and discuss with us or others.
- Ask or answer questions in the [issues section](https://github.com/zitadel/zitadel/issues)
- Share your thoughts and ideas in the [discussions section](https://github.com/zitadel/zitadel/discussions)
+Make Zitadel more popular and give it a ⭐
+
+Follow [@zitadel](https://twitter.com/zitadel) on twitter
+
[Contribute](#how-to-contribute)
- [Contribute code](#contribute)
-- If you found a mistake on our [docs page](https://zitadel.com/docs) or something is missing please read [the docs section](#contribute-docs)
+- If you found a mistake on our [docs page](https://zitadel.com/docs) or something is missing please read [the docs section](contribute-docs)
- [Translate](#contribute-internationalization) and improve texts
-Follow [@zitadel](https://twitter.com/zitadel) on twitter
-
## How to contribute
We strongly recommend to [talk to us](https://zitadel.com/contact) before you start contributing to streamline our and your work.
@@ -40,6 +46,21 @@ If you are unfamiliar with git have a look at Github's documentation on [creatin
Please draft the pull request as soon as possible.
Go through the following checklist before you submit the final pull request:
+### Components
+
+The code consists of the following parts:
+
+| name | description | language | where to find | Development Guide |
+| --------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------- |
+| backend | Service that serves the grpc(-web) and RESTful API | [go](https://go.dev) | [API implementation](./internal/api/grpc) | [Contribute to Backend](contribute-backend) |
+| API definitions | Specifications of the API | [Protobuf](https://developers.google.com/protocol-buffers) | [./proto/zitadel](./proto/zitadel) | [Contribute to Backend](contribute-backend) |
+| console | Frontend the user interacts with after log in | [Angular](https://angular.io), [Typescript](https://www.typescriptlang.org) | [./console](./console) | [Contribute to Frontend](contribute-frontend) |
+| login | Modern authentication UI built with Next.js | [Next.js](https://nextjs.org), [React](https://reactjs.org), [TypeScript](https://www.typescriptlang.org) | [./login](./login) | [Contribute to Frontend](contribute-frontend) |
+| docs | Project documentation made with docusaurus | [Docusaurus](https://docusaurus.io/) | [./docs](./docs) | [Contribute to Frontend](contribute-frontend) |
+| translations | Internationalization files for default languages | YAML | [./console](./console) and [./internal](./internal) | [Contribute Translations](contribute-translations) |
+
+Please follow the guides to validate and test the code before you contribute.
+
### Submit a pull request (PR)
1. [Fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) the [zitadel/zitadel](https://github.com/zitadel/zitadel) repository on GitHub
@@ -104,25 +125,6 @@ Please make sure you cover your changes with tests before marking a Pull Request
- [ ] Integration tests ensure that certain commands emit expected events that trigger notifications.
- [ ] Integration tests ensure that certain events trigger expected notifications.
-## Contribute
-
-The code consists of the following parts:
-
-| name | description | language | where to find |
-| --------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------- | -------------------------------------------------- |
-| backend | Service that serves the grpc(-web) and RESTful API | [go](https://go.dev) | [API implementation](./internal/api/grpc) |
-| console | Frontend the user interacts with after log in | [Angular](https://angular.io), [Typescript](https://www.typescriptlang.org) | [./console](./console) |
-| login | Server side rendered frontend the user interacts with during login | [go](https://go.dev), [go templates](https://pkg.go.dev/html/template) | [./internal/api/ui/login](./internal/api/ui/login) |
-| API definitions | Specifications of the API | [Protobuf](https://developers.google.com/protocol-buffers) | [./proto/zitadel](./proto/zitadel) |
-| docs | Project documentation made with docusaurus | [Docusaurus](https://docusaurus.io/) | [./docs](./docs) |
-
-Please validate and test the code before you contribute.
-
-We add the label "good first issue" for problems we think are a good starting point to contribute to ZITADEL.
-
-- [Issues for first time contributors](https://github.com/zitadel/zitadel/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22)
-- [All issues](https://github.com/zitadel/zitadel/issues)
-
### General Guidelines
#### Gender Neutrality and Inclusive Language
@@ -143,34 +145,62 @@ Choose alternative words depending on the context.
### API
-ZITADEL follows an API first approach. This means all features can not only be accessed via the UI but also via the API.
+Zitadel follows an API first approach. This means all features can not only be accessed via the UI but also via the API.
The API is designed to be used by different clients, such as web applications, mobile applications, and other services.
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.
-### Developing ZITADEL with Dev Containers
-Follow the instructions provided by your code editor/IDE to initiate the development 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)
+#### >Developing Zitadel with Dev Containers
-When you are connected to the container run the following commands to start ZITADEL.
+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:
+Zitadel serves traffic as soon as you can see the following log line:
`INFO[0001] server is listening on [::]:8080`
-### Backend/login
+## Contribute Backend Code
-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.
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://localhost:8080 and by verifying the database.
Once you are happy with your changes, you run end-to-end tests and tear everything down.
-ZITADEL uses [golangci-lint](https://golangci-lint.run) for code quality checks. Please use [this configuration](.golangci.yaml) when running `golangci-lint`. We recommend to set golangci-lint as linter in your IDE.
+Zitadel uses [golangci-lint](https://golangci-lint.run) for code quality checks. Please use [this configuration](.golangci.yaml) when running `golangci-lint`. We recommend to set golangci-lint as linter in your IDE.
The commands in this section are tested against the following software versions:
@@ -199,10 +229,10 @@ make compile
> Build the binary: `make compile`
You can now run and debug the binary in .artifacts/zitadel/zitadel using your favourite IDE, for example GoLand.
-You can test if ZITADEL does what you expect by using the UI at http://localhost:8080/ui/console.
+You can test if Zitadel does what you expect by using the UI at http://localhost:8080/ui/console.
Also, you can verify the data by running `psql "host=localhost dbname=zitadel sslmode=disable"` and running SQL queries.
-#### Run Local Unit Tests
+### Run Local Unit Tests
To test the code without dependencies, run the unit tests:
@@ -210,11 +240,11 @@ To test the code without dependencies, run the unit tests:
make core_unit_test
```
-#### Run Local Integration Tests
+### Run Local Integration Tests
-Integration tests are run as gRPC clients against a running ZITADEL server binary.
+Integration tests are run as gRPC clients against a running Zitadel server binary.
The server binary is typically [build with coverage enabled](https://go.dev/doc/build-cover).
-It is also possible to run a ZITADEL sever in a debugger and run the integrations tests like that. In order to run the server, a database is required.
+It is also possible to run a Zitadel sever in a debugger and run the integrations tests like that. In order to run the server, a database is required.
In order to prepare the local system, the following will bring up the database, builds a coverage binary, initializes the database and starts the sever.
@@ -237,7 +267,7 @@ To run all available integration tests:
make core_integration_test_packages
```
-When you change any ZITADEL server code, be sure to rebuild and restart the server before the next test run.
+When you change any Zitadel server code, be sure to rebuild and restart the server before the next test run.
```bash
make core_integration_server_stop core_integration_server_start
@@ -251,69 +281,83 @@ make core_integration_server_stop core_integration_db_down
The test binary has the race detector enabled. `core_core_integration_server_stop` checks for any race logs reported by Go and will print them along a `66` exit code when found. Note that the actual race condition may have happened anywhere during the server lifetime, including start, stop or serving gRPC requests during tests.
-#### Run Local End-to-End Tests
+### Run Local End-to-End Tests
To test the whole system, including the console UI and the login UI, run the E2E tests.
```bash
# Build the production docker image
-export ZITADEL_IMAGE=zitadel:local GOOS=linux
+export Zitadel_IMAGE=zitadel:local GOOS=linux
make docker_image
# If you made changes in the e2e directory, make sure you reformat the files
-make console_lint
+pnpm turbo lint:fix --filter=e2e
# Run the tests
-docker compose --file ./e2e/config/host.docker.internal/docker-compose.yaml run --service-ports e2e
+docker compose --file ./e2e/docker-compose.yaml run --service-ports e2e
```
When you are happy with your changes, you can cleanup your environment.
```bash
# Stop and remove the docker containers for zitadel and the database
-docker compose --file ./e2e/config/host.docker.internal/docker-compose.yaml down
+docker compose --file ./e2e/docker-compose.yaml down
```
-#### Run Local End-to-End Tests Against Your Dev Server Console
+### Run Local End-to-End Tests Against Your Dev Server Console
If you also make [changes to the console](#console), you can run the test suite against your locally built backend code and frontend server.
-But you will have to install the relevant node dependencies.
```bash
-# Install dependencies
-(cd ./e2e && npm install)
+# Install dependencies (from repository root)
+pnpm install
# Run the tests interactively
-(cd ./e2e && npm run open:golangangular)
+pnpm run open:golangangular
# Run the tests non-interactively
-(cd ./e2e && npm run e2e:golangangular)
+pnpm run e2e:golangangular
```
When you are happy with your changes, you can cleanup your environment.
```bash
# Stop and remove the docker containers for zitadel and the database
-docker compose --file ./e2e/config/host.docker.internal/docker-compose.yaml down
+docker compose --file ./e2e/docker-compose.yaml down
```
-### Console
+## Contribute Frontend Code
-By executing the commands from this section, you run everything you need to develop the console locally.
-Using [Docker Compose](https://docs.docker.com/compose/), you run [PostgreSQL](https://www.postgresql.org/download/) and the [latest release of ZITADEL](https://github.com/zitadel/zitadel/releases/latest) on your local machine.
-You use the ZITADEL container as backend for your console.
-The console is run in your [Node](https://nodejs.org/en/about/) environment using [a local development server for Angular](https://angular.io/cli/serve#ng-serve), so you have fast feedback about your changes.
+This repository uses **pnpm** as package manager and **Turbo** for build orchestration.
+All frontend packages are managed as a monorepo with shared dependencies and optimized builds:
-We use angular-eslint/Prettier for linting/formatting, so please run `yarn lint:fix` before committing. (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)
+- [apps/login](contribute-login) (depends on packages/zitadel-client and packages/zitadel-proto)
+- apps/login/integration
+- apps/login/acceptance
+- [console](contribute-console) (depends on packages/zitadel-client)
+- packages/zitadel-client
+- packages/zitadel-proto
+- [docs](contribute-docs)
-Once you are happy with your changes, you run end-to-end tests and tear everything down.
+### Frontend Development Requirements
+
+The frontend components are run in a [Node](https://nodejs.org/en/about/) environment and are managed using the pnpm package manager and the Turborepo orchestrator.
+
+> [!INFO]
+> Some [dev containers are available](dev-containers) for remote development with docker and pipeline debugging in isolated environments.
+> If you don't want to use one of the dev containers, you can develop the frontend components directly on your local machine.
+> To do so, proceed with installing the necessary dependencies.
+
+We use **pnpm** as package manager and **Turbo** for build orchestration. Use angular-eslint/Prettier for linting/formatting.
+VSCode users, check out [this ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) and [this Prettier extension](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) to fix lint and formatting issues during development.
The commands in this section are tested against the following software versions:
- [Docker version 20.10.17](https://docs.docker.com/engine/install/)
-- [Node version v16.17.0](https://nodejs.org/en/download/)
-- [npm version 8.18.0](https://docs.npmjs.com/try-the-latest-stable-version-of-npm)
-- [Cypress runtime dependencies](https://docs.cypress.io/guides/continuous-integration/introduction#Dependencies)
+- [Node version v20.x](https://nodejs.org/en/download/)
+- [pnpm version 9.x](https://pnpm.io/installation)
+
+To run tests with Cypress, ensure you have installed the required [Cypress runtime dependencies](https://docs.cypress.io/guides/continuous-integration/introduction#Dependencies)
Note for WSL2 on Windows 10
@@ -325,97 +369,165 @@ The commands in this section are tested against the following software versions:
4. When starting XLaunch, make sure to disable access control