cache, integration

This commit is contained in:
Elio Bischof
2025-06-07 17:00:32 +02:00
parent d5ffa18dfe
commit 05d28c0d82
23 changed files with 297 additions and 249 deletions

View File

@@ -21,3 +21,9 @@ public/dist
/playwright/.cache/
/out
/docker
Makefile
docker-bake.hcl
*.md
.gitignore
scripts

146
Makefile
View File

@@ -1,73 +1,102 @@
LOGIN_BASE_TAG ?= "zitadel-login-base:local"
LOGIN_DEPENDENCIES_TAG ?= "zitadel-login-dev-dependencies:local"
LOGIN_IMAGE_TAG ?= "zitadel-login:local"
CORE_MOCK_TAG ?= "zitadel-core-mock:local"
LOGIN_INTEGRATION_TESTSUITE_TAG ?= "zitadel-login-integration-testsuite:local"
CORE_MOCK_CONTAINER_NAME ?= zitadel-mock-grpc-server
LOGIN_CONTAINER_NAME ?= zitadel-login
XDG_CACHE_HOME ?= $(HOME)/.cache
CACHE_DIR ?= $(XDG_CACHE_HOME)/zitadel-make
export CACHE_DIR ?= $(XDG_CACHE_HOME)/zitadel-make
.PHONY: help
help:
@echo "Makefile for the login service"
@echo "Available targets:"
@echo " help - Show this help message"
@echo " lint - Run linting and formatting checks"
@echo " lint-force - Force run linting and formatting checks"
@echo " unit - Run unit tests"
@echo " unit-force - Force run unit tests"
@echo " integration - Run integration tests"
@echo " integration-force - Force run integration tests"
@echo " login-image - Build the login image"
@echo " quality - Run all quality checks (lint, unit, integration)"
@echo " ci - Run all CI tasks. Run it with the -j flag to parallelize. make -j ci"
@echo " help - Show this help message"
@echo " login - Start the login service"
@echo " login-lint - Run linting and formatting checks"
@echo " login-lint-force - Force run linting and formatting checks"
@echo " login-unit - Run unit tests"
@echo " login-unit-force - Force run unit tests"
@echo " login-integration - Run integration tests"
@echo " login-integration-force - Force run integration tests"
@echo " login-image - Build the login image"
@echo " login-quality - Run all quality checks (login-lint, unit, integration)"
@echo " login-ci - Run all CI tasks. Run it with the -j flag to parallelize. make -j ci"
@echo " show-cache - Show cached digests and exit codes"
@echo " clean-cache - Remove the cache directory"
@echo " core-mock - Start the core mock server"
@echo " core-mock-stop - Stop the core mock server"
.PHONY: lint-force
lint-force:
docker run --rm $(LOGIN_BASE_TAG) lint
docker run --rm $(LOGIN_BASE_TAG) format --check
.PHONY: lint
lint:
$(call run_or_skip,lint-force,lint,$(LOGIN_BASE_TAG))
.PHONY: login-lint-force
login-lint-force: login-dev-dependencies
docker run --rm $(LOGIN_DEPENDENCIES_TAG) lint
docker run --rm $(LOGIN_DEPENDENCIES_TAG) format --check
unit-run: login-base
docker run --rm $(LOGIN_BASE_TAG) test:unit
.PHONY: login-lint
login-lint:
./scripts/run_or_skip.sh login-lint-force $(LOGIN_DEPENDENCIES_TAG)
.PHONY: unit-force
unit-force:
docker run --rm $(LOGIN_BASE_TAG) test:unit
.PHONY: login-unit-force
login-unit-force: login-dev-dependencies
docker run --rm $(LOGIN_DEPENDENCIES_TAG) test:unit
.PHONY: unit
unit:
$(call run_or_skip,unit-force,unit,$(LOGIN_BASE_TAG))
.PHONY: login-unit
login-unit:
./scripts/run_or_skip.sh login-unit-force $(LOGIN_DEPENDENCIES_TAG)
.PHONY: integration-force
integration-force:
docker run --rm $(CORE_MOCK_TAG) test:integration
.PHONY: login-integration-force
login-integration-force: login core-mock login-integration-testsuite
docker run --rm $(LOGIN_INTEGRATION_TESTSUITE_TAG)
$(MAKE) core-mock-stop
.PHONY: integration
integration:
$(call run_or_skip,integration-force,integration,$(CORE_MOCK_TAG))
.PHONY: login-integration
login-integration:
./scripts/run_or_skip.sh login-integration-force '$(LOGIN_DEPENDENCIES_TAG);$(CORE_MOCK_TAG);$(LOGIN_INTEGRATION_TESTSUITE_TAG)'
.PHONY: login-quality
login-quality: core-mock-build login-quality-after-build
login-quality-after-build: login-lint login-unit login-integration
@:
.PHONY: login-ci
login-ci: core-mock-build login-ci-after-build
login-ci-after-build: login-quality-after-build login-image
@:
login-dev-dependencies:
docker buildx bake login-dev-dependencies --set login-dev-dependencies.tags=$(LOGIN_DEPENDENCIES_TAG);
.PHONY: login-image
login-image:
docker buildx bake login-image
docker buildx bake login-image --set login-image.tags=$(LOGIN_IMAGE_TAG);
.PHONY: quality
quality: lint unit integration
.PHONY: login
login: login-image login-stop
docker run --detach --rm --name $(LOGIN_CONTAINER_NAME) --publish 3000:3000 $(LOGIN_IMAGE_TAG)
.PHONY: ci
ci: core-mock ci-after-build
ci-after-build: quality login-image
@:
login-stop:
docker rm --force $(LOGIN_CONTAINER_NAME) 2>/dev/null || true
login-base:
docker buildx bake login-base --set login-base.tags=$(LOGIN_BASE_TAG);
core-mock-build:
docker buildx bake core-mock --set core-mock.tags=$(CORE_MOCK_TAG);
core-mock:
docker buildx bake core-mock --set login-base.tags=$(CORE_MOCK_TAG);
login-integration-testsuite: login-dev-dependencies
docker buildx bake login-integration-testsuite --set login-integration-testsuite.tags=$(LOGIN_INTEGRATION_TESTSUITE_TAG)
.PHONY: core-mock
core-mock: core-mock-build core-mock-stop
docker run --detach --rm --name $(CORE_MOCK_CONTAINER_NAME) --publish 22221:22221 --publish 22222:22222 $(CORE_MOCK_TAG)
.PHONY: core-mock-stop
core-mock-stop:
docker rm --force $(CORE_MOCK_CONTAINER_NAME) 2>/dev/null || true
.PHONY: clean-cache
clean-cache:
@echo "Removing cache directory: $(CACHE_DIR)"
@rm -rf "$(CACHE_DIR)"
rm -rf "$(CACHE_DIR)"
.PHONY: show-cache
show-cache:
@@ -75,30 +104,3 @@ show-cache:
@find "$(CACHE_DIR)" -type f 2>/dev/null | while read file; do \
echo "$$file: $$(cat $$file)"; \
done
# run_or_skip: runs a task only if the Docker image has changed and caches the result
# $(1): Taskname (e.g. "lint-force")
# $(2): Cache-ID (e.g. "lint")
# $(3): Docker-Image (e.g. "zitadel-login-base:local")
define run_or_skip
@digest_file="$(CACHE_DIR)/$(2).$(3)"; \
mkdir -p $(CACHE_DIR); \
if [ -f "$$digest_file" ]; then \
digest_before=$$(cut -d',' -f1 "$$digest_file"); \
status_before=$$(cut -d',' -f2 "$$digest_file"); \
else \
digest_before=""; \
status_before=1; \
fi; \
current_digest=$$(docker image inspect $(3) --format='{{.Id}}'); \
if [ "$$digest_before" = "$$current_digest" ]; then \
echo "Skipping $(1) image unchanged, returning cached status $$status_before"; \
exit $$status_before; \
else \
echo "Running $(1)..."; \
$(MAKE) $(1); \
status=$$?; \
echo "$$current_digest,$$status" > "$$digest_file"; \
exit $$status; \
fi
endef

View File

@@ -0,0 +1,6 @@
FROM cypress/factory AS login-integration-testsuite
WORKDIR /opt/app
COPY --from=login-dev-dependencies /app/apps/login/node_modules .
RUN npx cypress install
COPY . .
CMD ["npx", "cypress", "run"]

View File

@@ -4,7 +4,7 @@ export default defineConfig({
reporter: "list",
e2e: {
baseUrl: "http://localhost:3000",
specPattern: "cypress/integration/**/*.cy.{js,jsx,ts,tsx}",
specPattern: "integration/**/*.cy.{js,jsx,ts,tsx}",
setupNodeEvents(on, config) {
// implement node event listeners here
},

View File

@@ -0,0 +1,22 @@
{
"name": "login-integration-testsuite",
"private": true,
"scripts": {
"test:integration": "pnpm exec concurrently --names 'mock,test' --success command-test --kill-others 'pnpm:mock' 'env-cmd -f ./.env.integration start-server-and-test start http://localhost:3000 \"test:integration:run\"'",
"test:integration:watch:run": "pnpm exec concurrently --names 'mock,test' --kill-others 'pnpm:mock' 'env-cmd -f ./.env.integration start-server-and-test dev http://localhost:3000 \"pnpm nodemon -e js,jsx,ts,tsx,css,scss --ignore \\\"__test__/**\\\" --exec \\\"pnpm test:integration:run\\\"\"'",
"test:integration:watch:open": "pnpm exec concurrently --names 'mock,test' --kill-others 'pnpm:mock' 'env-cmd -f ./.env.integration start-server-and-test dev http://localhost:3000 \"pnpm nodemon -e js,jsx,ts,tsx,css,scss --ignore \\\"__test__/**\\\" --exec \\\"pnpm test:integration:open\\\"\"'",
"test:integration:run": "pnpm exec cypress run --config-file ./cypress/cypress.config.ts --quiet",
"test:integration:open": "pnpm exec cypress open --config-file ./cypress/cypress.config.ts",
"mock": "pnpm mock:stop && docker run --rm --name zitadel-mock-grpc-server --publish 22220:22220 --publish 22222:22222 ${CORE_MOCK_TAG:-zitadel-core-mock:local}",
"mock:stop": "docker rm --force zitadel-mock-grpc-server 2>/dev/null || true"
},
"devDependencies": {
"@types/node": "^22.14.1",
"concurrently": "^9.1.2",
"cypress": "^14.3.2",
"env-cmd": "^10.0.0",
"nodemon": "^3.1.9",
"start-server-and-test": "^2.0.11",
"typescript": "^5.8.3"
}
}

View File

@@ -0,0 +1,14 @@
{
"extends": ["///"],
"tasks": {
"test": {
"dependsOn": ["@zitadel/client#build"]
},
"test:integration": {
"dependsOn": ["@zitadel/client#build"]
},
"test:integration:run": {
"dependsOn": ["@zitadel/client#build"]
}
}
}

View File

@@ -1,13 +1,9 @@
FROM scratch AS config
COPY mocked-services.cfg .
COPY initial-stubs initial-stubs
COPY --from=protos /proto .
FROM golang:1.20.5-alpine3.18
RUN go install github.com/eliobischof/grpc-mock/cmd/grpc-mock@01b09f60db1b501178af59bed03b2c22661df48c
COPY --from=config / .
COPY mocked-services.cfg .
COPY initial-stubs initial-stubs
COPY --from=protos . .
ENTRYPOINT [ "sh", "-c", "grpc-mock -v 1 -proto $(tr '\n' ',' < ./mocked-services.cfg) -stub-dir ./initial-stubs" ]
ENTRYPOINT [ "sh", "-c", "grpc-mock -v 1 -protos $(tr '\n' ',' < ./mocked-services.cfg) -stub-dir ./initial-stubs" ]

View File

@@ -5,29 +5,19 @@
"scripts": {
"dev": "pnpm exec next dev --turbopack",
"test": "pnpm exec concurrently --timings --kill-others-on-fail 'npm:test:unit' 'npm:test:integration'",
"test:watch": "cpnpm exec oncurrently --kill-others 'npm:test:unit:watch' 'npm:test:integration:watch'",
"test:watch": "pnpm exec oncurrently --kill-others 'npm:test:unit:watch' 'npm:test:integration:watch'",
"test:unit": "pnpm exec vitest",
"test:unit:watch": "pnpm test:unit --watch",
"test:integration": "pnpm mock:build && pnpm exec concurrently --names 'mock,test' --success command-test --kill-others 'pnpm:mock' 'env-cmd -f ./.env.integration start-server-and-test start http://localhost:3000 \"test:integration:run\"'",
"test:integration:watch:run": "pnpm exec concurrently --names 'mock,test' --kill-others 'pnpm:mock' 'env-cmd -f ./.env.integration start-server-and-test dev http://localhost:3000 \"pnpm nodemon -e js,jsx,ts,tsx,css,scss --ignore \\\"__test__/**\\\" --exec \\\"pnpm test:integration:run\\\"\"'",
"test:integration:watch:open": "pnpm exec concurrently --names 'mock,test' --kill-others 'pnpm:mock' 'env-cmd -f ./.env.integration start-server-and-test dev http://localhost:3000 \"pnpm nodemon -e js,jsx,ts,tsx,css,scss --ignore \\\"__test__/**\\\" --exec \\\"pnpm test:integration:open\\\"\"'",
"test:integration:run": "pnpm exec cypress run --config-file ./cypress/cypress.config.ts --quiet",
"test:integration:open": "pnpm exec cypress open --config-file ./cypress/cypress.config.ts",
"mock": "pnpm mock:build && pnpm mock:run",
"mock:run": "pnpm mock:stop && docker run --rm --name zitadel-mock-grpc-server --publish 22220:22220 --publish 22222:22222 zitadel-mock-grpc-server",
"mock:build": "DOCKER_BUILDKIT=1 docker build --tag zitadel-mock-grpc-server ./mock",
"mock:build:nocache": "pnpm mock:build --no-cache",
"mock": "pnpm mock:stop && docker run --rm --name zitadel-mock-grpc-server --publish 22220:22220 --publish 22222:22222 ${CORE_MOCK_TAG:-zitadel-core-mock:local}",
"mock:stop": "docker rm --force zitadel-mock-grpc-server 2>/dev/null || true",
"mock:destroy": "docker rmi --force zitadel-mock-grpc-server 2>/dev/null || true",
"lint": "pnpm exec next lint && pnpm exec prettier --check .",
"lint:fix": "pnpm exec prettier --write .",
"lint-staged": "lint-staged",
"build": "pnpm exec next build",
"build:standalone": "NEXT_OUTPUT_MODE=standalone pnpm build",
"prestart": "pnpm build",
"start": "pnpm exec next start",
"start": "pnpm build && pnpm exec next start",
"start:built": "pnpm exec next start",
"clean": "pnpm mock:destroy && rm -rf .turbo && rm -rf node_modules && rm -rf .next"
"clean": "pnpm mock:stop && rm -rf .turbo && rm -rf node_modules && rm -rf .next"
},
"git": {
"pre-commit": "lint-staged"
@@ -77,18 +67,13 @@
"@zitadel/tsconfig": "workspace:*",
"autoprefixer": "10.4.21",
"concurrently": "^9.1.2",
"cypress": "^14.3.2",
"del-cli": "6.0.0",
"env-cmd": "^10.0.0",
"grpc-tools": "1.13.0",
"jsdom": "^26.1.0",
"lint-staged": "15.5.1",
"make-dir-cli": "4.0.0",
"nodemon": "^3.1.9",
"postcss": "8.5.3",
"prettier-plugin-tailwindcss": "0.6.11",
"sass": "^1.87.0",
"start-server-and-test": "^2.0.11",
"tailwindcss": "3.4.14",
"ts-proto": "^2.7.0",
"typescript": "^5.8.3"

View File

@@ -6,15 +6,11 @@
"dependsOn": ["^build"]
},
"build:standalone": {
"outputs": ["dist/**", ".next/**", "!.next/cache/**"],
"dependsOn": ["^build"]
"outputs": ["dist/**", ".next/**", "!.next/cache/**"]
},
"test": {
"dependsOn": ["@zitadel/client#build"]
},
"test:integration": {
"dependsOn": ["@zitadel/client#build"]
},
"test:unit": {
"dependsOn": ["@zitadel/client#build"]
},

View File

@@ -1,44 +1,65 @@
variable "release_tags" {
default = ["zitadel-login:local"]
}
group "default" {
targets = ["login-generate"]
targets = ["typescript-proto-client"]
}
target "login-base" {
context = "."
dockerfile = "dockerfiles/login-base.Dockerfile"
target "login-platform" {
dockerfile = "dockerfiles/login-platform.Dockerfile"
}
target "download-protos" {
dockerfile = "dockerfiles/download-protos.Dockerfile"
contexts = {
base = "target:login-base"
}
target "login-dev-base" {
dockerfile = "dockerfiles/login-dev-base.Dockerfile"
contexts = {
login-platform = "target:login-platform"
}
}
target "login-dev-dependencies" {
dockerfile = "dockerfiles/login-dev-dependencies.Dockerfile"
contexts = {
login-dev-base = "target:login-dev-base"
}
}
# proto-files is only used to build core-mock against which the integration tests run.
# To build the proto-client, we use buf to generate and download the client code directly.
target "proto-files" {
dockerfile = "dockerfiles/proto-files.Dockerfile"
contexts = {
login-dev-base = "target:login-dev-dependencies"
}
}
target "core-mock" {
dockerfile = "dockerfiles/core-mock.Dockerfile"
context = "apps/login/mock"
dockerfile = "Dockerfile"
contexts = {
protos = "target:download-protos"
protos = "target:proto-files"
}
}
target "login-generate" {
dockerfile = "dockerfiles/login-generate.Dockerfile"
target "login-integration-testsuite" {
context = "apps/login/cypress"
contexts = {
base = "target:login-base"
login-dev-dependencies = "target:login-dev-dependencies"
}
}
target "typescript-proto-client" {
dockerfile = "dockerfiles/typescript-proto-client.Dockerfile"
contexts = {
# We directly generate and download the client server-side with buf, so we don't need the proto files
login-dev-base = "target:login-dev-dependencies"
}
}
# We run integration and acceptance tests against the next standalone server for docker.
target "login-image" {
dockerfile = "dockerfiles/login-image.Dockerfile"
tags = "${release_tags}"
args = {
NODE_ENV = "production"
}
contexts = {
generated = "target:login-generate"
login-platform = "target:login-platform"
login-dev-base = "target:login-dev-dependencies"
}
}

View File

@@ -1,7 +0,0 @@
FROM base
RUN cd packages/zitadel-proto && \
pnpm buf export https://github.com/envoyproxy/protoc-gen-validate.git --path validate --output /proto && \
pnpm buf export https://github.com/grpc-ecosystem/grpc-gateway.git --path protoc-gen-openapiv2 --output /proto && \
pnpm 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 && \
pnpm buf export https://github.com/zitadel/zitadel.git --path ./proto/zitadel --output /proto

View File

@@ -0,0 +1,10 @@
FROM login-platform AS login-dev-base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
RUN apk add --no-cache libc6-compat bash git
WORKDIR /app

View File

@@ -1,13 +1,4 @@
FROM node:20-alpine AS base
ENV PNPM_HOME="/pnpm"
ENV PATH="$PNPM_HOME:$PATH"
RUN corepack enable
RUN apk add --no-cache libc6-compat bash git
WORKDIR /app
FROM login-dev-base AS login-dev-dependencies
COPY \
turbo.json \
@@ -25,10 +16,9 @@ COPY packages/zitadel-proto/package.json ./packages/zitadel-proto/
COPY packages/zitadel-tailwind-config/package.json ./packages/zitadel-tailwind-config/
COPY packages/zitadel-tsconfig/package.json ./packages/zitadel-tsconfig/
COPY apps/login/package.json ./apps/login/
COPY apps/login/cypress/package.json ./apps/login/cypress/
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
pnpm install --frozen-lockfile
COPY . .
ENTRYPOINT ["pnpm"]

View File

@@ -1,3 +0,0 @@
FROM base AS generated
RUN pnpm generate

View File

@@ -1,8 +1,20 @@
FROM generated AS build-for-docker
FROM login-dev-base AS prune-for-docker
RUN NEXT_PUBLIC_BASE_PATH=/ui/v2/login pnpm build:docker
RUN pnpm install turbo --global
FROM node:20-alpine
COPY . .
RUN turbo prune @zitadel/login --docker
FROM login-dev-base AS installer
COPY --from=prune-for-docker /app/out/json/ .
RUN pnpm install --frozen-lockfile
COPY --from=prune-for-docker /app/out/full/ .
RUN NEXT_PUBLIC_BASE_PATH=/ui/v2/login NEXT_OUTPUT_MODE=standalone pnpm exec turbo run build
RUN ls -la /app/apps/login/.next
FROM login-platform AS login-image
WORKDIR /app
@@ -12,9 +24,9 @@ RUN addgroup --system --gid 1001 nodejs && \
# 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 --from=build-for-docker /app/docker/apps/login/.next/standalone ./
COPY --chown=nextjs:nodejs --from=build-for-docker /app/docker/apps/login/.next/static ./apps/login/.next/static
COPY --chown=nextjs:nodejs --from=build-for-docker /app/docker/apps/login/public ./apps/login/public
COPY --chown=nextjs:nodejs --from=installer /app/apps/login/.next/standalone ./
COPY --chown=nextjs:nodejs --from=installer /app/apps/login/.next/static ./apps/login/.next/static
COPY --chown=nextjs:nodejs --from=installer /app/apps/login/public ./apps/login/public
USER nextjs
ENV HOSTNAME="0.0.0.0"

View File

@@ -0,0 +1 @@
FROM node:20-alpine AS login-platform

View File

@@ -0,0 +1,10 @@
FROM bufbuild/buf:1.54.0 AS proto-files
RUN buf export https://github.com/envoyproxy/protoc-gen-validate.git --path validate --output /proto-files && \
buf export https://github.com/grpc-ecosystem/grpc-gateway.git --path protoc-gen-openapiv2 --output /proto-files && \
buf export https://github.com/googleapis/googleapis.git --path google/api/annotations.proto --path google/api/http.proto --path google/api/field_behavior.proto --output /proto-files && \
buf export https://github.com/zitadel/zitadel.git --path ./proto/zitadel --output /proto-files
FROM scratch
COPY --from=proto-files /proto-files /

View File

@@ -0,0 +1,9 @@
FROM login-dev-base AS zitadel-proto
COPY packages/zitadel-proto packages/zitadel-proto
RUN pnpm generate
FROM scratch
COPY --from=zitadel-proto /app/packages/zitadel-proto /

View File

@@ -13,6 +13,7 @@
"start:built": "pnpm exec turbo run start:built",
"test:unit": "pnpm exec turbo run test:unit -- --passWithNoTests",
"test:integration": "pnpm exec turbo run test:integration",
"test:integration:run": "pnpm exec turbo run test:integration:run",
"test:acceptance": "pnpm exec playwright test",
"test:watch": "pnpm exec turbo run test:watch",
"dev": "pnpm exec turbo run dev --no-cache --continue",

123
pnpm-lock.yaml generated
View File

@@ -192,15 +192,6 @@ importers:
concurrently:
specifier: ^9.1.2
version: 9.1.2
cypress:
specifier: ^14.3.2
version: 14.3.2
del-cli:
specifier: 6.0.0
version: 6.0.0
env-cmd:
specifier: ^10.0.0
version: 10.1.0
grpc-tools:
specifier: 1.13.0
version: 1.13.0
@@ -213,9 +204,6 @@ importers:
make-dir-cli:
specifier: 4.0.0
version: 4.0.0
nodemon:
specifier: ^3.1.9
version: 3.1.9
postcss:
specifier: 8.5.3
version: 8.5.3
@@ -225,9 +213,6 @@ importers:
sass:
specifier: ^1.87.0
version: 1.87.0
start-server-and-test:
specifier: ^2.0.11
version: 2.0.11
tailwindcss:
specifier: 3.4.14
version: 3.4.14
@@ -238,6 +223,30 @@ importers:
specifier: ^5.8.3
version: 5.8.3
apps/login/cypress:
devDependencies:
'@types/node':
specifier: ^22.14.1
version: 22.14.1
concurrently:
specifier: ^9.1.2
version: 9.1.2
cypress:
specifier: ^14.3.2
version: 14.3.2
env-cmd:
specifier: ^10.0.0
version: 10.1.0
nodemon:
specifier: ^3.1.9
version: 3.1.9
start-server-and-test:
specifier: ^2.0.11
version: 2.0.11
typescript:
specifier: ^5.8.3
version: 5.8.3
packages/zitadel-client:
dependencies:
'@bufbuild/protobuf':
@@ -1344,10 +1353,6 @@ packages:
'@sideway/pinpoint@2.0.0':
resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==}
'@sindresorhus/merge-streams@2.3.0':
resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==}
engines: {node: '>=18'}
'@swc/counter@0.1.3':
resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==}
@@ -2130,15 +2135,6 @@ packages:
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
engines: {node: '>= 0.4'}
del-cli@6.0.0:
resolution: {integrity: sha512-9nitGV2W6KLFyya4qYt4+9AKQFL+c0Ehj5K7V7IwlxTc6RMCfQUGY9E9pLG6e8TQjtwXpuiWIGGZb3mfVxyZkw==}
engines: {node: '>=18'}
hasBin: true
del@8.0.0:
resolution: {integrity: sha512-R6ep6JJ+eOBZsBr9esiNN1gxFbZE4Q2cULkUSFumGYecAiS6qodDvcPx/sFuWHMNul7DWmrtoEOpYSm7o6tbSA==}
engines: {node: '>=18'}
delayed-stream@1.0.0:
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
engines: {node: '>=0.4.0'}
@@ -2741,10 +2737,6 @@ packages:
resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
engines: {node: '>=10'}
globby@14.0.2:
resolution: {integrity: sha512-s3Fq41ZVh7vbbe2PN3nrW7yC7U7MFVc5c98/iTl9c2GawNMKx/J648KQRW6WKkuU8GIbbh2IXfIRQjOZnXcTnw==}
engines: {node: '>=18'}
globrex@0.1.2:
resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
@@ -2981,18 +2973,10 @@ packages:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
is-path-cwd@3.0.0:
resolution: {integrity: sha512-kyiNFFLU0Ampr6SDZitD/DwUo4Zs1nSdnygUBqsu3LooL00Qvb5j+UnvApUn/TTj1J3OuE6BTdQ5rudKmU2ZaA==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
is-path-inside@3.0.3:
resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
engines: {node: '>=8'}
is-path-inside@4.0.0:
resolution: {integrity: sha512-lJJV/5dYS+RcL8uQdBDW9c9uWFLLBNRyFhnAKXw5tVqLlKZ4RMGZKv+YQ/IA3OhD+RpbJa1LLFM1FQPGyIXvOA==}
engines: {node: '>=12'}
is-potential-custom-element-name@1.0.1:
resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
@@ -3578,10 +3562,6 @@ packages:
resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
engines: {node: '>=10'}
p-map@7.0.2:
resolution: {integrity: sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==}
engines: {node: '>=18'}
p-try@2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
@@ -3626,10 +3606,6 @@ packages:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
path-type@5.0.0:
resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==}
engines: {node: '>=12'}
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
@@ -4110,10 +4086,6 @@ packages:
resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
engines: {node: '>=8'}
slash@5.1.0:
resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==}
engines: {node: '>=14.16'}
slice-ansi@3.0.0:
resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==}
engines: {node: '>=8'}
@@ -4535,10 +4507,6 @@ packages:
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
unicorn-magic@0.1.0:
resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==}
engines: {node: '>=18'}
universalify@0.1.2:
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
engines: {node: '>= 4.0.0'}
@@ -5798,8 +5766,6 @@ snapshots:
'@sideway/pinpoint@2.0.0': {}
'@sindresorhus/merge-streams@2.3.0': {}
'@swc/counter@0.1.3': {}
'@swc/helpers@0.5.15':
@@ -6689,20 +6655,6 @@ snapshots:
has-property-descriptors: 1.0.2
object-keys: 1.1.1
del-cli@6.0.0:
dependencies:
del: 8.0.0
meow: 13.2.0
del@8.0.0:
dependencies:
globby: 14.0.2
is-glob: 4.0.3
is-path-cwd: 3.0.0
is-path-inside: 4.0.0
p-map: 7.0.2
slash: 5.1.0
delayed-stream@1.0.0: {}
delegates@1.0.0: {}
@@ -6988,7 +6940,7 @@ snapshots:
debug: 4.4.0(supports-color@5.5.0)
enhanced-resolve: 5.17.1
eslint: 8.57.1
eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.1))(eslint@8.57.1)
fast-glob: 3.3.2
get-tsconfig: 4.8.0
is-bun-module: 1.1.0
@@ -7001,7 +6953,7 @@ snapshots:
- eslint-import-resolver-webpack
- supports-color
eslint-module-utils@2.8.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1):
eslint-module-utils@2.8.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.1))(eslint@8.57.1):
dependencies:
debug: 3.2.7(supports-color@8.1.1)
optionalDependencies:
@@ -7022,7 +6974,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1)
eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.1))(eslint@8.57.1)
hasown: 2.0.2
is-core-module: 2.15.1
is-glob: 4.0.3
@@ -7520,15 +7472,6 @@ snapshots:
merge2: 1.4.1
slash: 3.0.0
globby@14.0.2:
dependencies:
'@sindresorhus/merge-streams': 2.3.0
fast-glob: 3.3.2
ignore: 5.3.2
path-type: 5.0.0
slash: 5.1.0
unicorn-magic: 0.1.0
globrex@0.1.2: {}
gopd@1.0.1:
@@ -7745,12 +7688,8 @@ snapshots:
is-number@7.0.0: {}
is-path-cwd@3.0.0: {}
is-path-inside@3.0.3: {}
is-path-inside@4.0.0: {}
is-potential-custom-element-name@1.0.1: {}
is-regex@1.1.4:
@@ -8336,8 +8275,6 @@ snapshots:
dependencies:
aggregate-error: 3.1.0
p-map@7.0.2: {}
p-try@2.2.0: {}
package-json-from-dist@1.0.1: {}
@@ -8371,8 +8308,6 @@ snapshots:
path-type@4.0.0: {}
path-type@5.0.0: {}
pathe@2.0.3: {}
pathval@2.0.0: {}
@@ -8822,8 +8757,6 @@ snapshots:
slash@3.0.0: {}
slash@5.1.0: {}
slice-ansi@3.0.0:
dependencies:
ansi-styles: 4.3.0
@@ -9291,8 +9224,6 @@ snapshots:
undici-types@6.21.0: {}
unicorn-magic@0.1.0: {}
universalify@0.1.2: {}
universalify@2.0.1: {}

View File

@@ -1,3 +1,4 @@
packages:
- "apps/*"
- "apps/login/cypress"
- "packages/*"

44
scripts/run_or_skip.sh Executable file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/env bash
# Usage: ./run_or_skip.sh <Make target> <images>
# Example: ./run_or_skip.sh lint-force "img1;img2"
set -euo pipefail
if [ -z "$CACHE_DIR" ]; then
echo "CACHE_DIR is not set. Please set it to a valid directory."
exit 1
fi
MAKE_TARGET=$1
IMAGES=$2
DIGEST_FILE="$CACHE_DIR/$MAKE_TARGET.digests"
mkdir -p "$CACHE_DIR"
get_image_ids() {
local ids=""
for img in $(echo "$IMAGES" | tr ';' ' '); do
local id=$(docker image inspect "$img" --format='{{.Id}}' 2>/dev/null || true)
id=${id:-new-or-error}
ids="${ids}${id};"
done
ids=${ids%;} # Remove trailing semicolon
echo "$ids"
}
OLD_DIGEST=$(cat "$DIGEST_FILE" 2>/dev/null || echo "")
OLD_STATUS=$(echo "$OLD_DIGEST" | cut -d ';' -f1)
OLD_IDS=$(echo "$OLD_DIGEST" | cut -d ';' -f2-9)
if [[ "$OLD_IDS" == "$(get_image_ids)" ]]; then
echo "Skipping $MAKE_TARGET all images unchanged, returning cached status $OLD_STATUS"
exit $OLD_STATUS
else
echo "Running $MAKE_TARGET..."
set +e
make $MAKE_TARGET
STATUS=$?
set -e
echo "${STATUS};$(get_image_ids)" > $DIGEST_FILE
exit $STATUS
fi

View File

@@ -26,6 +26,7 @@
"start:built": {},
"test:unit": {},
"test:integration": {},
"test:integration:run": {},
"test:watch": {
"persistent": true
},