chore(deps): bump virtualenv to 21.3.0 and backrefs to 7.0 #322
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: UML-MCP CI/CD Pipeline | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - "mcp_core/**" | |
| - "tools/**" | |
| - "app.py" | |
| - "api/**" | |
| - "server.py" | |
| - "smithery.yaml" | |
| - "Dockerfile" | |
| - "pyproject.toml" | |
| - "requirements.txt" | |
| - ".github/workflows/**" | |
| pull_request: | |
| branches: [main] | |
| release: | |
| types: [created] | |
| workflow_dispatch: | |
| inputs: | |
| version_increment: | |
| description: 'Version increment type (patch, minor, major)' | |
| required: true | |
| default: 'patch' | |
| run_docker_validation: | |
| description: 'Run Docker build and smoke test (manual dispatch only)' | |
| type: boolean | |
| required: false | |
| default: false | |
| publish_to_pypi: | |
| description: 'Publish to PyPI after build' | |
| type: boolean | |
| required: false | |
| default: false | |
| jobs: | |
| lint: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: ['3.12'] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| version: "latest" | |
| python-version: ${{ matrix.python-version }} | |
| enable-cache: true | |
| - name: Install dependencies | |
| run: uv sync --all-groups | |
| - name: Lint | |
| run: | | |
| uv run ruff check . | |
| uv run ruff format --check . | |
| - name: Check typing | |
| run: uv run ty check | |
| test: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.12", "3.14"] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| version: "latest" | |
| python-version: ${{ matrix.python-version }} | |
| enable-cache: true | |
| - name: Validate Python package structure | |
| run: | | |
| for dir in mcp_core tools; do | |
| if [ -d "$dir" ] && [ ! -f "$dir/__init__.py" ]; then | |
| echo "Creating missing __init__.py in $dir" | |
| touch "$dir/__init__.py" | |
| fi | |
| done | |
| - name: Install dependencies | |
| run: uv sync --all-groups | |
| - name: List installed packages | |
| run: uv pip list | |
| - name: Run tests | |
| run: uv run pytest | |
| build: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.12", "3.14"] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| version: "latest" | |
| python-version: ${{ matrix.python-version }} | |
| enable-cache: true | |
| - name: Install dependencies | |
| run: uv sync --all-groups | |
| - name: Build package | |
| run: | | |
| uv build | |
| echo "Built package for Python ${{ matrix.python-version }}" | |
| ls -la dist/ | |
| - name: Assert wheel layout | |
| run: | | |
| python - <<'PY' | |
| import glob | |
| import sys | |
| import zipfile | |
| for whl in glob.glob("dist/*.whl"): | |
| with zipfile.ZipFile(whl) as z: | |
| tops = { | |
| n.split("/")[0] | |
| for n in z.namelist() | |
| if n and not n.endswith("/") | |
| } | |
| if "mcp_core" not in tops: | |
| print(f"FAIL: {whl} must include mcp_core", file=sys.stderr) | |
| sys.exit(1) | |
| if "tools" not in tops: | |
| print(f"FAIL: {whl} must include tools", file=sys.stderr) | |
| sys.exit(1) | |
| print("wheel layout OK") | |
| PY | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: uml-mcp-dist-${{ matrix.python-version }} | |
| path: dist/ | |
| retention-days: 5 | |
| bump-version: | |
| needs: [lint, test, build] | |
| if: github.event_name == 'workflow_dispatch' && github.event.inputs.publish_to_pypi == 'true' | |
| runs-on: ubuntu-latest | |
| outputs: | |
| new_version: ${{ env.NEW_VERSION }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Set up Python | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: '3.12' | |
| - name: Bump version | |
| env: | |
| INCREMENT: ${{ github.event.inputs.version_increment }} | |
| run: | | |
| NEW_VERSION=$(python - <<'PY' | |
| import os, re | |
| inc = os.environ.get("INCREMENT", "patch") | |
| with open("pyproject.toml") as f: | |
| content = f.read() | |
| m = re.search(r'version = "(\d+)\.(\d+)\.(\d+)"', content) | |
| if not m: | |
| raise SystemExit("Could not find version in pyproject.toml") | |
| major, minor, patch = int(m.group(1)), int(m.group(2)), int(m.group(3)) | |
| if inc == "major": | |
| major, minor, patch = major + 1, 0, 0 | |
| elif inc == "minor": | |
| minor, patch = minor + 1, 0 | |
| else: | |
| patch += 1 | |
| new_version = f"{major}.{minor}.{patch}" | |
| content = re.sub(r'version = "\d+\.\d+\.\d+"', f'version = "{new_version}"', content) | |
| with open("pyproject.toml", "w") as f: | |
| f.write(content) | |
| print(new_version) | |
| PY | |
| ) | |
| echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV | |
| echo "Version bumped to $NEW_VERSION" | |
| VERSION_FILE="mcp_core/core/config.py" | |
| if [ -f "$VERSION_FILE" ] && grep -q "version = " "$VERSION_FILE"; then | |
| sed -i "s/version = \".*\"/version = \"$NEW_VERSION\"/" $VERSION_FILE | |
| echo "Updated version in $VERSION_FILE" | |
| fi | |
| git config --global user.name "GitHub Actions Bot" | |
| git config --global user.email "actions@github.com" | |
| git add pyproject.toml | |
| [ -f "$VERSION_FILE" ] && git add $VERSION_FILE | |
| git commit -m "Bump version to $NEW_VERSION [skip ci]" | |
| git tag -a "v$NEW_VERSION" -m "Version $NEW_VERSION" | |
| git push origin main | |
| git push origin "v$NEW_VERSION" | |
| publish-to-pypi: | |
| needs: [lint, test, build, bump-version] | |
| if: | | |
| always() && | |
| needs.lint.result == 'success' && | |
| needs.test.result == 'success' && | |
| needs.build.result == 'success' && | |
| (needs.bump-version.result == 'success' || needs.bump-version.result == 'skipped') && | |
| ((github.event_name == 'workflow_dispatch' && github.event.inputs.publish_to_pypi == 'true') || github.event_name == 'release') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| ref: ${{ github.event_name == 'workflow_dispatch' && 'main' || github.ref }} | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| version: "latest" | |
| python-version: '3.12' | |
| enable-cache: true | |
| - name: Get version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| echo "NEW_VERSION=${{ needs.bump-version.outputs.new_version }}" >> $GITHUB_ENV | |
| else | |
| NEW_VERSION=$(python -c "import re; print(re.search(r'version = \"([^\"]+)\"', open('pyproject.toml').read()).group(1))") | |
| echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_ENV | |
| fi | |
| echo "Using version ${{ env.NEW_VERSION }}" | |
| - name: Build package | |
| run: | | |
| uv build | |
| echo "Built package for version ${{ env.NEW_VERSION }}" | |
| ls -la dist/ | |
| - name: Assert wheel layout | |
| run: | | |
| python - <<'PY' | |
| import glob | |
| import sys | |
| import zipfile | |
| for whl in glob.glob("dist/*.whl"): | |
| with zipfile.ZipFile(whl) as z: | |
| tops = { | |
| n.split("/")[0] | |
| for n in z.namelist() | |
| if n and not n.endswith("/") | |
| } | |
| if "mcp_core" not in tops: | |
| print(f"FAIL: {whl} must include mcp_core", file=sys.stderr) | |
| sys.exit(1) | |
| if "tools" not in tops: | |
| print(f"FAIL: {whl} must include tools", file=sys.stderr) | |
| sys.exit(1) | |
| print("wheel layout OK") | |
| PY | |
| - name: Publish package to PyPI | |
| env: | |
| TWINE_USERNAME: __token__ | |
| TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} | |
| run: | | |
| uv pip install twine | |
| uv run twine upload dist/* | |
| echo "Published version ${{ env.NEW_VERSION }} to PyPI" | |
| - name: Create release artifact | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: uml-mcp-${{ env.NEW_VERSION }} | |
| path: dist/ | |
| retention-days: 30 | |
| validate-docker: | |
| needs: [lint, test, build] | |
| if: | | |
| (github.event_name == 'push' && github.ref == 'refs/heads/main') || | |
| (github.event_name == 'workflow_dispatch' && github.event.inputs.run_docker_validation == 'true') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| version: "latest" | |
| python-version: '3.12' | |
| enable-cache: true | |
| - name: Install runtime dependencies from lockfile | |
| run: | | |
| uv sync --frozen --no-dev | |
| - name: Verify setup | |
| run: | | |
| uv run python -c "import fastapi, httpx, rich, pydantic; from mcp_core.core.server import main" | |
| echo "Basic imports successful" | |
| - name: Build Docker image | |
| run: | | |
| docker build -t uml-mcp:latest . | |
| echo "Docker build successful" | |
| - name: Test Docker image | |
| run: | | |
| docker run --rm -i uml-mcp:latest < /dev/null & | |
| sleep 5 | |
| echo "Docker image test completed" |