Skip to content

chore(deps): bump virtualenv to 21.3.0 and backrefs to 7.0 #322

chore(deps): bump virtualenv to 21.3.0 and backrefs to 7.0

chore(deps): bump virtualenv to 21.3.0 and backrefs to 7.0 #322

Workflow file for this run

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"