fix(CI3): bruk regional Cloud Build client i get_build_status

This commit is contained in:
chrischristiansen-glitch 2026-06-10 04:00:43 +02:00
parent e5b4e2faa5
commit 791a8e2b42

View File

@ -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