77 branches : [main]
88
99jobs :
10- test :
10+ python-tests :
1111 name : Python ${{ matrix.python-version }} / ${{ matrix.os }}
1212 runs-on : ${{ matrix.os }}
1313 strategy :
@@ -32,3 +32,100 @@ jobs:
3232
3333 - name : Lint
3434 run : ruff check src/ tests/
35+
36+ godot-tests :
37+ name : Godot handler tests
38+ runs-on : ubuntu-latest
39+ container :
40+ image : barichello/godot-ci:4.6.2
41+
42+ steps :
43+ - uses : actions/checkout@v4
44+
45+ - name : Set up Python
46+ run : |
47+ apt-get update -qq && apt-get install -y -qq python3 python3-pip python3-venv > /dev/null
48+ python3 -m venv /tmp/venv
49+ /tmp/venv/bin/pip install -e ".[dev]" > /dev/null
50+
51+ - name : Start MCP server
52+ run : |
53+ /tmp/venv/bin/python -m godot_ai --transport streamable-http --port 8000 &
54+ # Wait for server to be ready
55+ for i in $(seq 1 30); do
56+ if curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8000/mcp -X POST \
57+ -H "Content-Type: application/json" \
58+ -H "Accept: application/json, text/event-stream" \
59+ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"ci","version":"1.0"}}}' | grep -q 200; then
60+ echo "Server ready"
61+ break
62+ fi
63+ sleep 1
64+ done
65+
66+ - name : Run Godot with plugin (headless)
67+ run : |
68+ # Import the project first (generates .godot/ cache)
69+ timeout 30 godot --headless --path test_project --import || true
70+ # Start Godot editor headless — plugin will connect to server
71+ timeout 60 godot --headless --path test_project --editor &
72+ GODOT_PID=$!
73+ # Wait for plugin to connect (watch server logs for session)
74+ for i in $(seq 1 30); do
75+ if curl -s http://127.0.0.1:8000/mcp -X POST \
76+ -H "Content-Type: application/json" \
77+ -H "Accept: application/json, text/event-stream" \
78+ -d '{"jsonrpc":"2.0","id":99,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"ci","version":"1.0"}}}' 2>/dev/null | grep -q "Godot AI"; then
79+ break
80+ fi
81+ sleep 2
82+ done
83+ # Give plugin a moment to fully initialize
84+ sleep 3
85+
86+ - name : Run handler tests via MCP
87+ run : |
88+ # Initialize a session
89+ SESSION_ID=$(curl -si http://127.0.0.1:8000/mcp -X POST \
90+ -H "Content-Type: application/json" \
91+ -H "Accept: application/json, text/event-stream" \
92+ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"ci","version":"1.0"}}}' 2>&1 | grep -i 'mcp-session-id' | tr -d '\r' | awk '{print $2}')
93+
94+ curl -s http://127.0.0.1:8000/mcp -X POST \
95+ -H "Content-Type: application/json" \
96+ -H "Accept: application/json, text/event-stream" \
97+ -H "Mcp-Session-Id: $SESSION_ID" \
98+ -d '{"jsonrpc":"2.0","method":"notifications/initialized"}' > /dev/null
99+
100+ # Call run_tests
101+ RESULT=$(curl -s http://127.0.0.1:8000/mcp -X POST \
102+ -H "Content-Type: application/json" \
103+ -H "Accept: application/json, text/event-stream" \
104+ -H "Mcp-Session-Id: $SESSION_ID" \
105+ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"run_tests","arguments":{}}}')
106+
107+ echo "$RESULT" | python3 -c "
108+ import json, sys
109+ raw = sys.stdin.read()
110+ # Parse SSE format
111+ for line in raw.split('\n'):
112+ if line.startswith('data: '):
113+ data = json.loads(line[6:])
114+ content = data.get('result', {}).get('structuredContent', {})
115+ if not content:
116+ text = data.get('result', {}).get('content', [{}])[0].get('text', '{}')
117+ content = json.loads(text)
118+ passed = content.get('passed', 0)
119+ failed = content.get('failed', 0)
120+ total = content.get('total', 0)
121+ print(f'Godot tests: {passed}/{total} passed, {failed} failed')
122+ if content.get('failures'):
123+ for f in content['failures']:
124+ print(f' FAIL: {f[\"suite\"]}.{f[\"test\"]}: {f[\"message\"]}')
125+ if failed > 0:
126+ sys.exit(1)
127+ if total == 0:
128+ print('ERROR: No tests ran')
129+ sys.exit(1)
130+ break
131+ "
0 commit comments