Skip to content

chore: bump version to 0.39.0 #335

chore: bump version to 0.39.0

chore: bump version to 0.39.0 #335

# Triggered on changes to Sources/mirroir-mcp, Sources/HelperLib, MCPServerTests,
# MCPProtocolTests, ensure-mcp-compliance.sh, or this file. Manual via workflow_dispatch.
name: MCP Compliance
on:
push:
# Every branch, not just main: this repo squash-merges locally and opens no
# pull requests of its own, so a feature branch has no other way to reach
# this gate before it lands. The removed glob list could not match the
# branch names actually used here (feat/..., fix/...) in any case — and
# 'feature/*' would not have matched a nested name even with that prefix.
# This workflow names no `tags`, so omitting `branches` means every branch.
paths:
- 'Sources/mirroir-mcp/**'
- 'Sources/HelperLib/**'
- 'Tests/MCPServerTests/**'
- 'Tests/HelperLibTests/MCPProtocolTests.swift'
- 'scripts/ci/ensure-mcp-compliance.sh'
- 'scripts/ci/mcp-modern-conformance.py'
- 'scripts/ci/mcp-schema-2026-07-28.json'
- '.github/workflows/mcp-compliance.yml'
pull_request:
branches: [ main ]
paths:
- 'Sources/mirroir-mcp/**'
- 'Sources/HelperLib/**'
- 'Tests/MCPServerTests/**'
- 'Tests/HelperLibTests/MCPProtocolTests.swift'
- 'scripts/ci/ensure-mcp-compliance.sh'
- 'scripts/ci/mcp-modern-conformance.py'
- 'scripts/ci/mcp-schema-2026-07-28.json'
- '.github/workflows/mcp-compliance.yml'
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
mcp-compliance:
name: MCP Protocol Compliance
runs-on: macos-15
steps:
- name: Checkout code
uses: actions/checkout@v4
- uses: ./.github/actions/setup-embacle
- name: Clone skills repo
run: |
git clone https://github.com/jfarcand/mirroir-skills.git ../mirroir-skills
mkdir -p .mirroir-mcp
ln -s "$(cd ../mirroir-skills && pwd)" .mirroir-mcp/skills
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
# Validates modern-revision results against the specification's schema.
- name: Install schema validator
run: pip install jsonschema
- name: Build release binary
run: swift build -c release
- name: Verify binary exists
run: |
test -x .build/release/mirroir-mcp || { echo "Binary not found"; exit 1; }
file .build/release/mirroir-mcp
- name: Validate MCP protocol version is latest
run: |
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
| .build/release/mirroir-mcp 2>/dev/null \
| python3 -c "
import sys, json
obj = json.loads(sys.stdin.readline())
version = obj['result']['protocolVersion']
assert version == '2025-11-25', f'Protocol version must be 2025-11-25 (latest), got: {version}'
print(f'MCP protocol version: {version} (latest)')
"
- name: Run MCP compliance validation
run: ./scripts/ci/ensure-mcp-compliance.sh
- name: Run unit tests (XCTest)
timeout-minutes: 15
run: swift test --skip IntegrationTests --disable-swift-testing
- name: Run unit tests (Swift Testing)
timeout-minutes: 5
run: swift test --skip IntegrationTests --disable-xctest --no-parallel
- name: Build and package FakeMirroring
run: |
swift build -c release --product FakeMirroring
./scripts/package-fake-app.sh
- name: Quit Setup Assistant (macos-15 runner intercepts taps)
run: |
# Some macos-15 runners boot with Setup Assistant in the foreground
# — it intercepts cghidEventTap mouse events and the target app
# receives no mouseUp. Quit it before launching FakeMirroring.
osascript -e 'tell application "Setup Assistant" to quit' 2>/dev/null || true
pkill -f "Setup Assistant" 2>/dev/null || true
sleep 1
- name: Ensure display fits the FakeMirroring window
# GH macOS runners boot with a display too short for the 410x930
# window: the bottom ~60pt (the simulated tab bar) is clipped
# off-screen and CGEvent taps there never land. Grow the virtual
# display before launching FakeMirroring.
run: |
brew install --quiet jakehilborn/jakehilborn/displayplacer || brew install --quiet displayplacer || true
echo "--- displays before ---"
displayplacer list 2>/dev/null | grep -E "Persistent|Resolution" || true
SCREEN_ID=$(displayplacer list 2>/dev/null | awk -F': ' '/Persistent screen id/{print $2; exit}')
if [ -n "$SCREEN_ID" ]; then
for RES in 1920x1080 1680x1050 1600x1200; do
if displayplacer "id:$SCREEN_ID res:$RES" 2>/dev/null; then
echo "display set to $RES"
break
fi
done
fi
echo "--- displays after ---"
displayplacer list 2>/dev/null | grep -E "Resolution" || true
- name: Launch FakeMirroring
run: |
open .build/release/FakeMirroring.app
sleep 3
- name: Integration tests (FakeMirroring)
env:
MIRROIR_BUNDLE_ID: com.jfarcand.FakeMirroring
MIRROIR_PROCESS_NAME: FakeMirroring
run: swift test --filter IntegrationTests