Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/pr-feedback.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,12 @@ jobs:
# ===================
echo "### 🎨 Code Formatting" >> pr-feedback.md
if ! ruff format --check . > format_output.txt 2>&1; then
format_issues=$(ruff format --check . 2>&1 | grep -c "would reformat" || echo "0")
# `grep -c` prints 0 AND exits 1 when nothing matches, so `|| echo "0"`
# produced the literal string "0\n0" and broke the arithmetic below.
# Recent ruff versions also report "N files would be reformatted", so
# parse the summary line instead of counting per-file markers.
format_issues=$(grep -oE '[0-9]+ files? would be reformatted' format_output.txt | grep -oE '^[0-9]+' | tail -1 || true)
format_issues=${format_issues:-1}
echo "❌ **$format_issues file(s) need formatting**" >> pr-feedback.md
echo "" >> pr-feedback.md
echo "<details><summary>Click to see formatting issues</summary>" >> pr-feedback.md
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/pre-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ jobs:
changelog.append('')

changelog.append('### 🧪 Testing')
changelog.append('- Install: \`pip install markitdown-mcp==$VERSION\`')
changelog.append('- Install: \`pip install trsdn-markitdown-mcp==$VERSION\`')
changelog.append('- Feedback: Report issues in GitHub with pre-release label')
changelog.append('')

Expand Down Expand Up @@ -345,7 +345,7 @@ jobs:
# Install from Test PyPI
pip install --index-url https://test.pypi.org/simple/ \
--extra-index-url https://pypi.org/simple/ \
markitdown-mcp==$VERSION
trsdn-markitdown-mcp==$VERSION

# Test basic functionality
python -c "
Expand Down Expand Up @@ -383,7 +383,7 @@ jobs:
This is a pre-release version for testing purposes.

🧪 **Testing Instructions:**
- Install: pip install markitdown-mcp==${{ needs.prepare-prerelease.outputs.version }}
- Install: pip install trsdn-markitdown-mcp==${{ needs.prepare-prerelease.outputs.version }}
- Test your workflows with this version
- Report any issues with the 'pre-release' label

Expand All @@ -404,7 +404,7 @@ jobs:

### Installation
```bash
pip install markitdown-mcp==$VERSION
pip install trsdn-markitdown-mcp==$VERSION
```

### Testing Checklist
Expand Down Expand Up @@ -453,7 +453,7 @@ jobs:
VERSION="${{ needs.prepare-prerelease.outputs.version }}"

# Install from PyPI
pip install markitdown-mcp==$VERSION
pip install trsdn-markitdown-mcp==$VERSION

# Comprehensive functionality test
python -c "
Expand Down Expand Up @@ -498,7 +498,7 @@ jobs:
echo ""
echo "📦 **Version**: $TAG"
echo "🔗 **Release**: https://github.com/${{ github.repository }}/releases/tag/$TAG"
echo "📥 **Install**: pip install markitdown-mcp==$VERSION"
echo "📥 **Install**: pip install trsdn-markitdown-mcp==$VERSION"
echo ""

if [[ "${{ needs.create-prerelease.result }}" == "success" ]]; then
Expand Down
114 changes: 92 additions & 22 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ on:
push:
tags:
- 'v*.*.*'

workflow_dispatch:
inputs:
tag:
description: 'Existing release tag to (re-)run the pipeline for, e.g. v1.2.3'
required: true
type: string

# Least privilege by default; jobs opt into what they need.
# `id-token: write` is granted ONLY to the publish job (PyPI Trusted Publishing).
permissions:
contents: write
id-token: write
packages: write
contents: read

# Ensure only one release runs at a time
concurrency:
Expand All @@ -30,11 +36,12 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ inputs.tag || github.ref }}

- name: Extract version from tag
id: version
run: |
TAG=${GITHUB_REF#refs/tags/}
TAG="${{ inputs.tag || github.ref_name }}"
VERSION=${TAG#v}

echo "tag=${TAG}" >> $GITHUB_OUTPUT
Expand Down Expand Up @@ -80,6 +87,8 @@ jobs:
python-version: ['3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.tag || github.ref }}

- uses: actions/setup-python@v5
with:
Expand Down Expand Up @@ -135,6 +144,8 @@ jobs:
needs: validate-release
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.tag || github.ref }}

- uses: actions/setup-python@v5
with:
Expand Down Expand Up @@ -176,6 +187,8 @@ jobs:
package-version: ${{ steps.build.outputs.package-version }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.tag || github.ref }}

- uses: actions/setup-python@v5
with:
Expand All @@ -188,9 +201,26 @@ jobs:
- name: Build package
id: build
run: |
# Update version in pyproject.toml to match tag
# Update version in pyproject.toml to match tag.
# NOTE: a plain `sed s/version = ".*"/.../` also rewrites `python_version`
# and `target-version` in the [tool.*] sections, so anchor on the line start
# and replace exactly one occurrence.
VERSION="${{ needs.validate-release.outputs.version }}"
sed -i "s/version = \".*\"/version = \"$VERSION\"/" pyproject.toml
python - "$VERSION" <<'PY'
import pathlib
import re
import sys

version = sys.argv[1]
path = pathlib.Path("pyproject.toml")
text = path.read_text(encoding="utf-8")
text, count = re.subn(
r'^version = ".*"$', f'version = "{version}"', text, count=1, flags=re.M
)
if count != 1:
raise SystemExit("Could not update [project] version in pyproject.toml")
path.write_text(text, encoding="utf-8")
PY

# Build package
python -m build
Expand All @@ -212,18 +242,35 @@ jobs:

# Test basic functionality
python -c "
from importlib.metadata import version

import markitdown_mcp
print(f'✅ Package installed successfully: {markitdown_mcp.__version__}')

print(f'✅ Package installed successfully: {version(\"trsdn-markitdown-mcp\")}')
print(f' import package: {markitdown_mcp.__name__}')
"

# Test MCP server
echo '{}' | markitdown-mcp || echo "⚠️ MCP server test skipped"
# Test every documented entrypoint against a real MCP request
REQUEST='{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
echo "$REQUEST" | timeout 60 markitdown-mcp | tee /tmp/tools-list.json
echo "$REQUEST" | timeout 60 trsdn-markitdown-mcp > /dev/null
echo "$REQUEST" | timeout 60 python -m markitdown_mcp > /dev/null

python -c "
import json
import pathlib

tools = json.loads(pathlib.Path('/tmp/tools-list.json').read_text())['result']['tools']
assert len(tools) >= 3, f'expected 3+ tools, got {len(tools)}'
print(f'✅ MCP entrypoints OK: {len(tools)} tools')
"

- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: dist-${{ needs.validate-release.outputs.version }}
path: dist/
if-no-files-found: error
retention-days: 30

# ==========================================
Expand All @@ -240,6 +287,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ inputs.tag || github.ref }}

- name: Generate changelog from commits
id: changelog
Expand Down Expand Up @@ -370,14 +418,19 @@ jobs:
"

# ==========================================
# Publish to PyPI
# Publish to PyPI (Trusted Publishing / OIDC)
# ==========================================
publish-pypi:
# Publisher configuration on PyPI must match EXACTLY:
# repository: trsdn/markitdown-mcp | workflow: release.yml | environment: pypi
publish:
name: Publish to PyPI
runs-on: ubuntu-latest
needs: [validate-release, build-package, generate-changelog]
needs: [validate-release, quality-gates, security-scan, build-package, generate-changelog]
if: needs.validate-release.outputs.is-prerelease == 'false'
environment: release
environment: pypi
# No API tokens: authentication happens via short-lived OIDC credentials.
permissions:
id-token: write
steps:
- name: Download build artifacts
uses: actions/download-artifact@v4
Expand All @@ -394,23 +447,37 @@ jobs:
run: |
sleep 30 # Wait for PyPI to update

pip install markitdown-mcp==${{ needs.validate-release.outputs.version }}
pip install trsdn-markitdown-mcp==${{ needs.validate-release.outputs.version }}

python -c "
import markitdown_mcp
print(f'✅ Successfully published to PyPI: v{markitdown_mcp.__version__}')
from importlib.metadata import version

import markitdown_mcp # noqa: F401

print(f'✅ Successfully published to PyPI: v{version(\"trsdn-markitdown-mcp\")}')
"

# ==========================================
# Create GitHub Release
# Create GitHub Release (after the PyPI publish)
# ==========================================
create-github-release:
name: Create GitHub Release
runs-on: ubuntu-latest
needs: [validate-release, build-package, generate-changelog, publish-pypi]
if: always() && needs.validate-release.result == 'success'
needs: [validate-release, build-package, generate-changelog, publish]
# `always()` so prereleases (where `publish` is skipped) still get a GitHub
# release, but never when a required upstream job actually failed.
if: |
always()
&& needs.validate-release.result == 'success'
&& needs.build-package.result == 'success'
&& needs.generate-changelog.result == 'success'
&& (needs.publish.result == 'success' || needs.publish.result == 'skipped')
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
ref: ${{ inputs.tag || github.ref }}

- name: Download build artifacts
uses: actions/download-artifact@v4
Expand Down Expand Up @@ -443,11 +510,14 @@ jobs:
runs-on: ubuntu-latest
needs: [validate-release, generate-changelog, create-github-release]
if: needs.validate-release.outputs.is-prerelease == 'false'
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
ref: main

- name: Update CHANGELOG.md
run: |
Expand Down Expand Up @@ -492,7 +562,7 @@ jobs:
post-release-validation:
name: Post-Release Validation
runs-on: ubuntu-latest
needs: [validate-release, create-github-release, publish-pypi, update-docs]
needs: [validate-release, create-github-release, publish, update-docs]
if: always()
steps:
- name: Validate release completion
Expand All @@ -512,7 +582,7 @@ jobs:

# Check PyPI (skip for prereleases)
if [[ "${{ needs.validate-release.outputs.is-prerelease }}" == "false" ]]; then
if pip index versions markitdown-mcp | grep -q "$VERSION"; then
if pip index versions trsdn-markitdown-mcp | grep -q "$VERSION"; then
echo "✅ PyPI package published"
else
echo "❌ PyPI package missing"
Expand Down
Loading
Loading