Skip to main content
Glama

Django Shell MCP Server

release.py5.89 kB
# /// script # requires-python = ">=3.10" # dependencies = [ # "rich", # "typer", # ] # /// from __future__ import annotations import re import subprocess from pathlib import Path from typing import Annotated import typer from rich.console import Console cli = typer.Typer() console = Console() def run( cmd: list[str], *, dry_run: bool = False, force_run: bool = False, ) -> str: command_str = " ".join(cmd) console.print( f"would run command: {command_str}" if dry_run and not force_run else f"running command: {command_str}" ) if dry_run and not force_run: return "" try: return subprocess.check_output(cmd, text=True, stderr=subprocess.STDOUT).strip() except subprocess.CalledProcessError as e: console.print(f"[red]{cmd[0]} failed: {e.output}[/red]") raise typer.Exit(1) from e def get_calver() -> str: """Read CalVer version from .github/VERSION file.""" version_file = Path(".github/VERSION") if not version_file.exists(): console.print("[red]No .github/VERSION file found. Run bump.py first.[/red]") raise typer.Exit(1) calver = version_file.read_text().strip() console.print(f"[dim]Found CalVer: {calver}[/dim]") return calver def get_workspace_packages() -> list[str]: """Get list of workspace packages from packages/ directory.""" packages_dir = Path("packages") if not packages_dir.exists(): return [] packages = [] for pkg_dir in packages_dir.iterdir(): if pkg_dir.is_dir() and (pkg_dir / "pyproject.toml").exists(): packages.append(pkg_dir.name) return sorted(packages) def get_package_versions() -> dict[str, str]: """Get current versions of all packages using uv.""" packages = {} # Get root package version console.print("[dim]Getting package versions...[/dim]") output = run(["uv", "version"], force_run=True) # Parse output like "mcp-django 0.2.0" or just "0.2.0" if match := re.search(r"(?:mcp-django\s+)?([\d.]+(?:[-.\w]*)?)", output): packages["mcp-django"] = match.group(1) console.print(f" mcp-django: {match.group(1)}") # Get workspace package versions for package in get_workspace_packages(): output = run(["uv", "version", "--package", package], force_run=True) # Parse output like "mcp-django-shell 0.9.0" or just "0.9.0" if match := re.search(r"(?:[\w-]+\s+)?([\d.]+(?:[-.\w]*)?)", output): packages[package] = match.group(1) console.print(f" {package}: {match.group(1)}") return packages @cli.command() def release( dry_run: Annotated[ bool, typer.Option("--dry-run", "-d", help="Show commands without executing") ] = False, force: Annotated[ bool, typer.Option("--force", "-f", help="Skip safety checks") ] = False, ): """Create a new release with CalVer and package-specific tags.""" # Safety checks current_branch = run(["git", "branch", "--show-current"], force_run=True).strip() if current_branch != "main" and not force: console.print( f"[red]Must be on main branch to create release (currently on {current_branch})[/red]" ) raise typer.Exit(1) if run(["git", "status", "--porcelain"], force_run=True) and not force: console.print( "[red]Working directory is not clean. Commit or stash changes first.[/red]" ) raise typer.Exit(1) run(["git", "fetch", "origin", "main"], dry_run=dry_run) local_sha = run(["git", "rev-parse", "@"], force_run=True).strip() remote_sha = run(["git", "rev-parse", "@{u}"], force_run=True).strip() if local_sha != remote_sha and not force: console.print( "[red]Local main is not up to date with remote. Pull changes first.[/red]" ) raise typer.Exit(1) # Get CalVer from VERSION file calver = get_calver() # Check if CalVer release already exists (with v prefix) calver_tag = f"v{calver}" try: run(["gh", "release", "view", calver_tag], force_run=True) if not force: console.print(f"[red]Release {calver_tag} already exists![/red]") raise typer.Exit(1) except Exception: pass # Release doesn't exist, good to proceed # Get current package versions packages = get_package_versions() # Show what we're about to release console.print(f"\n[bold]Creating release {calver}[/bold]") for package, version in packages.items(): console.print(f" [cyan]{package}:[/cyan] {version}") # Confirm with user if not force and not dry_run: typer.confirm("\nProceed with release?", abort=True) # Create tags console.print("\n[bold]Creating tags...[/bold]") tags = [] # CalVer tag with v prefix calver_tag = f"v{calver}" tags.append(calver_tag) console.print(f" [green]✓[/green] {calver_tag}") # Package-specific tags for package, version in packages.items(): tag = f"{package}-v{version}" tags.append(tag) console.print(f" [green]✓[/green] {tag}") # Create all tags locally for tag in tags: run(["git", "tag", tag], dry_run=dry_run) # Push all tags at once console.print("\n[bold]Pushing tags to origin...[/bold]") run(["git", "push", "origin"] + tags, dry_run=dry_run) # Create GitHub release with CalVer tag console.print(f"\n[bold]Creating GitHub release {calver_tag}...[/bold]") run(["gh", "release", "create", calver_tag, "--generate-notes"], dry_run=dry_run) # Success message console.print(f"\n[bold green]✓ Released {calver_tag}![/bold green]") console.print( "\n[dim]The CI/CD pipeline will now build and publish packages to PyPI.[/dim]" ) if __name__ == "__main__": cli()

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/joshuadavidthomas/mcp-django-shell'

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