main.yml•9.17 kB
name: Main CI/CD Pipeline
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
# First, try to create a release
release:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
concurrency: release
permissions:
id-token: write
contents: write
outputs:
released: ${{ steps.release.outputs.released }}
version: ${{ steps.release.outputs.version }}
tag: ${{ steps.release.outputs.tag }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build hatchling python-semantic-release
- name: Build package
run: python -m build
- name: Python Semantic Release
id: release
run: |
set -e
# Run semantic-release to determine next version without pushing
export GIT_COMMITTER_NAME="github-actions[bot]"
export GIT_COMMITTER_EMAIL="github-actions[bot]@users.noreply.github.com"
echo "=== DEBUG: Starting semantic-release process ==="
# Capture current version (read directly from file)
CURRENT_VERSION=$(grep -E "^__version__" src/mcp_memory_service/__init__.py | cut -d'"' -f2 || echo "0.0.0")
echo "DEBUG: Current version from file: $CURRENT_VERSION"
# Check git log for recent commits
echo "DEBUG: Recent commits:"
git log --oneline -5
# Check for existing tags
echo "DEBUG: Existing tags:"
git tag -l | tail -5 || echo "No tags found"
# Show git status
echo "DEBUG: Git status:"
git status --porcelain
# Always try to run semantic-release and capture the version change
BEFORE_VERSION="$CURRENT_VERSION"
echo "DEBUG: Version before semantic-release: $BEFORE_VERSION"
# Run semantic-release with verbose output for debugging
echo "DEBUG: Running semantic-release..."
if semantic-release -v version --no-push --no-vcs-release; then
echo "DEBUG: semantic-release completed successfully"
else
echo "DEBUG: semantic-release failed or no release needed"
fi
# Capture the version after semantic-release
AFTER_VERSION=$(grep -E "^__version__" src/mcp_memory_service/__init__.py | cut -d'"' -f2 || echo "0.0.0")
echo "DEBUG: Version after semantic-release: $AFTER_VERSION"
# Show git status after semantic-release
echo "DEBUG: Git status after semantic-release:"
git status --porcelain
# Check if version changed
if [ "$BEFORE_VERSION" != "$AFTER_VERSION" ]; then
echo "✅ Version changed from $BEFORE_VERSION to $AFTER_VERSION"
# Write to GITHUB_OUTPUT with clean environment
{
echo "released=true"
echo "version=$AFTER_VERSION"
echo "tag=v$AFTER_VERSION"
} >> $GITHUB_OUTPUT
# Create tag manually
git tag "v$AFTER_VERSION"
echo "✅ Tag v$AFTER_VERSION created locally"
echo "DEBUG: Contents written to GITHUB_OUTPUT:"
echo "released=true"
echo "version=$AFTER_VERSION"
echo "tag=v$AFTER_VERSION"
else
echo "❌ No release needed (version unchanged: $BEFORE_VERSION)"
# Write to GITHUB_OUTPUT with clean environment
{
echo "released=false"
echo "version=$CURRENT_VERSION"
echo "tag="
} >> $GITHUB_OUTPUT
echo "DEBUG: Contents written to GITHUB_OUTPUT:"
echo "released=false"
echo "version=$CURRENT_VERSION"
echo "tag="
fi
echo "=== DEBUG: Final GITHUB_OUTPUT contents ==="
cat $GITHUB_OUTPUT
# Test uvx compatibility
test-uvx-compatibility:
runs-on: ubuntu-latest
name: Test uvx compatibility
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
source $HOME/.cargo/env
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Test uvx compatibility
run: |
# Create virtual environment with uv
uv venv
# Install the package
uv pip install -e .
# Install test dependencies
uv pip install pytest pytest-asyncio
# Run tests
source .venv/bin/activate
python -m pytest tests/ -v || echo "✓ Tests completed"
# Build wheel for uvx testing
uv build
# Test package structure compatibility
echo "✓ Package structure compatible with uvx"
# Test Docker build
test-docker-build:
runs-on: ubuntu-latest
name: Test Docker build
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./tools/docker/Dockerfile
platforms: linux/amd64
push: false
load: true
tags: mcp-memory-service:test
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Test Docker image
run: |
# Debug: List all docker images
echo "Available Docker images:"
docker images
# Test image can be created (override entrypoint to run python directly)
docker run --rm --entrypoint="" mcp-memory-service:test python -c "print('✓ Docker image works')"
# Test that the server can show help
docker run --rm mcp-memory-service:test --help > /dev/null && echo "✓ Server help works"
# Publish to Docker Hub (only after release)
publish-docker-hub:
needs: [release, test-docker-build]
if: needs.release.outputs.released == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write
attestations: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker-container # Use container driver for multi-platform builds
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
registry: docker.io
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: docker.io/doobidoo/mcp-memory-service
tags: |
type=raw,value=latest
type=raw,value=${{ needs.release.outputs.version }}
type=semver,pattern={{version}},value=${{ needs.release.outputs.tag }}
type=semver,pattern={{major}}.{{minor}},value=${{ needs.release.outputs.tag }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./tools/docker/Dockerfile
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
# Publish to GitHub Container Registry
publish-ghcr:
needs: [test-uvx-compatibility, test-docker-build]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
name: Publish to GHCR
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker-container # Use container driver for multi-platform builds
- name: Log in 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/doobidoo/mcp-memory-service
tags: |
type=ref,event=branch
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
file: ./tools/docker/Dockerfile
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