Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ on:
- main
paths-ignore:
- "conductor-clients/**"
- "ui-next/**"
pull_request:
paths-ignore:
- "conductor-clients/**"
- "ui-next/**"
workflow_dispatch:
inputs:
redis_es8:
Expand Down
77 changes: 63 additions & 14 deletions .github/workflows/ui-next-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ on:
- main
paths:
- "ui-next/**"
push:
branches:
- main
paths:
- "ui-next/**"

permissions:
contents: read
Expand All @@ -21,26 +26,18 @@ jobs:
steps:
- uses: actions/checkout@v6

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 22

- name: Setup pnpm
uses: pnpm/action-setup@v5
with:
version: 10.32.0

- name: Get pnpm store directory
id: pnpm-cache
run: echo "store=$(pnpm store path)" >> $GITHUB_OUTPUT

- name: Cache pnpm store
uses: actions/cache@v4
# setup-node must come after pnpm/action-setup so it can locate the store.
- name: Setup Node.js
uses: actions/setup-node@v6
with:
path: ${{ steps.pnpm-cache.outputs.store }}
key: ${{ runner.os }}-pnpm-${{ hashFiles('ui-next/pnpm-lock.yaml') }}
restore-keys: ${{ runner.os }}-pnpm-
node-version: 22
cache: pnpm
cache-dependency-path: ui-next/pnpm-lock.yaml

- name: Install dependencies
run: pnpm install --frozen-lockfile
Expand All @@ -59,3 +56,55 @@ jobs:

- name: Build
run: pnpm build

e2e-mocked:
name: E2E (Mocked)
runs-on: ubuntu-latest
needs: lint-format-test
defaults:
run:
working-directory: ui-next

steps:
- uses: actions/checkout@v6

- name: Setup pnpm
uses: pnpm/action-setup@v5
with:
version: 10.32.0

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 22
cache: pnpm
cache-dependency-path: ui-next/pnpm-lock.yaml

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Cache Playwright browsers
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-chromium-${{ hashFiles('ui-next/pnpm-lock.yaml') }}

- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: pnpm exec playwright install chromium

# OS-level dependencies (apt packages) cannot be cached — always install.
- name: Install Playwright OS dependencies
run: pnpm exec playwright install-deps chromium

- name: Run mocked E2E tests
run: pnpm test:e2e

- name: Upload Playwright report
uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-report
path: ui-next/playwright-report/
retention-days: 7
98 changes: 98 additions & 0 deletions .github/workflows/ui-next-integration-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
name: UI v2 Integration CI

# Run whenever server or UI code changes — integration tests exercise the full
# stack (real Conductor backend + UI), so they are relevant for both.
# conductor-clients changes don't affect the server or UI at runtime.
on:
pull_request:
branches:
- main
paths-ignore:
- "conductor-clients/**"
push:
branches:
- main
paths-ignore:
- "conductor-clients/**"

permissions:
contents: read

jobs:
e2e-integration:
name: E2E (Integration)
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6

- name: Setup pnpm
uses: pnpm/action-setup@v5
with:
version: 10.32.0

# setup-node must come after pnpm/action-setup so it can locate the store.
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 22
cache: pnpm
cache-dependency-path: ui-next/pnpm-lock.yaml

- name: Install dependencies
run: pnpm install --frozen-lockfile
working-directory: ui-next

- name: Cache Playwright browsers
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: ${{ runner.os }}-playwright-chromium-${{ hashFiles('ui-next/pnpm-lock.yaml') }}

- name: Install Playwright browsers
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: pnpm exec playwright install chromium
working-directory: ui-next

# OS-level dependencies (apt packages) cannot be cached — always install.
- name: Install Playwright OS dependencies
run: pnpm exec playwright install-deps chromium
working-directory: ui-next

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Cache Docker layers for conductor:server
uses: actions/cache@v4
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-conductor-server-${{ hashFiles('docker/server/Dockerfile', '**/build.gradle', 'settings.gradle') }}
restore-keys: ${{ runner.os }}-conductor-server-

- name: Build conductor:server Docker image
uses: docker/build-push-action@v6
with:
context: .
file: docker/server/Dockerfile
tags: conductor:server
load: true
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max

- name: Move Docker layer cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache

- name: Run integration E2E tests
run: pnpm test:e2e:integration
working-directory: ui-next

- name: Upload Playwright integration report
uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-integration-report
path: ui-next/playwright-integration-report/
retention-days: 7
70 changes: 70 additions & 0 deletions docker/docker-compose-ui-e2e.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Docker Compose stack for Playwright UI integration tests.
#
# Uses the locally-built conductor:server image with Postgres as the backing
# store (no Elasticsearch required — Postgres full-text search is sufficient
# for the UI test workload).
#
# Build the server image once before running integration tests:
#
# docker build -t conductor:server -f docker/server/Dockerfile \
# --build-arg PREBUILT=false .
#
# Then start this stack (from the repo root):
#
# docker compose -f docker/docker-compose-ui-e2e.yaml up -d
#
# The Playwright global-setup script does this automatically when tests start.
# Container names are distinct from other compose stacks to allow both to
# run side-by-side without port or name conflicts.

services:
conductor-server:
image: conductor:server
build:
context: ../
dockerfile: docker/server/Dockerfile
container_name: conductor-server-ui-e2e
environment:
- CONFIG_PROP=config-postgres.properties
- conductor.app.ownerEmailMandatory=false
networks:
- internal
ports:
- "8000:8080"
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:8080/health"]
interval: 10s
timeout: 10s
retries: 24 # up to 4 minutes for a cold JVM start
links:
- conductor-postgres:postgresdb
depends_on:
conductor-postgres:
condition: service_healthy
logging:
driver: "json-file"
options:
max-size: "10k"
max-file: "3"

conductor-postgres:
image: postgres:16
container_name: conductor-postgres-ui-e2e
environment:
- POSTGRES_USER=conductor
- POSTGRES_PASSWORD=conductor
networks:
- internal
healthcheck:
test: timeout 5 bash -c 'cat < /dev/null > /dev/tcp/localhost/5432'
interval: 5s
timeout: 5s
retries: 12
logging:
driver: "json-file"
options:
max-size: "1k"
max-file: "3"

networks:
internal:
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public ObjectMapper objectMapper() {
}

@Bean
public RetryTemplate retryTemplate() {
public RetryTemplate postgresRetryTemplate() {
return new RetryTemplate();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.conductoross.conductor.scheduler.postgres.dao.PostgresSchedulerArchivalDAO;
import org.conductoross.conductor.scheduler.postgres.dao.PostgresSchedulerDAO;
import org.flywaydb.core.Flyway;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
Expand Down Expand Up @@ -55,14 +56,18 @@ public Flyway flywayForScheduler(DataSource dataSource) {
@Bean
@DependsOn("flywayForScheduler")
public SchedulerDAO schedulerDAO(
RetryTemplate retryTemplate, DataSource dataSource, ObjectMapper objectMapper) {
@Qualifier("postgresRetryTemplate") RetryTemplate retryTemplate,
DataSource dataSource,
ObjectMapper objectMapper) {
return new PostgresSchedulerDAO(retryTemplate, objectMapper, dataSource);
}

@Bean
@DependsOn("flywayForScheduler")
public SchedulerArchivalDAO schedulerArchivalDAO(
RetryTemplate retryTemplate, DataSource dataSource, ObjectMapper objectMapper) {
@Qualifier("postgresRetryTemplate") RetryTemplate retryTemplate,
DataSource dataSource,
ObjectMapper objectMapper) {
return new PostgresSchedulerArchivalDAO(retryTemplate, objectMapper, dataSource);
}
}
5 changes: 5 additions & 0 deletions ui-next/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ storybook-static
# Test / Playwright
/test-results/
/playwright-report/
/playwright-integration-report/
/playwright-snapshots-report/
/playwright/.cache/

# pnpm store (created inside project when running in Docker)
.pnpm-store/

# Turbo
.turbo

Expand Down
1 change: 1 addition & 0 deletions ui-next/.husky/pre-commit
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
cd ui-next
pnpm lint-staged
pnpm typecheck
pnpm test
Loading
Loading