2026-04-15 15:16:57 +01:00
|
|
|
version: '3'
|
|
|
|
|
|
|
|
|
|
output: prefixed
|
|
|
|
|
|
2026-04-28 17:26:04 +01:00
|
|
|
vars:
|
2026-05-20 13:57:41 +01:00
|
|
|
FIND_FREE_PORT_PS: powershell -NoProfile -File scripts/find-free-port.ps1
|
2026-04-28 17:26:04 +01:00
|
|
|
FIND_FREE_PORT_SH: bash scripts/find-free-port.sh
|
|
|
|
|
|
2026-04-15 15:16:57 +01:00
|
|
|
includes:
|
|
|
|
|
backend:
|
|
|
|
|
taskfile: .taskfiles/backend.yml
|
|
|
|
|
dir: .
|
|
|
|
|
frontend:
|
|
|
|
|
taskfile: .taskfiles/frontend.yml
|
|
|
|
|
dir: frontend
|
|
|
|
|
engine:
|
|
|
|
|
taskfile: .taskfiles/engine.yml
|
|
|
|
|
dir: engine
|
|
|
|
|
docker:
|
|
|
|
|
taskfile: .taskfiles/docker.yml
|
|
|
|
|
dir: .
|
|
|
|
|
desktop:
|
|
|
|
|
taskfile: .taskfiles/desktop.yml
|
|
|
|
|
dir: frontend
|
2026-05-11 15:50:07 +01:00
|
|
|
e2e:
|
|
|
|
|
taskfile: .taskfiles/e2e.yml
|
|
|
|
|
dir: .
|
2026-08-14 14:01:45 +01:00
|
|
|
cucumber:
|
|
|
|
|
taskfile: .taskfiles/cucumber.yml
|
|
|
|
|
dir: testing/cucumber
|
2026-06-18 13:55:53 +01:00
|
|
|
pre-commit:
|
|
|
|
|
taskfile: .taskfiles/pre-commit.yml
|
|
|
|
|
dir: .
|
2026-04-15 15:16:57 +01:00
|
|
|
|
|
|
|
|
tasks:
|
2026-06-19 11:44:30 +01:00
|
|
|
# ============================================================
|
|
|
|
|
# Help (shown when you run `task` with no arguments)
|
|
|
|
|
# ============================================================
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
desc: "List the most common commands"
|
|
|
|
|
silent: true
|
|
|
|
|
cmds:
|
|
|
|
|
- |
|
|
|
|
|
echo "Common commands (run 'task --list' to see all):"
|
|
|
|
|
echo ""
|
|
|
|
|
echo " task dev Start backend & frontend on free ports"
|
|
|
|
|
echo " task backend:dev Start backend on default port"
|
|
|
|
|
echo " task frontend:dev Start frontend on default port"
|
|
|
|
|
echo " task desktop:dev Start desktop app"
|
|
|
|
|
echo " task check Quality gate (lint, typecheck, test, etc.)"
|
|
|
|
|
|
2026-04-15 15:16:57 +01:00
|
|
|
# ============================================================
|
|
|
|
|
# Setup & Prerequisites
|
|
|
|
|
# ============================================================
|
|
|
|
|
|
|
|
|
|
install:
|
|
|
|
|
desc: "Install all project dependencies"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: frontend:install
|
|
|
|
|
- task: engine:install
|
|
|
|
|
|
|
|
|
|
# ============================================================
|
|
|
|
|
# Development
|
|
|
|
|
# ============================================================
|
|
|
|
|
|
|
|
|
|
dev:
|
2026-04-28 17:26:04 +01:00
|
|
|
desc: "Start backend + frontend concurrently on free ports"
|
|
|
|
|
vars:
|
|
|
|
|
PORTS:
|
2026-05-20 13:57:41 +01:00
|
|
|
sh: '{{if eq OS "windows"}}{{.FIND_FREE_PORT_PS}} 8080 5173{{else}}{{.FIND_FREE_PORT_SH}} 8080 5173{{end}}'
|
2026-04-28 17:26:04 +01:00
|
|
|
BACKEND_PORT: '{{index (splitList "\n" .PORTS) 0}}'
|
|
|
|
|
FRONTEND_PORT: '{{index (splitList "\n" .PORTS) 1}}'
|
2026-04-15 15:16:57 +01:00
|
|
|
deps:
|
2026-04-28 17:26:04 +01:00
|
|
|
- task: backend:dev
|
|
|
|
|
vars:
|
|
|
|
|
PORT: '{{.BACKEND_PORT}}'
|
|
|
|
|
- task: frontend:dev
|
|
|
|
|
vars:
|
|
|
|
|
PORT: '{{.FRONTEND_PORT}}'
|
|
|
|
|
BACKEND_URL: 'http://localhost:{{.BACKEND_PORT}}'
|
|
|
|
|
OPEN: "true"
|
2026-04-15 15:16:57 +01:00
|
|
|
|
2026-06-22 17:22:36 +01:00
|
|
|
dev:portal:
|
2026-07-03 14:20:02 +01:00
|
|
|
desc: "Start backend + editor; the portal is an admin route at /portal"
|
2026-06-22 17:22:36 +01:00
|
|
|
vars:
|
|
|
|
|
PORTS:
|
|
|
|
|
sh: '{{if eq OS "windows"}}{{.FIND_FREE_PORT_PS}} 8080 5173{{else}}{{.FIND_FREE_PORT_SH}} 8080 5173{{end}}'
|
|
|
|
|
BACKEND_PORT: '{{index (splitList "\n" .PORTS) 0}}'
|
2026-07-03 14:20:02 +01:00
|
|
|
EDITOR_PORT: '{{index (splitList "\n" .PORTS) 1}}'
|
2026-06-22 17:22:36 +01:00
|
|
|
deps:
|
|
|
|
|
- task: backend:dev
|
|
|
|
|
vars:
|
|
|
|
|
PORT: '{{.BACKEND_PORT}}'
|
|
|
|
|
SECURITY_ENABLELOGIN: "true"
|
|
|
|
|
- task: frontend:dev:proprietary
|
|
|
|
|
vars:
|
|
|
|
|
PORT: '{{.EDITOR_PORT}}'
|
|
|
|
|
BACKEND_URL: 'http://localhost:{{.BACKEND_PORT}}'
|
2026-07-03 14:20:02 +01:00
|
|
|
OPEN: "true"
|
2026-06-22 17:22:36 +01:00
|
|
|
|
2026-08-19 14:46:00 +00:00
|
|
|
# Set SAAS_DEV_PROJECT_REF in app/.env.saas.local to pick the PR.
|
2026-05-28 12:05:30 +01:00
|
|
|
dev:saas:
|
2026-08-19 14:46:00 +00:00
|
|
|
desc: "Start SaaS backend + frontend + engine against the current PR's preview branch"
|
2026-06-11 13:20:01 +01:00
|
|
|
cmds:
|
|
|
|
|
- task: dev:_all
|
2026-08-19 14:46:00 +00:00
|
|
|
vars: { FRONTEND: saas, BACKEND: saas, SAAS_ENV: dev }
|
|
|
|
|
|
|
|
|
|
staging:saas:
|
|
|
|
|
desc: "Start SaaS backend + frontend + engine against the shared v3 staging project"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: dev:_all
|
|
|
|
|
vars:
|
|
|
|
|
FRONTEND: saas
|
|
|
|
|
BACKEND: saas
|
|
|
|
|
BACKEND_TASK: backend:staging:saas
|
|
|
|
|
SAAS_ENV: staging
|
2026-05-28 12:05:30 +01:00
|
|
|
|
2026-04-15 15:16:57 +01:00
|
|
|
dev:all:
|
2026-04-28 17:26:04 +01:00
|
|
|
desc: "Start backend + frontend + engine concurrently on free ports"
|
2026-06-11 13:20:01 +01:00
|
|
|
cmds:
|
|
|
|
|
- task: dev:_all
|
|
|
|
|
|
2026-08-27 10:32:32 +00:00
|
|
|
# No engine: linking never calls it.
|
|
|
|
|
linked:staging:
|
|
|
|
|
desc: "SaaS on the shared v3 project + a self-hosted instance linked to it"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: linked:_all
|
|
|
|
|
vars: { SAAS_ENV: staging }
|
|
|
|
|
|
|
|
|
|
linked:dev:
|
|
|
|
|
desc: "SaaS on the current PR's preview branch + a self-hosted instance linked to it"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: linked:_all
|
|
|
|
|
vars: { SAAS_ENV: dev }
|
|
|
|
|
|
|
|
|
|
linked:_all:
|
|
|
|
|
internal: true
|
|
|
|
|
vars:
|
|
|
|
|
SAAS_ENV: '{{.SAAS_ENV | default "staging"}}'
|
|
|
|
|
PORTS:
|
|
|
|
|
sh: '{{if eq OS "windows"}}{{.FIND_FREE_PORT_PS}} 8081 5174 8080 5173{{else}}{{.FIND_FREE_PORT_SH}} 8081 5174 8080 5173{{end}}'
|
|
|
|
|
SAAS_BACKEND_PORT: '{{index (splitList "\n" .PORTS) 0}}'
|
|
|
|
|
SAAS_FRONTEND_PORT: '{{index (splitList "\n" .PORTS) 1}}'
|
|
|
|
|
APP_BACKEND_PORT: '{{index (splitList "\n" .PORTS) 2}}'
|
|
|
|
|
APP_FRONTEND_PORT: '{{index (splitList "\n" .PORTS) 3}}'
|
|
|
|
|
deps:
|
|
|
|
|
# APP_BASE_URL is the SaaS *frontend*: the approval page is served by vite, not
|
|
|
|
|
# by the API. BASE_PATH moves this backend's configs/pipeline aside so it does not
|
|
|
|
|
# race the self-hosted one, which keeps ./configs and its existing database.
|
|
|
|
|
- task: 'backend:{{.SAAS_ENV}}:saas'
|
|
|
|
|
vars:
|
|
|
|
|
PORT: '{{.SAAS_BACKEND_PORT}}'
|
|
|
|
|
APP_BASE_URL: 'http://localhost:{{.SAAS_FRONTEND_PORT}}'
|
|
|
|
|
BASE_PATH: 'tmp/linked-saas'
|
|
|
|
|
- task: frontend:dev:saas
|
|
|
|
|
vars:
|
|
|
|
|
PORT: '{{.SAAS_FRONTEND_PORT}}'
|
|
|
|
|
BACKEND_URL: 'http://localhost:{{.SAAS_BACKEND_PORT}}'
|
|
|
|
|
SAAS_ENV: '{{.SAAS_ENV}}'
|
|
|
|
|
- task: backend:dev:linked
|
|
|
|
|
vars:
|
|
|
|
|
PORT: '{{.APP_BACKEND_PORT}}'
|
|
|
|
|
SAAS_BASE_URL: 'http://localhost:{{.SAAS_BACKEND_PORT}}'
|
|
|
|
|
- task: frontend:dev:proprietary
|
|
|
|
|
vars:
|
|
|
|
|
PORT: '{{.APP_FRONTEND_PORT}}'
|
|
|
|
|
BACKEND_URL: 'http://localhost:{{.APP_BACKEND_PORT}}'
|
|
|
|
|
OPEN: "true"
|
|
|
|
|
- task: linked:_ready
|
|
|
|
|
vars:
|
|
|
|
|
SAAS_BACKEND_PORT: '{{.SAAS_BACKEND_PORT}}'
|
|
|
|
|
SAAS_FRONTEND_PORT: '{{.SAAS_FRONTEND_PORT}}'
|
|
|
|
|
APP_BACKEND_PORT: '{{.APP_BACKEND_PORT}}'
|
|
|
|
|
APP_FRONTEND_PORT: '{{.APP_FRONTEND_PORT}}'
|
|
|
|
|
|
|
|
|
|
# Waits for all four to answer, then prints where they landed.
|
|
|
|
|
linked:_ready:
|
|
|
|
|
internal: true
|
|
|
|
|
cmds:
|
|
|
|
|
- cmd: |
|
|
|
|
|
n=0
|
|
|
|
|
ok=0
|
|
|
|
|
while [ "$n" -lt 150 ]; do
|
|
|
|
|
ok=1
|
|
|
|
|
for u in "http://localhost:{{.SAAS_BACKEND_PORT}}" \
|
|
|
|
|
"http://localhost:{{.SAAS_FRONTEND_PORT}}" \
|
|
|
|
|
"http://localhost:{{.APP_BACKEND_PORT}}" \
|
|
|
|
|
"http://localhost:{{.APP_FRONTEND_PORT}}"; do
|
|
|
|
|
# Not -o /dev/null: Windows curl.exe treats it as a real path and exits 23.
|
|
|
|
|
curl -s -m 2 "$u" >/dev/null 2>&1 || ok=0
|
|
|
|
|
done
|
|
|
|
|
if [ "$ok" = 1 ]; then break; fi
|
|
|
|
|
n=$((n + 1))
|
|
|
|
|
# `sleep` is a binary, not a builtin, and Windows has none.
|
|
|
|
|
{{if eq OS "windows"}}powershell -NoProfile -Command "Start-Sleep -Seconds 2"{{else}}sleep 2{{end}}
|
|
|
|
|
done
|
|
|
|
|
echo ""
|
|
|
|
|
if [ "$ok" = 1 ]; then
|
|
|
|
|
echo ">> all four answering"
|
|
|
|
|
else
|
|
|
|
|
echo ">> still waiting on one or more after 5 minutes; addresses below anyway"
|
|
|
|
|
fi
|
|
|
|
|
echo ">> self-hosted UI http://localhost:{{.APP_FRONTEND_PORT}}/processor"
|
|
|
|
|
echo ">> self-hosted api http://localhost:{{.APP_BACKEND_PORT}}"
|
|
|
|
|
echo ">> saas UI http://localhost:{{.SAAS_FRONTEND_PORT}}"
|
|
|
|
|
echo ">> saas api http://localhost:{{.SAAS_BACKEND_PORT}}"
|
|
|
|
|
echo ""
|
|
|
|
|
|
2026-06-11 13:20:01 +01:00
|
|
|
dev:_all:
|
|
|
|
|
internal: true
|
2026-04-28 17:26:04 +01:00
|
|
|
vars:
|
2026-06-11 13:20:01 +01:00
|
|
|
FRONTEND: '{{.FRONTEND | default "proprietary"}}'
|
|
|
|
|
BACKEND: '{{.BACKEND | default "proprietary"}}'
|
2026-08-19 14:46:00 +00:00
|
|
|
BACKEND_TASK: '{{.BACKEND_TASK | default (printf "backend:dev:%s" .BACKEND)}}'
|
|
|
|
|
# Only meaningful to the saas frontend; every other flavor ignores it.
|
|
|
|
|
SAAS_ENV: '{{.SAAS_ENV | default ""}}'
|
2026-04-28 17:26:04 +01:00
|
|
|
PORTS:
|
2026-05-20 13:57:41 +01:00
|
|
|
sh: '{{if eq OS "windows"}}{{.FIND_FREE_PORT_PS}} 8080 5173 5001{{else}}{{.FIND_FREE_PORT_SH}} 8080 5173 5001{{end}}'
|
2026-04-28 17:26:04 +01:00
|
|
|
BACKEND_PORT: '{{index (splitList "\n" .PORTS) 0}}'
|
|
|
|
|
FRONTEND_PORT: '{{index (splitList "\n" .PORTS) 1}}'
|
|
|
|
|
ENGINE_PORT: '{{index (splitList "\n" .PORTS) 2}}'
|
2026-04-15 15:16:57 +01:00
|
|
|
deps:
|
2026-04-28 17:26:04 +01:00
|
|
|
- task: engine:dev
|
|
|
|
|
vars:
|
|
|
|
|
PORT: '{{.ENGINE_PORT}}'
|
2026-08-19 14:46:00 +00:00
|
|
|
- task: '{{.BACKEND_TASK}}'
|
2026-04-28 17:26:04 +01:00
|
|
|
vars:
|
|
|
|
|
PORT: '{{.BACKEND_PORT}}'
|
|
|
|
|
AIENGINE_URL: 'http://localhost:{{.ENGINE_PORT}}'
|
2026-06-18 11:08:50 +01:00
|
|
|
AIENGINE_ENABLED: "true"
|
2026-06-11 13:20:01 +01:00
|
|
|
- task: 'frontend:dev:{{.FRONTEND}}'
|
2026-04-28 17:26:04 +01:00
|
|
|
vars:
|
|
|
|
|
PORT: '{{.FRONTEND_PORT}}'
|
|
|
|
|
BACKEND_URL: 'http://localhost:{{.BACKEND_PORT}}'
|
|
|
|
|
OPEN: "true"
|
2026-08-19 14:46:00 +00:00
|
|
|
SAAS_ENV: '{{.SAAS_ENV}}'
|
2026-04-15 15:16:57 +01:00
|
|
|
|
|
|
|
|
# ============================================================
|
|
|
|
|
# Build
|
|
|
|
|
# ============================================================
|
|
|
|
|
|
|
|
|
|
build:
|
|
|
|
|
desc: "Build all components"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: backend:build
|
|
|
|
|
- task: frontend:build
|
|
|
|
|
|
|
|
|
|
# ============================================================
|
|
|
|
|
# Test
|
|
|
|
|
# ============================================================
|
|
|
|
|
|
|
|
|
|
test:
|
|
|
|
|
desc: "Run ALL tests (backend + frontend + engine)"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: backend:test
|
|
|
|
|
- task: frontend:test
|
|
|
|
|
- task: engine:test
|
|
|
|
|
|
|
|
|
|
# ============================================================
|
|
|
|
|
# Lint & Format
|
|
|
|
|
# ============================================================
|
|
|
|
|
|
|
|
|
|
lint:
|
|
|
|
|
desc: "Run all linters"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: frontend:lint
|
|
|
|
|
- task: engine:lint
|
2026-08-28 10:56:50 +00:00
|
|
|
- task: comment-lint
|
|
|
|
|
|
|
|
|
|
comment-lint:
|
|
|
|
|
desc: "Check comment quality on the lines this branch adds"
|
|
|
|
|
aliases: [comments]
|
|
|
|
|
cmds:
|
|
|
|
|
- task: pre-commit:comment-lint
|
|
|
|
|
vars: { CLI_ARGS: '{{.CLI_ARGS}}' }
|
|
|
|
|
|
|
|
|
|
comment-lint:branch:
|
|
|
|
|
desc: "Check comment quality on everything this branch adds over its base"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: pre-commit:comment-lint:branch
|
|
|
|
|
vars: { BASE: '{{.BASE}}' }
|
2026-04-15 15:16:57 +01:00
|
|
|
|
|
|
|
|
fix:
|
|
|
|
|
desc: "Auto-fix all components"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: backend:fix
|
|
|
|
|
- task: frontend:fix
|
|
|
|
|
- task: engine:fix
|
|
|
|
|
|
|
|
|
|
format:
|
|
|
|
|
desc: "Auto-fix formatting across all components"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: backend:format
|
|
|
|
|
- task: frontend:format
|
|
|
|
|
- task: engine:format
|
|
|
|
|
|
|
|
|
|
format:check:
|
|
|
|
|
desc: "Check formatting across all components"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: backend:format:check
|
|
|
|
|
- task: frontend:format:check
|
|
|
|
|
- task: engine:format:check
|
|
|
|
|
|
2026-07-07 08:47:07 +01:00
|
|
|
# ============================================================
|
|
|
|
|
# Code generation
|
|
|
|
|
# ============================================================
|
|
|
|
|
|
|
|
|
|
tool-models:
|
|
|
|
|
desc: "Generate all API models from the Java OpenAPI spec"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: frontend:tool-models
|
|
|
|
|
- task: engine:tool-models
|
|
|
|
|
|
2026-08-03 15:13:43 +01:00
|
|
|
tool-models:check:
|
|
|
|
|
desc: "Fail if any committed API model is out of date"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: frontend:tool-models:check
|
|
|
|
|
- task: engine:tool-models:check
|
|
|
|
|
|
2026-04-15 15:16:57 +01:00
|
|
|
# ============================================================
|
|
|
|
|
# Quality Gate
|
|
|
|
|
# ============================================================
|
|
|
|
|
|
|
|
|
|
check:
|
|
|
|
|
desc: "Quick quality gate for local development"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: backend:check
|
|
|
|
|
- task: frontend:check
|
|
|
|
|
- task: engine:check
|
|
|
|
|
|
|
|
|
|
check:all:
|
|
|
|
|
desc: "Full CI quality gate"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: backend:check
|
|
|
|
|
- task: frontend:check:all
|
|
|
|
|
- task: engine:check
|
|
|
|
|
|
|
|
|
|
# ============================================================
|
|
|
|
|
# Clean
|
|
|
|
|
# ============================================================
|
|
|
|
|
|
|
|
|
|
clean:
|
|
|
|
|
desc: "Clean all build artifacts"
|
|
|
|
|
cmds:
|
|
|
|
|
- task: backend:clean
|
2026-06-17 17:18:50 +01:00
|
|
|
- task: frontend:clean
|
2026-04-15 15:16:57 +01:00
|
|
|
- task: engine:clean
|
2026-06-18 13:55:53 +01:00
|
|
|
- task: pre-commit:clean
|