Skip to content

Commit a202bf3

Browse files
committed
feat : contribution baseline (#6)
* docs : pre-commit init * chore: ruff all file * chore: change ruff config * chore: change ruff config * docs: PR Template update * fix : uv.lock fix * docs : contributing documentation
1 parent b9717b7 commit a202bf3

File tree

12 files changed

+819
-590
lines changed

12 files changed

+819
-590
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## Overview
2+
<!-- Provide a brief description of what this PR does -->
3+
4+
## Key Changes
5+
<!-- List the main changes made in this PR -->
6+
-
7+
-
8+
9+
## Related Issues
10+
<!-- Link to related issues using "Fixes #123", "Closes #456", or "Relates to #789" -->
11+
-
12+
13+
## Additional context
14+
<!-- Any additional information that reviewers should know -->

.pre-commit-config.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
repos:
2+
- repo: https://github.com/astral-sh/ruff-pre-commit
3+
# Ruff version.
4+
rev: v0.12.7
5+
hooks:
6+
# Run the linter.
7+
- id: ruff-check
8+
args: [ --fix ]
9+
# Run the formatter.
10+
- id: ruff-format

CONTRIBUTING.rst

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
==============================
2+
Contributing to OpenStack MCP Server
3+
==============================
4+
5+
About the Project
6+
==================
7+
8+
OpenStack MCP Server is a project that integrates various OpenStack functionalities with the Model Context Protocol (MCP), enabling LLM-powered management of OpenStack resources.
9+
10+
How to Contribute
11+
=================
12+
13+
First, thank you for reading this document to contribute to our OpenStack MCP Server project. The following content explains the guidelines for contributing to our project, how to set up the development environment, and coding style guidelines.
14+
15+
PR Guidelines
16+
=============
17+
18+
Issue Report
19+
------------
20+
21+
Before submitting code for new features (and this also applies to some complex bug fixes), please first raise a **Feature request** or **Bug report**.
22+
23+
Review Process
24+
--------------
25+
26+
- This project currently uses main and develop branches as the base. PRs to the main branch are restricted to the develop branch.
27+
- All patches must be first merged into the develop branch and require approval from at least 2 code reviewers to be merged into develop.
28+
29+
Commit Message
30+
--------------
31+
32+
We use the `Conventional Commits <https://www.conventionalcommits.org/en/v1.0.0/>`_ convention for writing commit messages.
33+
34+
Format::
35+
36+
<type>[optional scope]: <description>
37+
[optional body]
38+
[optional footer(s)]
39+
40+
**Example**::
41+
42+
feat(nova): implement server management tools
43+
44+
Add Nova server listing and detail retrieval functionality
45+
for MCP clients with proper error handling and OpenStack SDK integration.
46+
47+
- Add get_nova_servers tool
48+
- Add get_server_details tool
49+
- Implement server status filtering
50+
- Add comprehensive error handling
51+
52+
Closes #123
53+
54+
Development Environment
55+
=======================
56+
57+
The following content is a guide for contributors to set up a development environment in their local environment.
58+
59+
Prerequisites
60+
=============
61+
62+
- This project uses uv to manage Python packages. Please set up an environment where you can use uv in your local environment for development environment setup. `Reference <https://docs.astral.sh/uv/getting-started/installation/>`_
63+
- We use ``python3.10`` as the default version. This is to ensure compatibility with other OpenStack projects.
64+
65+
UV Package Build
66+
----------------
67+
68+
.. code-block:: bash
69+
70+
uv sync --all-groups
71+
72+
Pre-commit
73+
----------
74+
75+
Code style is managed uniformly through ruff. We recommend setting up pre-commit hooks so that auto-formatting is applied at the commit stage.
76+
77+
.. code-block:: bash
78+
79+
pre-commit install
80+
81+
Testing
82+
=======
83+
84+
Unit Tests
85+
----------
86+
87+
All patches related to feature additions must implement unit test code. This project uses Pytest as the testing library, and if the project has been built successfully, you can run tests with the following command:
88+
89+
.. code-block:: bash
90+
91+
uv run pytest

pyproject.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@ dependencies = [
88
"mcp[cli]>=1.12.0",
99
"openstacksdk>=4.6.0",
1010
"pydantic>=2.11.7",
11-
"ruff>=0.12.5",
1211
]
1312

1413
[dependency-groups]
14+
dev = [
15+
"ruff>=0.12.5",
16+
"pre-commit>=4.2.0",
17+
]
1518
test = [
1619
"pytest>=8.4.1",
1720
]
@@ -34,6 +37,10 @@ python_functions = ["test_*"]
3437

3538
[tool.ruff]
3639
line-length = 79
40+
exclude = [
41+
"tests",
42+
"docs",
43+
]
3744

3845
[tool.ruff.format]
3946
quote-style = "double"

src/openstack_mcp_server/__init__.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
logging.basicConfig(
99
level=logging.INFO,
1010
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
11-
handlers=[logging.StreamHandler(sys.stderr)]
11+
handlers=[logging.StreamHandler(sys.stderr)],
1212
)
1313
logger = logging.getLogger("openstack-mcp-server")
1414

@@ -25,6 +25,7 @@ def main():
2525
# Import here to avoid circular imports
2626
from openstack_mcp_server.config import MCP_TRANSPORT
2727
from openstack_mcp_server.server import serve
28+
2829
parser = argparse.ArgumentParser(
2930
description="Openstack MCP Server",
3031
)
@@ -36,13 +37,16 @@ def main():
3637
# Validate transport protocol
3738
if MCP_TRANSPORT not in ["stdio", "sse", "streamable-http"]:
3839
logger.error(
39-
f"Invalid transport protocol: {MCP_TRANSPORT}. Using stdio instead.")
40+
f"Invalid transport protocol: {MCP_TRANSPORT}. Using stdio instead."
41+
)
4042
transport = "stdio"
4143
else:
4244
transport = MCP_TRANSPORT
4345

4446
# Start the server
45-
logger.info(f"Starting Openstack MCP Server with {transport} transport")
47+
logger.info(
48+
f"Starting Openstack MCP Server with {transport} transport"
49+
)
4650

4751
args = parser.parse_args()
4852

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
from openstack_mcp_server import main
22

33

4-
main()
4+
main()

src/openstack_mcp_server/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@
66
MCP_TRANSPORT = os.environ.get("TRANSPORT", "stdio")
77

88
# Application paths
9-
BASE_DIR = Path(__file__).parent.parent.parent
9+
BASE_DIR = Path(__file__).parent.parent.parent
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
from mcp.server.fastmcp import FastMCP
22

33

4-
def register_tool(mcp : FastMCP):
4+
def register_tool(mcp: FastMCP):
55
"""
66
Register Openstack MCP tools.
77
"""
88
from .nova_tools import NovaTools
99

10-
NovaTools().register_tools(mcp)
10+
NovaTools().register_tools(mcp)

src/openstack_mcp_server/tools/nova_tools.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,22 @@ def register_tools(self, mcp: FastMCP):
2121

2222
def get_nova_servers(self) -> str:
2323
"""
24-
Get the list of Nova servers by invoking the registered tool.
24+
Get the list of Nova servers by invoking the registered tool.
2525
26-
:return: A string containing the names, IDs, and statuses of the servers.
27-
"""
26+
:return: A string containing the names, IDs, and statuses of the servers.
27+
"""
2828

2929
# Initialize and turn on debug logging
3030
openstack.enable_logging(debug=True)
3131

3232
# Initialize connection
33-
conn = openstack.connect(cloud='openstack')
33+
conn = openstack.connect(cloud="openstack")
3434

3535
# List the servers
3636
server_list = []
3737
for server in conn.list_servers():
3838
server_list.append(
39-
f"{server.name} ({server.id}) - Status: {server.status}")
39+
f"{server.name} ({server.id}) - Status: {server.status}"
40+
)
4041

4142
return "\n".join(server_list)

tests/conftest.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,34 +5,45 @@
55
@pytest.fixture
66
def mock_openstack_logging():
77
"""Mock openstack.enable_logging function."""
8-
with patch('openstack_mcp_server.tools.nova_tools.openstack.enable_logging') as mock:
8+
with patch(
9+
"openstack_mcp_server.tools.nova_tools.openstack.enable_logging"
10+
) as mock:
911
yield mock
1012

1113

1214
@pytest.fixture
1315
def mock_openstack_connect():
1416
"""Mock openstack.connect function."""
15-
with patch('openstack_mcp_server.tools.nova_tools.openstack.connect') as mock:
17+
with patch(
18+
"openstack_mcp_server.tools.nova_tools.openstack.connect"
19+
) as mock:
1620
yield mock
1721

1822

1923
@pytest.fixture
2024
def mock_openstack_connection():
2125
"""Mock openstack connection object."""
2226
mock_conn = Mock()
23-
with patch('openstack_mcp_server.tools.nova_tools.openstack.connect', return_value=mock_conn) as mock_connect:
27+
with patch(
28+
"openstack_mcp_server.tools.nova_tools.openstack.connect",
29+
return_value=mock_conn,
30+
) as mock_connect:
2431
yield mock_conn, mock_connect
2532

2633

2734
@pytest.fixture
2835
def mock_server():
2936
"""Create a mock server object."""
30-
def _create_server(name="test-server", server_id="test-id", status="ACTIVE"):
37+
38+
def _create_server(
39+
name="test-server", server_id="test-id", status="ACTIVE"
40+
):
3141
mock = Mock()
3242
mock.name = name
3343
mock.id = server_id
3444
mock.status = status
3545
return mock
46+
3647
return _create_server
3748

3849

@@ -41,11 +52,11 @@ def sample_servers(mock_server):
4152
"""Create sample server list."""
4253
return [
4354
mock_server("server1", "id1", "ACTIVE"),
44-
mock_server("server2", "id2", "STOPPED")
55+
mock_server("server2", "id2", "STOPPED"),
4556
]
4657

4758

4859
@pytest.fixture
4960
def mock_fastmcp():
5061
"""Mock FastMCP instance."""
51-
return Mock()
62+
return Mock()

0 commit comments

Comments
 (0)