hot swappable dev services

This commit is contained in:
Elio Bischof
2025-07-22 14:13:44 +02:00
parent 9c2f9707b8
commit 41ab4c0c57
11 changed files with 97 additions and 70 deletions

View File

@@ -1,11 +0,0 @@
FROM mcr.microsoft.com/devcontainers/base:ubuntu AS dev
RUN apt-get update
RUN apt-get --no-install-recommends install -y \
libgtk2.0-0t64 libgtk-3-0t64 libgbm-dev libnotify-dev libnss3 libxss1 libasound2t64 libxtst6 xauth xvfb && \
# clean up
rm -rf /var/lib/apt/lists/* && \
apt-get clean
RUN pnpm install --recursive --frozen-lockfile .

View File

@@ -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

View File

@@ -8,11 +8,8 @@
"ghcr.io/devcontainers/features/go:1": { "ghcr.io/devcontainers/features/go:1": {
"version": "1.24" "version": "1.24"
}, },
"ghcr.io/devcontainers/features/node:1": {
"version": "lts/iron"
},
"ghcr.io/guiyomh/features/golangci-lint:0": {}, "ghcr.io/guiyomh/features/golangci-lint:0": {},
"ghcr.io/jungaretti/features/make:1": {}, "ghcr.io/jungaretti/features/make:1": {}
}, },
"forwardPorts": [ "forwardPorts": [
3000, 3000,
@@ -20,7 +17,8 @@
4200, 4200,
8080 8080
], ],
"onCreateCommand": "npm install -g sass@1.64.1", "remoteUser": "node",
"onCreateCommand": "pnpm install -g sass@1.64.1 && pnpm install --frozen-lockfile --recursive",
"customizations": { "customizations": {
"jetbrains": { "jetbrains": {
"settings": { "settings": {

View File

@@ -1,10 +1,12 @@
services: services:
devcontainer: devcontainer:
container_name: devcontainer
user: node
build: build:
context: . context: .
volumes: volumes:
- ..:/workspaces:cached - ../../:/workspaces:cached
- /tmp/.X11-unix:/tmp/.X11-unix:cached - /tmp/.X11-unix:/tmp/.X11-unix:cached
- ~/.cache:/home/vscode/.cache:delegated - ~/.cache:/home/vscode/.cache:delegated
command: sleep infinity command: sleep infinity
@@ -34,7 +36,7 @@ services:
mock-zitadel: mock-zitadel:
container_name: mock-zitadel container_name: mock-zitadel
build: build:
context: ../apps/login/packages/integration/core-mock context: ../../apps/login/packages/integration/core-mock
ports: ports:
- 22220:22220 - 22220:22220
- 22222:22222 - 22222:22222
@@ -42,10 +44,7 @@ services:
login-integration: login-integration:
container_name: login-integration container_name: login-integration
image: "${LOGIN_TAG:-ghcr.io/zitadel/zitadel-login:v4.0.0-rc.2}" image: "${LOGIN_TAG:-ghcr.io/zitadel/zitadel-login:v4.0.0-rc.2}"
env_file: env_file: ../../apps/login/apps/login/.env.test
- fileName: ../apps/login/apps/login/.env.test
volumes:
- ../apps/login/apps/login/.env.test:/env-files/.env:cached
network_mode: service:devcontainer network_mode: service:devcontainer
environment: environment:
PORT: 3001 PORT: 3001
@@ -58,8 +57,8 @@ services:
container_name: zitadel container_name: zitadel
command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --config /zitadel.yaml --steps /zitadel.yaml' command: 'start-from-init --masterkey "MasterkeyNeedsToHave32Characters" --config /zitadel.yaml --steps /zitadel.yaml'
volumes: volumes:
- ../apps/login/packages/acceptance/pat:/pat:delegated - ../../apps/login/packages/acceptance/pat:/pat:delegated
- ../apps/login/packages/acceptance/zitadel.yaml:/zitadel.yaml:cached - ../../apps/login/packages/acceptance/zitadel.yaml:/zitadel.yaml:cached
network_mode: service:devcontainer network_mode: service:devcontainer
healthcheck: healthcheck:
test: test:
@@ -76,7 +75,7 @@ services:
container_name: configure-login container_name: configure-login
restart: no restart: no
build: build:
context: ../apps/login/packages/acceptance/setup context: ../../apps/login/packages/acceptance/setup
dockerfile: ../go-command.Dockerfile dockerfile: ../go-command.Dockerfile
entrypoint: "./setup.sh" entrypoint: "./setup.sh"
network_mode: service:devcontainer network_mode: service:devcontainer
@@ -91,18 +90,18 @@ services:
ZITADEL_API_DOMAIN: localhost ZITADEL_API_DOMAIN: localhost
ZITADEL_ADMIN_USER: zitadel-admin@zitadel.localhost ZITADEL_ADMIN_USER: zitadel-admin@zitadel.localhost
volumes: volumes:
- ../apps/login/packages/acceptance/pat:/pat:cached # Read the PAT file from zitadels setup - ../../apps/login/packages/acceptance/pat:/pat:cached # Read the PAT file from zitadels setup
- ../apps/login/apps/login:/login-env:delegated # Write the environment variables file for the login - ../../apps/login/apps/login:/login-env:delegated # Write the environment variables file for the login
depends_on: depends_on:
zitadel: zitadel:
condition: "service_healthy" condition: "service_healthy"
login: login-acceptance:
container_name: login container_name: login
image: "${LOGIN_TAG:-ghcr.io/zitadel/zitadel-login:v4.0.0-rc.2}" image: "${LOGIN_TAG:-ghcr.io/zitadel/zitadel-login:v4.0.0-rc.2}"
network_mode: service:devcontainer network_mode: service:devcontainer
volumes: volumes:
- ../apps/login/apps/login/.env.test.local:/env-files/.env:cached - ../../apps/login/apps/login/.env.test.local:/env-files/.env:cached
depends_on: depends_on:
configure-login: configure-login:
condition: service_completed_successfully condition: service_completed_successfully
@@ -110,7 +109,7 @@ services:
mock-notifications: mock-notifications:
container_name: mock-notifications container_name: mock-notifications
build: build:
context: ../apps/login/packages/acceptance/sink context: ../../apps/login/packages/acceptance/sink
dockerfile: ../go-command.Dockerfile dockerfile: ../go-command.Dockerfile
args: args:
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine} - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
@@ -134,7 +133,7 @@ services:
mock-oidcrp: mock-oidcrp:
container_name: mock-oidcrp container_name: mock-oidcrp
build: build:
context: ../apps/login/packages/acceptance/oidcrp context: ../../apps/login/packages/acceptance/oidcrp
dockerfile: ../go-command.Dockerfile dockerfile: ../go-command.Dockerfile
args: args:
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine} - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
@@ -149,7 +148,7 @@ services:
PORT: '8000' PORT: '8000'
SCOPES: 'openid profile email' SCOPES: 'openid profile email'
volumes: volumes:
- ../apps/login/packages/acceptance/pat:/pat:cached - ../../apps/login/packages/acceptance/pat:/pat:cached
depends_on: depends_on:
configure-login: configure-login:
condition: "service_completed_successfully" condition: "service_completed_successfully"
@@ -157,7 +156,7 @@ services:
# mock-oidcop: # mock-oidcop:
# container_name: mock-oidcop # container_name: mock-oidcop
# build: # build:
# context: ../apps/login/packages/acceptance/idp/oidc # context: ../../apps/login/packages/acceptance/idp/oidc
# dockerfile: ../../go-command.Dockerfile # dockerfile: ../../go-command.Dockerfile
# args: # args:
# - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine} # - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
@@ -178,7 +177,7 @@ services:
mock-samlsp: mock-samlsp:
container_name: mock-samlsp container_name: mock-samlsp
build: build:
context: ../apps/login/packages/acceptance/samlsp context: ../../apps/login/packages/acceptance/samlsp
dockerfile: ../go-command.Dockerfile dockerfile: ../go-command.Dockerfile
args: args:
- LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine} - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}
@@ -200,7 +199,7 @@ services:
# mock-samlidp: # mock-samlidp:
# container_name: mock-samlidp # container_name: mock-samlidp
# build: # build:
# context: ../apps/login/packages/acceptance/idp/saml # context: ../../apps/login/packages/acceptance/idp/saml
# dockerfile: ../../go-command.Dockerfile # dockerfile: ../../go-command.Dockerfile
# args: # args:
# - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine} # - LOGIN_TEST_ACCEPTANCE_GOLANG_TAG=${LOGIN_TEST_ACCEPTANCE_GOLANG_TAG:-golang:1.24-alpine}

View File

@@ -0,0 +1,22 @@
{
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
"name": "debug-login-integration",
"dockerComposeFile": [
"../base/docker-compose.yml",
"docker-compose.yml"
],
"service": "debug-login-integration",
"runServices": ["debug-login-integration"],
"workspaceFolder": "/workspaces",
"forwardPorts": [3001],
"remoteUser": "node",
"onCreateCommand": "pnpm install --frozen-lockfile --recursive",
"postAttachCommand": "pnpm turbo daemon clean && pnpm turbo @zitadel/login#dev",
"customizations": {
"jetbrains": {
"settings": {
"com.intellij:app:HttpConfigurable.use_proxy_pac": true
}
}
}
}

View File

@@ -0,0 +1,12 @@
services:
debug-login-integration:
extends:
file: ../base/docker-compose.yml
service: devcontainer
container_name: debug-login-integration
environment:
NODE_ENV: 'test'
PORT: 3001
depends_on:
mock-zitadel:
condition: service_started

View File

@@ -1,18 +1,17 @@
{ {
"$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json", "$schema": "https://raw.githubusercontent.com/devcontainers/spec/refs/heads/main/schemas/devContainer.schema.json",
"name": "login", "name": "debug-turbo-lint-unit",
"dockerComposeFile": [ "dockerComposeFile": [
"../docker-compose.yml", "../base/docker-compose.yml",
"docker-compose.yml" "docker-compose.yml"
], ],
"service": "devcontainer", "service": "debug-turbo-lint-unit",
"runServices": ["debug-turbo-lint-unit"],
"workspaceFolder": "/workspaces", "workspaceFolder": "/workspaces",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "lts/iron"
}
},
"forwardPorts": [3001], "forwardPorts": [3001],
"remoteUser": "node",
"onCreateCommand": "pnpm install --frozen-lockfile --recursive",
"postAttachCommand": "pnpm turbo daemon clean && pnpm turbo watch lint test:unit",
"customizations": { "customizations": {
"jetbrains": { "jetbrains": {
"settings": { "settings": {

View File

@@ -0,0 +1,6 @@
services:
debug-turbo-lint-unit:
extends:
file: ../base/docker-compose.yml
service: devcontainer
container_name: debug-turbo-lint-unit

View File

@@ -1,14 +0,0 @@
services:
login-integration:
extends:
file: ../docker-compose.yml
service: devcontainer
container_name: login-integration
command: pnpm turbo @zitadel/login#dev
network_mode: service:devcontainer
environment:
NODE_ENV: 'test'
PORT: 3001
depends_on:
mock-zitadel:
condition: service_started

View File

@@ -5,10 +5,8 @@
"scripts": { "scripts": {
"changeset": "changeset", "changeset": "changeset",
"devcontainer": "devcontainer", "devcontainer": "devcontainer",
"test:integration": "cd login/integration && pnpm test:integration", "test:integration": "cd apps/login/packages/integration && pnpm test:integration",
"test:integration:setup": "cd login/integration && NODE_ENV=test pnpm exec turbo run test:integration:setup", "test:acceptance": "cd apps/login/packages/acceptance && pnpm test:acceptance"
"test:acceptance": "cd login/acceptance && pnpm test:acceptance",
"test:acceptance:setup": "cd login/apps/login-test-acceptance && pnpm test:acceptance:setup"
}, },
"pnpm": { "pnpm": {
"overrides": { "overrides": {
@@ -19,7 +17,7 @@
}, },
"devDependencies": { "devDependencies": {
"@changesets/cli": "^2.29.5", "@changesets/cli": "^2.29.5",
"devcontainer": "^0.3.0", "@devcontainers/cli": "^0.80.0",
"turbo": "2.5.5" "turbo": "2.5.5"
} }
} }

18
pnpm-lock.yaml generated
View File

@@ -16,9 +16,9 @@ importers:
'@changesets/cli': '@changesets/cli':
specifier: ^2.29.5 specifier: ^2.29.5
version: 2.29.5 version: 2.29.5
devcontainer: '@devcontainers/cli':
specifier: ^0.3.0 specifier: ^0.80.0
version: 0.3.0 version: 0.80.0
turbo: turbo:
specifier: 2.5.5 specifier: 2.5.5
version: 2.5.5 version: 2.5.5
@@ -2166,6 +2166,11 @@ packages:
'@cypress/xvfb@1.2.4': '@cypress/xvfb@1.2.4':
resolution: {integrity: sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==} resolution: {integrity: sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==}
'@devcontainers/cli@0.80.0':
resolution: {integrity: sha512-w2EaxgjyeVGyzfA/KUEZBhyXqu/5PyWNXcnrXsZOBrt3aN2zyGiHrXoG54TF6K0b5DSCF01Rt5fnIyrCeFzFKw==}
engines: {node: ^16.13.0 || >=18.0.0}
hasBin: true
'@discoveryjs/json-ext@0.5.7': '@discoveryjs/json-ext@0.5.7':
resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==}
engines: {node: '>=10.0.0'} engines: {node: '>=10.0.0'}
@@ -7363,9 +7368,6 @@ packages:
engines: {node: '>= 4.0.0'} engines: {node: '>= 4.0.0'}
hasBin: true hasBin: true
devcontainer@0.3.0:
resolution: {integrity: sha512-RAZPW5YLy7bgX3rYRjAzxedQPccJPgRPgfXOUGC3uIJSmcw5x4GEigNPswk/IH4N3f2BIeCAlNKeG6l1xYbXzg==}
devlop@1.1.0: devlop@1.1.0:
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
@@ -16861,6 +16863,8 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@devcontainers/cli@0.80.0': {}
'@discoveryjs/json-ext@0.5.7': {} '@discoveryjs/json-ext@0.5.7': {}
'@docsearch/css@3.9.0': {} '@docsearch/css@3.9.0': {}
@@ -23381,8 +23385,6 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
devcontainer@0.3.0: {}
devlop@1.1.0: devlop@1.1.0:
dependencies: dependencies:
dequal: 2.0.3 dequal: 2.0.3