Skip to content

Add Helm chart, deploy workflow, and staging support for MCP server#201

Merged
RafaelPo merged 1 commit intomainfrom
deploy-mcp-server
Feb 24, 2026
Merged

Add Helm chart, deploy workflow, and staging support for MCP server#201
RafaelPo merged 1 commit intomainfrom
deploy-mcp-server

Conversation

@RafaelPo
Copy link
Contributor

@RafaelPo RafaelPo commented Feb 24, 2026

Summary

Re-adds deployment infrastructure deferred from PR #165 (commits 390c80e3 and 61819ca2 removed the Helm chart and deploy workflow). Updated for the current codebase, with staging support and security hardening for the public repo.

Helm chart (everyrow-mcp/deploy/chart/)

  • Deployment with /health probes, rolling update, hyperdisk node tolerations
  • ClusterIP Service (80 → 8000)
  • Gateway API HTTPRoute via shared TLS gateway
  • SOPS-encrypted secrets via GCP KMS
  • All templates use {{ .Release.Name }} for resource names — staging resources get distinct names (everyrow-mcp-staging, everyrow-mcp-staging-secrets)
  • HTTPRoute uses {{ .Release.Namespace }} for namespace isolation

GitHub Actions workflow (.github/workflows/deploy-mcp.yaml)

  • PR trigger: runs checks only (ruff, pytest)
  • Manual dispatch with deploy_production / deploy_staging boolean toggles — no auto-deploy
  • Pipeline: setupchecksbuild-and-push (GAR) → deploy (Helm)
  • Checks must pass before build starts
  • Secret decryption is conditional — staging-only deploys don't touch prod secrets
  • --atomic rollback + cancel-in-progress: false (safe for deploys)
  • Slack notification on failure

Staging environment

Production Staging
Trigger Manual: deploy_production=true Manual: deploy_staging=true
Namespace everyrow-mcp everyrow-mcp-staging
Helm release everyrow-mcp everyrow-mcp-staging
MCP URL mcp.everyrow.io mcp-staging.everyrow.io
Supabase production staging
Redis DB 13 14

EVERYROW_API_URL is intentionally not overridden for staging — there is no staging API. Both environments use the production EveryRow API.

Security (public repo)

Sensitive values (Supabase URLs, anon keys, Redis Sentinel endpoints) are in SOPS-encrypted files, not in plain values.yaml.

Other changes

  • Remove redundant REDIS_DB = 13 constant from redis_store.py — use settings.redis_db directly

How to deploy

# Staging
gh workflow run deploy-mcp.yaml -f deploy_staging=true

# Production
gh workflow run deploy-mcp.yaml -f deploy_production=true

# Both
gh workflow run deploy-mcp.yaml -f deploy_staging=true -f deploy_production=true

# From a specific branch
gh workflow run deploy-mcp.yaml -f deploy_staging=true -f branch=my-branch

Before first deploy

  • Verify DNS for mcp.everyrow.io and mcp-staging.everyrow.io points to the shared TLS gateway

Test plan

  • helm lint passes
  • helm template renders correct YAML for both prod and staging
  • Resource names use release name (everyrow-mcp vs everyrow-mcp-staging)
  • HTTPRoute namespace uses .Release.Namespace
  • SOPS secrets encrypt/decrypt correctly
  • PR triggers checks job in CI
  • After merge: manual dispatch with deploy_staging=true deploys to staging
  • After merge: manual dispatch with deploy_production=true deploys to production

🤖 Generated with Claude Code

@RafaelPo
Copy link
Contributor Author

@claude code review

@github-actions

This comment was marked as outdated.

@RafaelPo
Copy link
Contributor Author

@claude code review

@github-actions

This comment was marked as outdated.

@RafaelPo RafaelPo requested a review from hnykda February 24, 2026 17:18
@RafaelPo RafaelPo force-pushed the deploy-mcp-server branch 4 times, most recently from a89e4e7 to 9948527 Compare February 24, 2026 17:25
Restore deployment infra deferred from PR #165, updated for current codebase:

Helm chart (everyrow-mcp/deploy/chart/):
- Deployment with /health probes, rolling update, hyperdisk tolerations
- ClusterIP Service (80 -> 8000)
- Gateway API HTTPRoute using .Release.Namespace for staging isolation
- SOPS-encrypted secrets via GCP KMS (Supabase keys, URLs, Redis config)

GitHub Actions workflow (.github/workflows/deploy-mcp.yaml):
- PR trigger: runs checks only (ruff, pytest, basedpyright)
- Manual dispatch with deploy_production / deploy_staging toggles
- Pipeline: setup -> checks -> build-and-push (GAR) -> deploy (Helm)
- Slack notification on failure, --atomic rollback

Staging environment:
- Namespace: everyrow-mcp-staging
- Staging Supabase, Redis DB 14, mcp-staging.everyrow.io
- Values overlay: values.yaml + values.staging.yaml + staging secrets

Sensitive values (Supabase URLs, Redis endpoints) are in SOPS-encrypted
files, not in plain values.yaml, since the repo is public.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@RafaelPo RafaelPo merged commit f86b1ce into main Feb 24, 2026
13 checks passed
@RafaelPo RafaelPo deleted the deploy-mcp-server branch February 24, 2026 17:45
Copy link
Contributor

@hnykda hnykda left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good!

Comment on lines +3 to +6
SUPABASE_ANON_KEY: ENC[AES256_GCM,data:SDHdb1p3B56tCsZDMY+8rM/+fSZCJmZito/fmHsqChlPOqRmI2vNLOLIfavbEw==,iv:qotbOW4BUeyRAL8kAFpZ5iOwCDyjeOynlDNG1/a6NRc=,tag:SH7yEMGyS0NlIdDnPmPIsQ==,type:str]
SUPABASE_URL: ENC[AES256_GCM,data:c4UIrv/WFIqENnjQlMHn4RqJ/lJ6d8fWSyoYlswZOmM/Is8ohp2U4w==,iv:g6VSbaEwH9cn+pL9BhO5R4uLvLue4GCCHew5HZSy5go=,tag:BP0NESsL2E7vwc4aMyn2+g==,type:str]
REDIS_SENTINEL_ENDPOINTS: ENC[AES256_GCM,data:9SS/lteI3EANPDYzWdZZWq3x0Bl30EgSorUesY2vS1BPKCs=,iv:7+XnRIZrRG25Rjg7N+u34gDW4iVbHPzQbJ8pp39L6ao=,tag:N+WFMVUwKRA6H1ro1bbtZw==,type:str]
REDIS_SENTINEL_MASTER_NAME: ENC[AES256_GCM,data:iL8r8pQ4TIU=,iv:xFSpe5B3NJtKOqWZCgqFihxfVOFSe/ysJDE37Ak/vW4=,tag:AXTyzU7m3u/eqfqCgm1slA==,type:str]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

none of this should be in the secrets (maybe the endpoints if they contain password), should be env

RafaelPo added a commit that referenced this pull request Feb 25, 2026
SUPABASE_URL, REDIS_SENTINEL_ENDPOINTS, and REDIS_SENTINEL_MASTER_NAME
are infrastructure addresses, not credentials. They don't grant access
without the corresponding keys/passwords which remain SOPS-encrypted.

Addresses PR #201 review feedback from @hnykda.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
RafaelPo added a commit that referenced this pull request Feb 25, 2026
SUPABASE_URL, REDIS_SENTINEL_ENDPOINTS, and REDIS_SENTINEL_MASTER_NAME
are infrastructure addresses, not credentials. They don't grant access
without the corresponding keys/passwords which remain SOPS-encrypted.

Addresses PR #201 review feedback from @hnykda.

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants