diff --git a/.github/actions/setup-node-env/action.yml b/.github/actions/setup-node-env/action.yml index 3d7b97b5e..b99d9016c 100644 --- a/.github/actions/setup-node-env/action.yml +++ b/.github/actions/setup-node-env/action.yml @@ -62,6 +62,11 @@ runs: uses: oven-sh/setup-bun@v2 with: bun-version: ${{ inputs.bun-version }} + + - name: Setup Supabase CLI + uses: supabase/setup-cli@v1 + with: + version: latest - name: Install dependencies run: pnpm install --frozen-lockfile${{ inputs.install-filter && format(' --filter={0}', inputs.install-filter) || '' }} diff --git a/.github/workflows/build-lint-unit.yml b/.github/workflows/build-lint-unit.yml index ab61024ac..acd179af5 100644 --- a/.github/workflows/build-lint-unit.yml +++ b/.github/workflows/build-lint-unit.yml @@ -14,37 +14,10 @@ env: jobs: # Build job - runs in parallel build: - name: Build - runs-on: blacksmith-4vcpu-ubuntu-2404 + name: all-ci-in-one + runs-on: blacksmith-8vcpu-ubuntu-2404 timeout-minutes: 10 - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node Environment - uses: ./.github/actions/setup-node-env - with: - cache-key: build-lint-unit - - - name: Build all packages (excluding web) - run: pnpm turbo build --filter="!@buster-app/web" - env: - NODE_ENV: production - SKIP_ENV_CHECK: true - TURBO_CACHE_DIR: .turbo - TURBO_TELEMETRY_DISABLED: 1 - - - name: Typecheck web app - run: pnpm turbo typecheck --filter=@buster-app/web - env: - TURBO_CACHE_DIR: .turbo - TURBO_TELEMETRY_DISABLED: 1 - - # Lint job - runs in parallel - lint: - name: Lint - runs-on: blacksmith-2vcpu-ubuntu-2404 - timeout-minutes: 5 + environment: testing steps: - name: Checkout code uses: actions/checkout@v4 @@ -57,43 +30,402 @@ jobs: - name: Lint all packages run: pnpm turbo lint env: - TURBO_CACHE_DIR: .turbo TURBO_TELEMETRY_DISABLED: 1 - # Test job - runs after build completes - test: - name: Test - runs-on: blacksmith-4vcpu-ubuntu-2404 - timeout-minutes: 10 - steps: - - name: Checkout code - uses: actions/checkout@v4 - - - name: Setup Node Environment - uses: ./.github/actions/setup-node-env - with: - cache-key: build-lint-unit - - - name: Build required packages - run: pnpm turbo build --filter="!@buster-app/web" + - name: Build all packages + run: pnpm turbo build env: NODE_ENV: production SKIP_ENV_CHECK: true - TURBO_CACHE_DIR: .turbo TURBO_TELEMETRY_DISABLED: 1 + # Pass all secrets from the testing environment for build + DATABASE_URL: ${{ secrets.DATABASE_URL }} + SUPABASE_URL: ${{ secrets.SUPABASE_URL }} + SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }} + SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }} + VITE_PUBLIC_API_URL: ${{ secrets.VITE_PUBLIC_API_URL }} + VITE_PUBLIC_API2_URL: ${{ secrets.VITE_PUBLIC_API2_URL }} + VITE_PUBLIC_SUPABASE_URL: ${{ secrets.VITE_PUBLIC_SUPABASE_URL }} + VITE_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.VITE_PUBLIC_SUPABASE_ANON_KEY }} + VITE_PUBLIC_URL: ${{ secrets.VITE_PUBLIC_URL }} - - name: Run all unit tests - run: pnpm turbo test:unit + - name: Pre-pull Docker images + run: | + echo "๐Ÿณ Pre-pulling Docker images for faster startup..." + # Pull all images in parallel + docker pull electricsql/electric & + docker pull supabase/postgres:15.1.0.147 & + docker pull supabase/gotrue:v2.149.0 & + docker pull supabase/realtime:v2.28.32 & + docker pull supabase/postgrest:v12.2.0 & + docker pull supabase/storage-api:v0.46.4 & + docker pull supabase/postgres-meta:v0.83.2 & + docker pull supabase/studio:20240422.09 & + docker pull supabase/edge-runtime:v1.53.4 & + docker pull kong:2.8.1 & + docker pull darthsim/imgproxy:v3.8.0 & + wait + echo "โœ… Docker images pre-pulled successfully" + + - name: Start services and wait for readiness + run: pnpm turbo start + # echo "๐Ÿš€ Starting all services..." + # # Start services in background and wait for them to be ready + # ./scripts/start-and-wait-for-services.sh & + # SERVICES_PID=$! + + # # Wait for services to be ready (script will exit when ready or fail) + # wait $SERVICES_PID + + # # Services are now ready for testing + # echo "โœ… All services are ready!" env: - TURBO_CACHE_DIR: .turbo + SKIP_ENV_CHECK: true TURBO_TELEMETRY_DISABLED: 1 + # Pass all secrets from the testing environment + MOMENTIC_API_KEY: ${{ secrets.MOMENTIC_API_KEY }} + DATABASE_URL: ${{ secrets.DATABASE_URL }} + SUPABASE_URL: ${{ secrets.SUPABASE_URL }} + SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }} + SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }} + SUPABASE_PUBLIC_URL: ${{ secrets.SUPABASE_PUBLIC_URL }} + VITE_PUBLIC_API_URL: ${{ secrets.VITE_PUBLIC_API_URL }} + VITE_PUBLIC_API2_URL: ${{ secrets.VITE_PUBLIC_API2_URL }} + VITE_PUBLIC_WEB_SOCKET_URL: ${{ secrets.VITE_PUBLIC_WEB_SOCKET_URL }} + VITE_PUBLIC_URL: ${{ secrets.VITE_PUBLIC_URL }} + VITE_PUBLIC_SUPABASE_URL: ${{ secrets.VITE_PUBLIC_SUPABASE_URL }} + VITE_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.VITE_PUBLIC_SUPABASE_ANON_KEY }} + VITE_PUBLIC_WS_URL: ${{ secrets.VITE_PUBLIC_WS_URL }} + VITE_PUBLIC_POSTHOG_KEY: ${{ secrets.VITE_PUBLIC_POSTHOG_KEY }} + VITE_PUBLIC_POSTHOG_HOST: ${{ secrets.VITE_PUBLIC_POSTHOG_HOST }} + VITE_SLACK_APP_SUPPORT_URL: ${{ secrets.VITE_SLACK_APP_SUPPORT_URL }} + VITE_PRIVATE_SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.VITE_PRIVATE_SUPABASE_SERVICE_ROLE_KEY }} + SERVER_PORT: ${{ secrets.SERVER_PORT }} + ELECTRIC_PROXY_URL: ${{ secrets.ELECTRIC_PROXY_URL }} + ELECTRIC_PORT: ${{ secrets.ELECTRIC_PORT }} + ELECTRIC_INSECURE: ${{ secrets.ELECTRIC_INSECURE }} + ELECTRIC_SECRET: ${{ secrets.ELECTRIC_SECRET }} + ELECTRIC_SOURCE_ID: ${{ secrets.ELECTRIC_SOURCE_ID }} + RERANK_API_KEY: ${{ secrets.RERANK_API_KEY }} + RERANK_MODEL: ${{ secrets.RERANK_MODEL }} + RERANK_BASE_URL: ${{ secrets.RERANK_BASE_URL }} + LLM_API_KEY: ${{ secrets.LLM_API_KEY }} + LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }} + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + TURBOPUFFER_API_KEY: ${{ secrets.TURBOPUFFER_API_KEY }} + TURBOPUFFER_REGION: ${{ secrets.TURBOPUFFER_REGION }} + POSTHOG_TELEMETRY_KEY: ${{ secrets.POSTHOG_TELEMETRY_KEY }} + BRAINTRUST_KEY: ${{ secrets.BRAINTRUST_KEY }} + BRAINTRUST_API_KEY: ${{ secrets.BRAINTRUST_API_KEY }} + TRIGGER_SECRET_KEY: ${{ secrets.TRIGGER_SECRET_KEY }} + TRIGGER_ACCESS_TOKEN: ${{ secrets.TRIGGER_ACCESS_TOKEN }} + R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + R2_BUCKET: ${{ secrets.R2_BUCKET }} + GITHUB_APP_ID: ${{ secrets.GITHUB_APP_ID }} + GITHUB_APP_PRIVATE_KEY_BASE64: ${{ secrets.GITHUB_APP_PRIVATE_KEY_BASE64 }} + GITHUB_WEBHOOK_SECRET: ${{ secrets.GITHUB_WEBHOOK_SECRET }} + # Additional variables from .env + ENVIRONMENT: ${{ secrets.ENVIRONMENT }} + LOG_LEVEL: ${{ secrets.LOG_LEVEL }} + BUSTER_URL: ${{ secrets.BUSTER_URL }} + BUSTER_WH_TOKEN: ${{ secrets.BUSTER_WH_TOKEN }} + POOLER_URL: ${{ secrets.POOLER_URL }} + SERVER_URL: ${{ secrets.SERVER_URL }} + JWT_SECRET: ${{ secrets.JWT_SECRET }} + SLACK_CLIENT_ID: ${{ secrets.SLACK_CLIENT_ID }} + SLACK_CLIENT_SECRET: ${{ secrets.SLACK_CLIENT_SECRET }} + SLACK_SIGNING_SECRET: ${{ secrets.SLACK_SIGNING_SECRET }} + SLACK_APP_SUPPORT_URL: ${{ secrets.SLACK_APP_SUPPORT_URL }} + AI_GATEWAY_API_KEY: ${{ secrets.AI_GATEWAY_API_KEY }} + DAYTONA_API_KEY: ${{ secrets.DAYTONA_API_KEY }} - - name: Upload test coverage - uses: actions/upload-artifact@v4 - if: always() - with: - name: coverage - path: | - **/coverage/** - !**/coverage/tmp/** - retention-days: 7 \ No newline at end of file + # # Lint job - runs in parallel + # lint: + # name: Lint + # runs-on: blacksmith-2vcpu-ubuntu-2404 + # timeout-minutes: 5 + # needs: build + # steps: + # - name: Checkout code + # uses: actions/checkout@v4 + + # - name: Setup Node Environment + # uses: ./.github/actions/setup-node-env + # with: + # cache-key: build-lint-unit + + # - name: Lint all packages + # run: pnpm turbo lint + # env: + # TURBO_TELEMETRY_DISABLED: 1 + + # # Test job - runs in parallel + # test: + # name: Test + # runs-on: blacksmith-8vcpu-ubuntu-2404 + # timeout-minutes: 10 + # needs: build + # steps: + # - name: Checkout code + # uses: actions/checkout@v4 + + # - name: Mount node_modules sticky disk + # uses: useblacksmith/stickydisk@v1 + # with: + # key: ${{ github.repository }}-${{ github.ref_name }}-node-modules + # path: node_modules + + # - name: Mount pnpm store sticky disk + # uses: useblacksmith/stickydisk@v1 + # with: + # key: ${{ github.repository }}-${{ github.ref_name }}-pnpm-store + # path: ~/.pnpm-store + + # - name: Mount turbo cache sticky disk + # uses: useblacksmith/stickydisk@v1 + # with: + # key: ${{ github.repository }}-${{ github.ref_name }}-turbo + # path: .turbo + + # - name: Setup Node Environment + # uses: ./.github/actions/setup-node-env + # with: + # cache-key: build-lint-unit + + # - name: Run all unit tests + # run: pnpm turbo test:unit + # env: + # TURBO_TELEMETRY_DISABLED: 1 + + # - name: Upload test coverage + # uses: actions/upload-artifact@v4 + # if: always() + # with: + # name: coverage + # path: | + # **/coverage/** + # !**/coverage/tmp/** + # retention-days: 7 + + # # E2E Tests - runs after build completes + # e2e-tests: + # name: E2E Tests + # runs-on: blacksmith-8vcpu-ubuntu-2404 + # timeout-minutes: 20 + # needs: build # Wait for build to complete + # environment: testing + # steps: + # - name: Checkout code + # uses: actions/checkout@v4 + + # - name: Mount node_modules sticky disk + # uses: useblacksmith/stickydisk@v1 + # with: + # key: ${{ github.repository }}-${{ github.ref_name }}-node-modules + # path: node_modules + + # - name: Mount pnpm store sticky disk + # uses: useblacksmith/stickydisk@v1 + # with: + # key: ${{ github.repository }}-${{ github.ref_name }}-pnpm-store + # path: ~/.pnpm-store + + # - name: Mount turbo cache sticky disk + # uses: useblacksmith/stickydisk@v1 + # with: + # key: ${{ github.repository }}-${{ github.ref_name }}-turbo + # path: .turbo + + # - name: Mount Docker cache sticky disk + # uses: useblacksmith/stickydisk@v1 + # with: + # key: ${{ github.repository }}-${{ github.ref_name }}-docker-cache + # path: /var/lib/docker + + # - name: Setup Node Environment + # uses: ./.github/actions/setup-node-env + # with: + # cache-key: build-lint-unit + + + # - name: Start services + # run: | + # echo "๐Ÿš€ Starting all services (includes Supabase)..." + # # Turbo start will use cached builds from .turbo + # pnpm turbo start > turbo.log 2>&1 & + # echo $! > turbo.pid + # echo "Started turbo with PID $(cat turbo.pid)" + + # # Give services a moment to start and show initial logs + # sleep 10 + # echo "=== Initial turbo start output ===" + # head -50 turbo.log || true + # env: + # SKIP_ENV_CHECK: true + # TURBO_TELEMETRY_DISABLED: 1 + # # Pass all secrets from the testing environment + # MOMENTIC_API_KEY: ${{ secrets.MOMENTIC_API_KEY }} + # DATABASE_URL: ${{ secrets.DATABASE_URL }} + # SUPABASE_URL: ${{ secrets.SUPABASE_URL }} + # SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.SUPABASE_SERVICE_ROLE_KEY }} + # SUPABASE_ANON_KEY: ${{ secrets.SUPABASE_ANON_KEY }} + # SUPABASE_PUBLIC_URL: ${{ secrets.SUPABASE_PUBLIC_URL }} + # VITE_PUBLIC_API_URL: ${{ secrets.VITE_PUBLIC_API_URL }} + # VITE_PUBLIC_API2_URL: ${{ secrets.VITE_PUBLIC_API2_URL }} + # VITE_PUBLIC_WEB_SOCKET_URL: ${{ secrets.VITE_PUBLIC_WEB_SOCKET_URL }} + # VITE_PUBLIC_URL: ${{ secrets.VITE_PUBLIC_URL }} + # VITE_PUBLIC_SUPABASE_URL: ${{ secrets.VITE_PUBLIC_SUPABASE_URL }} + # VITE_PUBLIC_SUPABASE_ANON_KEY: ${{ secrets.VITE_PUBLIC_SUPABASE_ANON_KEY }} + # VITE_PUBLIC_WS_URL: ${{ secrets.VITE_PUBLIC_WS_URL }} + # VITE_PUBLIC_POSTHOG_KEY: ${{ secrets.VITE_PUBLIC_POSTHOG_KEY }} + # VITE_PUBLIC_POSTHOG_HOST: ${{ secrets.VITE_PUBLIC_POSTHOG_HOST }} + # VITE_SLACK_APP_SUPPORT_URL: ${{ secrets.VITE_SLACK_APP_SUPPORT_URL }} + # VITE_PRIVATE_SUPABASE_SERVICE_ROLE_KEY: ${{ secrets.VITE_PRIVATE_SUPABASE_SERVICE_ROLE_KEY }} + # SERVER_PORT: ${{ secrets.SERVER_PORT }} + # ELECTRIC_PROXY_URL: ${{ secrets.ELECTRIC_PROXY_URL }} + # ELECTRIC_PORT: ${{ secrets.ELECTRIC_PORT }} + # ELECTRIC_INSECURE: ${{ secrets.ELECTRIC_INSECURE }} + # ELECTRIC_SECRET: ${{ secrets.ELECTRIC_SECRET }} + # ELECTRIC_SOURCE_ID: ${{ secrets.ELECTRIC_SOURCE_ID }} + # RERANK_API_KEY: ${{ secrets.RERANK_API_KEY }} + # RERANK_MODEL: ${{ secrets.RERANK_MODEL }} + # RERANK_BASE_URL: ${{ secrets.RERANK_BASE_URL }} + # LLM_API_KEY: ${{ secrets.LLM_API_KEY }} + # LLM_BASE_URL: ${{ secrets.LLM_BASE_URL }} + # OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + # ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + # TURBOPUFFER_API_KEY: ${{ secrets.TURBOPUFFER_API_KEY }} + # TURBOPUFFER_REGION: ${{ secrets.TURBOPUFFER_REGION }} + # POSTHOG_TELEMETRY_KEY: ${{ secrets.POSTHOG_TELEMETRY_KEY }} + # BRAINTRUST_KEY: ${{ secrets.BRAINTRUST_KEY }} + # BRAINTRUST_API_KEY: ${{ secrets.BRAINTRUST_API_KEY }} + # TRIGGER_SECRET_KEY: ${{ secrets.TRIGGER_SECRET_KEY }} + # R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} + # R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} + # R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} + # R2_BUCKET: ${{ secrets.R2_BUCKET }} + # GITHUB_APP_ID: ${{ secrets.GITHUB_APP_ID }} + # GITHUB_APP_PRIVATE_KEY_BASE64: ${{ secrets.GITHUB_APP_PRIVATE_KEY_BASE64 }} + # GITHUB_WEBHOOK_SECRET: ${{ secrets.GITHUB_WEBHOOK_SECRET }} + # # Additional variables from .env + # ENVIRONMENT: ${{ secrets.ENVIRONMENT }} + # LOG_LEVEL: ${{ secrets.LOG_LEVEL }} + # BUSTER_URL: ${{ secrets.BUSTER_URL }} + # BUSTER_WH_TOKEN: ${{ secrets.BUSTER_WH_TOKEN }} + # POOLER_URL: ${{ secrets.POOLER_URL }} + # SERVER_URL: ${{ secrets.SERVER_URL }} + # JWT_SECRET: ${{ secrets.JWT_SECRET }} + # SLACK_CLIENT_ID: ${{ secrets.SLACK_CLIENT_ID }} + # SLACK_CLIENT_SECRET: ${{ secrets.SLACK_CLIENT_SECRET }} + # SLACK_SIGNING_SECRET: ${{ secrets.SLACK_SIGNING_SECRET }} + # SLACK_APP_SUPPORT_URL: ${{ secrets.SLACK_APP_SUPPORT_URL }} + # AI_GATEWAY_API_KEY: ${{ secrets.AI_GATEWAY_API_KEY }} + # DAYTONA_API_KEY: ${{ secrets.DAYTONA_API_KEY }} + + # - name: Wait for services to be ready + # run: | + # echo "Waiting for services to start..." + # sleep 15 + + # # Track if any service fails + # failed=false + + # # 1. Check Supabase status + # echo "๐Ÿ” Checking Supabase status..." + # # Wait a bit more for Supabase to fully start + # sleep 10 + # cd packages/database && supabase status && cd ../.. + # if [ $? -eq 0 ]; then + # echo "โœ… Supabase is healthy!" + # else + # echo "โŒ Supabase status check failed" + # failed=true + # fi + + # # 2. Check services in order: 3003 (Electric), 3002 (Server), 3001 (API), 3000 (Web) + # for port in 3003 3002 3001 3000; do + # service_name="" + # case $port in + # 3003) service_name="Electric" ;; + # 3002) service_name="Server" ;; + # 3001) service_name="API" ;; + # 3000) service_name="Web" ;; + # esac + + # echo "๐Ÿ” Checking $service_name on localhost:$port..." + # max_attempts=30 + # attempt=0 + # while [ $attempt -lt $max_attempts ]; do + # # Use curl with connection timeout and capture the http code + # http_code=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 2 --max-time 5 http://localhost:$port 2>/dev/null || echo "000") + + # # Check if we got a valid HTTP response (any 3-digit code starting with 1-5) + # if [[ "$http_code" =~ ^[1-5][0-9][0-9]$ ]]; then + # echo "โœ… $service_name on port $port is responding (HTTP $http_code)" + # break + # else + # echo " Waiting for $service_name on port $port (attempt $((attempt+1))/$max_attempts)..." + + # # Try curl with verbose error to see what's happening + # if [ $((attempt % 10)) -eq 0 ]; then + # echo " Detailed connection attempt:" + # curl -v --connect-timeout 2 --max-time 5 http://localhost:$port 2>&1 | head -10 || true + # fi + + # sleep 3 + # attempt=$((attempt+1)) + # fi + # done + # if [ $attempt -eq $max_attempts ]; then + # echo "โŒ $service_name on port $port failed to respond" + # failed=true + + # # Show logs for debugging when a service fails + # echo "=== Turbo logs at time of failure ===" + # tail -100 turbo.log || true + + # # Check if the turbo process is still running + # if [ -f turbo.pid ]; then + # if ! kill -0 $(cat turbo.pid) 2>/dev/null; then + # echo "โŒ Turbo process has crashed!" + # echo "=== Full turbo output ===" + # cat turbo.log || true + # fi + # fi + # fi + # done + + # # Exit with error if any service failed + # if [ "$failed" = true ]; then + # echo "โŒ One or more services failed to start properly" + # exit 1 + # fi + + # echo "โœ… All services are healthy!" + + # - name: Run Momentic E2E Tests + # run: | + # echo "๐Ÿงช Running Momentic E2E tests..." + # cd apps/momentic + # pnpm dlx momentic install-browsers --all + # pnpm dlx momentic run --api-key $MOMENTIC_API_KEY + # env: + # MOMENTIC_API_KEY: ${{ secrets.MOMENTIC_API_KEY }} + + # - name: Stop services + # if: always() + # run: | + # # Show final logs before stopping + # echo "=== Final turbo output ===" + # tail -100 turbo.log || true + + # if [ -f turbo.pid ]; then + # kill $(cat turbo.pid) || true + # rm turbo.pid + # fi + + # echo "๐Ÿ›‘ Stopping Supabase..." + # cd packages/database && supabase stop || true \ No newline at end of file diff --git a/apps/electric-server/scripts/start.ts b/apps/electric-server/scripts/start.ts index bb9ac36c4..871d1cabc 100644 --- a/apps/electric-server/scripts/start.ts +++ b/apps/electric-server/scripts/start.ts @@ -11,24 +11,28 @@ const __dirname = dirname(__filename); const projectRoot = join(__dirname, '..'); // Database connection details from docker-compose.yml -const DB_HOST = 'host.docker.internal'; +const DB_HOST = 'localhost'; const DB_PORT = '54322'; -const DB_NAME = 'postgres'; const DB_USER = 'postgres'; -const DB_PASSWORD = 'postgres'; // Function to check if database is accessible -function isDatabaseRunning(): boolean { +async function isDatabaseRunning(): Promise { try { // Use pg_isready to check if PostgreSQL is accepting connections - execSync(`docker run --rm postgres:15 pg_isready -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER}`, { + const result = execSync(`pg_isready -h ${DB_HOST} -p ${DB_PORT} -U ${DB_USER}`, { stdio: 'pipe', timeout: 45000 }); + console.info('pg_isready result:', result); + return true; + } catch (error) { + try { + await waitForDatabaseReady(); return true; } catch (error) { return false; } + } } // Function to check if electric service is running @@ -38,6 +42,7 @@ function isElectricRunning(): boolean { encoding: 'utf8', cwd: projectRoot }); + console.info(result); return result.includes('electric-server-electric-1') || result.includes('electric-server_electric_1'); } catch (error) { console.error('โš ๏ธ Error checking docker containers:', error); @@ -53,7 +58,7 @@ async function waitForDatabaseReady(timeoutSeconds: number = 60): Promise const timeoutMs = timeoutSeconds * 1000; while (Date.now() - startTime < timeoutMs) { - if (isDatabaseRunning()) { + if (await isDatabaseRunning()) { console.log('โœ… Database is now accessible!'); return; } @@ -130,7 +135,7 @@ async function main(): Promise { console.log('๐Ÿ” Checking system status...'); // Check if database is accessible - if (!isDatabaseRunning()) { + if (!await isDatabaseRunning()) { console.log('๐Ÿ”Œ Database not accessible. Please ensure PostgreSQL is running on port 54322'); console.log('๐Ÿ’ก You may need to start your local Supabase or PostgreSQL instance first'); process.exit(1); diff --git a/apps/momentic/tests/save-metric-to-favorites.test.yaml b/apps/momentic/tests/save-metric-to-favorites.test.yaml new file mode 100644 index 000000000..e34556781 --- /dev/null +++ b/apps/momentic/tests/save-metric-to-favorites.test.yaml @@ -0,0 +1,113 @@ +fileType: momentic/test +id: bfe02fef-22ed-40d4-9874-eca9dfdef543 +name: save-metric-to-favorites +description: Save a metric to the favorites and confirm it worked +schemaVersion: 1.0.21 +advanced: + viewport: + width: 1920 + height: 1080 + browserType: Chromium +retries: 0 +envs: + - name: development + default: true +steps: + - id: b0f51405-5b33-4297-a0bc-d12fed7e88eb + type: MODULE + moduleId: defc36e9-b0a7-4bfe-940f-7901493d5e5e + - id: 31cb958b-8e95-4b3c-9162-d9bd22b20469 + type: PRESET_ACTION + command: + id: 7e4653f4-09ea-40d1-86cb-76e3b2657e74 + type: CLICK + target: + type: description + elementDescriptor: Metrics in the left side navigation panel + - id: 341f3233-f380-4acb-a00c-7987da78ffc7 + type: PRESET_ACTION + command: + id: d48eee61-a38a-4065-b967-1bf1739a726e + type: CLICK + target: + type: description + elementDescriptor: On any Metric title from the list that does not already exist + under the Favorites on the left navigation panel + - id: 67c6dc53-130b-495c-b5f8-17207e93c285 + type: PRESET_ACTION + command: + id: 1fd3971d-91a5-491b-88ae-6b780c864935 + type: CLICK + target: + type: description + elementDescriptor: Three dot ... above the metric + - id: d2f3716f-8a34-4f2b-ab8a-571426b31d76 + type: PRESET_ACTION + command: + id: 2d8b55b7-4b12-4a67-af26-46c374f18030 + type: CLICK + target: + type: description + elementDescriptor: Add to favorites from the drop down + - id: 4ad9618a-bdea-4ad7-8d83-91785e6296be + type: PRESET_ACTION + command: + id: eebf59ea-282f-431c-aa16-81042ad3910e + type: AI_ASSERTION + assertion: The same title above the metric in the middle of the page or the + beginning of the title should exist as the first option under Favorites + left navigation Bar. + - id: 10b08a0d-065e-436c-b537-31a6f35e8ff8 + type: PRESET_ACTION + command: + id: 88ad5705-7ea0-4cdd-8d43-11f10e465b5e + loadTimeout: 2 + type: NAVIGATE + url: "{{env.BASE_URL}}/app/home" + - id: 3a9cd80c-ceab-4fc4-bb9e-cc119c8b2b03 + type: PRESET_ACTION + command: + id: a4f92783-eb8f-41db-a8e0-771f307796d4 + type: CLICK + target: + type: description + elementDescriptor: The first title under Favorites in the navigation bar + - id: 7e80c36e-2717-413f-8045-4d68b7da7f10 + type: PRESET_ACTION + command: + id: 622a637e-dfb6-4b58-bf6a-9e54b3c5d692 + type: WAIT_FOR_URL + matcher: + type: SUBSTRING + url: /metrics + timeout: 2 + - id: 4094278b-4ff8-48cf-8c34-ffc71fd462d9 + type: PRESET_ACTION + command: + id: 47113c57-80ef-4676-92fc-a7bf18c2a693 + type: AI_ASSERTION + assertion: There should be a metric in the middle of the screen. Either a graph, + chart, table, or value. + - id: c93fa9b4-9f44-408d-8417-dbf4979069ea + type: PRESET_ACTION + command: + id: f5edce84-7157-4c30-a41d-7ac7350c4c11 + type: CLICK + target: + type: description + elementDescriptor: Three dots ... above the metric + - id: f88d0644-2b83-4e87-952d-9e95b753c944 + type: PRESET_ACTION + command: + id: b277bb43-9557-4066-85aa-1335402f067f + type: CLICK + target: + type: description + elementDescriptor: Remove from favorites in the dropdown + - id: d4f77644-6fca-4351-bea7-f2b89bbf0ae8 + type: PRESET_ACTION + command: + id: 73bd7307-ea43-4647-afc7-52e7119d3633 + type: AI_ASSERTION + assertion: Verify the title above the metric is not the first option below + Favorites in the left side navigation bar. diff --git a/apps/momentic/tests/share-each-asset-type.test.yaml b/apps/momentic/tests/share-each-asset-type.test.yaml new file mode 100644 index 000000000..222dfcac5 --- /dev/null +++ b/apps/momentic/tests/share-each-asset-type.test.yaml @@ -0,0 +1,76 @@ +fileType: momentic/test +id: f0f9b7ff-ed35-43f1-bacd-2b6c3eb457c7 +name: share-each-asset-type +description: Share a report with another user and make sure that they can view it as well +schemaVersion: 1.0.21 +advanced: + viewport: + width: 1920 + height: 1080 + browserType: Chromium +retries: 0 +envs: + - name: development + default: true +steps: + - id: 90190516-2ac2-4c62-99ca-ad489694182c + type: MODULE + moduleId: defc36e9-b0a7-4bfe-940f-7901493d5e5e + - id: 120c51a6-4a5a-485d-9603-0a5f5a1f6b15 + type: PRESET_ACTION + command: + id: 5038aa2a-8eea-4e19-ad77-ed8f008bc8a4 + loadTimeout: 2 + type: NAVIGATE + url: "{{env.BASE_URL}}/app/metrics" + - id: 6a9a21b7-f989-4aa1-84d0-846038d6a72f + type: PRESET_ACTION + command: + id: 17579c61-f67e-43d7-b963-aee0012453dc + type: WAIT_FOR_URL + matcher: + type: SUBSTRING + url: /metrics + timeout: 2 + - id: 4d62512b-6748-49a2-a8d5-11c4489f0376 + type: PRESET_ACTION + command: + id: 7bf9208d-a6a9-40b0-96fa-6a0b20b8029b + type: CLICK + target: + type: description + elementDescriptor: any Metric title that is private and has a C for the owner + - id: bdfb3001-afef-4f7e-9767-e01a7a39f0cf + type: PRESET_ACTION + command: + id: 5f8ae3e7-932e-4cad-b1c9-c0f4edfbeb7c + type: CLICK + target: + type: description + elementDescriptor: Three dot icon ... above the asset + - id: c8e96d19-a83d-4532-bdf0-262ec0251f98 + type: PRESET_ACTION + command: + id: f3fb21f8-d7c6-4ded-a536-8509d99e8ca0 + type: CLICK + target: + type: description + elementDescriptor: '"Share metric| dashboard | report" from the dropdown' + doubleClick: true + - id: 8faabc6c-282d-4bf3-b6a6-af2bdd1e7012 + type: PRESET_ACTION + command: + id: 0e048159-7540-4e98-bc13-58ceda51ba70 + type: CLICK + target: + type: description + elementDescriptor: the 'not shared' span in the workspace share row + doubleClick: false + - id: 1c549d2b-c954-4e07-921e-dc38efcf664e + type: PRESET_ACTION + command: + id: 3211ed30-52da-4919-977d-50164387e415 + type: CLICK + target: + type: description + elementDescriptor: the 'can edit, but not share with others' span diff --git a/apps/trigger/package.json b/apps/trigger/package.json index 89dd0cca9..607c05795 100644 --- a/apps/trigger/package.json +++ b/apps/trigger/package.json @@ -5,7 +5,7 @@ "type": "module", "scripts": { "dev": "echo 'y' | npx trigger.dev@latest dev --env-file ../../.env", - "dev:fast": "echo 'y' | npx trigger.dev@latest dev", + "dev:fast": "echo 'y' | npx trigger.dev@latest login &&echo 'y' | npx trigger.dev@latest dev", "start": "pnpm run dev:fast", "deploy": "echo 'y' | npx trigger.dev@latest deploy", "build": "echo 'No build step required' && tsc --noEmit", diff --git a/apps/web/turbo.json b/apps/web/turbo.json index 74d73043c..a41399fd4 100644 --- a/apps/web/turbo.json +++ b/apps/web/turbo.json @@ -32,7 +32,7 @@ "outputs": [".output/**", ".vercel/**"] }, "start": { - "dependsOn": ["build", "@buster-app/supabase#start"], + "dependsOn": ["build", "@buster-app/supabase#start", "@buster/database#start"], "cache": true, "persistent": true, "with": ["@buster-app/server#start", "@buster-app/api-legacy#start"] diff --git a/apps/web/vite.config.ts b/apps/web/vite.config.ts index 42829e9b3..9156e8cab 100644 --- a/apps/web/vite.config.ts +++ b/apps/web/vite.config.ts @@ -58,6 +58,7 @@ const config = defineConfig(({ command, mode }) => { build: { chunkSizeWarningLimit: 1250, minify: isProduction ? 'esbuild' : false, + sourcemap: false, // Disable source maps to reduce cache size reportCompressedSize: false, // Disable gzip size reporting to speed up build rollupOptions: { // Exclude test and stories files from build diff --git a/packages/server-shared/turbo.json b/packages/server-shared/turbo.json index 63f98b106..ba80cbcd0 100644 --- a/packages/server-shared/turbo.json +++ b/packages/server-shared/turbo.json @@ -9,8 +9,7 @@ "!src/**/*.spec.{ts,tsx,js,jsx}", "package.json", "tsconfig.json" - ], - "outputs": ["dist/**/*"] + ] }, "dev": { "cache": false, diff --git a/scripts/start-and-wait-for-services.sh b/scripts/start-and-wait-for-services.sh new file mode 100755 index 000000000..b5ed62911 --- /dev/null +++ b/scripts/start-and-wait-for-services.sh @@ -0,0 +1,119 @@ +#!/bin/bash + +set -e + +echo "๐Ÿš€ Starting services in background..." + +# Start turbo in background and capture PID +pnpm turbo start > turbo.log 2>&1 & +TURBO_PID=$! +echo $TURBO_PID > turbo.pid +echo "Started turbo with PID $TURBO_PID" + +# Function to cleanup on exit +cleanup() { + echo "๐Ÿ›‘ Cleaning up..." + if [ -f turbo.pid ]; then + kill $(cat turbo.pid) 2>/dev/null || true + rm turbo.pid + fi +} +trap cleanup EXIT + +# Function to check if a service is ready +check_service() { + local port=$1 + local service_name=$2 + local max_attempts=60 + local attempt=0 + + echo "๐Ÿ” Checking $service_name on port $port..." + + while [ $attempt -lt $max_attempts ]; do + if curl -s --connect-timeout 2 --max-time 5 http://localhost:$port > /dev/null 2>&1; then + echo "โœ… $service_name is ready!" + return 0 + fi + + echo " Waiting for $service_name (attempt $((attempt+1))/$max_attempts)..." + sleep 3 + attempt=$((attempt+1)) + done + + echo "โŒ $service_name failed to start on port $port" + return 1 +} + +# Function to check database +check_database() { + local max_attempts=40 + local attempt=0 + + echo "๐Ÿ” Checking database connectivity..." + + while [ $attempt -lt $max_attempts ]; do + if pg_isready -h localhost -p 54322 -U postgres > /dev/null 2>&1; then + echo "โœ… Database is ready!" + return 0 + fi + + echo " Waiting for database (attempt $((attempt+1))/$max_attempts)..." + sleep 2 + attempt=$((attempt+1)) + done + + echo "โŒ Database failed to start" + return 1 +} + +# Wait for services to start +echo "โณ Waiting for services to be ready..." + +# Check database first (foundational service) +if ! check_database; then + echo "๐Ÿ’ฅ Database startup failed" + exit 1 +fi + +# Check other services in dependency order +# Note: Adjust ports based on your actual service ports +services=( + "3003:Electric" + "3002:Server" + "3001:API" + "3000:Web" +) + +failed_services=() +for service in "${services[@]}"; do + port=$(echo $service | cut -d: -f1) + name=$(echo $service | cut -d: -f2) + + if ! check_service $port "$name"; then + failed_services+=("$name") + fi +done + +# Report results +if [ ${#failed_services[@]} -eq 0 ]; then + echo "๐ŸŽ‰ All services are ready!" + echo "Services started successfully. You can now run additional commands." + + # Show current status + echo "๐Ÿ“Š Service Status:" + echo " Database: โœ… (port 54322)" + for service in "${services[@]}"; do + port=$(echo $service | cut -d: -f1) + name=$(echo $service | cut -d: -f2) + echo " $name: โœ… (port $port)" + done + + # Keep running (don't exit) + echo "๐Ÿ”„ Services running in background. Press Ctrl+C to stop." + wait $TURBO_PID +else + echo "๐Ÿ’ฅ Some services failed to start: ${failed_services[*]}" + echo "=== Turbo logs ===" + tail -50 turbo.log || true + exit 1 +fi