Skip to main content
Glama
ci.yml11.5 kB
name: CI Pipeline on: push: branches: [ main, develop ] pull_request: branches: [ main, develop ] workflow_dispatch: env: PYTHON_VERSION: "3.11" UV_CACHE_DIR: /tmp/.uv-cache jobs: setup: name: Setup and Cache runs-on: ubuntu-latest outputs: cache-hit: ${{ steps.cache-uv.outputs.cache-hit }} python-version: ${{ env.PYTHON_VERSION }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install UV uses: astral-sh/setup-uv@v3 with: enable-cache: true - name: Cache UV dependencies id: cache-uv uses: actions/cache@v4 with: path: ${{ env.UV_CACHE_DIR }} key: ${{ runner.os }}-uv-${{ hashFiles('**/uv.lock', '**/pyproject.toml') }} restore-keys: | ${{ runner.os }}-uv- - name: Install dependencies if: steps.cache-uv.outputs.cache-hit != 'true' run: | uv sync --dev --all-extras uv pip install --system bandit[toml] safety lint: name: Code Quality & Linting runs-on: ubuntu-latest needs: setup strategy: matrix: check: [black, isort, flake8, mypy] steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ needs.setup.outputs.python-version }} - name: Install UV uses: astral-sh/setup-uv@v3 with: enable-cache: true - name: Restore UV cache uses: actions/cache@v4 with: path: ${{ env.UV_CACHE_DIR }} key: ${{ runner.os }}-uv-${{ hashFiles('**/uv.lock', '**/pyproject.toml') }} - name: Install dependencies run: uv sync --dev --all-extras - name: Run Black (formatting check) if: matrix.check == 'black' run: uv run black --check --diff . - name: Run isort (import sorting check) if: matrix.check == 'isort' run: uv run isort --check-only --diff . - name: Run Flake8 (linting) if: matrix.check == 'flake8' run: uv run flake8 packages/ mcp-server/ || true - name: Run MyPy (type checking) if: matrix.check == 'mypy' run: | uv run mypy packages/mcp-server/src/ || true uv run mypy packages/dashboard-api/src/ || true uv run mypy packages/shared/src/ || true test: name: Test Suite runs-on: ubuntu-latest needs: setup strategy: matrix: package: [mcp-server, dashboard-api, shared, database] services: postgres: image: postgres:15 env: POSTGRES_PASSWORD: testpass POSTGRES_USER: testuser POSTGRES_DB: tiger_mcp_test options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 5432:5432 redis: image: redis:7-alpine options: >- --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 ports: - 6379:6379 steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ needs.setup.outputs.python-version }} - name: Install UV uses: astral-sh/setup-uv@v3 with: enable-cache: true - name: Restore UV cache uses: actions/cache@v4 with: path: ${{ env.UV_CACHE_DIR }} key: ${{ runner.os }}-uv-${{ hashFiles('**/uv.lock', '**/pyproject.toml') }} - name: Install dependencies run: uv sync --dev --all-extras - name: Setup test environment run: | cp .env.template .env || echo "No .env.template found" echo "DATABASE_URL=postgresql://testuser:testpass@localhost:5432/tiger_mcp_test" >> .env echo "REDIS_URL=redis://localhost:6379/0" >> .env echo "TIGER_PRIVATE_KEY=dummy" >> .env echo "TIGER_CLIENT_ID=test" >> .env echo "TIGER_ACCOUNT=test" >> .env - name: Run package tests run: | if [ -d "packages/${{ matrix.package }}" ]; then cd packages/${{ matrix.package }} uv run pytest tests/ -v --cov=src --cov-report=xml --cov-report=term-missing || true elif [ "${{ matrix.package }}" == "mcp-server" ] && [ -d "mcp-server" ]; then cd mcp-server uv run pytest tests/ -v --cov=. --cov-report=xml --cov-report=term-missing || true else echo "Package ${{ matrix.package }} not found, skipping tests" fi - name: Upload coverage reports if: matrix.package != 'database' uses: codecov/codecov-action@v4 with: file: packages/${{ matrix.package }}/coverage.xml flags: ${{ matrix.package }} name: codecov-${{ matrix.package }} security: name: Security Scanning runs-on: ubuntu-latest needs: setup steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ needs.setup.outputs.python-version }} - name: Install UV uses: astral-sh/setup-uv@v3 with: enable-cache: true - name: Restore UV cache uses: actions/cache@v4 with: path: ${{ env.UV_CACHE_DIR }} key: ${{ runner.os }}-uv-${{ hashFiles('**/uv.lock', '**/pyproject.toml') }} - name: Install dependencies run: | uv sync --dev --all-extras uv pip install --system bandit[toml] safety - name: Run Bandit security linter run: | uv run bandit -r packages/ mcp-server/ -f json -o bandit-report.json || true uv run bandit -r packages/ mcp-server/ || true - name: Run Safety dependency scanner run: | uv pip freeze | uv run safety check --stdin --json --output safety-report.json || true uv pip freeze | uv run safety check --stdin || true - name: Upload security reports uses: actions/upload-artifact@v4 if: always() with: name: security-reports path: | bandit-report.json safety-report.json retention-days: 30 build: name: Build and Test Docker Images runs-on: ubuntu-latest needs: [lint, test, security] if: always() && (needs.lint.result == 'success' && needs.test.result == 'success') strategy: matrix: service: [mcp-server, dashboard-api, database] steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Cache Docker layers uses: actions/cache@v4 with: path: /tmp/.buildx-cache key: ${{ runner.os }}-buildx-${{ matrix.service }}-${{ github.sha }} restore-keys: | ${{ runner.os }}-buildx-${{ matrix.service }}- - name: Build Docker image uses: docker/build-push-action@v5 with: context: . file: docker/${{ matrix.service }}/Dockerfile push: false tags: tiger-mcp-${{ matrix.service }}:test cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max build-args: | BUILDKIT_INLINE_CACHE=1 - name: Test Docker image run: | # Test that the image can be created and basic functionality works docker run --rm tiger-mcp-${{ matrix.service }}:test echo "Image build successful" - name: Move cache run: | rm -rf /tmp/.buildx-cache mv /tmp/.buildx-cache-new /tmp/.buildx-cache integration: name: Integration Tests runs-on: ubuntu-latest needs: build if: github.event_name == 'push' && github.ref == 'refs/heads/main' steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} - name: Install UV uses: astral-sh/setup-uv@v3 - name: Create test environment run: | cp .env.template .env || echo "Creating basic .env file" echo "POSTGRES_PASSWORD=testpass123" >> .env echo "REDIS_PASSWORD=testredis123" >> .env echo "TIGER_PRIVATE_KEY=dummy" >> .env echo "TIGER_CLIENT_ID=test" >> .env echo "TIGER_ACCOUNT=test" >> .env - name: Run integration tests run: | # Start services with docker-compose docker-compose -f docker-compose.yml up -d --wait || docker-compose up -d sleep 10 # Install test dependencies and run integration tests uv sync --dev uv run python tests/test_integration_scenarios.py || true uv run python tests/test_performance_compatibility.py || true - name: Cleanup if: always() run: | docker-compose -f docker-compose.yml down -v || docker-compose down -v quality-gate: name: Quality Gate runs-on: ubuntu-latest needs: [lint, test, security, build] if: always() steps: - name: Check job statuses run: | echo "Lint status: ${{ needs.lint.result }}" echo "Test status: ${{ needs.test.result }}" echo "Security status: ${{ needs.security.result }}" echo "Build status: ${{ needs.build.result }}" # Quality gate logic if [[ "${{ needs.lint.result }}" == "success" && "${{ needs.test.result }}" == "success" && ("${{ needs.security.result }}" == "success" || "${{ needs.security.result }}" == "skipped") && ("${{ needs.build.result }}" == "success" || "${{ needs.build.result }}" == "skipped") ]]; then echo "✅ Quality gate passed" echo "QUALITY_GATE_PASSED=true" >> $GITHUB_ENV else echo "❌ Quality gate failed" echo "QUALITY_GATE_PASSED=false" >> $GITHUB_ENV exit 1 fi - name: Quality Gate Summary run: | echo "## Quality Gate Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY echo "| Lint | ${{ needs.lint.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY echo "| Test | ${{ needs.test.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY echo "| Security | ${{ needs.security.result == 'success' && '✅ Passed' || needs.security.result == 'skipped' && '⏭️ Skipped' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY echo "| Build | ${{ needs.build.result == 'success' && '✅ Passed' || needs.build.result == 'skipped' && '⏭️ Skipped' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/luxiaolei/tiger-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server