fix(mcp-server): normalize shared KB list shape for name resolution #27
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: Build & Publish (mcp-server) | |
| # Build, test, and publish the Python MCP server (mcp-server/) to PyPI. | |
| # Publishing uses PyPI Trusted Publishing (OIDC) — no API token required, | |
| # only the GitHub→PyPI OIDC trust configured on the repo. | |
| # | |
| # Release policy: publishing does NOT depend on tags. Bump the version in | |
| # mcp-server/pyproject.toml (and the synced version strings in setup.py, | |
| # __init__.py, weknora_mcp_server.py server_version, main.py --version), | |
| # merge to main, and the pipeline builds + publishes automatically. | |
| # A pre-publish check queries PyPI and skips upload if that version is | |
| # already published, so re-running on an unchanged version stays green. | |
| # Releases also still trigger on mcp-server-v* tags (back-compat). | |
| on: | |
| push: | |
| branches: [main] | |
| tags: | |
| - "mcp-server-v*" | |
| paths: | |
| - "mcp-server/**" | |
| - ".github/workflows/mcp-server.yml" | |
| pull_request: | |
| paths: | |
| - "mcp-server/**" | |
| - ".github/workflows/mcp-server.yml" | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| test: | |
| name: Test (Python ${{ matrix.python-version }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| python-version: ["3.10", "3.11", "3.12", "3.13"] | |
| defaults: | |
| run: | |
| working-directory: mcp-server | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| run: uv python install ${{ matrix.python-version }} | |
| - name: Install dependencies (test extras) | |
| run: uv sync --python ${{ matrix.python-version }} --extra test | |
| - name: Run tests | |
| # unittest avoids pytest importing __init__.py as a broken package root. | |
| # Manual diagnostics live in check_imports.py (not matched by test_*.py). | |
| run: uv run --python ${{ matrix.python-version }} python -m unittest discover -s . -p "test_*.py" -v | |
| build: | |
| name: Build sdist + wheel | |
| needs: test | |
| runs-on: ubuntu-latest | |
| # Build on push to main, manual runs, and release tags — but never on PRs. | |
| if: github.event_name != 'pull_request' | |
| defaults: | |
| run: | |
| working-directory: mcp-server | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v4 | |
| - name: Set up Python | |
| run: uv python install 3.12 | |
| - name: Build package | |
| run: uv build | |
| - name: Verify wheel contains upload_paths.py (regression guard) | |
| run: | | |
| set -e | |
| if ! python3 -c "import glob, zipfile, sys; whl=glob.glob('dist/*.whl')[0]; z=zipfile.ZipFile(whl); sys.exit(0 if 'upload_paths.py' in z.namelist() else 1)"; then | |
| echo "::error::upload_paths.py is missing from the wheel — check py-modules in pyproject.toml/setup.py" | |
| exit 1 | |
| fi | |
| echo "upload_paths.py present in wheel ✓" | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist | |
| path: mcp-server/dist/ | |
| publish: | |
| name: Publish to PyPI | |
| needs: build | |
| runs-on: ubuntu-latest | |
| # Publish on push to main, manual runs (main/tags only), and release tags — never on PRs. | |
| if: >- | |
| github.event_name != 'pull_request' && | |
| (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/mcp-server-v')) | |
| permissions: | |
| id-token: write | |
| environment: | |
| name: pypi | |
| url: https://pypi.org/project/tencent-weknora-mcp/ | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Check if version is already published | |
| id: check_pypi | |
| working-directory: mcp-server | |
| # Read the version from pyproject.toml and query PyPI. If that exact | |
| # version already exists, skip publishing (so re-runs on an unchanged | |
| # version stay green instead of failing with "File already exists"). | |
| run: | | |
| set -e | |
| version="$(python3 -c 'import tomllib; print(tomllib.load(open("pyproject.toml","rb"))["project"]["version"])')" | |
| echo "packaged version: $version" | |
| exists="$(python3 -c ' | |
| import json, sys, urllib.request | |
| v = sys.argv[1] | |
| try: | |
| d = json.load(urllib.request.urlopen("https://pypi.org/pypi/tencent-weknora-mcp/json")) | |
| print("true" if v in d.get("releases", {}) else "false") | |
| except Exception: | |
| # If PyPI is unreachable or the project is brand-new (404), treat as unpublished. | |
| print("false") | |
| ' "$version")" | |
| echo "already on PyPI: $exists" | |
| if [ "$exists" = "true" ]; then | |
| echo "should_publish=false" >> "$GITHUB_OUTPUT" | |
| echo "::warning::tencent-weknora-mcp $version is already on PyPI; skipping publish. Bump pyproject.toml (and synced version strings) to release new changes." | |
| else | |
| echo "should_publish=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Download artifacts | |
| if: steps.check_pypi.outputs.should_publish == 'true' | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| - name: Publish to PyPI | |
| if: steps.check_pypi.outputs.should_publish == 'true' | |
| uses: pypa/gh-action-pypi-publish@release/v1 |