Skip to content
Back to skills

Customerio Deploy Pipeline

ASecurity

'Deploy Customer.io integrations to production cloud platforms.

  • 2,719 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 21, 2026
ai-agentstypescriptgobashnodeexpresskubernetesawsgcpgitapi

Works with

  • claude code
  • cli
  • api

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 21, 2026

npx -y skills add jeremylongshore/claude-code-plugins-plus --skill customerio-deploy-pipeline --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Customerio Deploy Pipeline?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Customerio Deploy Pipeline
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/jeremylongshore-customerio-deploy-pipeline-64860b24/badge)](https://www.skillsdirectory.com/skills/jeremylongshore-customerio-deploy-pipeline-64860b24)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: customerio-deploy-pipeline
description: 'Deploy Customer.io integrations to production cloud platforms.

  Use when deploying to Cloud Run, Vercel, AWS Lambda, or Kubernetes

  with proper secrets management and health checks.

  Trigger: "deploy customer.io", "customer.io cloud run",

  "customer.io kubernetes", "customer.io lambda", "customer.io vercel".

  '
allowed-tools: Read, Write, Edit, Bash(npm:*), Bash(gcloud:*), Bash(kubectl:*), Glob,
  Grep
version: 1.14.0
license: MIT
author: Jeremy Longshore <jeremy@intentsolutions.io>
tags:
- saas
- customer-io
- deployment
- cloud-run
- kubernetes
compatibility: Designed for Claude Code
---
# Customer.io Deploy Pipeline

## Output

- A versioned, staged deployment of Customer.io configuration/code with owner approval, validation evidence, and a rollback reference.
- A protected promotion path that prevents unreviewed changes from affecting production recipients.

## Examples

Validate an event/template configuration in development and staging with synthetic profiles, attach schema/template test results to the change, then release through an approved canary. If the canary shows wrong audience, consent, or rendering behavior, stop promotion and restore the last approved configuration.

## Overview

Deploy Customer.io integrations to production: GCP Cloud Run with Secret Manager, Vercel serverless functions, AWS Lambda with SSM, Kubernetes with external secrets, plus health check endpoints and blue-green deployment scripts.

## Prerequisites

- CI/CD pipeline configured (see `customerio-ci-integration`)
- Cloud platform credentials and access
- Production Customer.io credentials in a secrets manager

## Instructions

### Step 1: Deploy to Google Cloud Run

```yaml
# .github/workflows/deploy-cloud-run.yml
name: Deploy to Cloud Run
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write  # Required for Workload Identity Federation
    steps:
      - uses: actions/checkout@v4

      - id: auth
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: ${{ secrets.WIF_PROVIDER }}
          service_account: ${{ secrets.WIF_SA }}

      - uses: google-github-actions/setup-gcloud@v2

      - name: Build and push
        run: |
          gcloud builds submit --tag gcr.io/${{ secrets.GCP_PROJECT }}/cio-service

      - name: Deploy
        run: |
          gcloud run deploy cio-service \
            --image gcr.io/${{ secrets.GCP_PROJECT }}/cio-service \
            --region us-central1 \
            --set-secrets "CUSTOMERIO_SITE_ID=cio-site-id:latest,\
              CUSTOMERIO_TRACK_API_KEY=cio-track-key:latest,\
              CUSTOMERIO_APP_API_KEY=cio-app-key:latest" \
            --set-env-vars "CUSTOMERIO_REGION=us,NODE_ENV=production" \
            --min-instances 1 \
            --max-instances 10 \
            --memory 512Mi \
            --cpu 1 \
            --allow-unauthenticated
```

### Step 2: Health Check Endpoint

```typescript
// routes/health.ts
import { TrackClient, RegionUS } from "customerio-node";
import { Router } from "express";

const router = Router();

router.get("/health", async (_req, res) => {
  const checks: Record<string, { status: string; latency_ms?: number }> = {};

  // Check Track API
  const cio = new TrackClient(
    process.env.CUSTOMERIO_SITE_ID!,
    process.env.CUSTOMERIO_TRACK_API_KEY!,
    { region: RegionUS }
  );

  const start = Date.now();
  try {
    await cio.identify("health-check", {
      email: "health@internal.example.com",
      _health_check: true,
    });
    checks.track_api = { status: "ok", latency_ms: Date.now() - start };
  } catch (err: any) {
    checks.track_api = { status: `error: ${err.statusCode}` };
  }

  const allOk = Object.values(checks).every((c) => c.status === "ok");

  res.status(allOk ? 200 : 503).json({
    status: allOk ? "healthy" : "degraded",
    checks,
    version: process.env.npm_package_version ?? "unknown",
    uptime_seconds: Math.floor(process.uptime()),
    timestamp: new Date().toISOString(),
  });
});

export default router;
```

### Step 3: Vercel Serverless Functions

```typescript
// api/customerio/identify.ts (Vercel serverless function)
import type { VercelRequest, VercelResponse } from "@vercel/node";
import { TrackClient, RegionUS } from "customerio-node";

const cio = new TrackClient(
  process.env.CUSTOMERIO_SITE_ID!,
  process.env.CUSTOMERIO_TRACK_API_KEY!,
  { region: RegionUS }
);

export default async function handler(req: VercelRequest, res: VercelResponse) {
  if (req.method !== "POST") {
    return res.status(405).json({ error: "Method not allowed" });
  }

  const { userId, attributes } = req.body;
  if (!userId || !attributes?.email) {
    return res.status(400).json({ error: "userId and attributes.email required" });
  }

  try {
    await cio.identify(userId, {
      ...attributes,
      last_seen_at: Math.floor(Date.now() / 1000),
    });
    return res.status(200).json({ success: true });
  } catch (err: any) {
    return res.status(err.statusCode ?? 500).json({ error: err.message });
  }
}
```

### Step 4: Kubernetes Deployment

```yaml
# k8s/customerio-service.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: customerio-service
spec:
  replicas: 2
  selector:
    matchLabels:
      app: customerio-service
  template:
    metadata:
      labels:
        app: customerio-service
    spec:
      containers:
        - name: app
          image: gcr.io/my-project/cio-service:latest
          ports:
            - containerPort: 3000
          env:
            - name: CUSTOMERIO_SITE_ID
              valueFrom:
                secretKeyRef:
                  name: customerio-secrets
                  key: site-id
            - name: CUSTOMERIO_TRACK_API_KEY
              valueFrom:
                secretKeyRef:
                  name: customerio-secrets
                  key: track-api-key
            - name: CUSTOMERIO_APP_API_KEY
              valueFrom:
                secretKeyRef:
                  name: customerio-secrets
                  key: app-api-key
            - name: CUSTOMERIO_REGION
              value: "us"
            - name: NODE_ENV
              value: "production"
          resources:
            requests:
              cpu: 100m
              memory: 256Mi
            limits:
              cpu: 500m
              memory: 512Mi
          readinessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /health
              port: 3000
            initialDelaySeconds: 15
            periodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
  name: customerio-service
spec:
  selector:
    app: customerio-service
  ports:
    - port: 80
      targetPort: 3000
```

### Step 5: Blue-Green Deployment

```bash
#!/usr/bin/env bash
set -euo pipefail
# scripts/blue-green-deploy.sh

SERVICE="cio-service"
REGION="us-central1"
IMAGE="gcr.io/${GCP_PROJECT}/${SERVICE}:${COMMIT_SHA}"

echo "=== Blue-Green Deploy: ${SERVICE} ==="

# 1. Deploy with no traffic
gcloud run deploy "${SERVICE}" \
  --image "${IMAGE}" \
  --region "${REGION}" \
  --no-traffic \
  --tag "canary"

echo "Deployed canary. Running health check..."

# 2. Health check on canary
CANARY_URL=$(gcloud run services describe "${SERVICE}" \
  --region "${REGION}" --format 'value(status.url)' \
  | sed 's|https://|https://canary---|')

HEALTH=$(curl -s -o /dev/null -w "%{http_code}" "${CANARY_URL}/health")
if [ "${HEALTH}" != "200" ]; then
  echo "FAIL: Health check returned ${HEALTH}. Aborting."
  exit 1
fi

# 3. Shift traffic: 10% → 50% → 100%
for pct in 10 50 100; do
  echo "Shifting ${pct}% traffic to canary..."
  gcloud run services update-traffic "${SERVICE}" \
    --region "${REGION}" \
    --to-tags "canary=${pct}"
  sleep 30
done

echo "Deploy complete. 100% traffic on new revision."
```

## Deployment Checklist

- [ ] Production secrets in secrets manager (not env files)
- [ ] Health check endpoint responds 200
- [ ] Readiness and liveness probes configured
- [ ] Resource limits set (CPU, memory)
- [ ] Min instances > 0 (avoid cold starts)
- [ ] Blue-green or canary deployment configured
- [ ] Rollback procedure documented
- [ ] Post-deploy smoke test automated

## Error Handling

| Issue | Solution |
|-------|----------|
| Secret not found | Verify secret name in secrets manager |
| Health check timeout | Increase initialDelaySeconds, check CIO connectivity |
| Cold start latency | Set `--min-instances 1` (Cloud Run) or keep-alive |
| Memory OOM | Increase memory limits, check for event queue buildup |

## Resources

- [Cloud Run Documentation](https://cloud.google.com/run/docs)
- [Vercel Serverless Functions](https://vercel.com/docs/functions)
- [Kubernetes Secrets](https://kubernetes.io/docs/concepts/configuration/secret/)

## Next Steps

After deployment, proceed to `customerio-webhooks-events` for webhook handling.

Files in this skill

  • SKILL.md8.9 KB
  • references/implementation-guide.md7.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.