login makefile

This commit is contained in:
Elio Bischof
2025-06-06 10:56:02 +02:00
parent 8f86294312
commit d5ffa18dfe
16 changed files with 205 additions and 177 deletions

View File

@@ -1,2 +1,23 @@
.git
.DS_Store
node_modules
.turbo
*.log
.next
dist
dist-ssr
*.local
.env
.cache
server/dist
public/dist
.vscode
.idea
.vercel
.env*.local
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/out
/docker

View File

@@ -1,109 +0,0 @@
name: Docker
on:
push:
branches:
- main
- qa
workflow_dispatch:
permissions:
packages: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Cache turbo build setup
uses: actions/cache@v4
with:
path: .turbo
key: ${{ runner.os }}-turbo-${{ github.sha }}
restore-keys: |
${{ runner.os }}-turbo-
- name: Setup Node.js environment
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker-container
- name: Login Public
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login Private
uses: docker/login-action@v3
with:
registry: ${{ secrets.DOCKER_REGISTRY }}
username: ${{ secrets.DOCKER_REGISTRY_USERNAME }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
ghcr.io/zitadel/login
${{ secrets.DOCKER_IMAGE }}
tags: |
type=edge
type=ref,event=branch
type=ref,event=tag
type=ref,event=pr
type=sha
- name: Install dependencies
run: pnpm install
- name: Generate stubs
run: pnpm generate
- name: Build for Docker
run: NEXT_PUBLIC_BASE_PATH=/ui/v2/login pnpm build:docker
- name: Build and Push Image
id: build
uses: docker/build-push-action@v5
timeout-minutes: 10
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Export digest
run: |
mkdir -p /tmp/digests/app
digest="${{ steps.build.outputs.digest }}"
touch "/tmp/digests/app/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
with:
name: digests
path: /tmp/digests
if-no-files-found: error
retention-days: 1

4
.gitignore vendored
View File

@@ -7,13 +7,9 @@ dist
dist-ssr
*.local
.env
apps/login/.env.local
apps/login/.env.acceptance
.cache
server/dist
public/dist
.turbo
packages/zitadel-server/src/app/proto
.vscode
.idea
.vercel

View File

@@ -1,6 +1,6 @@
{
"printWidth": 125,
"trailingComma": "all",
"plugins": ["prettier-plugin-organize-imports"]
"plugins": ["prettier-plugin-organize-imports"],
"filepath": ""
}

104
Makefile Normal file
View File

@@ -0,0 +1,104 @@
LOGIN_BASE_TAG ?= "zitadel-login-base:local"
CORE_MOCK_TAG ?= "zitadel-core-mock:local"
XDG_CACHE_HOME ?= $(HOME)/.cache
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"
.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))
unit-run: login-base
docker run --rm $(LOGIN_BASE_TAG) test:unit
.PHONY: unit-force
unit-force:
docker run --rm $(LOGIN_BASE_TAG) test:unit
.PHONY: unit
unit:
$(call run_or_skip,unit-force,unit,$(LOGIN_BASE_TAG))
.PHONY: integration-force
integration-force:
docker run --rm $(CORE_MOCK_TAG) test:integration
.PHONY: integration
integration:
$(call run_or_skip,integration-force,integration,$(CORE_MOCK_TAG))
.PHONY: login-image
login-image:
docker buildx bake login-image
.PHONY: quality
quality: lint unit integration
.PHONY: ci
ci: core-mock ci-after-build
ci-after-build: quality login-image
@:
login-base:
docker buildx bake login-base --set login-base.tags=$(LOGIN_BASE_TAG);
core-mock:
docker buildx bake core-mock --set login-base.tags=$(CORE_MOCK_TAG);
.PHONY: clean-cache
clean-cache:
@echo "Removing cache directory: $(CACHE_DIR)"
@rm -rf "$(CACHE_DIR)"
.PHONY: show-cache
show-cache:
@echo "Showing cached digests and exit codes in $(CACHE_DIR):"
@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

3
apps/login/.dockerignore Normal file
View File

@@ -0,0 +1,3 @@
custom-config.js
.env.local
.env.acceptance

View File

@@ -1,2 +1,3 @@
custom-config.js
.env.local
.env.local
.env.acceptance

View File

@@ -1,20 +0,0 @@
FROM bufbuild/buf:1.21.0 as protos
RUN buf export https://github.com/envoyproxy/protoc-gen-validate.git --path validate --output /proto
RUN buf export https://github.com/grpc-ecosystem/grpc-gateway.git --path protoc-gen-openapiv2 --output /proto
RUN 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
RUN buf export https://github.com/zitadel/zitadel.git --path ./proto/zitadel --output /proto
FROM scratch AS config
COPY mocked-services.cfg .
COPY initial-stubs initial-stubs
COPY --from=protos /proto .
FROM golang:1.20.5-alpine3.18 as grpc-mock
RUN go install github.com/eliobischof/grpc-mock/cmd/grpc-mock@01b09f60db1b501178af59bed03b2c22661df48c
COPY --from=config / .
ENTRYPOINT [ "sh", "-c", "grpc-mock -v 1 -proto $(tr '\n' ',' < ./mocked-services.cfg) -stub-dir ./initial-stubs" ]

View File

@@ -1,4 +0,0 @@
# BUILD STAGE
FROM base
RUN pnpm generate

View File

@@ -1,37 +1,44 @@
variable "tags" {
variable "release_tags" {
default = ["zitadel-login:local"]
}
variable "login-context" {
default = "."
}
group "default" {
targets = ["login-docker-image"]
targets = ["login-generate"]
}
target "typescript-base" {
context = "${login-context}"
dockerfile = "bake/base.Dockerfile"
target "login-base" {
context = "."
dockerfile = "dockerfiles/login-base.Dockerfile"
}
target "proto" {
context = "${login-context}"
dockerfile = "bake/proto.Dockerfile"
output = ["type=local,dest=./packages/zitadel-proto"]
target "download-protos" {
dockerfile = "dockerfiles/download-protos.Dockerfile"
contexts = {
base = "target:login-base"
}
}
target "core-mock" {
dockerfile = "dockerfiles/core-mock.Dockerfile"
contexts = {
base = "target:typescript-base"
protos = "target:download-protos"
}
}
target "login-docker-image" {
context = "${login-context}"
dockerfile = "bake/login-for-docker.Dockerfile"
tags = "${tags}"
target "login-generate" {
dockerfile = "dockerfiles/login-generate.Dockerfile"
contexts = {
base = "target:login-base"
}
}
target "login-image" {
dockerfile = "dockerfiles/login-image.Dockerfile"
tags = "${release_tags}"
args = {
NODE_ENV = "production"
}
contexts = {
proto = "target:proto"
generated = "target:login-generate"
}
}

View File

@@ -0,0 +1,13 @@
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 / .
ENTRYPOINT [ "sh", "-c", "grpc-mock -v 1 -proto $(tr '\n' ',' < ./mocked-services.cfg) -stub-dir ./initial-stubs" ]

View File

@@ -0,0 +1,7 @@
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

@@ -1,19 +1,22 @@
# BUILD STAGE
FROM node:20-alpine
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
RUN apk add --no-cache libc6-compat bash git
RUN corepack enable && corepack prepare pnpm@latest --activate
COPY \
turbo.json \
.npmrc \
package.json \
pnpm-lock.yaml \
pnpm-workspace.yaml \
./
# Copy remote turbo.json config for pruning
COPY turbo.json ./
COPY .npmrc ./
# pnpm store + turbo build cache
RUN mkdir -p .pnpm-store .next
# Copy just lockfile & manifests for better cache-hit
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
COPY packages/zitadel-client/package.json ./packages/zitadel-client/
COPY packages/zitadel-eslint-config/package.json ./packages/zitadel-eslint-config/
@@ -23,8 +26,9 @@ COPY packages/zitadel-tailwind-config/package.json ./packages/zitadel-tailwind-c
COPY packages/zitadel-tsconfig/package.json ./packages/zitadel-tsconfig/
COPY apps/login/package.json ./apps/login/
RUN --mount=type=cache,target=/app/.pnpm-store \
pnpm install --frozen-lockfile --store-dir .pnpm-store
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
pnpm install --frozen-lockfile
# Full source
COPY . .
ENTRYPOINT ["pnpm"]

View File

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

View File

@@ -1,9 +1,7 @@
# BUILD STAGE
FROM proto AS build-for-docker
FROM generated AS build-for-docker
RUN NEXT_PUBLIC_BASE_PATH=/ui/v2/login pnpm build:docker
# RUNTIME
FROM node:20-alpine
WORKDIR /app

View File

@@ -0,0 +1,4 @@
zitadel
google
protoc-gen-openapiv2
validate