diff --git a/.github/scripts/increment_version.py b/.github/scripts/increment_version.py new file mode 100644 index 0000000..1d7257c --- /dev/null +++ b/.github/scripts/increment_version.py @@ -0,0 +1,170 @@ +#!/bin/env python +import argparse +from dataclasses import dataclass + +from packaging.version import Version + +PYPROJECT_PATH = "pyproject.toml" +DEFAULT_CHANGELOG_PATH = "CHANGELOG.md" +DEFAULT_YDB_VERSION_FILE = "ydb_mcp/version.py" +MARKER = "# AUTOVERSION" + + +@dataclass(init=False) +class VersionLine: + old_line: str + major: int + minor: int + patch: int + pre: int + + def __init__(self, old_line: str, version_str: str): + self.old_line = old_line + + version = Version(version_str) + self.major = version.major + self.minor = version.minor + self.micro = version.micro + + if version.pre is None: + self.pre = 0 + else: + self.pre = version.pre[1] + + def increment(self, part_name: str, with_beta: bool): + if part_name == "minor": + self.increment_minor(with_beta) + elif part_name == "patch" or part_name == "micro": + self.increment_micro(with_beta) + else: + raise Exception("unexpected increment type: '%s'" % part_name) + + def increment_minor(self, with_beta: bool): + if with_beta: + if self.pre == 0 or self.micro != 0: + self.increment_minor(False) + self.pre += 1 + return + + if self.micro == 0 and self.pre > 0: + self.pre = 0 + return + + self.minor += 1 + self.micro = 0 + self.pre = 0 + + def increment_micro(self, with_beta: bool): + if with_beta: + if self.pre == 0: + self.increment_micro(False) + self.pre += 1 + return + + if self.pre > 0: + self.pre = 0 + return + + self.micro += 1 + + def __str__(self): + if self.pre > 0: + pre = "b%s" % self.pre + else: + pre = "" + + return "%s.%s.%s%s" % (self.major, self.minor, self.micro, pre) + + def version_line_with_mark(self): + return 'version = "%s" %s' % (str(self), MARKER) + + +def extract_version(pyproject_content: str): + version_line = "" + for line in pyproject_content.splitlines(): + if MARKER in line: + version_line = line + break + + if version_line == "": + raise Exception("Not found version line") + + version_line = version_line.strip() + + parts = version_line.split('"') + version_part = parts[1] + + return VersionLine(old_line=version_line, version_str=version_part) + + +def increment_version_at_pyproject( + pyproject_path: str, inc_type: str, with_beta: bool +) -> str: + with open(pyproject_path, "rt") as f: + setup_content = f.read() + + version = extract_version(setup_content) + version.increment(inc_type, with_beta) + setup_content = setup_content.replace( + version.old_line, version.version_line_with_mark() + ) + + with open(pyproject_path, "w") as f: + f.write(setup_content) + + return str(version) + + +def add_changelog_version(changelog_path, version: str): + with open(changelog_path, "rt") as f: + content = f.read() + content = content.strip() + + if content.startswith("##"): + return + + content = """## %s ## +%s +""" % (version, content) + with open(changelog_path, "w") as f: + f.write(content) + + +def set_version_in_version_file(file_path: str, version: str): + with open(file_path, "w") as f: + f.write('VERSION = "%s"\n' % version) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--inc-type", + default="minor", + help="increment version type: patch or minor", + choices=["minor", "patch"], + ) + parser.add_argument( + "--beta", choices=["true", "false"], help="is beta version" + ) + parser.add_argument( + "--changelog-path", + default=DEFAULT_CHANGELOG_PATH, + help="path to changelog", + type=str, + ) + parser.add_argument("--pyproject-path", default=PYPROJECT_PATH) + + args = parser.parse_args() + + is_beta = args.beta == "true" + + new_version = increment_version_at_pyproject( + args.pyproject_path, args.inc_type, is_beta + ) + add_changelog_version(args.changelog_path, new_version) + set_version_in_version_file(DEFAULT_YDB_VERSION_FILE, new_version) + print(new_version) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml new file mode 100644 index 0000000..e4f460f --- /dev/null +++ b/.github/workflows/python-publish.yml @@ -0,0 +1,113 @@ +# This workflow will upload a Python Package using Twine when a release is created +# For more information see: https://help.github.com/en/actions/language-and-framework-guides/using-python-with-github-actions#publishing-to-package-registries + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Publish package release + +on: + workflow_dispatch: + inputs: + version-change: + description: Version part + required: true + type: choice + default: patch + options: + - minor + - patch + beta: + description: Is beta version + required: true + type: boolean + default: False +jobs: + publish: + env: + VERSION_CHANGE: ${{ github.event.inputs.version-change }} + WITH_BETA: ${{ github.event.inputs.beta }} + GH_TOKEN: ${{ secrets.YDB_PLATFORM_BOT_TOKEN_REPO }} + CHANGELOG_FILE: CHANGELOG.md + PYPROJECT_PATH: pyproject.toml + + permissions: + contents: write + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + token: ${{ secrets.YDB_PLATFORM_BOT_TOKEN_REPO }} + + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: '3.9' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install packaging build + + - name: read changelog + id: read-changelog + run: | + CHANGELOG=$(cat $CHANGELOG_FILE | sed -e '/^## .*$/,$d') + echo "CHANGELOG<> $GITHUB_ENV + echo "$CHANGELOG" >> $GITHUB_ENV + echo "CHANGELOGEOF_MARKER" >> $GITHUB_ENV + echo "# Changelog" >> $GITHUB_STEP_SUMMARY + echo "$CHANGELOG" >> $GITHUB_STEP_SUMMARY + + + - name: Increment version + id: increment-version + run: | + NEW_VERSION=$(python3 ./.github/scripts/increment_version.py --inc-type=$VERSION_CHANGE --beta=$WITH_BETA) + echo new version: $NEW_VERSION + echo "NEW_VERSION=$NEW_VERSION" >> $GITHUB_OUTPUT + echo "New version: $NEW_VERSION" >> $GITHUB_STEP_SUMMARY + + - name: Build package + run: python -m build + + - name: Publish release on github + run: | + if [[ -z "$CHANGELOG" ]] + then + echo "CHANGELOG empty" + exit 1; + fi; + + TAG="${{ steps.increment-version.outputs.NEW_VERSION }}" + + # Get previous version from changelog + # pre-incremented version not used for consistent changelog with release notes + # for example changelog may be rewrited when switch from beta to release + # and remove internal beta changes + LAST_TAG=$(cat $CHANGELOG_FILE | grep '^## .* ##$' | head -n 2 | tail -n 1 | cut -d ' ' -f 2) + + git config --global user.email "robot@umbrella"; + git config --global user.name "robot"; + git commit -am "Release: $TAG"; + + git tag "$TAG" + git push && git push --tags + + CHANGELOG="$CHANGELOG + + Full Changelog: [$LAST_TAG...$TAG](https://github.com/ydb-platform/ydb-sqlalchemy/compare/$LAST_TAG...$TAG)" + if [ "$WITH_BETA" = true ] + then + gh release create --prerelease $TAG --title "$TAG" --notes "$CHANGELOG" + else + gh release create $TAG --title "$TAG" --notes "$CHANGELOG" + fi; + + - name: Publish package + uses: pypa/gh-action-pypi-publish@release/v1.8 \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..3fa76e0 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,4 @@ +* Update package + +# 0.1.0 +* First version \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 52d17bb..50848f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,26 +4,25 @@ build-backend = "setuptools.build_meta" [project] name = "ydb-mcp" -version = "0.1.0" +version = "0.1.0" # AUTOVERSION description = "Model Context Protocol server for YDB DBMS" readme = "README.md" authors = [ {name = "YDB MCP Team", email = "info@ydb.tech"} ] license = {text = "Apache 2.0"} -requires-python = ">=3.8" +requires-python = ">=3.10" classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ] dependencies = [ - "ydb>=3.0.0", - "mcp-server>=0.1.0", - "httpx>=0.25.0", + "ydb>=3.21.0", + "mcp>=1.6.0", ] [project.optional-dependencies] diff --git a/requirements.txt b/requirements.txt index 678a3f2..8a4c5b9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,2 @@ -ydb>=3.0.0 -mcp-server>=0.1.0 \ No newline at end of file +ydb>=3.21.0 +mcp>=1.6.0 \ No newline at end of file diff --git a/setup.py b/setup.py deleted file mode 100644 index c586abb..0000000 --- a/setup.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python3 -"""YDB MCP - Model Context Protocol server for YDB.""" - -import os -from setuptools import setup, find_packages - - -def read(fname): - """Read file content.""" - with open(os.path.join(os.path.dirname(__file__), fname)) as f: - return f.read() - - -setup( - name="ydb-mcp", - version="0.1.0", - author="MCP Team", - author_email="mcp@example.com", - description="Model Context Protocol server for YDB", - long_description=read("README.md") if os.path.exists("README.md") else "", - long_description_content_type="text/markdown", - url="https://github.com/blinkov/ydb-mcp", - packages=find_packages(), - classifiers=[ - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", - ], - python_requires=">=3.8", - install_requires=[ - "ydb>=2.11.0", - "mcp-server>=0.1.0", - ], - extras_require={ - "dev": [ - "pytest>=7.3.1", - "pytest-asyncio>=0.21.0", - "pytest-cov>=4.1.0", - "black>=23.3.0", - "isort>=5.12.0", - "mypy>=1.3.0", - "flake8>=6.0.0", - ], - } -) \ No newline at end of file diff --git a/ydb_mcp/__init__.py b/ydb_mcp/__init__.py index 14c9013..0959556 100644 --- a/ydb_mcp/__init__.py +++ b/ydb_mcp/__init__.py @@ -1,6 +1,8 @@ """YDB MCP - Model Context Protocol server for YDB.""" +from .version import VERSION -__version__ = "0.1.0" + +__version__ = VERSION # Import order matters to avoid circular imports from ydb_mcp.connection import YDBConnection diff --git a/ydb_mcp/version.py b/ydb_mcp/version.py new file mode 100644 index 0000000..58c8455 --- /dev/null +++ b/ydb_mcp/version.py @@ -0,0 +1 @@ +VERSION = "0.1.0" \ No newline at end of file