fix(mcp): swap TextContent block order — text summary last for single… #104
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: QA - MCP EU AI Act | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| workflow_dispatch: | |
| jobs: | |
| test: | |
| name: Tests & Coverage | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: ['3.10', '3.11', '3.12'] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| cache: 'pip' | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install pytest pytest-cov pytest-asyncio | |
| if [ -f requirements.txt ]; then pip install -r requirements.txt; fi | |
| - name: Run tests with coverage | |
| run: | | |
| pytest tests/ -v \ | |
| --cov=. \ | |
| --cov-report=term-missing \ | |
| --cov-report=xml \ | |
| --cov-report=html \ | |
| --cov-fail-under=80 | |
| - name: Upload coverage to Codecov | |
| if: matrix.python-version == '3.11' | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| file: ./coverage.xml | |
| flags: unittests | |
| name: codecov-mcp-eu-ai-act | |
| fail_ci_if_error: false | |
| - name: Archive coverage HTML report | |
| if: matrix.python-version == '3.11' | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage-report | |
| path: htmlcov/ | |
| retention-days: 30 | |
| quality-gates: | |
| name: Quality Gates | |
| runs-on: ubuntu-latest | |
| needs: test | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| cache: 'pip' | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install pytest pytest-cov pytest-asyncio | |
| if [ -f requirements.txt ]; then pip install -r requirements.txt; fi | |
| - name: Check test files exist | |
| run: | | |
| if [ ! -d "tests" ]; then | |
| echo "❌ No tests/ directory found" | |
| exit 1 | |
| fi | |
| TEST_COUNT=$(find tests -name "test_*.py" | wc -l) | |
| if [ $TEST_COUNT -eq 0 ]; then | |
| echo "❌ No test files found" | |
| exit 1 | |
| fi | |
| echo "✅ Found $TEST_COUNT test files" | |
| - name: Verify pytest configuration | |
| run: | | |
| if [ ! -f "pytest.ini" ] && [ ! -f "pyproject.toml" ] && [ ! -f "setup.cfg" ]; then | |
| echo "⚠️ No pytest configuration found (pytest.ini, pyproject.toml, or setup.cfg)" | |
| echo "Continuing anyway..." | |
| else | |
| echo "✅ Pytest configuration found" | |
| fi | |
| - name: Check for security test markers | |
| run: | | |
| SECURITY_TESTS=$(grep -r "@pytest.mark.security" tests/ | wc -l || echo "0") | |
| if [ $SECURITY_TESTS -eq 0 ]; then | |
| echo "⚠️ No security tests found (no @pytest.mark.security markers)" | |
| echo "Consider adding security tests" | |
| else | |
| echo "✅ Found $SECURITY_TESTS security test markers" | |
| fi | |
| - name: Check for code smells (TODO/FIXME/HACK) | |
| run: | | |
| SMELLS=$(grep -r "TODO\|FIXME\|HACK" --include="*.py" --exclude-dir=tests . | wc -l || echo "0") | |
| if [ $SMELLS -gt 0 ]; then | |
| echo "⚠️ Found $SMELLS code smells (TODO/FIXME/HACK)" | |
| grep -r "TODO\|FIXME\|HACK" --include="*.py" --exclude-dir=tests . || true | |
| echo "This is a warning, not blocking the build" | |
| else | |
| echo "✅ No code smells found" | |
| fi | |
| - name: Run coverage check | |
| run: | | |
| coverage run -m pytest tests/ | |
| coverage report --fail-under=80 | |
| coverage json | |
| COVERAGE=$(python -c "import json; print(json.load(open('coverage.json'))['totals']['percent_covered'])") | |
| echo "📊 Coverage: ${COVERAGE}%" | |
| echo "coverage=${COVERAGE}" >> $GITHUB_OUTPUT | |
| id: coverage | |
| - name: Generate coverage badge | |
| if: github.ref == 'refs/heads/main' | |
| run: | | |
| COVERAGE=${{ steps.coverage.outputs.coverage }} | |
| COLOR="red" | |
| if (( $(echo "$COVERAGE >= 80" | bc -l) )); then | |
| COLOR="brightgreen" | |
| elif (( $(echo "$COVERAGE >= 70" | bc -l) )); then | |
| COLOR="green" | |
| elif (( $(echo "$COVERAGE >= 50" | bc -l) )); then | |
| COLOR="yellow" | |
| fi | |
| echo "Coverage: ${COVERAGE}% (${COLOR})" | |
| # Badge will be created by shields.io: https://img.shields.io/badge/coverage-${COVERAGE}%25-${COLOR} | |
| integration-test: | |
| name: Integration Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| cache: 'pip' | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install pytest | |
| if [ -f requirements.txt ]; then pip install -r requirements.txt; fi | |
| - name: Run integration tests | |
| run: | | |
| if [ -d "tests" ]; then | |
| pytest tests/ -v -m "integration" --tb=short || echo "No integration tests found" | |
| fi | |
| - name: Test MCP server standalone | |
| run: | | |
| timeout 10s python3 server.py || echo "✅ Server ran successfully (timeout expected)" | |
| security-scan: | |
| name: Security Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.11' | |
| - name: Install security tools | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install bandit | |
| - name: Install pip-audit | |
| run: pip install pip-audit | |
| - name: Run Bandit (security linter) | |
| run: | | |
| bandit -r . -f json -o bandit-report.json || true | |
| bandit -r . -ll || true | |
| - name: Check dependencies for vulnerabilities (pip-audit) | |
| run: | | |
| if [ -f requirements.txt ]; then | |
| pip-audit -r requirements.txt --format=json -o pip-audit-report.json || echo "⚠️ Vulnerabilities found, check pip-audit-report.json" | |
| pip-audit -r requirements.txt || true | |
| else | |
| echo "No requirements.txt found, skipping pip-audit" | |
| fi | |
| - name: Upload security reports | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: security-reports | |
| path: | | |
| bandit-report.json | |
| pip-audit-report.json | |
| retention-days: 30 | |
| build-status: | |
| name: Build Status Summary | |
| runs-on: ubuntu-latest | |
| needs: [test, quality-gates, integration-test, security-scan] | |
| if: always() | |
| steps: | |
| - name: Check build status | |
| run: | | |
| echo "===================================" | |
| echo " MCP EU AI Act - Build Summary" | |
| echo "===================================" | |
| echo "" | |
| echo "✅ Tests: ${{ needs.test.result }}" | |
| echo "✅ Quality Gates: ${{ needs.quality-gates.result }}" | |
| echo "✅ Integration: ${{ needs.integration-test.result }}" | |
| echo "✅ Security: ${{ needs.security-scan.result }}" | |
| echo "" | |
| if [ "${{ needs.test.result }}" != "success" ] || [ "${{ needs.quality-gates.result }}" != "success" ]; then | |
| echo "❌ Build FAILED" | |
| exit 1 | |
| else | |
| echo "✅ Build PASSED" | |
| fi |