chore: bump version to 0.39.0 #335
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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 |