Add complete automation SOP system for BlackRoad ERP

This implements the "Automate The Company" initiative with comprehensive
Standard Operating Procedures for GitHub + Salesforce + Asana integration.

New directory: sop/
├── workflows/ - End-to-end process documentation
│   ├── new-client-kickoff.md - Flagship workflow from deal → repos → Asana
│   └── release-pipeline.md - Deploy → update Salesforce + Asana
├── playbooks/ - Human-friendly checklists
│   └── brenda-new-client-checklist.md - Non-technical operator guide
├── salesforce/ - Salesforce automation specifications
│   ├── flows/opp-automation-onstagechange.md - Trigger on Closed Won
│   └── orchestrations/new-client-kickoff-orchestration.md - Multi-stage process
├── integrations/ - API integration specifications
│   ├── salesforce-to-github.md - Create repos from Salesforce
│   ├── github-to-salesforce.md - Update Salesforce after deploy
│   └── salesforce-to-asana.md - Create Asana projects from Salesforce
└── templates/ - Reusable templates
    ├── github-actions/ - CI/CD workflows (ci.yml, deploy.yml, safety.yml)
    └── repo-template/ - Standard repo config (PR template, labels, branch protection)

Key Features:
- Event-driven automation (Closed Won → repos + Asana creation)
- GitHub Actions templates for CI/CD baseline
- Salesforce Flow & Orchestration specs
- Complete API integration documentation
- Operator-friendly playbooks
- Two-view approach (operator + engineer)
- No manual status syncing across systems

This provides the complete backbone for next-gen ERP automation.
This commit is contained in:
Claude
2025-11-17 08:17:51 +00:00
parent 9b137af555
commit 7cde897040
18 changed files with 6077 additions and 0 deletions

View File

@@ -0,0 +1,189 @@
name: CI Pipeline
on:
push:
branches: ["**"]
pull_request:
branches: ["main"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
name: Test (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12"]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pytest pytest-cov pytest-asyncio pytest-mock
- name: Run tests with coverage
run: |
pytest --cov=. --cov-report=xml --cov-report=term-missing --cov-report=html -v
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
if: matrix.python-version == '3.12'
with:
file: ./coverage.xml
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false
- name: Archive coverage report
uses: actions/upload-artifact@v4
if: matrix.python-version == '3.12'
with:
name: coverage-report
path: htmlcov/
retention-days: 7
lint:
name: Lint & Format Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
- name: Install linting tools
run: |
pip install ruff black isort mypy
- name: Run ruff (fast Python linter)
run: |
ruff check . --output-format=github
- name: Check code formatting with black
run: |
black --check --diff .
- name: Check import sorting with isort
run: |
isort --check-only --diff .
- name: Type check with mypy
run: |
mypy . --ignore-missing-imports --show-error-codes
continue-on-error: true # Don't fail CI on type errors initially
security:
name: Security Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install safety & bandit
run: |
pip install safety bandit[toml]
- name: Check for known vulnerabilities in dependencies
run: |
pip install -r requirements.txt
safety check --json || true
- name: Run bandit security linter
run: |
bandit -r . -f json -o bandit-report.json || true
bandit -r . -f screen
- name: Upload security reports
uses: actions/upload-artifact@v4
with:
name: security-reports
path: |
bandit-report.json
retention-days: 30
build:
name: Build & Test Container
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker image
uses: docker/build-push-action@v5
with:
context: .
push: false
tags: test-build:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
load: true
- name: Test container starts and responds
run: |
docker run -d --name test-container -p 8000:8000 test-build:${{ github.sha }}
sleep 10
# Check if container is still running
if [ "$(docker inspect -f '{{.State.Running}}' test-container)" != "true" ]; then
echo "Container failed to start"
docker logs test-container
exit 1
fi
# Check health endpoint
curl -f http://localhost:8000/health || exit 1
docker stop test-container
docker rm test-container
summary:
name: CI Summary
runs-on: ubuntu-latest
needs: [test, lint, security, build]
if: always()
steps:
- name: Check all jobs status
run: |
echo "Test: ${{ needs.test.result }}"
echo "Lint: ${{ needs.lint.result }}"
echo "Security: ${{ needs.security.result }}"
echo "Build: ${{ needs.build.result }}"
if [ "${{ needs.test.result }}" != "success" ] || \
[ "${{ needs.lint.result }}" != "success" ] || \
[ "${{ needs.build.result }}" != "success" ]; then
echo "❌ CI pipeline failed"
exit 1
fi
echo "✅ All CI checks passed"

View File

@@ -0,0 +1,303 @@
name: Deploy to Production
on:
push:
branches:
- main
release:
types: [published]
workflow_dispatch:
inputs:
environment:
description: 'Environment to deploy to'
required: true
default: 'production'
type: choice
options:
- staging
- production
env:
RAILWAY_SERVICE: backend
ENVIRONMENT: ${{ github.event.inputs.environment || 'production' }}
jobs:
deploy-backend:
name: Deploy Backend to Railway
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.environment || 'production' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Railway CLI
run: |
curl -fsSL https://railway.app/install.sh | sh
echo "$HOME/.railway/bin" >> $GITHUB_PATH
- name: Deploy to Railway
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
run: |
railway up --service ${{ env.RAILWAY_SERVICE }} --environment ${{ env.ENVIRONMENT }}
- name: Wait for deployment to complete
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
run: |
echo "Waiting for Railway deployment to stabilize..."
sleep 30
- name: Get deployment URL
id: get-url
env:
RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }}
run: |
DEPLOY_URL=$(railway domain --service ${{ env.RAILWAY_SERVICE }} --environment ${{ env.ENVIRONMENT }} 2>/dev/null || echo "")
echo "DEPLOY_URL=$DEPLOY_URL" >> $GITHUB_OUTPUT
echo "Backend deployed to: $DEPLOY_URL"
- name: Health check
if: steps.get-url.outputs.DEPLOY_URL != ''
run: |
echo "Running health check on ${{ steps.get-url.outputs.DEPLOY_URL }}"
# Retry health check up to 10 times
for i in {1..10}; do
if curl -f "${{ steps.get-url.outputs.DEPLOY_URL }}/health" 2>/dev/null; then
echo "✅ Health check passed"
exit 0
fi
echo "Health check attempt $i failed, retrying in 10s..."
sleep 10
done
echo "❌ Health check failed after 10 attempts"
exit 1
- name: Save deployment metadata
id: metadata
run: |
echo "DEPLOY_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> $GITHUB_OUTPUT
echo "DEPLOY_SHA=${{ github.sha }}" >> $GITHUB_OUTPUT
echo "DEPLOY_ACTOR=${{ github.actor }}" >> $GITHUB_OUTPUT
echo "DEPLOY_BRANCH=${{ github.ref_name }}" >> $GITHUB_OUTPUT
outputs:
deploy_url: ${{ steps.get-url.outputs.DEPLOY_URL }}
deploy_time: ${{ steps.metadata.outputs.DEPLOY_TIME }}
deploy_sha: ${{ steps.metadata.outputs.DEPLOY_SHA }}
deploy-frontend:
name: Deploy Frontend to Cloudflare Pages
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.environment || 'production' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build frontend
env:
VITE_API_URL: ${{ secrets.VITE_API_URL }}
VITE_ENV: ${{ env.ENVIRONMENT }}
run: npm run build
- name: Deploy to Cloudflare Pages
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: ${{ secrets.CLOUDFLARE_PROJECT_NAME }}
directory: dist
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
branch: ${{ github.ref_name }}
- name: Verify frontend deployment
run: |
FRONTEND_URL="${{ secrets.CLOUDFLARE_PAGES_URL }}"
echo "Verifying frontend at $FRONTEND_URL"
# Wait for Cloudflare propagation
sleep 30
# Check if frontend loads
for i in {1..5}; do
if curl -f "$FRONTEND_URL" 2>/dev/null; then
echo "✅ Frontend is accessible"
exit 0
fi
echo "Attempt $i failed, retrying in 10s..."
sleep 10
done
echo "❌ Frontend verification failed"
exit 1
notify-stakeholders:
name: Notify Stakeholders
needs: [deploy-backend, deploy-frontend]
runs-on: ubuntu-latest
if: success()
steps:
- name: Extract Project Key from repo name
id: project-key
run: |
# Extract from repo name: blackroad-ACME-X7K9-backend → ACME-X7K9
REPO_NAME="${{ github.repository }}"
PROJECT_KEY=$(echo "$REPO_NAME" | sed -n 's/.*blackroad-\([A-Z0-9-]*\)-.*/\1/p')
if [ -z "$PROJECT_KEY" ]; then
echo "Warning: Could not extract project key from repo name"
PROJECT_KEY="UNKNOWN"
fi
echo "PROJECT_KEY=$PROJECT_KEY" >> $GITHUB_OUTPUT
echo "Extracted project key: $PROJECT_KEY"
- name: Update Salesforce Project record
if: steps.project-key.outputs.PROJECT_KEY != 'UNKNOWN'
env:
SF_INSTANCE_URL: ${{ secrets.SALESFORCE_INSTANCE_URL }}
SF_ACCESS_TOKEN: ${{ secrets.SALESFORCE_ACCESS_TOKEN }}
run: |
curl -X PATCH \
"$SF_INSTANCE_URL/services/data/v58.0/sobjects/Project__c/Project_Key__c/${{ steps.project-key.outputs.PROJECT_KEY }}" \
-H "Authorization: Bearer $SF_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"Last_Deploy_At__c": "${{ needs.deploy-backend.outputs.deploy_time }}",
"Last_Deploy_SHA__c": "${{ needs.deploy-backend.outputs.deploy_sha }}",
"Last_Deploy_Branch__c": "${{ github.ref_name }}",
"Last_Deploy_Actor__c": "${{ github.actor }}",
"Deploy_Status__c": "Success",
"Environment__c": "${{ env.ENVIRONMENT }}",
"Backend_URL__c": "${{ needs.deploy-backend.outputs.deploy_url }}",
"Release_Notes_URL__c": "https://github.com/${{ github.repository }}/commit/${{ github.sha }}"
}' || echo "Warning: Failed to update Salesforce"
- name: Create Salesforce Deployment record
if: steps.project-key.outputs.PROJECT_KEY != 'UNKNOWN'
env:
SF_INSTANCE_URL: ${{ secrets.SALESFORCE_INSTANCE_URL }}
SF_ACCESS_TOKEN: ${{ secrets.SALESFORCE_ACCESS_TOKEN }}
run: |
curl -X POST \
"$SF_INSTANCE_URL/services/data/v58.0/sobjects/Deployment__c" \
-H "Authorization: Bearer $SF_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"Name": "${{ steps.project-key.outputs.PROJECT_KEY }} - ${{ github.sha }}",
"Project_Key__c": "${{ steps.project-key.outputs.PROJECT_KEY }}",
"Deployed_At__c": "${{ needs.deploy-backend.outputs.deploy_time }}",
"Git_SHA__c": "${{ github.sha }}",
"Git_Branch__c": "${{ github.ref_name }}",
"Deployed_By__c": "${{ github.actor }}",
"Status__c": "Success",
"Environment__c": "${{ env.ENVIRONMENT }}",
"Repository__c": "${{ github.repository }}",
"Commit_URL__c": "https://github.com/${{ github.repository }}/commit/${{ github.sha }}"
}' || echo "Warning: Failed to create Deployment record"
- name: Update Asana tasks
if: steps.project-key.outputs.PROJECT_KEY != 'UNKNOWN' && env.ENVIRONMENT == 'production'
env:
ASANA_PAT: ${{ secrets.ASANA_PAT }}
ASANA_WORKSPACE_GID: ${{ secrets.ASANA_WORKSPACE_GID }}
run: |
PROJECT_KEY="${{ steps.project-key.outputs.PROJECT_KEY }}"
# Find Asana project by name containing PROJECT_KEY
PROJECT_GID=$(curl -s "https://app.asana.com/api/1.0/projects?workspace=$ASANA_WORKSPACE_GID&opt_fields=name,gid" \
-H "Authorization: Bearer $ASANA_PAT" | \
jq -r ".data[] | select(.name | contains(\"$PROJECT_KEY\")) | .gid" | head -n 1)
if [ -z "$PROJECT_GID" ]; then
echo "Warning: Could not find Asana project for $PROJECT_KEY"
exit 0
fi
echo "Found Asana project: $PROJECT_GID"
# Find "Deploy" task
TASK_GID=$(curl -s "https://app.asana.com/api/1.0/projects/$PROJECT_GID/tasks?opt_fields=name,gid,completed" \
-H "Authorization: Bearer $ASANA_PAT" | \
jq -r '.data[] | select(.name | test("Deploy.*production"; "i")) | select(.completed == false) | .gid' | head -n 1)
if [ -z "$TASK_GID" ]; then
echo "No pending deploy task found in Asana"
exit 0
fi
echo "Found deploy task: $TASK_GID"
# Mark task as complete
curl -X PUT "https://app.asana.com/api/1.0/tasks/$TASK_GID" \
-H "Authorization: Bearer $ASANA_PAT" \
-H "Content-Type: application/json" \
-d '{"data": {"completed": true}}' || echo "Warning: Failed to complete task"
# Add comment with deploy details
curl -X POST "https://app.asana.com/api/1.0/tasks/$TASK_GID/stories" \
-H "Authorization: Bearer $ASANA_PAT" \
-H "Content-Type: application/json" \
-d '{
"data": {
"text": "✅ Deployed to production\n\n**Commit:** ${{ github.sha }}\n**By:** ${{ github.actor }}\n**Time:** ${{ needs.deploy-backend.outputs.deploy_time }}\n**Link:** https://github.com/${{ github.repository }}/commit/${{ github.sha }}"
}
}' || echo "Warning: Failed to add comment"
- name: Notify Slack
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_DEPLOYS }}
run: |
STATUS_EMOJI="✅"
curl -X POST "$SLACK_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d '{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "'"$STATUS_EMOJI"' *Deploy to '"${{ env.ENVIRONMENT }}"'*\n\n*Project:* '"${{ steps.project-key.outputs.PROJECT_KEY }}"'\n*Repo:* `${{ github.repository }}`\n*Commit:* <https://github.com/${{ github.repository }}/commit/${{ github.sha }}|'"${GITHUB_SHA:0:7}"'>\n*By:* ${{ github.actor }}\n*Backend:* ${{ needs.deploy-backend.outputs.deploy_url }}"
}
}
]
}' || echo "Warning: Failed to send Slack notification"
rollback-on-failure:
name: Rollback on Failure
needs: [deploy-backend, deploy-frontend]
runs-on: ubuntu-latest
if: failure()
steps:
- name: Notify failure
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_DEPLOYS }}
run: |
curl -X POST "$SLACK_WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d '{
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "❌ *Deploy FAILED*\n\n*Repo:* `${{ github.repository }}`\n*Commit:* <https://github.com/${{ github.repository }}/commit/${{ github.sha }}|'"${GITHUB_SHA:0:7}"'>\n*By:* ${{ github.actor }}\n\n⚠ Manual intervention may be required. Check the <https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|workflow run> for details."
}
}
]
}' || true

View File

@@ -0,0 +1,238 @@
name: Security & Safety Checks
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
schedule:
# Run weekly on Monday at 9am UTC
- cron: '0 9 * * 1'
workflow_dispatch:
permissions:
contents: read
security-events: write
actions: read
jobs:
dependency-scan:
name: Dependency Vulnerability Scan
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install safety pip-audit
- name: Run safety check
continue-on-error: true
run: |
safety check --json --output safety-report.json || true
safety check
- name: Run pip-audit
continue-on-error: true
run: |
pip-audit --format json --output pip-audit-report.json || true
pip-audit
- name: Upload vulnerability reports
uses: actions/upload-artifact@v4
with:
name: dependency-vulnerability-reports
path: |
safety-report.json
pip-audit-report.json
retention-days: 90
sast-scan:
name: Static Application Security Testing
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install bandit
run: pip install bandit[toml]
- name: Run bandit security linter
run: |
bandit -r . \
-f json \
-o bandit-report.json \
--exclude './tests/*,./venv/*,./.venv/*,*/site-packages/*' \
-ll || true
bandit -r . \
-f screen \
--exclude './tests/*,./venv/*,./.venv/*,*/site-packages/*' \
-ll
- name: Upload SAST report
uses: actions/upload-artifact@v4
with:
name: sast-report
path: bandit-report.json
retention-days: 90
secret-scan:
name: Secret Detection
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Full history for secret scanning
- name: Run Gitleaks
uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE}}
codeql:
name: CodeQL Analysis
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: python, javascript
queries: security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:python"
license-check:
name: License Compliance Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install pip-licenses
run: pip install pip-licenses
- name: Install project dependencies
run: pip install -r requirements.txt
- name: Check licenses
run: |
echo "Generating license report..."
pip-licenses --format=json --output-file=licenses.json
pip-licenses --format=markdown --output-file=licenses.md
# Check for problematic licenses (GPL, AGPL, etc.)
PROBLEMATIC=$(pip-licenses --format=json | jq -r '.[] | select(.License | test("GPL|AGPL")) | .Name')
if [ -n "$PROBLEMATIC" ]; then
echo "⚠️ Warning: Found packages with potentially problematic licenses:"
echo "$PROBLEMATIC"
# Don't fail the build, just warn
else
echo "✅ No problematic licenses found"
fi
- name: Upload license report
uses: actions/upload-artifact@v4
with:
name: license-report
path: |
licenses.json
licenses.md
retention-days: 90
container-scan:
name: Container Image Scan
runs-on: ubuntu-latest
if: github.event_name != 'schedule'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t security-scan:${{ github.sha }} .
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: security-scan:${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'CRITICAL,HIGH'
- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: 'trivy-results.sarif'
- name: Run Trivy for readable output
uses: aquasecurity/trivy-action@master
with:
image-ref: security-scan:${{ github.sha }}
format: 'table'
severity: 'CRITICAL,HIGH,MEDIUM'
summary:
name: Security Summary
needs: [dependency-scan, sast-scan, secret-scan, license-check]
runs-on: ubuntu-latest
if: always()
steps:
- name: Security check summary
run: |
echo "### Security Scan Results"
echo ""
echo "- Dependency Scan: ${{ needs.dependency-scan.result }}"
echo "- SAST Scan: ${{ needs.sast-scan.result }}"
echo "- Secret Scan: ${{ needs.secret-scan.result }}"
echo "- License Check: ${{ needs.license-check.result }}"
echo ""
if [ "${{ needs.secret-scan.result }}" == "failure" ]; then
echo "❌ CRITICAL: Secrets detected in repository!"
exit 1
fi
if [ "${{ needs.dependency-scan.result }}" == "failure" ] || \
[ "${{ needs.sast-scan.result }}" == "failure" ]; then
echo "⚠️ Security vulnerabilities detected. Review the reports."
# Don't fail the build for vulnerability warnings
else
echo "✅ No critical security issues detected"
fi

View File

@@ -0,0 +1,61 @@
---
name: Bug Report
about: Report a bug or unexpected behavior
title: '[BUG] '
labels: 'type:bug, priority:p2'
assignees: ''
---
## Description
<!-- Clear and concise description of the bug -->
## Steps to Reproduce
1.
2.
3.
## Expected Behavior
<!-- What should happen -->
## Actual Behavior
<!-- What actually happens -->
## Environment
- **Environment:** (production / staging / local)
- **Browser/Client:** (if applicable)
- **OS:** (if applicable)
- **Version/Commit:**
## Screenshots/Logs
<!-- If applicable, add screenshots or relevant error logs -->
```
Paste error logs here
```
## Possible Fix
<!-- Optional: Suggest a potential solution or workaround -->
## Additional Context
<!-- Any other relevant information -->
## Impact
- [ ] Blocks production users
- [ ] Blocks internal users
- [ ] Minor inconvenience
- [ ] Nice to have fix
## Related
- **Asana Task:** [link]
- **Salesforce Case:** [link]
- **Related Issues:** #

View File

@@ -0,0 +1,114 @@
---
name: Deployment Checklist
about: Pre/post deployment checklist
title: '[DEPLOY] Release v'
labels: 'type:deployment, priority:p1'
assignees: ''
---
## Release Information
- **Version:** v
- **Target Date:**
- **Environment:** (staging / production)
- **Deployment Window:**
## Pre-Deployment Checklist
### Code & Testing
- [ ] All PRs merged to `main`
- [ ] CI pipeline passes (tests, lint, build)
- [ ] Security scans pass
- [ ] Code review completed
- [ ] Release notes drafted
### Infrastructure
- [ ] Database migrations tested in staging
- [ ] Environment variables updated (if needed)
- [ ] Secrets rotated (if needed)
- [ ] Resource scaling planned (if needed)
### Stakeholder Communication
- [ ] Asana tasks updated with deploy plan
- [ ] Salesforce Project record current
- [ ] #deploys channel notified
- [ ] Customer success team informed (if customer-facing changes)
### Backup & Rollback
- [ ] Database backup created
- [ ] Current version tagged for rollback
- [ ] Rollback procedure documented
## Deployment Steps
1. [ ] Tag release in GitHub
2. [ ] Trigger deploy workflow
3. [ ] Monitor deployment logs
4. [ ] Wait for health checks to pass
5. [ ] Verify backend API responding
6. [ ] Verify frontend loads correctly
## Post-Deployment Checklist
### Verification
- [ ] Health checks passing
- [ ] Critical user flows tested
- [ ] Database migrations applied
- [ ] No errors in application logs
- [ ] No spike in error rates (monitoring)
- [ ] Performance metrics within acceptable range
### Stakeholder Updates
- [ ] Salesforce Project record updated (automated)
- [ ] Asana deploy task marked complete (automated)
- [ ] Slack notification sent (automated)
- [ ] Release notes published
### Monitoring
- [ ] Set up alerts for next 24 hours
- [ ] Monitor error rates
- [ ] Monitor performance metrics
- [ ] Check user feedback channels
## Rollback Plan
**Trigger Rollback If:**
- Critical functionality broken
- Error rate > 5%
- Performance degradation > 50%
- Database corruption detected
**Rollback Procedure:**
1. Navigate to: https://github.com/$REPO/actions/workflows/rollback.yml
2. Click "Run workflow"
3. Enter previous stable SHA:
4. Enter rollback reason:
5. Monitor rollback completion
## Issues Discovered
<!-- Document any issues found during/after deployment -->
| Issue | Severity | Status | Resolution |
|-------|----------|--------|------------|
| | | | |
## Post-Mortem Notes
<!-- After deployment, document lessons learned -->
**What went well:**
-
**What could be improved:**
-
**Action items:**
- [ ]
- [ ]
## Related
- **Release Notes:** [link]
- **Salesforce Project:** [link]
- **Asana Deploy Task:** [link]

View File

@@ -0,0 +1,57 @@
---
name: Feature Request
about: Suggest a new feature or enhancement
title: '[FEATURE] '
labels: 'type:feature, priority:p3'
assignees: ''
---
## Problem/Need
<!-- What problem does this feature solve? Who needs it? -->
## Proposed Solution
<!-- Describe your proposed solution -->
## Alternatives Considered
<!-- What other approaches did you consider? Why is this the best option? -->
## User Stories
<!-- How will users interact with this feature? -->
As a **[user type]**, I want **[goal]** so that **[benefit]**.
## Success Criteria
<!-- How will we know this feature is successful? -->
- [ ] Criterion 1
- [ ] Criterion 2
- [ ] Criterion 3
## Technical Considerations
<!-- Any technical constraints, dependencies, or implementation notes -->
## Mockups/Designs
<!-- Optional: Add mockups, wireframes, or design references -->
## Priority Justification
- **Business Value:** (High / Medium / Low)
- **Technical Complexity:** (High / Medium / Low)
- **User Impact:** (High / Medium / Low)
## Related
- **Asana Epic:** [link]
- **Salesforce Opportunity:** [link]
- **Related Issues:** #
## Additional Context
<!-- Any other relevant information -->

View File

@@ -0,0 +1,206 @@
# Branch Protection Configuration
This document specifies the branch protection rules to be applied to all BlackRoad project repositories.
## Main Branch Protection
**Branch:** `main`
### Settings
**Require Pull Request:**
- ✅ Require a pull request before merging
- Require approvals: **1**
- Dismiss stale pull request approvals when new commits are pushed
- Require review from Code Owners (if CODEOWNERS file exists)
**Status Checks:**
- ✅ Require status checks to pass before merging
- ✅ Require branches to be up to date before merging
**Required Status Checks:**
- `test (3.11)`
- `test (3.12)`
- `lint`
- `build`
- `security / summary` (allow to fail)
**Restrictions:**
- ✅ Restrict who can push to matching branches
- Allowed to push: **Repository admins only**
- Allowed to bypass: **None** (not even admins)
**Other Rules:**
- ✅ Require linear history (enforce rebase or squash merge)
- ✅ Require deployments to succeed before merging (if applicable)
- ✅ Lock branch (prevent all changes) - **❌ Disabled** (allow normal development)
- ✅ Do not allow force pushes
- ✅ Do not allow deletions
**Enforcement:**
- ✅ Include administrators (admins must follow the same rules)
---
## Development Branch Protection (Optional)
**Branch:** `develop` (if using GitFlow)
### Settings
**Require Pull Request:**
- ✅ Require a pull request before merging
- Require approvals: **1**
**Status Checks:**
- ✅ Require status checks to pass before merging
- Required checks: `test`, `lint`, `build`
**Other Rules:**
- ✅ Do not allow force pushes
- ✅ Do not allow deletions
---
## Tag Protection
**Pattern:** `v*` (all version tags)
### Settings
- ✅ Only repository admins can create tags matching this pattern
- ✅ Only repository admins can delete tags matching this pattern
**Purpose:** Prevent accidental or malicious deletion of release tags
---
## Implementation
### Via GitHub API
Use this script to apply branch protection rules programmatically:
```bash
#!/bin/bash
REPO="blackboxprogramming/blackroad-{PROJECT_KEY}-backend"
BRANCH="main"
TOKEN="${GITHUB_TOKEN}"
curl -X PUT \
"https://api.github.com/repos/${REPO}/branches/${BRANCH}/protection" \
-H "Authorization: token ${TOKEN}" \
-H "Accept: application/vnd.github.v3+json" \
-d '{
"required_status_checks": {
"strict": true,
"contexts": [
"test (3.11)",
"test (3.12)",
"lint",
"build"
]
},
"enforce_admins": true,
"required_pull_request_reviews": {
"dismissal_restrictions": {},
"dismiss_stale_reviews": true,
"require_code_owner_reviews": true,
"required_approving_review_count": 1
},
"restrictions": null,
"required_linear_history": true,
"allow_force_pushes": false,
"allow_deletions": false
}'
```
### Via GitHub Web UI
1. Go to repository → Settings → Branches
2. Click "Add branch protection rule"
3. Branch name pattern: `main`
4. Configure settings as specified above
5. Click "Create" or "Save changes"
---
## CODEOWNERS File
Create `.github/CODEOWNERS` to automatically request reviews from specific teams:
```
# Default owners for everything
* @blackboxprogramming/engineering
# Backend code
/backend/ @blackboxprogramming/backend-team
# Frontend code
/frontend/ @blackboxprogramming/frontend-team
# Infrastructure
/ops/ @blackboxprogramming/devops-team
/terraform/ @blackboxprogramming/devops-team
/.github/workflows/ @blackboxprogramming/devops-team
# Documentation
/docs/ @blackboxprogramming/documentation-team
*.md @blackboxprogramming/documentation-team
# Security-sensitive files
/secrets/ @blackboxprogramming/security-team
.env.* @blackboxprogramming/security-team
```
---
## Merge Strategy
**Preferred:** Squash and merge
**Reasoning:**
- Clean, linear history
- Each PR becomes a single commit
- Easy to revert if needed
- Clear attribution
**Alternative:** Rebase and merge (for repos with well-structured commit history)
**Avoid:** Merge commits (creates messy history)
---
## Exceptions
**When to bypass branch protection:**
- **NEVER** for regular development
- Only in absolute emergencies:
- Critical production bug fix (with manager approval)
- Security vulnerability patch (with security team approval)
- Service outage (with on-call engineer approval)
**Process for emergency bypass:**
1. Get approval in #ops or #engineering Slack channel
2. Document reason in channel
3. Make the emergency change
4. Create follow-up PR immediately after to document the change
5. Post-mortem within 24 hours
---
## Monitoring
**Weekly:** Review bypass logs
**Monthly:** Audit branch protection settings across all repos
**Quarterly:** Review and update required status checks
**Tool:** Use GitHub audit log API to track who bypassed protection and why
---
## Related
- [GitHub Actions: CI Workflow](../../github-actions/ci.yml)
- [New Client Kickoff Workflow](../../workflows/new-client-kickoff.md)
- [Pull Request Template](./pull_request_template.md)

View File

@@ -0,0 +1,137 @@
[
{
"name": "type:feature",
"color": "0E8A16",
"description": "New feature or enhancement"
},
{
"name": "type:bug",
"color": "D73A4A",
"description": "Bug or defect"
},
{
"name": "type:docs",
"color": "0075CA",
"description": "Documentation changes"
},
{
"name": "type:refactor",
"color": "FBCA04",
"description": "Code refactoring without functionality change"
},
{
"name": "type:test",
"color": "BFD4F2",
"description": "Test-related changes"
},
{
"name": "type:chore",
"color": "FEF2C0",
"description": "Maintenance, dependencies, tooling"
},
{
"name": "type:security",
"color": "D93F0B",
"description": "Security-related changes"
},
{
"name": "type:deployment",
"color": "5319E7",
"description": "Deployment or release-related"
},
{
"name": "priority:p0",
"color": "B60205",
"description": "Critical - Drop everything"
},
{
"name": "priority:p1",
"color": "D93F0B",
"description": "High - Should be next"
},
{
"name": "priority:p2",
"color": "FBCA04",
"description": "Medium - Normal priority"
},
{
"name": "priority:p3",
"color": "C5DEF5",
"description": "Low - Nice to have"
},
{
"name": "area:backend",
"color": "5319E7",
"description": "Backend/API changes"
},
{
"name": "area:frontend",
"color": "1D76DB",
"description": "Frontend/UI changes"
},
{
"name": "area:ops",
"color": "0E8A16",
"description": "Infrastructure/DevOps"
},
{
"name": "area:infra",
"color": "006B75",
"description": "Infrastructure as code"
},
{
"name": "area:database",
"color": "5319E7",
"description": "Database/schema changes"
},
{
"name": "status:blocked",
"color": "D93F0B",
"description": "Blocked by external dependency"
},
{
"name": "status:in-review",
"color": "FBCA04",
"description": "In code review"
},
{
"name": "status:needs-info",
"color": "D876E3",
"description": "Needs more information"
},
{
"name": "status:wontfix",
"color": "FFFFFF",
"description": "Will not be addressed"
},
{
"name": "release",
"color": "0E8A16",
"description": "Trigger deployment on merge"
},
{
"name": "breaking-change",
"color": "D93F0B",
"description": "Contains breaking changes"
},
{
"name": "good-first-issue",
"color": "7057FF",
"description": "Good for newcomers"
},
{
"name": "help-wanted",
"color": "008672",
"description": "Extra attention needed"
},
{
"name": "automation",
"color": "BFDADC",
"description": "Automation or workflow changes"
},
{
"name": "automation-bug",
"color": "D93F0B",
"description": "Automation system malfunction"
}
]

View File

@@ -0,0 +1,50 @@
## What
<!-- Brief description of what this PR changes -->
## Why
<!-- Business/technical justification for these changes -->
## How
<!-- Implementation approach and key technical decisions -->
## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests pass
- [ ] Manual testing completed
- [ ] Edge cases considered
## Checklist
- [ ] Code follows project style guidelines
- [ ] Self-reviewed the code
- [ ] Commented complex/non-obvious code
- [ ] Documentation updated (if applicable)
- [ ] No new warnings introduced
- [ ] Backward compatibility maintained (or breaking changes documented)
## Screenshots/Logs
<!-- If applicable, add screenshots or relevant logs -->
## Related
- **Asana Task:** [link]
- **Salesforce Project:** [link]
- **Related Issues:** Closes #
## Deployment Notes
<!-- Any special deployment steps, migrations, or configuration changes needed -->
---
**Reviewer Checklist:**
- [ ] Code is clean and maintainable
- [ ] Tests are adequate
- [ ] No security vulnerabilities introduced
- [ ] Performance implications considered
- [ ] Documentation is clear