# .github/workflows/release.yml
name: Auto Release
on:
push:
branches: [main]
paths: ['pyproject.toml'] # Only trigger when pyproject.toml changes
jobs:
check-version-bump:
runs-on: ubuntu-latest
outputs:
should-release: ${{ steps.check.outputs.should-release }}
new-version: ${{ steps.check.outputs.new-version }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 2 # Need to compare with previous commit
- name: Set up uv
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7
with:
enable-cache: true
- name: Check if version was bumped
id: check
run: |
# Get current version
CURRENT_VERSION=$(uv version | cut -d' ' -f2)
echo "Current version: $CURRENT_VERSION"
# Get previous version from git (before this commit)
git checkout HEAD~1 -- pyproject.toml || true
PREVIOUS_VERSION=$(uv version | cut -d' ' -f2) 2>/dev/null || echo "0.0.0"
git checkout HEAD -- pyproject.toml
echo "Previous version: $PREVIOUS_VERSION"
# Check if version actually changed
if [[ "$CURRENT_VERSION" != "$PREVIOUS_VERSION" ]]; then
echo "✅ Version bump detected: $PREVIOUS_VERSION → $CURRENT_VERSION"
echo "should-release=true" >> $GITHUB_OUTPUT
echo "new-version=$CURRENT_VERSION" >> $GITHUB_OUTPUT
else
echo "ℹ️ No version change detected"
echo "should-release=false" >> $GITHUB_OUTPUT
fi
release:
needs: check-version-bump
if: needs.check-version-bump.outputs.should-release == 'true'
runs-on: ubuntu-latest
env:
VERSION: ${{ needs.check-version-bump.outputs.new-version }}
permissions:
contents: write
packages: write
id-token: write # Required for PyPI Trusted Publishing
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
- name: Set up uv
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7
with:
enable-cache: true
- name: Set up Bun
uses: oven-sh/setup-bun@3d267786b128fe76c2f16a390aa2448b815359f3 # v2
- name: Update manifest.json and docker-compose.yml version
run: |
set -e
sed -i 's/"version": ".*"/"version": "'$VERSION'"/' manifest.json
sed -i 's/stickerdaniel\/linkedin-mcp-server:[^"]*/stickerdaniel\/linkedin-mcp-server:'$VERSION'/' manifest.json
sed -i 's/stickerdaniel\/linkedin-mcp-server:[^ ]*/stickerdaniel\/linkedin-mcp-server:'$VERSION'/' docker-compose.yml
echo "✅ Updated manifest.json and docker-compose.yml to version $VERSION"
- name: Remove branch protection (temporary)
run: |
gh api repos/${{ github.repository }}/branches/main/protection \
--method DELETE
env:
GH_TOKEN: ${{ secrets.GH_ADMIN_TOKEN }}
- name: Commit version updates
run: |
set -e
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
git add manifest.json docker-compose.yml
if git diff --staged --quiet; then
echo "ℹ️ No changes to commit"
else
git commit -m "chore: update manifest.json and docker-compose.yml to v$VERSION [skip ci]"
git push origin main
echo "✅ Committed version updates"
fi
- name: Restore branch protection
if: always()
env:
GH_TOKEN: ${{ secrets.GH_ADMIN_TOKEN }}
PAYLOAD: >-
{
"required_status_checks": {
"strict": true,
"checks": [
{"context": "lint-and-check", "app_id": 15368},
{"context": "test", "app_id": 15368}
]
},
"enforce_admins": true,
"required_pull_request_reviews": {
"dismiss_stale_reviews": false,
"require_code_owner_reviews": false,
"required_approving_review_count": 0
},
"restrictions": null
}
run: |
echo "$PAYLOAD" | gh api repos/${{ github.repository }}/branches/main/protection \
--method PUT \
--input -
- name: Create release tag
run: |
set -e
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"
if git tag -l "v$VERSION" | grep -q "v$VERSION"; then
echo "⚠️ Tag v$VERSION already exists, skipping tag creation"
else
git tag "v$VERSION"
git push origin "v$VERSION"
echo "✅ Created and pushed tag v$VERSION"
fi
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3
- name: Log in to Docker Hub
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push Docker images
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
with:
context: .
push: true
tags: |
stickerdaniel/linkedin-mcp-server:${{ env.VERSION }}
stickerdaniel/linkedin-mcp-server:latest
platforms: linux/amd64,linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Update Docker Hub description
uses: peter-evans/dockerhub-description@1b9a80c056b620d92cedb9d9b5a223409c68ddfa # v5
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
repository: stickerdaniel/linkedin-mcp-server
readme-filepath: docs/docker-hub.md
- name: Optimize uv cache for CI
run: uv cache prune --ci
- name: Build DXT extension
run: |
bunx @anthropic-ai/dxt pack
mv linkedin-mcp-server.dxt linkedin-mcp-server-v$VERSION.dxt
- name: Generate release notes
run: |
envsubst < RELEASE_NOTES_TEMPLATE.md > RELEASE_NOTES.md
echo "✅ Generated release notes from template"
- name: Create GitHub Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2
with:
tag_name: v${{ env.VERSION }}
files: |
*.dxt
generate_release_notes: true
draft: false
prerelease: false
name: "LinkedIn MCP Server v${{ env.VERSION }}"
body_path: RELEASE_NOTES.md
- name: Build package distributions
run: |
uv build
echo "Built package distributions:"
ls -lh dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
print-hash: true
verbose: true
- name: Summary
run: |
echo "Successfully released v$VERSION!"
echo "Docker: stickerdaniel/linkedin-mcp-server:$VERSION"
echo "PyPI: https://pypi.org/project/linkedin-scraper-mcp/$VERSION/"
echo "GitHub: https://github.com/${{ github.repository }}/releases/tag/v$VERSION"