Skip to content

feat(chat): add embedded assistant and MCP workflows #9641

feat(chat): add embedded assistant and MCP workflows

feat(chat): add embedded assistant and MCP workflows #9641

name: Klicker automated testing with cypress
on:
push:
branches: ['v3', 'v3*']
# paths:
# - apps/**
# - packages/**
pull_request:
branches: ['v3', 'v3*']
types: [opened, synchronize, reopened, ready_for_review]
paths:
- apps/**
- packages/**
- cypress/**
- .github/workflows/cypress-testing.yml
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref_name }}
cancel-in-progress: true
env:
REGISTRY: ghcr.io
# This workflow runs Cypress tests with two different strategies:
# 1. Draft PRs: Fast parallel testing with cypress-split (8 containers, no Cloud)
# 2. Non-draft PRs & direct v3 pushes: Full Cypress Cloud recording for production visibility
#
# Event handling strategy (with redundancy for reliability):
# - Feature branches (v3-*): Handled by BOTH push and pull_request events for redundancy
# - Draft PRs: Use parallel testing regardless of event type
# - Non-draft PRs: Use Cypress Cloud with recording
# - Concurrency group prevents duplicate runs when both events fire
jobs:
# Runs parallel Cypress tests for development (draft PRs and feature branch pushes)
# Uses cypress-split to distribute tests across 8 containers for faster feedback
# No Cypress Cloud recording to save costs during development
cypress-run-parallel-draft:
if: (github.event_name == 'pull_request' && github.event.pull_request.draft == true)
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
containers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: klicker-prod
POSTGRES_PASSWORD: klicker
POSTGRES_DB: klicker-prod
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
postgres_hatchet:
image: postgres:15
env:
POSTGRES_USER: hatchet
POSTGRES_PASSWORD: hatchet
POSTGRES_DB: hatchet
options: >-
--health-cmd "pg_isready -U hatchet -d hatchet"
--health-interval 5s
--health-timeout 10s
--health-retries 10
--health-start-period 30s
ports:
- 5433:5432
redis_cache:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6380:6379
redis_exec:
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
image: redis:7
ports:
- 6379:6379
redis_assessment_exec:
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
image: redis:7
ports:
- 6381:6379
hatchet:
image: ghcr.io/hatchet-dev/hatchet/hatchet-lite:v0.73.1
ports:
- '8888:8888'
- '7077:7077'
env:
DATABASE_URL: 'postgresql://hatchet:hatchet@postgres_hatchet:5432/hatchet?sslmode=disable'
SERVER_AUTH_COOKIE_DOMAIN: localhost
SERVER_AUTH_COOKIE_INSECURE: 't'
SERVER_GRPC_BIND_ADDRESS: '0.0.0.0'
SERVER_GRPC_INSECURE: 't'
SERVER_GRPC_BROADCAST_ADDRESS: localhost:7077
SERVER_INTERNAL_CLIENT_INTERNAL_GRPC_BROADCAST_ADDRESS: localhost:7077
SERVER_GRPC_PORT: '7077'
SERVER_URL: http://localhost:8888
SERVER_AUTH_SET_EMAIL_VERIFIED: 't'
SERVER_DEFAULT_ENGINE_VERSION: 'V1'
SERVER_LOGGER_LEVEL: debug
SERVER_LOGGER_FORMAT: console
steps:
- run: echo "Running parallel Cypress tests for draft PR (container ${{ matrix.containers }})"
- name: Define node version
uses: actions/setup-node@v3
with:
node-version: 20
- name: Check out repository code
uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 10.15.0
run_install: false
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: |
${{ env.STORE_PATH }}
~/.cache/Cypress
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Cache turbo build artifacts
uses: actions/cache@v4
with:
path: |
.turbo
key: ${{ runner.os }}-turbo-${{ hashFiles('**/pnpm-lock.yaml', 'turbo.json') }}-${{ github.ref_name }}
restore-keys: |
${{ runner.os }}-turbo-${{ hashFiles('**/pnpm-lock.yaml', 'turbo.json') }}-
${{ runner.os }}-turbo-
- name: Install dependencies
run: pnpm install
- name: Build all packages and apps
run: pnpm run --filter @klicker-uzh/prisma build:test && pnpm run build:test
- name: Prepare .env files
run: |
./util/_create_hatchet_token_cypress.sh
- name: Apply migrations and seed the database
run: |
cd packages/prisma
pnpm run prisma:reset:raw -f
env:
DATABASE_URL: postgres://klicker-prod:klicker@localhost:5432/klicker-prod
- name: Start services and wait for readiness
run: |
chmod +x .github/scripts/wait-for-services.sh
.github/scripts/wait-for-services.sh
env:
APP_SECRET: abcd
DATABASE_URL: postgres://klicker-prod:klicker@localhost:5432/klicker-prod
NODE_ENV: production
SERVICE_ENDPOINTS: 'http://127.0.0.1:3000/healthz http://127.0.0.1:3001 http://127.0.0.1:3002 http://127.0.0.1:3003 http://127.0.0.1:3010'
TIMEOUT_SECONDS: '300'
CHECK_INTERVAL: '5'
REDIS_HOST: localhost
REDIS_PASS: ''
REDIS_PORT: 6379
REDIS_ASSESSMENT_PORT: 6381
REDIS_ASSESSMENT_PASS: ''
REDIS_ASSESSMENT_HOST: localhost
# Provide all app origins to the services and tests
APP_ORIGIN_API: http://127.0.0.1:3000
APP_ORIGIN_AUTH: http://127.0.0.1:3010
APP_ORIGIN_LTI: http://127.0.0.1:3005
APP_ORIGIN_PWA: http://127.0.0.1:3001
APP_ORIGIN_MANAGE: http://127.0.0.1:3002
APP_ORIGIN_CONTROL: http://127.0.0.1:3003
APP_ORIGIN_ASSESSMENT_API: http://127.0.0.1:3000
APP_ORIGIN_ASSESSMENT_PWA: http://127.0.0.1:3001
- name: Cypress run parallel with cypress-split
uses: cypress-io/github-action@v6
timeout-minutes: 120
with:
install: false
wait-on: 'http://127.0.0.1:3000/healthz, http://127.0.0.1:3001, http://127.0.0.1:3002, http://127.0.0.1:3003, http://127.0.0.1:3010'
wait-on-timeout: 300
browser: electron
working-directory: cypress
env:
CYPRESS_FAIL_FAST: 'false'
APP_SECRET: abcd
DATABASE_URL: postgres://klicker-prod:klicker@127.0.0.1:5432/klicker-prod
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_ENV: production
HATCHET_API_URL: http://127.0.0.1:8888
HATCHET_TENANT_ID: 707d0855-80ab-4e1f-a156-f1c4546cbf52
HATCHET_HOST_PORT: 7077
# Ensure Cypress process has all origins, too
APP_ORIGIN_API: http://127.0.0.1:3000
APP_ORIGIN_AUTH: http://127.0.0.1:3010
APP_ORIGIN_LTI: http://127.0.0.1:3005
APP_ORIGIN_PWA: http://127.0.0.1:3001
APP_ORIGIN_MANAGE: http://127.0.0.1:3002
APP_ORIGIN_CONTROL: http://127.0.0.1:3003
APP_ORIGIN_ASSESSMENT_API: http://127.0.0.1:3000
APP_ORIGIN_ASSESSMENT_PWA: http://127.0.0.1:3001
SPLIT: ${{ strategy.job-total }}
SPLIT_INDEX: ${{ strategy.job-index }}
SPLIT_FILE: timings.json
- if: always()
uses: actions/upload-artifact@v4
with:
name: cypress-artifacts-draft-${{ matrix.containers }}
path: |
cypress/cypress/videos
cypress/cypress/screenshots
if-no-files-found: ignore
retention-days: 1
# Runs Cypress tests with Cloud recording for production-ready code
# Triggers on:
# - Non-draft pull requests (for code review)
# - Direct pushes to v3 branch (for hotfixes/direct commits)
# Provides full video/screenshot recording and Cypress Dashboard visibility
cypress-run-cloud:
if: (github.event_name == 'pull_request' && github.event.pull_request.draft == false) || (github.event_name == 'push' && github.ref == 'refs/heads/v3')
runs-on: ubuntu-24.04
# strategy:
# fail-fast: false
# matrix:
# containers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: klicker-prod
POSTGRES_PASSWORD: klicker
POSTGRES_DB: klicker-prod
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
postgres_hatchet:
image: postgres:15
env:
POSTGRES_USER: hatchet
POSTGRES_PASSWORD: hatchet
POSTGRES_DB: hatchet
options: >-
--health-cmd "pg_isready -U hatchet -d hatchet"
--health-interval 5s
--health-timeout 10s
--health-retries 10
--health-start-period 30s
ports:
- 5433:5432
redis_cache:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6380:6379
redis_exec:
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
image: redis:7
ports:
- 6379:6379
redis_assessment_exec:
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
image: redis:7
ports:
- 6381:6379
hatchet:
image: ghcr.io/hatchet-dev/hatchet/hatchet-lite:v0.73.1
ports:
- '8888:8888'
- '7077:7077'
env:
DATABASE_URL: 'postgresql://hatchet:hatchet@postgres_hatchet:5432/hatchet?sslmode=disable'
SERVER_AUTH_COOKIE_DOMAIN: localhost
SERVER_AUTH_COOKIE_INSECURE: 't'
SERVER_GRPC_BIND_ADDRESS: '0.0.0.0'
SERVER_GRPC_INSECURE: 't'
SERVER_GRPC_BROADCAST_ADDRESS: localhost:7077
SERVER_INTERNAL_CLIENT_INTERNAL_GRPC_BROADCAST_ADDRESS: localhost:7077
SERVER_GRPC_PORT: '7077'
SERVER_URL: http://localhost:8888
SERVER_AUTH_SET_EMAIL_VERIFIED: 't'
SERVER_DEFAULT_ENGINE_VERSION: 'V1'
SERVER_LOGGER_LEVEL: debug
SERVER_LOGGER_FORMAT: console
steps:
- run: echo "Running Cypress tests with Cloud recording for non-draft PR or push to v3"
- name: Define node version
uses: actions/setup-node@v3
with:
node-version: 20
- name: Check out repository code
uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
with:
version: 10.15.0
run_install: false
- name: Get pnpm store directory
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- uses: actions/cache@v4
name: Setup pnpm cache
with:
path: |
${{ env.STORE_PATH }}
~/.cache/Cypress
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Cache turbo build artifacts
uses: actions/cache@v4
with:
path: |
.turbo
key: ${{ runner.os }}-turbo-${{ hashFiles('**/pnpm-lock.yaml', 'turbo.json') }}-${{ github.ref_name }}
restore-keys: |
${{ runner.os }}-turbo-${{ hashFiles('**/pnpm-lock.yaml', 'turbo.json') }}-
${{ runner.os }}-turbo-
- name: Install dependencies
run: pnpm install
- name: Build all packages and apps
run: pnpm run --filter @klicker-uzh/prisma build:test && pnpm run build:test
- name: Prepare .env files
run: |
./util/_create_hatchet_token_cypress.sh
- name: Apply migrations and seed the database
run: |
cd packages/prisma
pnpm run prisma:reset:raw -f
env:
DATABASE_URL: postgres://klicker-prod:klicker@localhost:5432/klicker-prod
- name: Start services and wait for readiness
run: |
chmod +x .github/scripts/wait-for-services.sh
.github/scripts/wait-for-services.sh
env:
APP_SECRET: abcd
DATABASE_URL: postgres://klicker-prod:klicker@localhost:5432/klicker-prod
NODE_ENV: production
SERVICE_ENDPOINTS: 'http://127.0.0.1:3000/healthz http://127.0.0.1:3001 http://127.0.0.1:3002 http://127.0.0.1:3003 http://127.0.0.1:3010'
TIMEOUT_SECONDS: '300'
CHECK_INTERVAL: '5'
# Provide all app origins to the services and tests
APP_ORIGIN_API: http://127.0.0.1:3000
APP_ORIGIN_AUTH: http://127.0.0.1:3010
APP_ORIGIN_LTI: http://127.0.0.1:3005
APP_ORIGIN_PWA: http://127.0.0.1:3001
APP_ORIGIN_MANAGE: http://127.0.0.1:3002
APP_ORIGIN_CONTROL: http://127.0.0.1:3003
APP_ORIGIN_ASSESSMENT_API: http://127.0.0.1:3000
APP_ORIGIN_ASSESSMENT_PWA: http://127.0.0.1:3001
- name: Upload service logs
if: always()
uses: actions/upload-artifact@v4
with:
name: service-logs
# path: service-${{ matrix.containers }}.log
path: service.log
if-no-files-found: warn
retention-days: 7
- name: Cypress run with Cloud recording
uses: cypress-io/github-action@v6
timeout-minutes: 120
with:
install: false
wait-on: 'http://127.0.0.1:3000/healthz, http://127.0.0.1:3001, http://127.0.0.1:3002, http://127.0.0.1:3003, http://127.0.0.1:3010'
wait-on-timeout: 300
record: true
browser: electron
# parallel: true
working-directory: cypress
env:
CYPRESS_FAIL_FAST: 'false'
APP_SECRET: abcd
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
DATABASE_URL: postgres://klicker-prod:klicker@127.0.0.1:5432/klicker-prod
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NODE_ENV: production
HATCHET_API_URL: http://127.0.0.1:8888
HATCHET_TENANT_ID: 707d0855-80ab-4e1f-a156-f1c4546cbf52
HATCHET_HOST_PORT: 7077
# Ensure Cypress process has all origins, too
APP_ORIGIN_API: http://127.0.0.1:3000
APP_ORIGIN_AUTH: http://127.0.0.1:3010
APP_ORIGIN_LTI: http://127.0.0.1:3005
APP_ORIGIN_PWA: http://127.0.0.1:3001
APP_ORIGIN_MANAGE: http://127.0.0.1:3002
APP_ORIGIN_CONTROL: http://127.0.0.1:3003
APP_ORIGIN_ASSESSMENT_API: http://127.0.0.1:3000
APP_ORIGIN_ASSESSMENT_PWA: http://127.0.0.1:3001
- if: always()
uses: actions/upload-artifact@v4
with:
# name: cypress-artifacts-cloud-${{ matrix.containers }}
name: cypress-artifacts-cloud
path: |
cypress/cypress/videos
cypress/cypress/screenshots
if-no-files-found: ignore
retention-days: 1
# - name: Archive code coverage results
# uses: actions/upload-artifact@v3
# with:
# name: code-coverage
# path: cypress/coverage
# - name: Coveralls
# uses: coverallsapp/github-action@v2