mirror of
https://github.com/mcp-use/mcp-use.git
synced 2026-09-14 18:06:01 +08:00
346 lines
12 KiB
YAML
346 lines
12 KiB
YAML
name: Python Release
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
paths:
|
|
- "libraries/python/**"
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: write
|
|
id-token: write
|
|
discussions: write
|
|
|
|
jobs:
|
|
detect-release:
|
|
name: Check Changes
|
|
runs-on: ubuntu-latest
|
|
outputs:
|
|
current_version: ${{ steps.current-version.outputs.version }}
|
|
latest_tag: ${{ steps.latest-release.outputs.tag }}
|
|
latest_version: ${{ steps.latest-release.outputs.version }}
|
|
should_publish: ${{ steps.compare.outputs.should_publish }}
|
|
should_draft: ${{ steps.compare.outputs.should_draft }}
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.11"
|
|
|
|
- name: Get current version
|
|
id: current-version
|
|
working-directory: libraries/python
|
|
run: |
|
|
VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
echo "Current version: $VERSION"
|
|
|
|
- name: Get latest published release
|
|
id: latest-release
|
|
run: |
|
|
# Get the latest published python release tag (not the draft)
|
|
LATEST_TAG=$(git tag -l "python-v*" --sort=-v:refname | head -n 1)
|
|
|
|
if [ -z "$LATEST_TAG" ]; then
|
|
echo "No previous python releases found"
|
|
echo "version=0.0.0" >> $GITHUB_OUTPUT
|
|
echo "tag=none" >> $GITHUB_OUTPUT
|
|
else
|
|
LATEST_VERSION=${LATEST_TAG#python-v}
|
|
echo "version=$LATEST_VERSION" >> $GITHUB_OUTPUT
|
|
echo "tag=$LATEST_TAG" >> $GITHUB_OUTPUT
|
|
echo "Latest published release: $LATEST_VERSION"
|
|
fi
|
|
|
|
- name: Compare versions
|
|
id: compare
|
|
run: |
|
|
CURRENT="${{ steps.current-version.outputs.version }}"
|
|
LATEST="${{ steps.latest-release.outputs.version }}"
|
|
|
|
echo "Comparing versions:"
|
|
echo " Current: $CURRENT"
|
|
echo " Latest: $LATEST"
|
|
|
|
if [ "$CURRENT" != "$LATEST" ]; then
|
|
echo "Version has been bumped - will publish release"
|
|
echo "should_publish=true" >> $GITHUB_OUTPUT
|
|
echo "should_draft=false" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "Version unchanged - will update draft"
|
|
echo "should_publish=false" >> $GITHUB_OUTPUT
|
|
echo "should_draft=true" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
update-draft:
|
|
name: Update python draft release
|
|
runs-on: ubuntu-latest
|
|
needs: [detect-release]
|
|
if: needs.detect-release.outputs.should_draft == 'true'
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Generate release notes for draft
|
|
id: draft-notes
|
|
run: |
|
|
PREV_TAG="${{ needs.detect-release.outputs.latest_tag }}"
|
|
|
|
chmod +x .github/scripts/generate-python-release-notes.sh
|
|
.github/scripts/generate-python-release-notes.sh "" "$PREV_TAG" "draft" > notes.md
|
|
|
|
cat notes.md
|
|
|
|
{
|
|
echo 'notes<<EOF'
|
|
cat notes.md
|
|
echo EOF
|
|
} >> $GITHUB_OUTPUT
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Update Draft Release
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
tag_name: python-draft
|
|
name: python-draft
|
|
body: ${{ steps.draft-notes.outputs.notes }}
|
|
draft: true
|
|
prerelease: false
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
create-github-release:
|
|
name: Create GitHub release
|
|
runs-on: ubuntu-latest
|
|
needs: [detect-release]
|
|
if: needs.detect-release.outputs.should_publish == 'true'
|
|
outputs:
|
|
version: ${{ needs.detect-release.outputs.current_version }}
|
|
release_exists: ${{ steps.check-release.outputs.exists }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Get release notes from draft
|
|
id: publish-notes
|
|
run: |
|
|
VERSION="${{ needs.detect-release.outputs.current_version }}"
|
|
PREV_TAG="${{ needs.detect-release.outputs.latest_tag }}"
|
|
|
|
# Check if draft release exists
|
|
if gh release view python-draft >/dev/null 2>&1; then
|
|
echo "Fetching release notes from python-draft..."
|
|
DRAFT_BODY=$(gh release view python-draft --json body -q '.body')
|
|
|
|
# Update header and remove draft-specific text (fix sed chaining)
|
|
UPDATED_BODY=$(echo "$DRAFT_BODY" | \
|
|
sed "s/## Draft Release/## What's Changed/" | \
|
|
sed "/This is a draft release tracking changes/d")
|
|
|
|
{
|
|
echo 'notes<<EOF'
|
|
echo "$UPDATED_BODY"
|
|
echo EOF
|
|
} >> $GITHUB_OUTPUT
|
|
else
|
|
echo "No python-draft release found, generating release notes from git history..."
|
|
|
|
# Make script executable
|
|
chmod +x .github/scripts/generate-python-release-notes.sh
|
|
|
|
# Generate notes using shared script
|
|
.github/scripts/generate-python-release-notes.sh "$VERSION" "$PREV_TAG" "publish" > notes.md
|
|
|
|
{
|
|
echo 'notes<<EOF'
|
|
cat notes.md
|
|
echo EOF
|
|
} >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
echo "Release notes prepared successfully"
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Check if release already exists
|
|
id: check-release
|
|
run: |
|
|
TAG_NAME="python-v${{ needs.detect-release.outputs.current_version }}"
|
|
|
|
# Check if a published release with this version already exists
|
|
if git rev-parse "$TAG_NAME" >/dev/null 2>&1; then
|
|
echo "Release $TAG_NAME already exists"
|
|
echo "exists=true" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "Release $TAG_NAME does not exist, will create it"
|
|
echo "exists=false" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Create Release
|
|
if: steps.check-release.outputs.exists == 'false'
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
tag_name: python-v${{ needs.detect-release.outputs.current_version }}
|
|
name: Python v${{ needs.detect-release.outputs.current_version }}
|
|
body: ${{ steps.publish-notes.outputs.notes }}
|
|
draft: false
|
|
prerelease: false
|
|
token: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
publish-pypi:
|
|
name: Publish to PyPI
|
|
runs-on: ubuntu-latest
|
|
needs: [create-github-release]
|
|
if: needs.create-github-release.outputs.release_exists == 'false'
|
|
outputs:
|
|
publish_needed: ${{ steps.check-pypi.outputs.publish_needed }}
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: "3.11"
|
|
|
|
- name: Install uv
|
|
uses: astral-sh/setup-uv@v4
|
|
|
|
- name: Build package
|
|
working-directory: libraries/python
|
|
run: |
|
|
uv build
|
|
|
|
- name: Check if already published to PyPI
|
|
id: check-pypi
|
|
working-directory: libraries/python
|
|
run: |
|
|
# Check if this version exists on PyPI
|
|
VERSION="${{ needs.create-github-release.outputs.version }}"
|
|
|
|
# Get all available versions from PyPI and check if our version is in the list
|
|
PYPI_VERSIONS=$(uv pip index versions mcp-use 2>/dev/null || echo "")
|
|
|
|
if echo "$PYPI_VERSIONS" | grep -qw "$VERSION"; then
|
|
echo "Version $VERSION already exists on PyPI"
|
|
echo "publish_needed=false" >> $GITHUB_OUTPUT
|
|
else
|
|
echo "Version $VERSION not found on PyPI, will publish"
|
|
echo "publish_needed=true" >> $GITHUB_OUTPUT
|
|
fi
|
|
|
|
- name: Publish to PyPI
|
|
if: steps.check-pypi.outputs.publish_needed == 'true'
|
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
with:
|
|
packages-dir: libraries/python/dist/
|
|
|
|
cleanup-draft:
|
|
name: Cleanup draft tag/release
|
|
runs-on: ubuntu-latest
|
|
needs: [create-github-release, publish-pypi]
|
|
if: needs.create-github-release.outputs.release_exists == 'false'
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Delete draft release
|
|
run: |
|
|
# Delete the python-draft release after successful publish
|
|
if gh release view python-draft >/dev/null 2>&1; then
|
|
gh release delete python-draft --yes
|
|
|
|
# Check if the tag exists on the remote before attempting to delete
|
|
if git ls-remote --tags origin python-draft | grep -q "refs/tags/python-draft$"; then
|
|
git push --delete origin python-draft
|
|
echo "Deleted python-draft tag from remote"
|
|
else
|
|
echo "No python-draft tag found on remote to delete"
|
|
fi
|
|
|
|
echo "Deleted python-draft release"
|
|
else
|
|
echo "No python-draft release found to delete"
|
|
fi
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
create-github-discussion:
|
|
name: Create GitHub Discussion
|
|
runs-on: ubuntu-latest
|
|
needs: [create-github-release, publish-pypi]
|
|
if: needs.publish-pypi.outputs.publish_needed == 'true'
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Prepare discussion body
|
|
id: body
|
|
run: |
|
|
VERSION="${{ needs.create-github-release.outputs.version }}"
|
|
TAG_NAME="python-v${VERSION}"
|
|
RELEASE_BODY=$(gh release view "$TAG_NAME" --json body -q '.body')
|
|
|
|
cat <<EOF > discussion_body.md
|
|
We've just published **Python v${VERSION}** to PyPI!
|
|
|
|
📦 \`pip install --upgrade mcp-use\`
|
|
|
|
${RELEASE_BODY}
|
|
|
|
---
|
|
📖 [Full changelog](https://mcp-use.com/python/changelog/${VERSION//./_})
|
|
🐙 [GitHub Release](https://github.com/mcp-use/mcp-use/releases/tag/${TAG_NAME})
|
|
EOF
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Create discussion
|
|
uses: abirismyname/create-discussion@v2.1.0
|
|
with:
|
|
title: "🚀 Python v${{ needs.create-github-release.outputs.version }} Released"
|
|
body-filepath: discussion_body.md
|
|
repository-id: R_kgDOOQKbDA
|
|
category-id: DIC_kwDOOQKbDM4CrC8-
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
send-discord-notification:
|
|
name: Notify Discord of published release
|
|
runs-on: ubuntu-latest
|
|
needs: [create-github-release, publish-pypi]
|
|
if: needs.publish-pypi.outputs.publish_needed == 'true'
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Send Discord notification
|
|
run: |
|
|
VERSION="${{ needs.create-github-release.outputs.version }}"
|
|
TAG_NAME="python-v${VERSION}"
|
|
RELEASE_URL="https://github.com/mcp-use/mcp-use/releases/tag/${TAG_NAME}"
|
|
RELEASE_BODY=$(gh release view "$TAG_NAME" --json body -q '.body' | head -c 1800)
|
|
|
|
# Build Discord embed payload
|
|
PAYLOAD=$(jq -n \
|
|
--arg title "Python v${VERSION}" \
|
|
--arg url "$RELEASE_URL" \
|
|
--arg desc "$RELEASE_BODY" \
|
|
'{embeds: [{title: $title, url: $url, description: $desc, color: 5814783}]}')
|
|
|
|
curl -s -H "Content-Type: application/json" \
|
|
-d "$PAYLOAD" \
|
|
"$WEBHOOK_URL"
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
WEBHOOK_URL: ${{ secrets.DISCORD_RELEASE_CHANNEL_WEBHOOK_URL }}
|