- Implement comprehensive git status verification in deploy_nomad_mcp.py - Add warning and interactive prompts for uncommitted changes - Check local branch status against remote repository - Provide options to continue or abort deployment - Update Nomad job configuration to use DEBUG logging level
243 lines
11 KiB
Python
243 lines
11 KiB
Python
#!/usr/bin/env python
|
|
"""
|
|
Script to deploy the Nomad MCP service using our own Nomad client.
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import subprocess
|
|
from dotenv import load_dotenv
|
|
from app.services.nomad_client import NomadService
|
|
|
|
# Load environment variables from .env file
|
|
load_dotenv()
|
|
|
|
def check_git_status():
|
|
"""Check if there are uncommitted changes in the git repository."""
|
|
try:
|
|
# Check for uncommitted changes
|
|
result = subprocess.run(
|
|
["git", "status", "--porcelain"],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True
|
|
)
|
|
|
|
if result.stdout.strip():
|
|
print("\n⚠️ WARNING: You have uncommitted changes in your repository!")
|
|
print("The Nomad job will pull code from Gitea, not your local changes.")
|
|
print("Uncommitted files:")
|
|
for line in result.stdout.strip().split('\n'):
|
|
print(f" - {line}")
|
|
|
|
# Check if we're behind the remote
|
|
result = subprocess.run(
|
|
["git", "status", "-sb"],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True
|
|
)
|
|
|
|
if "behind" in result.stdout:
|
|
print("\n⚠️ Your local branch is behind the remote repository!")
|
|
print("The deployed code will be from the remote repository, not your local version.")
|
|
|
|
print("\nDo you want to:")
|
|
print("1. Continue deployment anyway (will use the code in Gitea)")
|
|
print("2. Abort to commit and push your changes first")
|
|
|
|
choice = input("\nEnter your choice (1 or 2): ").strip()
|
|
if choice == "2":
|
|
print("\nDeployment aborted. Please commit and push your changes first:")
|
|
print(" git add .")
|
|
print(" git commit -m \"Your commit message\"")
|
|
print(" git push")
|
|
sys.exit(0)
|
|
elif choice == "1":
|
|
print("\nContinuing with deployment using the code in Gitea...")
|
|
else:
|
|
print("\nInvalid choice. Aborting deployment.")
|
|
sys.exit(1)
|
|
else:
|
|
# Check if we're up to date with remote
|
|
result = subprocess.run(
|
|
["git", "status", "-sb"],
|
|
capture_output=True,
|
|
text=True,
|
|
check=True
|
|
)
|
|
|
|
if "behind" in result.stdout:
|
|
print("\n⚠️ Your local branch is behind the remote repository!")
|
|
print("The deployed code will be from the remote repository, not your local version.")
|
|
print("Do you want to pull the latest changes before checking? (y/n)")
|
|
|
|
choice = input().strip().lower()
|
|
if choice == "y":
|
|
subprocess.run(["git", "pull"], check=True)
|
|
print("Successfully pulled latest changes.")
|
|
else:
|
|
print("Continuing with deployment using the code in Gitea...")
|
|
else:
|
|
print("✅ Git repository is clean and up to date with remote.")
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"\n⚠️ Warning: Failed to check git status: {e}")
|
|
print("Unable to verify if all changes are committed and pushed.")
|
|
print("Please ensure your code is committed and pushed to Gitea before deploying.")
|
|
|
|
print("\nDo you want to continue anyway? (y/n)")
|
|
choice = input().strip().lower()
|
|
if choice != "y":
|
|
print("Deployment aborted.")
|
|
sys.exit(0)
|
|
except Exception as e:
|
|
print(f"\n⚠️ Warning: Error checking git status: {str(e)}")
|
|
print("Unable to verify if all changes are committed and pushed.")
|
|
print("Please ensure your code is committed and pushed to Gitea before deploying.")
|
|
|
|
def main():
|
|
print("Deploying Nomad MCP service using our own Nomad client...")
|
|
|
|
# Check git status before deployment
|
|
check_git_status()
|
|
|
|
# Check if NOMAD_ADDR is configured
|
|
nomad_addr = os.getenv("NOMAD_ADDR")
|
|
if not nomad_addr:
|
|
print("Error: NOMAD_ADDR is not configured in .env file.")
|
|
sys.exit(1)
|
|
|
|
print(f"Connecting to Nomad at: {nomad_addr}")
|
|
|
|
try:
|
|
# Initialize the Nomad service
|
|
nomad_service = NomadService()
|
|
|
|
# Use the HCL file directly with the Nomad CLI
|
|
print("Registering and starting the nomad-mcp job...")
|
|
|
|
# Create a job specification directly
|
|
job_spec = {
|
|
"Job": {
|
|
"ID": "nomad-mcp",
|
|
"Name": "nomad-mcp",
|
|
"Type": "service",
|
|
"Datacenters": ["jm"],
|
|
"Namespace": "development",
|
|
"TaskGroups": [
|
|
{
|
|
"Name": "app",
|
|
"Count": 1,
|
|
"Networks": [
|
|
{
|
|
"DynamicPorts": [
|
|
{
|
|
"Label": "http",
|
|
"To": 8000
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"Tasks": [
|
|
{
|
|
"Name": "nomad-mcp",
|
|
"Driver": "docker",
|
|
"Config": {
|
|
"image": "registry.dev.meisheng.group/nomad_mcp:20250226",
|
|
"ports": ["http"],
|
|
"command": "python",
|
|
"args": ["-m", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"],
|
|
"mount": [
|
|
{
|
|
"type": "bind",
|
|
"source": "local/nomad_mcp",
|
|
"target": "/app",
|
|
"readonly": False
|
|
}
|
|
]
|
|
},
|
|
"Artifacts": [
|
|
{
|
|
"GetterSource": "git::ssh://git@gitea.service.mesh:2222/Mei_Sheng_Textiles/nomad_mcp.git",
|
|
"RelativeDest": "local/nomad_mcp",
|
|
"GetterOptions": {
|
|
"ref": "main",
|
|
"sshkey": "LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQkc1dmJtVUFBQUFFYm05dVpRQUFBQUFBQUFBQkFBQUFNd0FBQUF0emMyZ3RaVwpReU5UVXhPUUFBQUNBY01oYkNPVXhFOHBYQ3d5UEh0ZFR4aThHU0pzNEdTNXZ6ZTR6Tm1ueUYvUUFBQUtCQm5RZi9RWjBICi93QUFBQXR6YzJndFpXUXlOVFV4T1FBQUFDQWNNaGJDT1V4RThwWEN3eVBIdGRUeGk4R1NKczRHUzV2emU0ek5tbnlGL1EKQUFBRURreWwzQlZlek9YUWZUNzZac0NkYTZPNTFnMExsb25EMEd6L2Y4SHh3dzRCd3lGc0k1VEVUeWxjTERJOGUxMVBHTAp3WkltemdaTG0vTjdqTTJhZklYOUFBQUFHR1JsY0d4dmVTQnJaWGtnWm05eUlHNXZiV0ZrWDIxamNBRUNBd1FGCi0tLS0tRU5EIE9QRU5TU0ggUFJJVkFURSBLRVktLS0tLQo="
|
|
}
|
|
}
|
|
],
|
|
"Env": {
|
|
"NOMAD_ADDR": "http://pjmldk01.ds.meisheng.group:4646",
|
|
"NOMAD_NAMESPACE": "development",
|
|
"NOMAD_SKIP_VERIFY": "true",
|
|
"PORT": "8000",
|
|
"HOST": "0.0.0.0",
|
|
"LOG_LEVEL": "INFO",
|
|
"RELOAD": "true",
|
|
"PYTHONPATH": "/app",
|
|
"STATIC_DIR": "/local/nomad_mcp/static"
|
|
},
|
|
"Resources": {
|
|
"CPU": 200,
|
|
"MemoryMB": 256
|
|
},
|
|
"Services": [
|
|
{
|
|
"Name": "nomad-mcp",
|
|
"PortLabel": "http",
|
|
"Tags": [
|
|
"traefik.enable=true",
|
|
"traefik.http.routers.nomad-mcp.entryPoints=https",
|
|
"traefik.http.routers.nomad-mcp.rule=Host(`nomad_mcp.dev.meisheng.group`)",
|
|
"traefik.http.routers.nomad-mcp.middlewares=proxyheaders@consulcatalog"
|
|
],
|
|
"Checks": [
|
|
{
|
|
"Type": "http",
|
|
"Path": "/api/health",
|
|
"Interval": 10000000000,
|
|
"Timeout": 2000000000,
|
|
"CheckRestart": {
|
|
"Limit": 3,
|
|
"Grace": 60000000000
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"Update": {
|
|
"MaxParallel": 1,
|
|
"MinHealthyTime": 30000000000,
|
|
"HealthyDeadline": 300000000000,
|
|
"AutoRevert": True
|
|
}
|
|
}
|
|
}
|
|
|
|
# Start the job
|
|
response = nomad_service.start_job(job_spec)
|
|
|
|
print("\nJob registration response:")
|
|
print(json.dumps(response, indent=2))
|
|
|
|
if response.get("status") == "started":
|
|
print("\n✅ Nomad MCP service deployed successfully!")
|
|
print(f"Job ID: {response.get('job_id')}")
|
|
print(f"Evaluation ID: {response.get('eval_id')}")
|
|
print("\nThe service will be available at: https://nomad_mcp.dev.meisheng.group")
|
|
else:
|
|
print("\n❌ Failed to deploy Nomad MCP service.")
|
|
print(f"Status: {response.get('status')}")
|
|
print(f"Message: {response.get('message', 'Unknown error')}")
|
|
|
|
except Exception as e:
|
|
print(f"Error deploying Nomad MCP service: {str(e)}")
|
|
sys.exit(1)
|
|
|
|
if __name__ == "__main__":
|
|
main() |