fix(CI3): bruk regional Cloud Build client i get_build_status
This commit is contained in:
parent
e5b4e2faa5
commit
791a8e2b42
|
|
@ -23,7 +23,7 @@ CLOUD_RUN_SERVICE = os.environ.get("CLOUD_RUN_SERVICE", "osvauco-agent")
|
||||||
MCP_SECRET = os.environ.get("MCP_SECRET", "") # Secret Manager: mcp-server-key
|
MCP_SECRET = os.environ.get("MCP_SECRET", "") # Secret Manager: mcp-server-key
|
||||||
|
|
||||||
|
|
||||||
# ── Auth ───────────────────────────────────────────────────────────────────
|
# ── Auth ───────────────────────────────────────────────────────────────────────────
|
||||||
def verify_token(x_mcp_key: str = Header(default="")):
|
def verify_token(x_mcp_key: str = Header(default="")):
|
||||||
"""Enkel API-nøkkel auth. Byttes ut med IAP når tjenesten er på Cloud Run bak LB."""
|
"""Enkel API-nøkkel auth. Byttes ut med IAP når tjenesten er på Cloud Run bak LB."""
|
||||||
if MCP_SECRET and x_mcp_key != MCP_SECRET:
|
if MCP_SECRET and x_mcp_key != MCP_SECRET:
|
||||||
|
|
@ -31,7 +31,7 @@ def verify_token(x_mcp_key: str = Header(default="")):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
# ── Models ──────────────────────────────────────────────────────────────────
|
# ── Models ──────────────────────────────────────────────────────────────────────────
|
||||||
class PushStaticRequest(BaseModel):
|
class PushStaticRequest(BaseModel):
|
||||||
file_path: str # Lokal sti relativt til repo-rot, f.eks. "static/jason.html"
|
file_path: str # Lokal sti relativt til repo-rot, f.eks. "static/jason.html"
|
||||||
content: str # Fil-innhold (tekst/HTML)
|
content: str # Fil-innhold (tekst/HTML)
|
||||||
|
|
@ -49,7 +49,7 @@ class ToolCallRequest(BaseModel):
|
||||||
params: dict = {}
|
params: dict = {}
|
||||||
|
|
||||||
|
|
||||||
# ── Lifespan ──────────────────────────────────────────────────────────────────
|
# ── Lifespan ──────────────────────────────────────────────────────────────────────────────
|
||||||
@asynccontextmanager
|
@asynccontextmanager
|
||||||
async def lifespan(app: FastAPI):
|
async def lifespan(app: FastAPI):
|
||||||
logger.info(f"OPAX-MCP starting | project={PROJECT_ID} | bucket={STATIC_BUCKET}")
|
logger.info(f"OPAX-MCP starting | project={PROJECT_ID} | bucket={STATIC_BUCKET}")
|
||||||
|
|
@ -65,13 +65,13 @@ app = FastAPI(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
# ── Health ───────────────────────────────────────────────────────────────────
|
# ── Health ─────────────────────────────────────────────────────────────────────────────
|
||||||
@app.get("/health")
|
@app.get("/health")
|
||||||
async def health():
|
async def health():
|
||||||
return {"status": "ok", "service": "opax-mcp", "project": PROJECT_ID}
|
return {"status": "ok", "service": "opax-mcp", "project": PROJECT_ID}
|
||||||
|
|
||||||
|
|
||||||
# ── MCP Tool Registry ──────────────────────────────────────────────────────────
|
# ── MCP Tool Registry ──────────────────────────────────────────────────────────────────
|
||||||
@app.get("/mcp/tools")
|
@app.get("/mcp/tools")
|
||||||
async def list_tools(_: bool = Depends(verify_token)):
|
async def list_tools(_: bool = Depends(verify_token)):
|
||||||
"""MCP tool manifest — returnerer alle tilgjengelige verktøy med schema."""
|
"""MCP tool manifest — returnerer alle tilgjengelige verktøy med schema."""
|
||||||
|
|
@ -117,7 +117,7 @@ async def list_tools(_: bool = Depends(verify_token)):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# ── Tool: push_static ───────────────────────────────────────────────────────────
|
# ── Tool: push_static ─────────────────────────────────────────────────────────────────────
|
||||||
@app.post("/tools/push_static")
|
@app.post("/tools/push_static")
|
||||||
async def push_static(req: PushStaticRequest, _: bool = Depends(verify_token)):
|
async def push_static(req: PushStaticRequest, _: bool = Depends(verify_token)):
|
||||||
"""
|
"""
|
||||||
|
|
@ -148,16 +148,20 @@ async def push_static(req: PushStaticRequest, _: bool = Depends(verify_token)):
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
# ── Tool: get_build_status ─────────────────────────────────────────────────────────
|
# ── Tool: get_build_status ─────────────────────────────────────────────────────────────────────
|
||||||
@app.get("/tools/get_build_status")
|
@app.get("/tools/get_build_status")
|
||||||
async def get_build_status(_: bool = Depends(verify_token)):
|
async def get_build_status(_: bool = Depends(verify_token)):
|
||||||
"""
|
"""
|
||||||
Hent siste Cloud Build-kjøring.
|
Hent siste Cloud Build-kjøring fra us-central1.
|
||||||
Wrapper rundt samme logikk som /opax/build-status i osvauco-agent.
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from google.cloud.devtools import cloudbuild_v1
|
from google.cloud.devtools import cloudbuild_v1
|
||||||
client = cloudbuild_v1.CloudBuildClient()
|
from google.api_core.client_options import ClientOptions
|
||||||
|
client = cloudbuild_v1.CloudBuildClient(
|
||||||
|
client_options=ClientOptions(
|
||||||
|
api_endpoint=f"{REGION}-cloudbuild.googleapis.com"
|
||||||
|
)
|
||||||
|
)
|
||||||
request = cloudbuild_v1.ListBuildsRequest(
|
request = cloudbuild_v1.ListBuildsRequest(
|
||||||
project_id=PROJECT_ID,
|
project_id=PROJECT_ID,
|
||||||
filter='trigger_id!=""',
|
filter='trigger_id!=""',
|
||||||
|
|
@ -183,23 +187,28 @@ async def get_build_status(_: bool = Depends(verify_token)):
|
||||||
"commit": (b.substitutions or {}).get("SHORT_SHA", ""),
|
"commit": (b.substitutions or {}).get("SHORT_SHA", ""),
|
||||||
"duration_s": duration_s,
|
"duration_s": duration_s,
|
||||||
"log_url": b.log_url or "",
|
"log_url": b.log_url or "",
|
||||||
|
"region": REGION,
|
||||||
}
|
}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[get_build_status] Failed: {e}", exc_info=True)
|
logger.error(f"[get_build_status] Failed: {e}", exc_info=True)
|
||||||
return {"status": "error", "message": str(e)}
|
return {"status": "error", "message": str(e)}
|
||||||
|
|
||||||
|
|
||||||
# ── Tool: deploy_service ──────────────────────────────────────────────────────────
|
# ── Tool: deploy_service ──────────────────────────────────────────────────────────────────────
|
||||||
@app.post("/tools/deploy_service")
|
@app.post("/tools/deploy_service")
|
||||||
async def deploy_service(req: DeployServiceRequest, _: bool = Depends(verify_token)):
|
async def deploy_service(req: DeployServiceRequest, _: bool = Depends(verify_token)):
|
||||||
"""
|
"""
|
||||||
Trigger Cloud Build for å bygge + deploye osvauco-agent.
|
Trigger Cloud Build for å bygge + deploye osvauco-agent.
|
||||||
Bruker Cloud Build Run trigger API.
|
|
||||||
HITL-gate: logger kallet og returnerer build-ID for oppfølging.
|
HITL-gate: logger kallet og returnerer build-ID for oppfølging.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
from google.cloud.devtools import cloudbuild_v1
|
from google.cloud.devtools import cloudbuild_v1
|
||||||
client = cloudbuild_v1.CloudBuildClient()
|
from google.api_core.client_options import ClientOptions
|
||||||
|
client = cloudbuild_v1.CloudBuildClient(
|
||||||
|
client_options=ClientOptions(
|
||||||
|
api_endpoint=f"{REGION}-cloudbuild.googleapis.com"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
trigger_id = req.trigger_id or os.environ.get("CLOUD_BUILD_TRIGGER_ID", "")
|
trigger_id = req.trigger_id or os.environ.get("CLOUD_BUILD_TRIGGER_ID", "")
|
||||||
if not trigger_id:
|
if not trigger_id:
|
||||||
|
|
@ -224,7 +233,7 @@ async def deploy_service(req: DeployServiceRequest, _: bool = Depends(verify_tok
|
||||||
"build_id": build_id,
|
"build_id": build_id,
|
||||||
"branch": req.branch,
|
"branch": req.branch,
|
||||||
"trigger_id": trigger_id,
|
"trigger_id": trigger_id,
|
||||||
"message": f"Build triggered. Kall GET /tools/get_build_status for status.",
|
"message": "Build triggered. Kall GET /tools/get_build_status for status.",
|
||||||
}
|
}
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
|
|
@ -233,7 +242,7 @@ async def deploy_service(req: DeployServiceRequest, _: bool = Depends(verify_tok
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
# ── Tool: get_logs ──────────────────────────────────────────────────────────────────
|
# ── Tool: get_logs ───────────────────────────────────────────────────────────────────────────────
|
||||||
@app.get("/tools/get_logs")
|
@app.get("/tools/get_logs")
|
||||||
async def get_logs(
|
async def get_logs(
|
||||||
lines: int = 50,
|
lines: int = 50,
|
||||||
|
|
@ -276,14 +285,9 @@ async def get_logs(
|
||||||
raise HTTPException(status_code=500, detail=str(e))
|
raise HTTPException(status_code=500, detail=str(e))
|
||||||
|
|
||||||
|
|
||||||
# ── MCP unified tool call endpoint ────────────────────────────────────────────────
|
# ── MCP unified tool call endpoint ────────────────────────────────────────────────────────────
|
||||||
@app.post("/mcp/call")
|
@app.post("/mcp/call")
|
||||||
async def mcp_call(req: ToolCallRequest, _: bool = Depends(verify_token)):
|
async def mcp_call(req: ToolCallRequest, _: bool = Depends(verify_token)):
|
||||||
"""
|
|
||||||
Unified MCP tool call endpoint.
|
|
||||||
Jason/Emma kaller denne med {tool: "push_static", params: {...}}
|
|
||||||
— slipper å vite individuelle endepunkt-URLer.
|
|
||||||
"""
|
|
||||||
tool = req.tool
|
tool = req.tool
|
||||||
params = req.params
|
params = req.params
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user