Files
zitadel/apps/login/acceptance/setup/setup.sh
Elio Bischof b10455b51f chore: reproducible pipeline with dev containers (#10305)
# Which Problems Are Solved

- The previous monorepo in monorepo structure for the login app and its
related packages was fragmented, complicated and buggy.
- The process for building and testing the login container was
inconsistent between local development and CI.
- Lack of clear documentation as well as easy and reliable ways for
non-frontend developers to reproduce and fix failing PR checks locally.

# How the Problems Are Solved

- Consolidated the login app and its related npm packages by moving the
main package to `apps/login/apps/login` and merging
`apps/login/packages/integration` and `apps/login/packages/acceptance`
into the main `apps/login` package.
- Migrated from Docker Compose-based test setups to dev container-based
setups, adding support for multiple dev container configurations:
  - `.devcontainer/base`
  - `.devcontainer/turbo-lint-unit`
  - `.devcontainer/turbo-lint-unit-debug`
  - `.devcontainer/login-integration`
  - `.devcontainer/login-integration-debug`
- Added npm scripts to run the new dev container setups, enabling exact
reproduction of GitHub PR checks locally, and updated the pipeline to
use these containers.
- Cleaned up Dockerfiles and docker-bake.hcl files to only build the
production image for the login app.
- Cleaned up compose files to focus on dev environments in dev
containers.
- Updated `CONTRIBUTING.md` with guidance on running and debugging PR
checks locally using the new dev container approach.
- Introduced separate Dockerfiles for the login app to distinguish
between using published client packages and building clients from local
protos.
- Ensured the login container is always built in the pipeline for use in
integration and acceptance tests.
- Updated Makefile and GitHub Actions workflows to use
`--frozen-lockfile` for installing pnpm packages, ensuring reproducible
installs.
- Disabled GitHub release creation by the changeset action.
- Refactored the `/build` directory structure for clarity and
maintainability.
- Added a `clean` command to `docks/package.json`.
- Experimentally added `knip` to the `zitadel-client` package for
improved linting of dependencies and exports.

# Additional Changes

- Fixed Makefile commands for consistency and reliability.
- Improved the structure and clarity of the `/build` directory to
support seamless integration of the login build.
- Enhanced documentation and developer experience for running and
debugging CI checks locally.

# Additional Context

- See updated `CONTRIBUTING.md` for new local development and debugging
instructions.
- These changes are a prerequisite for further improvements to the CI
pipeline and local development workflow.
- Closes #10276
2025-07-24 14:22:32 +02:00

140 lines
6.0 KiB
Bash
Executable File

#!/bin/sh
set -e pipefail
PAT_FILE=${PAT_FILE:-./pat/zitadel-admin-sa.pat}
LOGIN_BASE_URL=${LOGIN_BASE_URL:-"http://localhost:3000"}
ZITADEL_API_PROTOCOL="${ZITADEL_API_PROTOCOL:-http}"
ZITADEL_API_DOMAIN="${ZITADEL_API_DOMAIN:-localhost}"
ZITADEL_API_PORT="${ZITADEL_API_PORT:-8080}"
ZITADEL_API_URL="${ZITADEL_API_URL:-${ZITADEL_API_PROTOCOL}://${ZITADEL_API_DOMAIN}:${ZITADEL_API_PORT}}"
ZITADEL_API_INTERNAL_URL="${ZITADEL_API_INTERNAL_URL:-${ZITADEL_API_URL}}"
SINK_EMAIL_INTERNAL_URL="${SINK_EMAIL_INTERNAL_URL:-"http://sink:3333/email"}"
SINK_SMS_INTERNAL_URL="${SINK_SMS_INTERNAL_URL:-"http://sink:3333/sms"}"
SINK_NOTIFICATION_URL="${SINK_NOTIFICATION_URL:-"http://localhost:3333/notification"}"
WRITE_ENVIRONMENT_FILE=${WRITE_ENVIRONMENT_FILE:-$(dirname "$0")/../apps/login/.env.test.local}
if [ -z "${PAT}" ]; then
echo "Reading PAT from file ${PAT_FILE}"
PAT=$(cat ${PAT_FILE})
fi
#################################################################
# ServiceAccount as Login Client
#################################################################
SERVICEACCOUNT_RESPONSE=$(curl -s --request POST \
--url "${ZITADEL_API_INTERNAL_URL}/management/v1/users/machine" \
--header "Authorization: Bearer ${PAT}" \
--header "Host: ${ZITADEL_API_DOMAIN}" \
--header "Content-Type: application/json" \
-d "{\"userName\": \"login\", \"name\": \"Login v2\", \"description\": \"Serviceaccount for Login v2\", \"accessTokenType\": \"ACCESS_TOKEN_TYPE_BEARER\"}")
echo "Received ServiceAccount response: ${SERVICEACCOUNT_RESPONSE}"
SERVICEACCOUNT_ID=$(echo ${SERVICEACCOUNT_RESPONSE} | jq -r '. | .userId')
echo "Received ServiceAccount ID: ${SERVICEACCOUNT_ID}"
MEMBER_RESPONSE=$(curl -s --request POST \
--url "${ZITADEL_API_INTERNAL_URL}/admin/v1/members" \
--header "Authorization: Bearer ${PAT}" \
--header "Host: ${ZITADEL_API_DOMAIN}" \
--header "Content-Type: application/json" \
-d "{\"userId\": \"${SERVICEACCOUNT_ID}\", \"roles\": [\"IAM_LOGIN_CLIENT\"]}")
echo "Received Member response: ${MEMBER_RESPONSE}"
SA_PAT_RESPONSE=$(curl -s --request POST \
--url "${ZITADEL_API_INTERNAL_URL}/management/v1/users/${SERVICEACCOUNT_ID}/pats" \
--header "Authorization: Bearer ${PAT}" \
--header "Host: ${ZITADEL_API_DOMAIN}" \
--header "Content-Type: application/json" \
-d "{\"expirationDate\": \"2519-04-01T08:45:00.000000Z\"}")
echo "Received Member response: ${MEMBER_RESPONSE}"
SA_PAT=$(echo ${SA_PAT_RESPONSE} | jq -r '. | .token')
echo "Received ServiceAccount Token: ${SA_PAT}"
#################################################################
# Environment files
#################################################################
echo "Writing environment file ${WRITE_ENVIRONMENT_FILE}."
echo "ZITADEL_API_URL=${ZITADEL_API_URL}
ZITADEL_SERVICE_USER_TOKEN=${SA_PAT}
ZITADEL_ADMIN_TOKEN=${PAT}
SINK_NOTIFICATION_URL=${SINK_NOTIFICATION_URL}
EMAIL_VERIFICATION=true
DEBUG=false
LOGIN_BASE_URL=${LOGIN_BASE_URL}
NODE_TLS_REJECT_UNAUTHORIZED=0
ZITADEL_ADMIN_USER=${ZITADEL_ADMIN_USER:-"zitadel-admin@zitadel.localhost"}
NEXT_PUBLIC_BASE_PATH=/ui/v2/login
" > ${WRITE_ENVIRONMENT_FILE}
echo "Wrote environment file ${WRITE_ENVIRONMENT_FILE}"
cat ${WRITE_ENVIRONMENT_FILE}
#################################################################
# SMS provider with HTTP
#################################################################
SMSHTTP_RESPONSE=$(curl -s --request POST \
--url "${ZITADEL_API_INTERNAL_URL}/admin/v1/sms/http" \
--header "Authorization: Bearer ${PAT}" \
--header "Host: ${ZITADEL_API_DOMAIN}" \
--header "Content-Type: application/json" \
-d "{\"endpoint\": \"${SINK_SMS_INTERNAL_URL}\", \"description\": \"test\"}")
echo "Received SMS HTTP response: ${SMSHTTP_RESPONSE}"
SMSHTTP_ID=$(echo ${SMSHTTP_RESPONSE} | jq -r '. | .id')
echo "Received SMS HTTP ID: ${SMSHTTP_ID}"
SMS_ACTIVE_RESPONSE=$(curl -s --request POST \
--url "${ZITADEL_API_INTERNAL_URL}/admin/v1/sms/${SMSHTTP_ID}/_activate" \
--header "Authorization: Bearer ${PAT}" \
--header "Host: ${ZITADEL_API_DOMAIN}" \
--header "Content-Type: application/json")
echo "Received SMS active response: ${SMS_ACTIVE_RESPONSE}"
#################################################################
# Email provider with HTTP
#################################################################
EMAILHTTP_RESPONSE=$(curl -s --request POST \
--url "${ZITADEL_API_INTERNAL_URL}/admin/v1/email/http" \
--header "Authorization: Bearer ${PAT}" \
--header "Host: ${ZITADEL_API_DOMAIN}" \
--header "Content-Type: application/json" \
-d "{\"endpoint\": \"${SINK_EMAIL_INTERNAL_URL}\", \"description\": \"test\"}")
echo "Received Email HTTP response: ${EMAILHTTP_RESPONSE}"
EMAILHTTP_ID=$(echo ${EMAILHTTP_RESPONSE} | jq -r '. | .id')
echo "Received Email HTTP ID: ${EMAILHTTP_ID}"
EMAIL_ACTIVE_RESPONSE=$(curl -s --request POST \
--url "${ZITADEL_API_INTERNAL_URL}/admin/v1/email/${EMAILHTTP_ID}/_activate" \
--header "Authorization: Bearer ${PAT}" \
--header "Host: ${ZITADEL_API_DOMAIN}" \
--header "Content-Type: application/json")
echo "Received Email active response: ${EMAIL_ACTIVE_RESPONSE}"
#################################################################
# Wait for projection of default organization in ZITADEL
#################################################################
DEFAULTORG_RESPONSE_RESULTS=0
# waiting for default organization
until [ ${DEFAULTORG_RESPONSE_RESULTS} -eq 1 ]
do
DEFAULTORG_RESPONSE=$(curl -s --request POST \
--url "${ZITADEL_API_INTERNAL_URL}/v2/organizations/_search" \
--header "Authorization: Bearer ${PAT}" \
--header "Host: ${ZITADEL_API_DOMAIN}" \
--header "Content-Type: application/json" \
-d "{\"queries\": [{\"defaultQuery\":{}}]}" )
echo "Received default organization response: ${DEFAULTORG_RESPONSE}"
DEFAULTORG_RESPONSE_RESULTS=$(echo $DEFAULTORG_RESPONSE | jq -r '.result | length')
echo "Received default organization response result: ${DEFAULTORG_RESPONSE_RESULTS}"
done