name: CLI Smoke Test on: push: branches: [ main ] paths: - 'packages/happy-cli/**' - 'packages/happy-server/**' - '.github/workflows/cli-smoke-test.yml' pull_request: branches: [ main ] paths: - 'packages/happy-cli/**' - 'packages/happy-server/**' - '.github/workflows/cli-smoke-test.yml' workflow_dispatch: jobs: smoke-test-linux: runs-on: ubuntu-latest strategy: matrix: node-version: [20, 24] steps: - name: Checkout code uses: actions/checkout@v4 - name: Install pnpm uses: pnpm/action-setup@v4 - name: Setup Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Build package run: pnpm --filter happy build # `happy server` resolves the self-host runtime and bundled webapp from # happy-server-self-host. The server package is JS/TS and lets npm install # platform-specific dependencies such as Prisma and sharp normally. - name: Generate Prisma client + bundle happy-server-self-host webapp run: | pnpm --filter happy-server-self-host generate pnpm --filter happy-server-self-host run bundle:webapp - name: Pack packages run: | pnpm --filter happy pack --pack-destination packages/happy-cli pnpm --filter happy-server-self-host pack --pack-destination packages/happy-server - name: Install packed packages globally run: | HAPPY_PACKAGE_FILE=$(ls packages/happy-cli/*.tgz) SERVER_PACKAGE_FILE=$(ls packages/happy-server/*.tgz) npm install -g "./$SERVER_PACKAGE_FILE" "./$HAPPY_PACKAGE_FILE" - name: Test binary execution run: | # Test that the binary starts successfully echo "Testing happy --help..." timeout 30s happy --help || { echo "Error: happy --help failed or timed out" exit 1 } echo "Testing happy --version..." timeout 10s happy --version || { echo "Error: happy --version failed or timed out" exit 1 } echo "Testing happy doctor..." timeout 30s happy doctor || { echo "Error: happy doctor failed or timed out" exit 1 } echo "Testing happy daemon status..." timeout 10s happy daemon status || { echo "Error: happy daemon status failed or timed out" exit 1 } echo "Binary smoke test passed on Linux!" - name: Test packaged server (happy server) run: | export HAPPY_HOME_DIR="$(mktemp -d)" timeout 90s happy server --port 4505 --host 127.0.0.1 --no-persist --reset > /tmp/happy-server.log 2>&1 & SERVER_PID=$! UP=0 for i in $(seq 1 60); do if curl -sf -m 2 http://127.0.0.1:4505/ -o /dev/null; then UP=1; echo "server up after ${i}s"; break; fi sleep 1 done # Exercise the Prisma native query engine via a DB-backed read. PK=$(node -e "console.log(Buffer.alloc(32).toString('base64'))") BODY=$(curl -s -m 5 -G http://127.0.0.1:4505/v1/auth/request/status --data-urlencode "publicKey=$PK" || true) echo "auth/request/status -> $BODY" kill "$SERVER_PID" 2>/dev/null || true pkill -f happy-server || true echo "=== happy server log ==="; cat /tmp/happy-server.log || true if [ "$UP" != "1" ]; then echo "Error: happy server did not become healthy"; exit 1; fi if ! echo "$BODY" | grep -q '"status"'; then echo "Error: Prisma-backed endpoint did not respond"; exit 1; fi if grep -qiE 'PrismaClientInitializationError|could not locate.*Query Engine' /tmp/happy-server.log; then echo "Error: Prisma query engine failed to load"; exit 1; fi echo "happy server smoke test passed (booted + Prisma query engine OK)" smoke-test-windows: runs-on: windows-latest strategy: matrix: node-version: [20, 24] steps: - name: Checkout code uses: actions/checkout@v4 - name: Install pnpm uses: pnpm/action-setup@v4 - name: Setup Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Build package run: pnpm --filter happy build - name: Pack package run: pnpm --filter happy pack --pack-destination packages/happy-cli - name: Install packed package globally shell: cmd run: | for %%f in (packages\happy-cli\*.tgz) do npm install -g "%%f" - name: Debug npm global installation structure shell: cmd run: | for /f "tokens=*" %%i in ('npm config get prefix') do set NPM_PREFIX=%%i echo NPM_PREFIX: %NPM_PREFIX% echo Listing npm prefix directory: dir "%NPM_PREFIX%" 2>nul || echo Failed to list NPM_PREFIX echo. echo Checking for node_modules in npm prefix: if exist "%NPM_PREFIX%\node_modules" ( echo Found node_modules directory dir "%NPM_PREFIX%\node_modules" 2>nul echo. echo Checking for happy package: if exist "%NPM_PREFIX%\node_modules\happy" ( echo Found happy package dir "%NPM_PREFIX%\node_modules\happy" 2>nul echo. echo Checking for dist directory: if exist "%NPM_PREFIX%\node_modules\happy\dist" ( echo Found dist directory dir "%NPM_PREFIX%\node_modules\happy\dist" 2>nul ) else ( echo No dist directory found ) ) else ( echo No happy package found ) ) else ( echo No node_modules directory found ) - name: Test binary execution shell: cmd run: | @echo on rem Get npm global prefix and add to PATH for /f "tokens=*" %%i in ('npm config get prefix') do set NPM_PREFIX=%%i set PATH=%NPM_PREFIX%;%PATH% echo NPM_PREFIX: %NPM_PREFIX% echo Current PATH: %PATH% rem Debug: Check if happy exists in various locations echo Checking for happy binary... where happy 2>nul && echo Found happy in PATH || echo happy not found in PATH if exist "%NPM_PREFIX%\happy.cmd" echo Found happy.cmd in NPM_PREFIX if exist "%NPM_PREFIX%\node_modules\.bin\happy.cmd" echo Found happy.cmd in .bin directory dir "%NPM_PREFIX%\*happy*" 2>nul || echo No happy files found in NPM_PREFIX rem Debug: Check the actual contents and encoding of the installed file if exist "%NPM_PREFIX%\happy.cmd" ( echo File size and type: dir "%NPM_PREFIX%\happy.cmd" echo. echo First few lines of the file: type "%NPM_PREFIX%\happy.cmd" | head -5 echo. echo Hex dump of first 50 bytes to check line endings: powershell -Command "Get-Content '%NPM_PREFIX%\happy.cmd' -Encoding Byte -TotalCount 50 | ForEach-Object { '{0:X2}' -f $_ } | Join-String -Separator ' '" echo. echo Testing with direct path... "%NPM_PREFIX%\happy.cmd" --help ) else ( echo Testing happy --help... happy --help ) if errorlevel 1 ( echo Error: happy --help failed exit /b 1 ) rem Test version if exist "%NPM_PREFIX%\happy.cmd" ( "%NPM_PREFIX%\happy.cmd" --version ) else ( happy --version ) if errorlevel 1 ( echo Error: happy --version failed exit /b 1 ) rem Test doctor echo Testing happy doctor... if exist "%NPM_PREFIX%\happy.cmd" ( "%NPM_PREFIX%\happy.cmd" doctor ) else ( happy doctor ) if errorlevel 1 ( echo Error: happy doctor failed exit /b 1 ) rem Test daemon status echo Testing happy daemon status... if exist "%NPM_PREFIX%\happy.cmd" ( "%NPM_PREFIX%\happy.cmd" daemon status ) else ( happy daemon status ) if errorlevel 1 ( echo Error: happy daemon status failed exit /b 1 ) echo Smoke test passed on Windows! # We don't need a smoke test for macOS because most contributors are developing on macOS.