blob: eaa037c537866018a53a8d0234ee029052996e6c [file]
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
name: CI
on:
pull_request:
push:
branches:
- master
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
quality:
name: Quality
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Check out repository
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803
with:
persist-credentials: false
- name: Check Apache license headers
uses: apache/skywalking-eyes/header@315732dd4b8d3a015d8d9b91936b935a0b854817
with:
token: ""
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1
with:
python-version: "3.12"
- name: Install uv
run: >-
python -m pip install --disable-pip-version-check --no-deps
uv==0.9.0
- name: Verify lock file
run: uv lock --check
- name: Sync development environment
run: uv sync --frozen --group dev
- name: Verify generated 1.0 tool catalog
run: uv run python generate_tool_catalog.py --check
- name: Ruff
run: uv run ruff check .
- name: Mypy
run: uv run mypy doris_mcp_server
- name: Bandit
run: >-
uv run bandit -q -c pyproject.toml -r
doris_mcp_server doris_mcp_client generate_requirements.py
generate_tool_catalog.py
test:
name: Tests
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Check out repository
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1
with:
python-version: "3.12"
- name: Install uv
run: >-
python -m pip install --disable-pip-version-check --no-deps
uv==0.9.0
- name: Sync development environment
run: uv sync --frozen --group dev
- name: Run full test suite
run: uv run pytest -q -W error
- name: Enforce domain coverage floors
run: |
uv run coverage json -o "$RUNNER_TEMP/coverage.json"
uv run python test/deployment/check_coverage_domains.py \
"$RUNNER_TEMP/coverage.json"
package:
name: Build and wheel smoke
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Check out repository
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803
with:
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1
with:
python-version: "3.12"
- name: Install uv
run: >-
python -m pip install --disable-pip-version-check --no-deps
uv==0.9.0
- name: Sync development environment
run: uv sync --frozen --group dev
- name: Build distributions
run: uv build
- name: Install and smoke-test clean wheel
run: |
set -euo pipefail
wheel_count="$(find dist -maxdepth 1 -type f -name '*.whl' | wc -l | tr -d ' ')"
test "$wheel_count" = "1"
wheel_path="$(find dist -maxdepth 1 -type f -name '*.whl' -print -quit)"
smoke_root="$RUNNER_TEMP/doris-mcp-wheel-smoke"
python -m venv "$smoke_root/venv"
"$smoke_root/venv/bin/python" -m pip install "$GITHUB_WORKSPACE/$wheel_path"
cd "$smoke_root"
"$smoke_root/venv/bin/doris-mcp-server" --version
"$smoke_root/venv/bin/doris-mcp-client" --help
"$smoke_root/venv/bin/python" -c \
"import doris_mcp_client, doris_mcp_server"
"$smoke_root/venv/bin/python" \
"$GITHUB_WORKSPACE/test/deployment/check_runtime_dependencies.py"
conformance:
name: MCP 2026-07-28 conformance
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Check out repository
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803
with:
persist-credentials: false
- name: Check out official MCP Conformance
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803
with:
repository: modelcontextprotocol/conformance
ref: 49103de6ed70804e940637bf3e9e29e4a3f54e64
path: .conformance
persist-credentials: false
- name: Set up Python
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1
with:
python-version: "3.12"
- name: Install uv
run: >-
python -m pip install --disable-pip-version-check --no-deps
uv==0.9.0
- name: Set up Node.js
uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38
with:
node-version: "24"
cache: npm
cache-dependency-path: .conformance/package-lock.json
- name: Sync development environment
run: uv sync --frozen --group dev
- name: Install and build official Conformance
working-directory: .conformance
run: |
npm ci
npm run build
- name: Run official server-stateless scenario
run: |
set -euo pipefail
server_log="$RUNNER_TEMP/doris-mcp-conformance-server.log"
uv run python test/protocol/conformance_server.py \
--transport http \
--host 127.0.0.1 \
--port 39124 \
>"$server_log" 2>&1 &
server_pid="$!"
cleanup() {
kill "$server_pid" 2>/dev/null || true
}
trap cleanup EXIT
ready=false
for _ in $(seq 1 30); do
if python -c \
'import socket; s = socket.create_connection(("127.0.0.1", 39124), 1); s.close()'
then
ready=true
break
fi
sleep 1
done
if [ "$ready" != "true" ]; then
cat "$server_log"
exit 1
fi
node .conformance/dist/index.js server \
--url http://127.0.0.1:39124/mcp \
--scenario server-stateless \
--verbose