chore(deps)(deps-dev): bump the lint group across 1 directory with 2 updates #128
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: full-stack-smoke | |
| # Boots the entire dev stack (postgres + valkey + api-dev + ui-dev + traefik) | |
| # via docker compose and exercises the register → login → /me happy path. | |
| # Requires monorepo apps/api and apps/ui (compose build contexts). | |
| # Triggered manually or on relevant pushes; slower than validate-compose. | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - "infra/compose/**" | |
| - "apps/api/**" | |
| - "apps/ui/**" | |
| - ".github/workflows/infra-compose-full-stack-smoke.yml" | |
| pull_request: | |
| paths: | |
| - "infra/compose/**" | |
| - "apps/api/**" | |
| - "apps/ui/**" | |
| - ".github/workflows/infra-compose-full-stack-smoke.yml" | |
| workflow_dispatch: | |
| concurrency: | |
| group: infra-compose-full-stack-smoke-full-stack-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| smoke: | |
| name: register → login → /me through the full stack | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Checkout monorepo | |
| uses: actions/checkout@v4 | |
| - name: Seed compose/.env | |
| working-directory: infra/compose/compose | |
| run: | | |
| cp .env.example .env | |
| # Inject the demo-user credentials the api-migrate one-shot seeds on | |
| # first boot. The smoke steps below log in as this user; without | |
| # these vars the seed script silently skips and login returns 401. | |
| { | |
| echo "" | |
| echo "# Smoke-test only — never use these in real deployments." | |
| echo "SUPERUSER_EMAIL=demo@example.com" | |
| echo "SUPERUSER_PASSWORD=password123" | |
| } >> .env | |
| - name: Make scripts executable | |
| run: | | |
| chmod +x infra/compose/compose/dev.sh | |
| chmod +x infra/compose/scripts/*.sh | |
| - name: Boot the dev stack | |
| working-directory: infra/compose/compose | |
| run: ./dev.sh up -d --build | |
| - name: Wait for API health | |
| run: | | |
| for i in {1..60}; do | |
| if curl -fsS http://localhost:3000/health > /dev/null 2>&1; then | |
| echo "API healthy after ${i}s" | |
| break | |
| fi | |
| sleep 1 | |
| done | |
| curl -fsS http://localhost:3000/health | |
| - name: Wait for UI | |
| run: | | |
| for i in {1..60}; do | |
| if curl -fsS http://localhost:3001/ > /dev/null 2>&1; then | |
| echo "UI ready after ${i}s" | |
| break | |
| fi | |
| sleep 1 | |
| done | |
| curl -fsSI http://localhost:3001/ | head -1 | |
| - name: Smoke — demo user can log in (seeded by api-migrate) | |
| run: | | |
| # The api-migrate one-shot seeds demo@example.com / password123 on | |
| # first boot. We verify the login round-trip through the Vite | |
| # proxy (so we also confirm the proxy path works end-to-end). | |
| # | |
| # We deliberately do NOT use `curl -f` here: when the server returns | |
| # a 4xx/5xx the response body almost always tells us why, and -f | |
| # discards it. Instead we capture the status code via -w and assert | |
| # on it explicitly, then dump body + status if anything looks wrong. | |
| set -euo pipefail | |
| run_curl() { | |
| local label="$1" url="$2" expected_status="$3" | |
| shift 3 | |
| local out status body | |
| out=$(curl -sS -o /tmp/body -w '%{http_code}' "$url" "$@") || { | |
| echo "❌ ${label}: curl failed (exit $?). url=${url}" >&2 | |
| cat /tmp/body >&2 || true | |
| return 1 | |
| } | |
| status="$out" | |
| body="$(cat /tmp/body)" | |
| if [ "$status" != "$expected_status" ]; then | |
| echo "❌ ${label}: expected HTTP ${expected_status}, got ${status}" >&2 | |
| echo "URL: ${url}" >&2 | |
| echo "BODY: ${body}" >&2 | |
| return 1 | |
| fi | |
| echo "✅ ${label}: HTTP ${status}" | |
| echo "$body" | |
| } | |
| LOGIN_BODY=$(run_curl "login" \ | |
| "http://localhost:3001/api/v1/auth/login" 200 \ | |
| -c /tmp/cookie.jar \ | |
| -X POST -H "Content-Type: application/json" \ | |
| -d '{"email":"demo@example.com","password":"password123"}') | |
| echo "$LOGIN_BODY" | grep -q '"success":true' || { | |
| echo "❌ login body missing success:true — got: $LOGIN_BODY" >&2 | |
| exit 1 | |
| } | |
| ME_BODY=$(run_curl "me" \ | |
| "http://localhost:3001/api/v1/users/me" 200 \ | |
| -b /tmp/cookie.jar) | |
| echo "$ME_BODY" | grep -q "demo@example.com" || { | |
| echo "❌ /me body missing demo@example.com — got: $ME_BODY" >&2 | |
| exit 1 | |
| } | |
| - name: Set up Bun | |
| uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0 | |
| with: | |
| bun-version: 1.3.14 | |
| - name: Check UI OpenAPI schema is up to date | |
| working-directory: apps/ui | |
| run: | | |
| # The ui-dev container runs as root and writes into the bind-mounted | |
| # apps/ui node_modules from the container, so the host runner can't recreate it. | |
| # Drop root-owned bits before installing as the runner user. | |
| sudo rm -rf node_modules | |
| bun install --frozen-lockfile | |
| bun run generate:api:check | |
| - name: Run UI Playwright E2E | |
| working-directory: apps/ui | |
| timeout-minutes: 12 | |
| env: | |
| PLAYWRIGHT_REUSE_SERVER: "true" | |
| run: | | |
| bun run e2e:install:chromium | |
| bun run e2e:ci:chromium | |
| - name: Smoke — register a brand-new user | |
| run: | | |
| set -e | |
| BODY='{"email":"ci-smoke@example.com","password":"Hunter2Strong!","firstName":"CI","lastName":"Smoke"}' | |
| OUT=$(curl -fsS -X POST -H "Content-Type: application/json" -d "$BODY" \ | |
| http://localhost:3001/api/v1/auth/register) | |
| echo "$OUT" | grep -q '"success":true' | |
| - name: Smoke — dashboard endpoints return real data | |
| run: | | |
| set -e | |
| # Log in to get a cookie: | |
| curl -fsS -c /tmp/cookie.jar -X POST -H "Content-Type: application/json" \ | |
| -d '{"email":"demo@example.com","password":"password123"}' \ | |
| http://localhost:3001/api/v1/auth/login > /dev/null | |
| # Summary should now reflect >=1 user + >=1 widget after seed/register. | |
| SUM=$(curl -fsS -b /tmp/cookie.jar http://localhost:3001/api/v1/dashboard/summary) | |
| echo "$SUM" | grep -q '"totalEvents"' | |
| echo "$SUM" | grep -q '"recentActivity"' | |
| - name: Compose ps on failure | |
| if: failure() | |
| working-directory: infra/compose/compose | |
| run: | | |
| docker compose -f docker-compose.yml -f docker-compose.development-labels.yml --profile dev ps | |
| - name: Container logs on failure | |
| if: failure() | |
| run: | | |
| # Full logs (not --tail) so request-time errors aren't hidden | |
| # behind startup chatter. | |
| for c in $(docker ps -aq); do | |
| echo "===== $(docker inspect --format '{{.Name}}' "$c") =====" | |
| docker logs "$c" 2>&1 || true | |
| done | |
| - name: Tear down | |
| if: always() | |
| working-directory: infra/compose/compose | |
| run: | | |
| ./dev.sh down -v || true |