From 11d189ec409f7b331154fe7adfef85b14d3f79b2 Mon Sep 17 00:00:00 2001 From: Chris Christiansen Date: Wed, 2 Sep 2026 12:34:08 +0000 Subject: [PATCH] ci(mcp): unify cloudbuild.yaml and enforce secret manager references --- cloudbuild.mcp.yaml | 110 -------------------------------------------- cloudbuild.yaml | 72 +++++++++-------------------- deploy-mcp.sh | 82 --------------------------------- 3 files changed, 23 insertions(+), 241 deletions(-) delete mode 100644 cloudbuild.mcp.yaml delete mode 100644 deploy-mcp.sh diff --git a/cloudbuild.mcp.yaml b/cloudbuild.mcp.yaml deleted file mode 100644 index 9196856..0000000 --- a/cloudbuild.mcp.yaml +++ /dev/null @@ -1,110 +0,0 @@ -# cloudbuild.mcp.yaml — CI/CD for opax-mcp Cloud Run service -# Trigger: push til main (opax-mcp/** endret) -# Service: opax-mcp (us-central1) -# SA: jason-vauger@propane-will-491900-m5.iam.gserviceaccount.com - -steps: - - name: 'alpine/git' - id: clone - entrypoint: 'sh' - args: - - '-c' - - | - git clone --depth=1 --branch=main \ - http://34.170.51.84:3000/chris/osvauco.git /workspace/src - cp -r /workspace/src/. /workspace/ - - # Steg 1: Bygg Docker-image - - name: 'gcr.io/cloud-builders/docker' - id: build - args: - - 'build' - - '--cache-from' - - '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_ARTIFACT_REPO}/opax-mcp:latest' - - '-t' - - '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_ARTIFACT_REPO}/opax-mcp:$BUILD_ID' - - '-t' - - '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_ARTIFACT_REPO}/opax-mcp:latest' - - 'opax-mcp' - - '-f' - - 'opax-mcp/Dockerfile' - - # Steg 2: Push image - - name: 'gcr.io/cloud-builders/docker' - id: push - waitFor: ['build'] - args: - - 'push' - - '--all-tags' - - '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_ARTIFACT_REPO}/opax-mcp' - - # Steg 3: Deploy til Cloud Run - - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' - id: deploy - waitFor: ['push'] - entrypoint: gcloud - args: - - 'run' - - 'deploy' - - 'opax-mcp' - - '--image=${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_ARTIFACT_REPO}/opax-mcp:$BUILD_ID' - - '--region=${_REGION}' - - '--project=${PROJECT_ID}' - - '--service-account=${_MCP_SA}' - - '--set-env-vars=GOOGLE_CLOUD_PROJECT=${PROJECT_ID},OPAX_BASE_URL=https://opax.vauco.no,OSVAUCO_AGENT_URL=https://osvauco-agent-357036551735.us-central1.run.app' - - '--update-secrets=MCP_SECRET=mcp-server-key:latest,INTERNAL_API_KEY=INTERNAL_API_KEY:latest' - - '--allow-unauthenticated' - - '--port=8080' - - '--memory=512Mi' - - '--cpu=1' - - '--min-instances=0' - - '--max-instances=2' - - '--quiet' - - # Steg 4: Smoke test - - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' - id: smoke-test - waitFor: ['deploy'] - entrypoint: bash - args: - - '-c' - - | - echo "=== MCP Smoke Test ===" - SVC_URL="https://opax-mcp-357036551735.us-central1.run.app" - echo "Service URL: $$SVC_URL" - TOKEN=$$(curl -s -H "Metadata-Flavor: Google" \ - "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=$$SVC_URL&format=full") - STATUS=$$(curl -s -o /dev/null -w "%{http_code}" \ - -H "Authorization: Bearer $$TOKEN" "$$SVC_URL/health" 2>/dev/null || echo "000") - echo "Health status: $$STATUS" - [ "$$STATUS" = "200" ] && echo "OK" || echo "WARN: health check returnerte $$STATUS" - echo "=== Smoke Test ferdig ===" - - # Steg 5: Notify - - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' - id: notify - waitFor: ['smoke-test'] - entrypoint: bash - args: - - '-c' - - | - WH_URL=$$(gcloud secrets versions access latest \ - --secret=webhook-url --project=${PROJECT_ID} 2>/dev/null || echo "") - if [[ -n "$$WH_URL" ]]; then - MSG="✅ opax-mcp deploy fullført\nCommit: $COMMIT_SHA\nService: opax-mcp (${_REGION})\nhttps://opax-mcp-357036551735.us-central1.run.app" - curl -s -X POST "$$WH_URL" \ - -H 'Content-Type: application/json' \ - -d "{\"text\": \"$$MSG\"}" || true - echo "✓ Varsel sendt" - else - echo "⚠️ Ingen webhook-url — hopper over varsling" - fi - -substitutions: - _REGION: us-central1 - _ARTIFACT_REPO: osvauco-repo - _MCP_SA: jason-vauger@propane-will-491900-m5.iam.gserviceaccount.com - -options: - substitutionOption: ALLOW_LOOSE - logging: CLOUD_LOGGING_ONLY diff --git a/cloudbuild.yaml b/cloudbuild.yaml index 586db94..bc71ea8 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -1,14 +1,3 @@ -# Cloud Build config for OSVx MCP (opax-mcp) -# -# Usage: -# gcloud builds submit . --config=opax-mcp/cloudbuild.yaml --substitutions=_ENV=staging -# gcloud builds submit . --config=opax-mcp/cloudbuild.yaml --substitutions=_ENV=prod -# -# This build: -# - Builds the Docker image with a commit-SHA label -# - Pushes to Artifact Registry -# - Deploys to the appropriate Cloud Run service (staging or prod) - steps: # 1. Build the container image - name: 'gcr.io/cloud-builders/docker' @@ -16,58 +5,43 @@ steps: args: - 'build' - '-t' - - '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPOSITORY}/opax-mcp:${SHORT_SHA}' - - '--build-arg' - - 'COMMIT_SHA=${SHORT_SHA}' + - 'us-central1-docker.pkg.dev/${PROJECT_ID}/cloud-run-source-deploy/opax-mcp:${BUILD_ID}' - '-f' - 'opax-mcp/Dockerfile' - 'opax-mcp' - waitFor: ['-'] - # 2. Push the image (explicit push step for clarity) + # 2. Push the image to Artifact Registry - name: 'gcr.io/cloud-builders/docker' id: push-image args: - 'push' - - '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPOSITORY}/opax-mcp:${SHORT_SHA}' + - 'us-central1-docker.pkg.dev/${PROJECT_ID}/cloud-run-source-deploy/opax-mcp:${BUILD_ID}' waitFor: ['build-image'] - # 3. Deploy to Cloud Run (staging or prod) - - name: 'gcr.io/cloud-builders/gcloud' - id: deploy-cloud-run - entrypoint: 'bash' + # 3. Deploy to Cloud Run with secure secret handling + - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk' + id: deploy-service + entrypoint: 'gcloud' args: - - '-c' - - | - set -e - if [ "${_ENV}" = "prod" ]; then - SERVICE="osvx-mcp-prod" - elif [ "${_ENV}" = "staging" ]; then - SERVICE="osvx-mcp-staging" - else - echo "Unknown _ENV: ${_ENV}. Use 'staging' or 'prod'." - exit 1 - fi - - gcloud run deploy "${SERVICE}" --project=${PROJECT_ID} --region=${_REGION} --image=${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPOSITORY}/opax-mcp:${SHORT_SHA} --platform=managed --allow-unauthenticated=false --set-env-vars="MCP_SECRET=${_MCP_SECRET}" --set-labels="gcb-commit-sha=${SHORT_SHA},env=${_ENV}" + - 'run' + - 'deploy' + - 'opax-mcp' + - '--image=us-central1-docker.pkg.dev/${PROJECT_ID}/cloud-run-source-deploy/opax-mcp:${BUILD_ID}' + - '--region=us-central1' + - '--project=${PROJECT_ID}' + - '--service-account=jason-vauger@propane-will-491900-m5.iam.gserviceaccount.com' + - '--set-secrets=MCP_SECRET=MCP_SECRET:latest' # Securely mount the MCP_SECRET + - '--allow-unauthenticated' # Allow public ingress for Perplexity; app-level auth provides security + - '--port=8080' + - '--memory=512Mi' + - '--cpu=1' + - '--min-instances=0' + - '--max-instances=2' + - '--quiet' waitFor: ['push-image'] images: - - '${_REGION}-docker.pkg.dev/${PROJECT_ID}/${_REPOSITORY}/opax-mcp:${SHORT_SHA}' - -# Optional: store build artifacts / manifest -artifacts: - objects: - location: 'gs://${PROJECT_ID}-builds/artifacts' - paths: ['cloudbuild.yaml'] - -# Substitutions (defaults can be overridden via --substitutions) -substitutions: - _REGION: us-central1 - _REPOSITORY: osvx-images - _ENV: staging # 'staging' or 'prod' - _MCP_SECRET: MCP_SECRET + - 'us-central1-docker.pkg.dev/${PROJECT_ID}/cloud-run-source-deploy/opax-mcp:${BUILD_ID}' options: logging: CLOUD_LOGGING_ONLY - substitutionOption: ALLOW_LOOSE diff --git a/deploy-mcp.sh b/deploy-mcp.sh deleted file mode 100644 index 566178a..0000000 --- a/deploy-mcp.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env bash -# -# deploy-mcp.sh -# -# Build and deploy the OSVx MCP service (opax-mcp) to staging or prod. -# -# Usage: -# ./deploy-mcp.sh staging -# ./deploy-mcp.sh prod -# -# Requirements: -# - gcloud configured with correct project/region -# - Docker available locally (or use Cloud Build only mode if adapted) -# - Artifact Registry repo created (e.g. osvx-images) -# -# Environment (can be overridden via env vars): -# PROJECT_ID - GCP project ID (default: 357036551735) -# REGION - GCP region (default: us-central1) -# REPOSITORY - Artifact Registry repo name (default: osvx-images) -# MCP_SECRET_NAME - Secret Manager secret name for MCP bearer token (default: MCP_SECRET) - -set -euo pipefail - -PROJECT_ID="${PROJECT_ID:-357036551735}" -REGION="${REGION:-us-central1}" -REPOSITORY="${REPOSITORY:-osvx-images}" -MCP_SECRET_NAME="${MCP_SECRET_NAME:-MCP_SECRET}" - -if [ "${1:-}" = "" ]; then - echo "Usage: $0 " - exit 1 -fi - -ENV="$1" - -if [ "$ENV" != "staging" ] && [ "$ENV" != "prod" ]; then - echo "Error: ENV must be 'staging' or 'prod', got: $ENV" - exit 1 -fi - -# Service names (aligned with PLATFORM_MAP.md) -if [ "$ENV" = "prod" ]; then - SERVICE="osvx-mcp-prod" -else - SERVICE="osvx-mcp-staging" -fi - -cd "$(git rev-parse --show-toplevel)" - -SHORT_SHA="$(git rev-parse --short HEAD)" -IMAGE_TAG="${REGION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/opax-mcp:${SHORT_SHA}" - -echo "=== Building opax-mcp for ${ENV} (${SERVICE}) ===" -echo "Project: ${PROJECT_ID}" -echo "Region: ${REGION}" -echo "Repo: ${REPOSITORY}" -echo "Commit: ${SHORT_SHA}" -echo "Image: ${IMAGE_TAG}" -echo "Service: ${SERVICE}" -echo - -# 1. Build the image -echo "[1/3] Building Docker image..." -docker build --build-arg COMMIT_SHA="${SHORT_SHA}" -t "${IMAGE_TAG}" -f opax-mcp/Dockerfile opax-mcp - -# 2. Push the image -echo "[2/3] Pushing Docker image..." -docker push "${IMAGE_TAG}" - -# 3. Deploy to Cloud Run -echo "[3/3] Deploying to Cloud Run (${SERVICE})..." -gcloud run deploy "${SERVICE}" --project="${PROJECT_ID}" --region="${REGION}" --image="${IMAGE_TAG}" --platform=managed --allow-unauthenticated=false --set-env-vars="MCP_SECRET=${MCP_SECRET_NAME}" --set-labels="gcb-commit-sha=${SHORT_SHA},env=${ENV}" - -echo -echo "=== Deployment complete ===" -echo "Service: ${SERVICE}" -echo "Env: ${ENV}" -echo "Image: ${IMAGE_TAG}" -echo "Commit: ${SHORT_SHA}" -echo -echo "Check status:" -echo " gcloud run services describe ${SERVICE} --project=${PROJECT_ID} --region=${REGION}"