mirror of
https://github.com/blackboxprogramming/BlackRoad-Operating-System.git
synced 2026-03-17 05:57:21 -05:00
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:
189
sop/templates/github-actions/ci.yml
Normal file
189
sop/templates/github-actions/ci.yml
Normal 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"
|
||||
303
sop/templates/github-actions/deploy.yml
Normal file
303
sop/templates/github-actions/deploy.yml
Normal 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
|
||||
238
sop/templates/github-actions/safety.yml
Normal file
238
sop/templates/github-actions/safety.yml
Normal 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
|
||||
61
sop/templates/repo-template/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
61
sop/templates/repo-template/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal 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:** #
|
||||
114
sop/templates/repo-template/.github/ISSUE_TEMPLATE/deployment_checklist.md
vendored
Normal file
114
sop/templates/repo-template/.github/ISSUE_TEMPLATE/deployment_checklist.md
vendored
Normal 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]
|
||||
57
sop/templates/repo-template/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
57
sop/templates/repo-template/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal 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 -->
|
||||
206
sop/templates/repo-template/.github/branch-protection.md
vendored
Normal file
206
sop/templates/repo-template/.github/branch-protection.md
vendored
Normal 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)
|
||||
137
sop/templates/repo-template/.github/labels.json
vendored
Normal file
137
sop/templates/repo-template/.github/labels.json
vendored
Normal 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"
|
||||
}
|
||||
]
|
||||
50
sop/templates/repo-template/.github/pull_request_template.md
vendored
Normal file
50
sop/templates/repo-template/.github/pull_request_template.md
vendored
Normal 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
|
||||
Reference in New Issue
Block a user