name: Test CI on: [push, pull_request] permissions: actions: write contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: # Check for duplicate runs check-duplicate-run: name: Check Duplicate Run runs-on: ubuntu-latest outputs: should_skip: ${{ steps.skip_check.outputs.should_skip }} steps: - id: skip_check uses: fkirc/skip-duplicate-actions@v5 with: concurrent_skipping: 'same_content_newer' skip_after_successful_duplicate: 'true' do_not_skip: '["workflow_dispatch", "schedule"]' # Package tests - all packages in single job to save runner resources test-packages: needs: check-duplicate-run if: needs.check-duplicate-run.outputs.should_skip != 'true' runs-on: ubuntu-latest name: Test Packages env: PACKAGES: '@lobechat/file-loaders @lobechat/prompts @lobechat/model-runtime @lobechat/web-crawler @lobechat/electron-server-ipc @lobechat/utils @lobechat/context-engine @lobechat/agent-runtime @lobechat/conversation-flow @lobechat/ssrf-safe-fetch @lobechat/memory-user-memory @lobechat/types @lobechat/trpc @lobechat/app-config @lobechat/locales @lobechat/env @lobechat/builtin-tool-lobe-agent model-bank @lobechat/agent-gateway-client @lobechat/agent-manager-runtime @lobechat/device-gateway-client @lobechat/device-identity @lobechat/eval-dataset-parser @lobechat/eval-rubric @lobechat/fetch-sse @lobechat/heterogeneous-agents' steps: - name: Checkout env: REF_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} REPOSITORY: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }} run: | git init . git remote add origin "https://github.com/${REPOSITORY}.git" git fetch --no-tags --depth=1 origin "${REF_SHA}" git checkout --force FETCH_HEAD - name: Setup environment uses: ./.github/actions/setup-env - name: Install deps run: pnpm install - name: Test packages with coverage run: | for package in $PACKAGES; do echo "::group::Testing $package" bun run --filter $package test:coverage echo "::endgroup::" done - name: Upload coverage to Codecov if: always() env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} run: | curl -Os https://cli.codecov.io/latest/linux/codecov chmod +x codecov # Build common args COMMON_ARGS="--git-service github" # PR args setup if [ "${{ github.event_name }}" == "pull_request" ]; then COMMON_ARGS="$COMMON_ARGS --pr ${{ github.event.pull_request.number }}" COMMON_ARGS="$COMMON_ARGS --sha ${{ github.event.pull_request.head.sha }}" # Fork PR needs username:branch format for tokenless upload if [ "${{ github.event.pull_request.head.repo.full_name }}" != "${{ github.repository }}" ]; then COMMON_ARGS="$COMMON_ARGS --branch ${{ github.event.pull_request.head.label }}" else COMMON_ARGS="$COMMON_ARGS --branch ${{ github.event.pull_request.head.ref }}" fi fi # Token (if available) if [ -n "$CODECOV_TOKEN" ]; then COMMON_ARGS="$COMMON_ARGS -t $CODECOV_TOKEN" fi for package in $PACKAGES; do dir="${package#@lobechat/}" if [ -f "./packages/$dir/coverage/lcov.info" ]; then flag="packages/$dir" case "$dir" in builtin-tool-*) flag="builtin-tools" ;; locales|env|device-gateway-client) echo "Skipping Codecov upload for $dir." continue ;; esac echo "Uploading coverage for $dir as $flag..." ./codecov upload-coverage \ $COMMON_ARGS \ --file ./packages/$dir/coverage/lcov.info \ --flag "$flag" \ --disable-search fi done # App tests - run sharded tests test-app: needs: check-duplicate-run if: needs.check-duplicate-run.outputs.should_skip != 'true' strategy: matrix: shard: [1, 2] name: Test App (shard ${{ matrix.shard }}/2) runs-on: ubuntu-latest steps: - name: Checkout env: REF_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} REPOSITORY: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }} run: | git init . git remote add origin "https://github.com/${REPOSITORY}.git" git fetch --no-tags --depth=1 origin "${REF_SHA}" git checkout --force FETCH_HEAD - name: Setup environment uses: ./.github/actions/setup-env - name: Install deps run: pnpm install - name: Run tests run: bunx vitest --coverage --silent='passed-only' --reporter=default --reporter=blob --shard=${{ matrix.shard }}/2 --exclude '**/apps/server/**' - name: Upload blob report if: ${{ !cancelled() }} uses: actions/upload-artifact@v6 with: name: blob-report-${{ matrix.shard }} path: .vitest-reports include-hidden-files: true retention-days: 1 # Merge sharded test reports and upload coverage merge-app-coverage: needs: test-app if: ${{ !cancelled() && needs.test-app.result == 'success' }} name: Merge and Upload App Coverage runs-on: ubuntu-latest steps: - name: Checkout env: REF_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} REPOSITORY: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }} run: | git init . git remote add origin "https://github.com/${REPOSITORY}.git" git fetch --no-tags --depth=1 origin "${REF_SHA}" git checkout --force FETCH_HEAD - name: Setup environment uses: ./.github/actions/setup-env - name: Install deps run: pnpm install - name: Download blob reports uses: actions/download-artifact@v7 with: path: .vitest-reports pattern: blob-report-* merge-multiple: true - name: Merge reports run: bunx vitest --merge-reports --reporter=default --coverage - name: Upload App Coverage to Codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./coverage/app/lcov.info flags: app test-desktop: needs: check-duplicate-run if: needs.check-duplicate-run.outputs.should_skip != 'true' name: Test Desktop App runs-on: ubuntu-latest steps: - name: Checkout env: REF_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} REPOSITORY: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }} run: | git init . git remote add origin "https://github.com/${REPOSITORY}.git" git fetch --no-tags --depth=1 origin "${REF_SHA}" git checkout --force FETCH_HEAD - name: Setup environment uses: ./.github/actions/setup-env - name: Install deps run: pnpm install working-directory: apps/desktop env: NODE_OPTIONS: --max-old-space-size=8192 - name: Typecheck Desktop run: pnpm type-check working-directory: apps/desktop - name: Test Desktop Client run: pnpm test working-directory: apps/desktop - name: Upload Desktop App Coverage to Codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./apps/desktop/coverage/lcov.info flags: desktop test-server: needs: check-duplicate-run if: needs.check-duplicate-run.outputs.should_skip != 'true' name: Test Server runs-on: ubuntu-latest steps: - name: Checkout env: REF_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} REPOSITORY: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }} run: | git init . git remote add origin "https://github.com/${REPOSITORY}.git" git fetch --no-tags --depth=1 origin "${REF_SHA}" git checkout --force FETCH_HEAD - name: Setup environment uses: ./.github/actions/setup-env - name: Install deps run: pnpm install - name: Test Server Coverage run: bunx vitest --coverage --silent='passed-only' --reporter=default --coverage.reportsDirectory=./apps/server/coverage --dir apps/server - name: Upload Server coverage to Codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./apps/server/coverage/lcov.info flags: server test-databsae: needs: check-duplicate-run if: needs.check-duplicate-run.outputs.should_skip != 'true' name: Test Database runs-on: ubuntu-latest services: postgres: image: paradedb/paradedb:latest env: POSTGRES_PASSWORD: postgres options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 steps: - name: Checkout env: REF_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} REPOSITORY: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name || github.repository }} run: | git init . git remote add origin "https://github.com/${REPOSITORY}.git" git fetch --no-tags --depth=1 origin "${REF_SHA}" git checkout --force FETCH_HEAD - name: Setup environment uses: ./.github/actions/setup-env - name: Install deps run: pnpm i - name: Lint run: bun run lint - name: Test Coverage run: pnpm --filter @lobechat/database test:coverage env: DATABASE_TEST_URL: postgresql://postgres:postgres@localhost:5432/postgres DATABASE_DRIVER: node KEY_VAULTS_SECRET: Kix2wcUONd4CX51E/ZPAd36BqM4wzJgKjPtz2sGztqQ= S3_PUBLIC_DOMAIN: https://example.com APP_URL: https://home.com - name: Upload Database coverage to Codecov uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} files: ./packages/database/coverage/lcov.info flags: database