feat: enforce markdown-only output for comment publishing #1
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: CI | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| security-events: write | |
| jobs: | |
| test: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: '3.13' | |
| enable-cache: true | |
| - run: uv sync | |
| - run: uv pip install pytest pytest-cov pytest-asyncio | |
| - name: Run tests with coverage | |
| run: | | |
| uv run pytest tests/ --cov=issuelab --cov-report=xml --cov-report=term-missing | |
| continue-on-error: false | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v4 | |
| with: | |
| file: ./coverage.xml | |
| flags: unittests | |
| name: codecov-umbrella | |
| fail_ci_if_error: false | |
| - name: Check coverage threshold | |
| run: | | |
| uv run python - << 'PY' | |
| import sys | |
| import xml.etree.ElementTree as ET | |
| from pathlib import Path | |
| coverage_xml = Path("coverage.xml") | |
| if not coverage_xml.exists(): | |
| print("❌ 未找到 coverage.xml(pytest-cov 未生成覆盖率报告)") | |
| sys.exit(1) | |
| root = ET.parse(coverage_xml).getroot() | |
| line_rate = root.attrib.get("line-rate") | |
| if line_rate is None: | |
| print("❌ coverage.xml 缺少 line-rate 字段,无法计算覆盖率") | |
| sys.exit(1) | |
| coverage = float(line_rate) * 100 | |
| threshold = 40 | |
| print(f"当前覆盖率: {coverage:.2f}%") | |
| if coverage < threshold: | |
| print(f"❌ 测试覆盖率 {coverage:.2f}% 低于阈值 {threshold}%") | |
| sys.exit(1) | |
| print(f"✅ 测试覆盖率 {coverage:.2f}% 达标") | |
| PY | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: '3.13' | |
| enable-cache: true | |
| - run: uv sync --extra dev | |
| - name: Run ruff (linting) | |
| run: uv run ruff check src/ tests/ || true | |
| - name: Run ruff (formatting check) | |
| run: uv run ruff format --check src/ tests/ || true | |
| - name: Run mypy (type checking) | |
| run: uv run mypy src/issuelab --ignore-missing-imports || true | |
| security: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| continue-on-error: true | |
| - name: Upload Trivy results to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@v4 | |
| with: | |
| sarif_file: 'trivy-results.sarif' | |
| continue-on-error: true | |
| build: | |
| runs-on: ubuntu-latest | |
| needs: [test, lint] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: astral-sh/setup-uv@v7 | |
| with: | |
| python-version: '3.13' | |
| enable-cache: true | |
| - run: uv sync | |
| - name: Build package | |
| run: | | |
| uv build | |
| - name: Check package | |
| run: | | |
| uv run python -m issuelab list-agents | |
| quality-gate: | |
| runs-on: ubuntu-latest | |
| needs: [test, lint, build] | |
| if: always() | |
| steps: | |
| - name: Check all jobs status | |
| run: | | |
| if [ "${{ needs.test.result }}" != "success" ]; then | |
| echo "❌ Tests failed" | |
| exit 1 | |
| fi | |
| if [ "${{ needs.build.result }}" != "success" ]; then | |
| echo "❌ Build failed" | |
| exit 1 | |
| fi | |
| echo "✅ All quality checks passed" |