feat: streamline GitHub Actions workflows and improve contributor experience

- Replace complex auto-version.yml with simple PR Docker build workflow
  - Builds Docker images for all PRs using pr-number-sha tagging
  - Removes redundant versioning logic (semantic-release handles this)
  - Adds automatic PR comments with Docker usage instructions

- Optimize test.yml workflow triggers
  - Remove redundant push triggers on main branch
  - Focus on PR testing only for better developer feedback

- Add docker-release.yml for production releases
  - Triggers on GitHub release publication
  - Multi-platform builds (linux/amd64, linux/arm64)
  - Updates release notes with Docker installation instructions

- Add semantic-release.yml workflow for automated versioning
  - Uses conventional commits for version bumping
  - Automatically generates releases and tags
  - Integrates with Docker workflow via release triggers

- Add pre-commit configuration for automatic code quality
  - Includes ruff (with auto-fix), black, isort
  - Provides faster development workflow option

- Enhance contribution documentation
  - Add pre-commit hook option as recommended approach
  - Keep manual script option for comprehensive testing
  - Improve developer workflow guidance

Fixes #215 (automatic changelog generation)
Addresses #110 (Docker builds automation)
References #107 (improved version tracking)

This creates a clean, modern CI/CD pipeline that eliminates redundancy
while addressing multiple community requests around changelog generation,
Docker builds, and release automation.
This commit is contained in:
Sven Lito
2025-08-08 17:33:51 +07:00
parent e29deb23db
commit af3a81543c
8 changed files with 397 additions and 283 deletions

View File

@@ -1,248 +1,111 @@
name: Auto Version name: PR Docker Build
on: on:
pull_request: pull_request:
types: [closed] types: [opened, synchronize, reopened]
branches: [main]
permissions:
contents: read
packages: write
pull-requests: write
jobs: jobs:
version: docker:
# Only run if PR was merged (not just closed) name: Build PR Docker Image
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: read
steps: steps:
- name: Checkout repository - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.PAT }}
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
- name: Determine version bump type
id: bump_type
run: |
PR_TITLE="${{ github.event.pull_request.title }}"
echo "PR Title: $PR_TITLE"
# Convert to lowercase for case-insensitive matching
PR_TITLE_LOWER=$(echo "$PR_TITLE" | tr '[:upper:]' '[:lower:]')
# Determine bump type based on PR title prefix
if [[ "$PR_TITLE_LOWER" =~ ^(breaking|breaking[[:space:]]change): ]]; then
echo "Detected BREAKING CHANGE - major version bump"
echo "bump_type=major" >> $GITHUB_OUTPUT
echo "should_bump=true" >> $GITHUB_OUTPUT
echo "should_build_docker=true" >> $GITHUB_OUTPUT
elif [[ "$PR_TITLE_LOWER" =~ ^feat: ]]; then
echo "Detected new feature - minor version bump"
echo "bump_type=minor" >> $GITHUB_OUTPUT
echo "should_bump=true" >> $GITHUB_OUTPUT
echo "should_build_docker=true" >> $GITHUB_OUTPUT
elif [[ "$PR_TITLE_LOWER" =~ ^(fix|perf|refactor): ]]; then
echo "Detected fix/perf/refactor - patch version bump"
echo "bump_type=patch" >> $GITHUB_OUTPUT
echo "should_bump=true" >> $GITHUB_OUTPUT
echo "should_build_docker=true" >> $GITHUB_OUTPUT
elif [[ "$PR_TITLE_LOWER" =~ ^docker: ]]; then
echo "Detected docker build request - no version bump but build Docker"
echo "bump_type=none" >> $GITHUB_OUTPUT
echo "should_bump=false" >> $GITHUB_OUTPUT
echo "should_build_docker=true" >> $GITHUB_OUTPUT
elif [[ "$PR_TITLE_LOWER" =~ ^(docs|chore|test|ci|style)\+docker: ]]; then
echo "Detected non-versioned change with Docker build request"
echo "bump_type=none" >> $GITHUB_OUTPUT
echo "should_bump=false" >> $GITHUB_OUTPUT
echo "should_build_docker=true" >> $GITHUB_OUTPUT
elif [[ "$PR_TITLE_LOWER" =~ ^(docs|chore|test|ci|style): ]]; then
echo "Detected non-versioned change - no version bump"
echo "bump_type=none" >> $GITHUB_OUTPUT
echo "should_bump=false" >> $GITHUB_OUTPUT
echo "should_build_docker=false" >> $GITHUB_OUTPUT
else
echo "No recognized prefix - no version bump"
echo "bump_type=none" >> $GITHUB_OUTPUT
echo "should_bump=false" >> $GITHUB_OUTPUT
echo "should_build_docker=false" >> $GITHUB_OUTPUT
fi
- name: Get current version
if: steps.bump_type.outputs.should_bump == 'true'
id: current_version
run: |
CURRENT_VERSION=$(python -c "from config import __version__; print(__version__)")
echo "Current version: $CURRENT_VERSION"
echo "version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
- name: Bump version
if: steps.bump_type.outputs.should_bump == 'true'
id: new_version
run: |
python scripts/bump_version.py ${{ steps.bump_type.outputs.bump_type }}
NEW_VERSION=$(python -c "from config import __version__; print(__version__)")
echo "New version: $NEW_VERSION"
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
- name: Commit version change
if: steps.bump_type.outputs.should_bump == 'true'
run: |
git add config.py
git commit -m "chore: bump version to ${{ steps.new_version.outputs.version }}
Automated version bump from PR #${{ github.event.pull_request.number }} - name: Set up Docker Buildx
${{ github.event.pull_request.title }} uses: docker/setup-buildx-action@v3
Co-authored-by: ${{ github.event.pull_request.user.login }} <${{ github.event.pull_request.user.id }}+${{ github.event.pull_request.user.login }}@users.noreply.github.com>"
git push
- name: Create git tag
if: steps.bump_type.outputs.should_bump == 'true'
run: |
git tag -a "v${{ steps.new_version.outputs.version }}" -m "Release v${{ steps.new_version.outputs.version }}
Changes in this release:
- ${{ github.event.pull_request.title }}
PR: #${{ github.event.pull_request.number }}
Author: @${{ github.event.pull_request.user.login }}"
git push origin "v${{ steps.new_version.outputs.version }}"
- name: Generate release notes
if: steps.bump_type.outputs.should_bump == 'true'
id: release_notes
run: |
# Extract PR body for release notes
PR_BODY=$(cat << 'EOF'
${{ github.event.pull_request.body }}
EOF
)
# Create release notes
RELEASE_NOTES=$(cat << EOF
## What's Changed
${{ github.event.pull_request.title }} by @${{ github.event.pull_request.user.login }} in #${{ github.event.pull_request.number }}
### Details
$PR_BODY
### Version Info
- Previous version: ${{ steps.current_version.outputs.version }}
- New version: ${{ steps.new_version.outputs.version }}
- Bump type: ${{ steps.bump_type.outputs.bump_type }}
**Full Changelog**: https://github.com/${{ github.repository }}/compare/v${{ steps.current_version.outputs.version }}...v${{ steps.new_version.outputs.version }}
EOF
)
# Save to file for GitHub release
echo "$RELEASE_NOTES" > release_notes.md
- name: Create GitHub release
if: steps.bump_type.outputs.should_bump == 'true'
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ steps.new_version.outputs.version }}
name: Release v${{ steps.new_version.outputs.version }}
body_path: release_notes.md
draft: false
prerelease: false
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Trigger Docker build
if: steps.bump_type.outputs.should_build_docker == 'true'
run: |
echo "🐳 Triggering Docker build and publish workflow"
# The Docker workflow will be triggered by the tag creation (if version bumped)
# or by repository_dispatch (if docker: prefix without version bump)
if [ "${{ steps.bump_type.outputs.should_bump }}" == "false" ]; then
# For docker: prefix without version bump, trigger via repository_dispatch
curl -X POST \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/dispatches" \
-d '{"event_type":"docker-build","client_payload":{"pr_number":"${{ github.event.pull_request.number }}","pr_title":"${{ github.event.pull_request.title }}","commit_sha":"${{ github.sha }}"}}'
# Add comment to PR about Docker build
COMMENT_BODY="🐳 **Docker Image Build Triggered**
This PR triggered a Docker image build because of the \`+docker\` suffix in the title. - name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
**Expected Image Tags:** - name: Extract metadata
- \`ghcr.io/${{ github.repository_owner }}/zen-mcp-server:pr-${{ github.event.pull_request.number }}\` id: meta
- \`ghcr.io/${{ github.repository_owner }}/zen-mcp-server:main-${{ github.sha }}\` uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
# PR-specific tag for testing
type=raw,value=pr-${{ github.event.number }}-${{ github.sha }}
type=raw,value=pr-${{ github.event.number }}
**To test the image after build completes:** - name: Build and push Docker image
\`\`\`bash uses: docker/build-push-action@v5
docker pull ghcr.io/${{ github.repository_owner }}/zen-mcp-server:pr-${{ github.event.pull_request.number }} with:
\`\`\` context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
**Claude Desktop config for testing:** - name: Comment on PR with Docker info
\`\`\`json uses: actions/github-script@v7
{ with:
\"mcpServers\": { script: |
\"gemini\": { const prNumber = context.payload.pull_request.number;
\"command\": \"docker\", const sha = context.sha.substring(0, 7);
\"args\": [ const repo = context.repo.repo;
\"run\", \"--rm\", \"-i\", const owner = context.repo.owner;
\"-e\", \"GEMINI_API_KEY\",
\"ghcr.io/${{ github.repository_owner }}/zen-mcp-server:pr-${{ github.event.pull_request.number }}\" const comment = `🐳 **Docker Image Built Successfully**
],
\"env\": { This PR has been built and pushed as a Docker image for testing:
\"GEMINI_API_KEY\": \"your-api-key-here\"
**Available Tags:**
- \`ghcr.io/${owner}/${repo}:pr-${prNumber}-${context.sha}\`
- \`ghcr.io/${owner}/${repo}:pr-${prNumber}\` (latest for this PR)
**Test the changes:**
\`\`\`bash
docker pull ghcr.io/${owner}/${repo}:pr-${prNumber}
\`\`\`
**Claude Desktop configuration:**
\`\`\`json
{
"mcpServers": {
"zen-mcp-server": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-e", "GEMINI_API_KEY",
"ghcr.io/${owner}/${repo}:pr-${prNumber}"
],
"env": {
"GEMINI_API_KEY": "your-api-key-here"
}
} }
} }
} }
} \`\`\`
\`\`\`
The image will be updated automatically when you push new commits to this PR.`;
github.rest.issues.createComment({
issue_number: prNumber,
owner: owner,
repo: repo,
body: comment
});
View the build progress in the [Actions tab](https://github.com/${{ github.repository }}/actions)." - name: Create deployment summary
run: |
curl -X POST \ echo "## 🐳 PR Docker Build Complete" >> $GITHUB_STEP_SUMMARY
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/comments" \
-d "{\"body\":\"$COMMENT_BODY\"}"
fi
- name: Summary
run: |
if [ "${{ steps.bump_type.outputs.should_bump }}" == "true" ]; then
echo "### ✅ Version Bumped Successfully" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "- **Previous version**: ${{ steps.current_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY echo "**PR**: #${{ github.event.number }}" >> $GITHUB_STEP_SUMMARY
echo "- **New version**: ${{ steps.new_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY echo "**Commit**: ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
echo "- **Bump type**: ${{ steps.bump_type.outputs.bump_type }}" >> $GITHUB_STEP_SUMMARY echo "**Images built:**" >> $GITHUB_STEP_SUMMARY
echo "- **Tag**: v${{ steps.new_version.outputs.version }}" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "- **PR**: #${{ github.event.pull_request.number }}" >> $GITHUB_STEP_SUMMARY echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
echo "- **Docker**: Will build and publish with new tag" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
elif [ "${{ steps.bump_type.outputs.should_build_docker }}" == "true" ]; then
echo "### 🐳 Docker Build Requested" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "No version bump but Docker image will be built and published." >> $GITHUB_STEP_SUMMARY
echo "- **PR**: #${{ github.event.pull_request.number }}" >> $GITHUB_STEP_SUMMARY
echo "- **Title**: ${{ github.event.pull_request.title }}" >> $GITHUB_STEP_SUMMARY
echo "- **Docker tag**: Based on commit SHA" >> $GITHUB_STEP_SUMMARY
else
echo "### No Version Bump Required" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "PR title prefix did not require a version bump." >> $GITHUB_STEP_SUMMARY
echo "- **PR**: #${{ github.event.pull_request.number }}" >> $GITHUB_STEP_SUMMARY
echo "- **Title**: ${{ github.event.pull_request.title }}" >> $GITHUB_STEP_SUMMARY
fi

116
.github/workflows/docker-release.yml vendored Normal file
View File

@@ -0,0 +1,116 @@
name: Docker Release Build
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: 'Tag to build (leave empty for latest release)'
required: false
type: string
permissions:
contents: read
packages: write
jobs:
docker:
name: Build and Push Docker Image
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
# If triggered by workflow_dispatch with a tag, checkout that tag
ref: ${{ inputs.tag || github.event.release.tag_name }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
# Tag with the release version
type=semver,pattern={{version}},value=${{ inputs.tag || github.event.release.tag_name }}
type=semver,pattern={{major}}.{{minor}},value=${{ inputs.tag || github.event.release.tag_name }}
type=semver,pattern={{major}},value=${{ inputs.tag || github.event.release.tag_name }}
# Also tag as latest for the most recent release
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Update release with Docker info
if: github.event_name == 'release'
run: |
RELEASE_TAG="${{ github.event.release.tag_name }}"
DOCKER_TAGS=$(echo "${{ steps.meta.outputs.tags }}" | tr '\n' ' ')
# Add Docker information to the release
gh release edit "$RELEASE_TAG" --notes-file - << EOF
${{ github.event.release.body }}
---
## 🐳 Docker Images
This release is available as Docker images:
$(echo "$DOCKER_TAGS" | sed 's/ghcr.io/- `ghcr.io/g' | sed 's/ /`\n/g')
**Quick start with Docker:**
\`\`\`bash
docker pull ghcr.io/${{ github.repository }}:$RELEASE_TAG
\`\`\`
**Claude Desktop configuration:**
\`\`\`json
{
"mcpServers": {
"zen-mcp-server": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-e", "GEMINI_API_KEY",
"ghcr.io/${{ github.repository }}:$RELEASE_TAG"
],
"env": {
"GEMINI_API_KEY": "your-api-key-here"
}
}
}
}
\`\`\`
EOF
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create deployment summary
run: |
echo "## 🐳 Docker Release Build Complete" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Release**: ${{ inputs.tag || github.event.release.tag_name }}" >> $GITHUB_STEP_SUMMARY
echo "**Images built:**" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY

61
.github/workflows/semantic-release.yml vendored Normal file
View File

@@ -0,0 +1,61 @@
name: Semantic Release
on:
push:
branches:
- main
permissions:
contents: write
issues: write
pull-requests: write
jobs:
release:
runs-on: ubuntu-latest
concurrency: release
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
persist-credentials: true
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install python-semantic-release
- name: Verify tests pass
run: |
pip install -r requirements.txt
pip install -r requirements-dev.txt
python -m pytest tests/ -v --ignore=simulator_tests/ -m "not integration"
- name: Run semantic release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
semantic-release version
semantic-release publish
- name: Upload build artifacts to release
if: hashFiles('dist/*') != ''
run: |
# Get the latest release tag
LATEST_TAG=$(gh release list --limit 1 --json tagName --jq '.[0].tagName')
if [ ! -z "$LATEST_TAG" ]; then
echo "Uploading artifacts to release $LATEST_TAG"
gh release upload "$LATEST_TAG" dist/* --clobber
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,10 +1,8 @@
name: Tests name: Tests
on: on:
push:
branches: [ main, develop ]
pull_request: pull_request:
branches: [ main ] branches: [main]
jobs: jobs:
test: test:
@@ -14,47 +12,46 @@ jobs:
python-version: ["3.10", "3.11", "3.12"] python-version: ["3.10", "3.11", "3.12"]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }} - name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: ${{ matrix.python-version }} python-version: ${{ matrix.python-version }}
- name: Install dependencies - name: Install dependencies
run: | run: |
python -m pip install --upgrade pip python -m pip install --upgrade pip
pip install -r requirements.txt pip install -r requirements.txt
pip install -r requirements-dev.txt pip install -r requirements-dev.txt
- name: Run unit tests - name: Run unit tests
run: | run: |
# Run only unit tests (exclude simulation tests and integration tests) # Run only unit tests (exclude simulation tests and integration tests)
# Integration tests require local-llama which isn't available in CI # Integration tests require local-llama which isn't available in CI
python -m pytest tests/ -v --ignore=simulator_tests/ -m "not integration" python -m pytest tests/ -v --ignore=simulator_tests/ -m "not integration"
env: env:
# Ensure no API key is accidentally used in CI # Ensure no API key is accidentally used in CI
GEMINI_API_KEY: "" GEMINI_API_KEY: ""
OPENAI_API_KEY: "" OPENAI_API_KEY: ""
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
- name: Run black formatter check
run: black --check . --exclude="test_simulation_files/"
- name: Run ruff linter
run: ruff check . --exclude test_simulation_files
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.11"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-dev.txt
- name: Run black formatter check
run: black --check . --exclude="test_simulation_files/"
- name: Run ruff linter
run: ruff check . --exclude test_simulation_files

40
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,40 @@
---
default_stages: [pre-commit, pre-push]
repos:
- repo: https://github.com/psf/black
rev: 25.1.0
hooks:
- id: black
exclude: ^test_simulation_files/
- repo: https://github.com/pycqa/isort
rev: 6.0.1
hooks:
- id: isort
args: ["--profile", "black"]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.12.8
hooks:
- id: ruff
args: [--fix]
exclude: ^test_simulation_files/
# Configuration for specific tools
default_language_version:
python: python3
# Exclude patterns
exclude: |
(?x)^(
\.git/|
\.venv/|
venv/|
\.zen_venv/|
__pycache__/|
\.pytest_cache/|
logs/|
dist/|
build/|
test_simulation_files/
)$

View File

@@ -23,8 +23,16 @@ We maintain high code quality standards. **All contributions must pass our autom
#### Required Code Quality Checks #### Required Code Quality Checks
Before submitting any PR, run our automated quality check script: **Option 1 - Automated (Recommended):**
```bash
# Install pre-commit hooks (one-time setup)
pre-commit install
# Now linting runs automatically on every commit
# Includes: ruff (with auto-fix), black, isort
```
**Option 2 - Manual:**
```bash ```bash
# Run the comprehensive quality checks script # Run the comprehensive quality checks script
./code_quality_checks.sh ./code_quality_checks.sh
@@ -32,7 +40,7 @@ Before submitting any PR, run our automated quality check script:
This script automatically runs: This script automatically runs:
- Ruff linting with auto-fix - Ruff linting with auto-fix
- Black code formatting - Black code formatting
- Import sorting with isort - Import sorting with isort
- Complete unit test suite (361 tests) - Complete unit test suite (361 tests)
- Verification that all checks pass 100% - Verification that all checks pass 100%
@@ -56,7 +64,7 @@ python -m pytest -xvs
python communication_simulator_test.py python communication_simulator_test.py
``` ```
**Important**: **Important**:
- **Every single test must pass** - we have zero tolerance for failing tests in CI - **Every single test must pass** - we have zero tolerance for failing tests in CI
- All linting must pass cleanly (ruff, black, isort) - All linting must pass cleanly (ruff, black, isort)
- Import sorting must be correct - Import sorting must be correct
@@ -69,12 +77,12 @@ python communication_simulator_test.py
1. **New features MUST include tests**: 1. **New features MUST include tests**:
- Add unit tests in `tests/` for new functions or classes - Add unit tests in `tests/` for new functions or classes
- Test both success and error cases - Test both success and error cases
2. **Tool changes require simulator tests**: 2. **Tool changes require simulator tests**:
- Add simulator tests in `simulator_tests/` for new or modified tools - Add simulator tests in `simulator_tests/` for new or modified tools
- Use realistic prompts that demonstrate the feature - Use realistic prompts that demonstrate the feature
- Validate output through server logs - Validate output through server logs
3. **Bug fixes require regression tests**: 3. **Bug fixes require regression tests**:
- Add a test that would have caught the bug - Add a test that would have caught the bug
- Ensure the bug cannot reoccur - Ensure the bug cannot reoccur
@@ -136,14 +144,14 @@ def process_model_response(
max_tokens: Optional[int] = None max_tokens: Optional[int] = None
) -> ProcessedResult: ) -> ProcessedResult:
"""Process and validate model response. """Process and validate model response.
Args: Args:
response: Raw response from the model provider response: Raw response from the model provider
max_tokens: Optional token limit for truncation max_tokens: Optional token limit for truncation
Returns: Returns:
ProcessedResult with validated and formatted content ProcessedResult with validated and formatted content
Raises: Raises:
ValueError: If response is invalid or exceeds limits ValueError: If response is invalid or exceeds limits
""" """
@@ -237,4 +245,4 @@ Contributors are recognized in:
- Release notes for significant contributions - Release notes for significant contributions
- Special mentions for exceptional work - Special mentions for exceptional work
Thank you for contributing to Zen MCP Server! Your efforts help make this tool better for everyone. Thank you for contributing to Zen MCP Server! Your efforts help make this tool better for everyone.

View File

@@ -1,6 +1,6 @@
[project] [project]
name = "zen-mcp-server" name = "zen-mcp-server"
version = "0.1.0" version = "1.1.0"
description = "AI-powered MCP server with multiple model providers" description = "AI-powered MCP server with multiple model providers"
requires-python = ">=3.9" requires-python = ">=3.9"
dependencies = [ dependencies = [
@@ -83,6 +83,33 @@ ignore = [
"tests/*" = ["B011"] "tests/*" = ["B011"]
"tests/conftest.py" = ["E402"] # Module level imports not at top of file - needed for test setup "tests/conftest.py" = ["E402"] # Module level imports not at top of file - needed for test setup
[tool.semantic_release]
version_toml = ["pyproject.toml:project.version"]
branch = "main"
build_command = "python -m pip install --upgrade build && python -m build"
dist_path = "dist/"
upload_to_vcs_release = true
upload_to_repository = false
remove_dist = false
commit_version_number = true
commit_message = "chore(release): {version}\n\nAutomatically generated by python-semantic-release"
tag_format = "v{version}"
[tool.semantic_release.branches.main]
match = "main"
prerelease = false
[tool.semantic_release.changelog]
exclude_commit_patterns = []
[tool.semantic_release.commit_parser_options]
allowed_tags = ["build", "chore", "ci", "docs", "feat", "fix", "perf", "style", "refactor", "test"]
minor_tags = ["feat"]
patch_tags = ["fix", "perf"]
[tool.semantic_release.remote.token]
env = "GH_TOKEN"
[build-system] [build-system]
requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.2"] requires = ["setuptools>=45", "wheel", "setuptools_scm[toml]>=6.2"]
build-backend = "setuptools.build_meta" build-backend = "setuptools.build_meta"

View File

@@ -3,4 +3,6 @@ pytest-asyncio>=0.21.0
pytest-mock>=3.11.0 pytest-mock>=3.11.0
black>=23.0.0 black>=23.0.0
ruff>=0.1.0 ruff>=0.1.0
isort>=5.12.0 isort>=5.12.0
python-semantic-release>=10.3.0
build>=1.0.0