57dc91585d
Internal SmartGift build of a Claude Code monitoring dashboard. Lanes: a durable unit of parallel agent work, one per working directory, tracked across session restarts. Managed lanes are git worktrees the dashboard provisions and can reset or remove behind a three-check destroy guard and a counted preflight; adopted lanes are directories you already own and are never destroyable. Pipelines: a lane moves through pipeline stages. A stage the agent declares with evidence renders green; a stage inferred from the tool-event stream renders dashed amber and never counts as done. Detection is forward-only within a 30-minute window, and never writes the declared stage. Workspace: one page at /run with a lane grid, the selected lane's pipeline, and a full Claude console behind a disclosure.
161 lines
5.8 KiB
YAML
161 lines
5.8 KiB
YAML
# ─────────────────────────────────────────────────────────────────────────────
|
||
# GitHub Actions Rollback Pipeline – Claude Code Agent Monitor
|
||
#
|
||
# Manual workflow to roll back a Helm deployment to a previous revision.
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
name: Rollback
|
||
|
||
on:
|
||
workflow_dispatch:
|
||
inputs:
|
||
environment:
|
||
description: "Target environment to rollback"
|
||
required: true
|
||
type: choice
|
||
options:
|
||
- staging
|
||
- production
|
||
revision:
|
||
description: "Helm revision number (leave empty for previous)"
|
||
required: false
|
||
type: string
|
||
reason:
|
||
description: "Reason for rollback"
|
||
required: true
|
||
type: string
|
||
|
||
permissions:
|
||
contents: read
|
||
id-token: write
|
||
|
||
concurrency:
|
||
group: deploy-${{ github.event.inputs.environment }}
|
||
cancel-in-progress: false
|
||
|
||
jobs:
|
||
rollback:
|
||
name: Rollback ${{ github.event.inputs.environment }}
|
||
runs-on: ubuntu-latest
|
||
environment:
|
||
name: ${{ github.event.inputs.environment }}
|
||
steps:
|
||
- name: Checkout code
|
||
uses: actions/checkout@v4
|
||
|
||
- name: Configure AWS credentials (OIDC)
|
||
uses: aws-actions/configure-aws-credentials@v4
|
||
with:
|
||
role-to-assume: ${{ github.event.inputs.environment == 'production' && secrets.AWS_ROLE_ARN_PRODUCTION || secrets.AWS_ROLE_ARN_STAGING }}
|
||
aws-region: ${{ vars.AWS_REGION || 'us-west-2' }}
|
||
|
||
- name: Setup kubectl
|
||
uses: azure/setup-kubectl@v3
|
||
with:
|
||
version: "v1.29.0"
|
||
|
||
- name: Setup Helm
|
||
uses: azure/setup-helm@v4
|
||
with:
|
||
version: "v3.14.0"
|
||
|
||
- name: Update kubeconfig
|
||
run: |
|
||
CLUSTER_NAME="${{ github.event.inputs.environment == 'production' && vars.EKS_CLUSTER_PRODUCTION || vars.EKS_CLUSTER_STAGING }}"
|
||
CLUSTER_NAME="${CLUSTER_NAME:-agent-monitor-${{ github.event.inputs.environment }}}"
|
||
aws eks update-kubeconfig \
|
||
--region ${{ vars.AWS_REGION || 'us-west-2' }} \
|
||
--name "${CLUSTER_NAME}"
|
||
|
||
- name: Show Helm history
|
||
run: |
|
||
NAMESPACE="agent-monitor-${{ github.event.inputs.environment }}"
|
||
echo "## Current Helm History"
|
||
helm history agent-monitor -n "${NAMESPACE}" --max 10 || echo "No history found"
|
||
|
||
- name: Execute rollback
|
||
run: |
|
||
NAMESPACE="agent-monitor-${{ github.event.inputs.environment }}"
|
||
REVISION="${{ github.event.inputs.revision }}"
|
||
|
||
echo "Rolling back in namespace: ${NAMESPACE}"
|
||
|
||
ROLLBACK_ARGS="helm rollback agent-monitor"
|
||
if [[ -n "${REVISION}" ]]; then
|
||
ROLLBACK_ARGS="${ROLLBACK_ARGS} ${REVISION}"
|
||
echo "Target revision: ${REVISION}"
|
||
else
|
||
echo "Target revision: previous"
|
||
fi
|
||
|
||
${ROLLBACK_ARGS} -n "${NAMESPACE}" --wait --timeout 300s
|
||
|
||
echo "✔ Rollback command succeeded"
|
||
|
||
- name: Health check after rollback
|
||
run: |
|
||
NAMESPACE="agent-monitor-${{ github.event.inputs.environment }}"
|
||
|
||
echo "Waiting for pods to be ready..."
|
||
kubectl wait --for=condition=ready pod \
|
||
-l app.kubernetes.io/name=agent-monitor \
|
||
-n "${NAMESPACE}" \
|
||
--timeout=300s
|
||
|
||
kubectl port-forward svc/agent-monitor 14820:4820 -n "${NAMESPACE}" &
|
||
PF_PID=$!
|
||
sleep 5
|
||
|
||
HEALTHY=false
|
||
for i in $(seq 1 10); do
|
||
if curl -sf http://localhost:14820/api/health | grep -q '"status":"ok"'; then
|
||
echo "✔ Health check passed after rollback"
|
||
HEALTHY=true
|
||
break
|
||
fi
|
||
echo "Attempt $i/10..."
|
||
sleep 5
|
||
done
|
||
|
||
kill $PF_PID 2>/dev/null || true
|
||
|
||
if [[ "$HEALTHY" != true ]]; then
|
||
echo "✖ Health check failed after rollback!"
|
||
exit 1
|
||
fi
|
||
|
||
- name: Show post-rollback status
|
||
if: always()
|
||
run: |
|
||
NAMESPACE="agent-monitor-${{ github.event.inputs.environment }}"
|
||
echo "## Post-Rollback Status"
|
||
echo ""
|
||
echo "### Helm Status"
|
||
helm status agent-monitor -n "${NAMESPACE}" || true
|
||
echo ""
|
||
echo "### Pod Status"
|
||
kubectl get pods -n "${NAMESPACE}" -l app.kubernetes.io/name=agent-monitor || true
|
||
echo ""
|
||
echo "### Recent Events"
|
||
kubectl get events -n "${NAMESPACE}" --sort-by='.lastTimestamp' | tail -20 || true
|
||
|
||
- name: Notify Slack
|
||
if: always()
|
||
uses: slackapi/slack-github-action@v1.26.0
|
||
with:
|
||
payload: |
|
||
{
|
||
"text": "${{ job.status == 'success' && '⏪' || '🚨' }} Rollback ${{ job.status }} on ${{ github.event.inputs.environment }}",
|
||
"blocks": [
|
||
{
|
||
"type": "section",
|
||
"text": {
|
||
"type": "mrkdwn",
|
||
"text": "${{ job.status == 'success' && ':rewind:' || ':rotating_light:' }} *Rollback ${{ job.status }}*\n*Environment:* `${{ github.event.inputs.environment }}`\n*Revision:* `${{ github.event.inputs.revision || 'previous' }}`\n*Reason:* ${{ github.event.inputs.reason }}\n*Actor:* ${{ github.actor }}\n*Workflow:* <${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|View Run>"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
env:
|
||
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
||
SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK
|