@chris1807/claude-kit 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +821 -0
- package/bin/cli.js +521 -0
- package/package.json +50 -0
- package/templates/agents/global/api-tester.md +75 -0
- package/templates/agents/global/azure-ops.md +59 -0
- package/templates/agents/global/backend.md +245 -0
- package/templates/agents/global/build-validator.md +50 -0
- package/templates/agents/global/frontend.md +254 -0
- package/templates/agents/global/legacy.md +218 -0
- package/templates/agents/global/lint-checker.md +86 -0
- package/templates/agents/global/manager.md +138 -0
- package/templates/agents/global/mockup.md +95 -0
- package/templates/agents/global/reviewer.md +149 -0
- package/templates/agents/global/security-auditor.md +74 -0
- package/templates/agents/global/test-runner.md +98 -0
- package/templates/agents/global/uat-generator.md +107 -0
- package/templates/agents/project/db-admin.md +106 -0
- package/templates/agents/project/deployer.md +113 -0
- package/templates/agents/project/devops-tracker.md +101 -0
- package/templates/commands/add-to-release.md +55 -0
- package/templates/commands/cherry-pick.md +96 -0
- package/templates/commands/cleanup-branches.md +73 -0
- package/templates/commands/create-release.md +65 -0
- package/templates/commands/deploy-release.md +147 -0
- package/templates/commands/deploy.md +65 -0
- package/templates/commands/explain.md +49 -0
- package/templates/commands/implement.md +170 -0
- package/templates/commands/promote.md +71 -0
- package/templates/commands/quote.md +39 -0
- package/templates/commands/review.md +32 -0
- package/templates/commands/rework.md +158 -0
- package/templates/commands/rollback.md +106 -0
- package/templates/commands/status.md +111 -0
- package/templates/hooks/auto-format.sh +46 -0
- package/templates/hooks/protected-files.sh +52 -0
- package/templates/hooks/secret-blocker.sh +68 -0
- package/templates/hooks/self-improve.sh +7 -0
- package/templates/hooks/sensitive-data-blocker.sh +43 -0
- package/templates/hooks/sensitive-data-mcp-blocker.sh +40 -0
- package/templates/hooks/sensitive-data-output-blocker.sh +63 -0
- package/templates/hooks/test-on-change.sh +46 -0
- package/templates/hooks/uat-reminder.sh +9 -0
- package/templates/infrastructure/CLAUDE-WORKFLOW.md +274 -0
- package/templates/infrastructure/azure-pipelines-template.yml +199 -0
- package/templates/infrastructure/mcp.json +35 -0
- package/templates/infrastructure/settings.json +94 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Sensitive Data Blocker Hook (PreToolUse - Bash)
|
|
3
|
+
# Blocks database queries that reference sensitive PII fields like TIN, SSN, etc.
|
|
4
|
+
# Even encrypted values must never be exposed.
|
|
5
|
+
# Exit code 2 = BLOCK the action.
|
|
6
|
+
|
|
7
|
+
# Read the tool input from stdin
|
|
8
|
+
INPUT=$(cat)
|
|
9
|
+
|
|
10
|
+
# Extract the command being run
|
|
11
|
+
COMMAND=$(echo "$INPUT" | python3 -c "
|
|
12
|
+
import sys, json
|
|
13
|
+
try:
|
|
14
|
+
data = json.load(sys.stdin)
|
|
15
|
+
tool = data.get('tool_name', '')
|
|
16
|
+
inp = data.get('tool_input', {})
|
|
17
|
+
if tool == 'Bash':
|
|
18
|
+
print(inp.get('command', ''))
|
|
19
|
+
except:
|
|
20
|
+
pass
|
|
21
|
+
" 2>/dev/null)
|
|
22
|
+
|
|
23
|
+
if [ -z "$COMMAND" ]; then
|
|
24
|
+
exit 0
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Only check commands that interact with MongoDB
|
|
28
|
+
if ! echo "$COMMAND" | grep -qE 'mongosh|mongo '; then
|
|
29
|
+
exit 0
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Case-insensitive check for sensitive field names in the query
|
|
33
|
+
SENSITIVE_PATTERN='\b(TIN|Tin|TaxId|TaxIdentificationNumber|EIN|SSN|SocialSecurityNumber|Social|EncryptedTin|EncryptedSSN|EncryptedTaxId|BankAccountNumber|AccountNumber|RoutingNumber)\b'
|
|
34
|
+
|
|
35
|
+
if echo "$COMMAND" | grep -qE "$SENSITIVE_PATTERN"; then
|
|
36
|
+
echo "BLOCKED: Database query references a sensitive PII field (TIN, SSN, bank account, etc.)"
|
|
37
|
+
echo "These fields contain encrypted sensitive data that must never be queried or displayed."
|
|
38
|
+
echo "Use explicit inclusion projections with only non-sensitive fields."
|
|
39
|
+
echo "If you need to work with this data, use the application UI instead."
|
|
40
|
+
exit 2
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
exit 0
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Sensitive Data MCP Blocker Hook (PreToolUse - MCP MongoDB/MSSQL/Postgres tools)
|
|
3
|
+
# Blocks MCP database tool calls that reference sensitive PII fields.
|
|
4
|
+
# Even encrypted values must never be exposed.
|
|
5
|
+
# Exit code 2 = BLOCK the action.
|
|
6
|
+
|
|
7
|
+
# Read the tool input from stdin
|
|
8
|
+
INPUT=$(cat)
|
|
9
|
+
|
|
10
|
+
# Extract tool name and full input JSON
|
|
11
|
+
TOOL_INFO=$(echo "$INPUT" | python3 -c "
|
|
12
|
+
import sys, json
|
|
13
|
+
try:
|
|
14
|
+
data = json.load(sys.stdin)
|
|
15
|
+
tool = data.get('tool_name', '')
|
|
16
|
+
inp = json.dumps(data.get('tool_input', {}))
|
|
17
|
+
print(f'{tool}\n{inp}')
|
|
18
|
+
except:
|
|
19
|
+
pass
|
|
20
|
+
" 2>/dev/null)
|
|
21
|
+
|
|
22
|
+
TOOL_NAME=$(echo "$TOOL_INFO" | head -1)
|
|
23
|
+
TOOL_INPUT=$(echo "$TOOL_INFO" | tail -1)
|
|
24
|
+
|
|
25
|
+
if [ -z "$TOOL_NAME" ]; then
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# Case-insensitive check for sensitive field names anywhere in the tool input
|
|
30
|
+
SENSITIVE_PATTERN='\b(TIN|Tin|TaxId|TaxIdentificationNumber|EIN|SSN|SocialSecurityNumber|Social|EncryptedTin|EncryptedSSN|EncryptedTaxId|BankAccountNumber|AccountNumber|RoutingNumber)\b'
|
|
31
|
+
|
|
32
|
+
if echo "$TOOL_INPUT" | grep -qE "$SENSITIVE_PATTERN"; then
|
|
33
|
+
echo "BLOCKED: MCP database query references a sensitive PII field (TIN, SSN, bank account, etc.)"
|
|
34
|
+
echo "These fields contain encrypted sensitive data that must never be queried or displayed."
|
|
35
|
+
echo "Use explicit inclusion projections with only non-sensitive fields."
|
|
36
|
+
echo "If you need to work with this data, use the application UI instead."
|
|
37
|
+
exit 2
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
exit 0
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Sensitive Data Output Blocker Hook (PostToolUse - Bash, Read, Grep, MCP DB tools)
|
|
3
|
+
# Scans tool output for sensitive PII field names that may have been returned
|
|
4
|
+
# by broad database queries, file reads of seed/dump data, or grep results.
|
|
5
|
+
# Exit code 2 = BLOCK (prevents the output from being used).
|
|
6
|
+
|
|
7
|
+
# Read the tool result from stdin
|
|
8
|
+
INPUT=$(cat)
|
|
9
|
+
|
|
10
|
+
# Extract output from any tool type (Bash stdout, Read content, Grep results, MCP results)
|
|
11
|
+
OUTPUT=$(echo "$INPUT" | python3 -c "
|
|
12
|
+
import sys, json
|
|
13
|
+
try:
|
|
14
|
+
data = json.load(sys.stdin)
|
|
15
|
+
tool = data.get('tool_name', '')
|
|
16
|
+
result = data.get('tool_result', '')
|
|
17
|
+
|
|
18
|
+
# Handle different result shapes
|
|
19
|
+
if isinstance(result, dict):
|
|
20
|
+
# Bash tool: check stdout
|
|
21
|
+
text = result.get('stdout', '')
|
|
22
|
+
# MCP/other tools: check content or stringify the whole result
|
|
23
|
+
if not text:
|
|
24
|
+
text = result.get('content', '')
|
|
25
|
+
if not text:
|
|
26
|
+
text = json.dumps(result)
|
|
27
|
+
elif isinstance(result, str):
|
|
28
|
+
text = result
|
|
29
|
+
else:
|
|
30
|
+
text = str(result)
|
|
31
|
+
|
|
32
|
+
print(text)
|
|
33
|
+
except:
|
|
34
|
+
pass
|
|
35
|
+
" 2>/dev/null)
|
|
36
|
+
|
|
37
|
+
if [ -z "$OUTPUT" ]; then
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Check if output contains sensitive field names as keys (indicating PII was returned)
|
|
42
|
+
# These patterns match field names in JSON documents, MongoDB output, C# properties, etc.
|
|
43
|
+
SENSITIVE_PATTERNS=(
|
|
44
|
+
# JSON/MongoDB style: "TIN": or 'TIN':
|
|
45
|
+
'"(TIN|Tin|TaxId|TaxIdentificationNumber|EIN|SSN|SocialSecurityNumber|EncryptedTin|EncryptedSSN|EncryptedTaxId|BankAccountNumber|AccountNumber|RoutingNumber)"\s*:'
|
|
46
|
+
# C# property style: .TIN = or .TaxId =
|
|
47
|
+
'\.(TIN|TaxId|TaxIdentificationNumber|EIN|SSN|SocialSecurityNumber|EncryptedTin|EncryptedSSN|EncryptedTaxId|BankAccountNumber|AccountNumber|RoutingNumber)\s*='
|
|
48
|
+
# YAML/config style: TIN: (start of line or after whitespace)
|
|
49
|
+
'(^|\s)(TIN|TaxId|TaxIdentificationNumber|EIN|SSN|SocialSecurityNumber|EncryptedTin|EncryptedSSN|EncryptedTaxId|BankAccountNumber|AccountNumber|RoutingNumber):\s'
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
for PATTERN in "${SENSITIVE_PATTERNS[@]}"; do
|
|
53
|
+
if echo "$OUTPUT" | grep -qE "$PATTERN"; then
|
|
54
|
+
echo "BLOCKED: Output contains sensitive PII fields (TIN, SSN, bank account, etc.)"
|
|
55
|
+
echo "The output includes documents or data with sensitive fields."
|
|
56
|
+
echo "For database queries: use an explicit inclusion projection listing only non-sensitive fields."
|
|
57
|
+
echo "For code searches: avoid reading seed data, test fixtures, or dump files containing PII."
|
|
58
|
+
echo "If you need to work with this data, use the application UI instead."
|
|
59
|
+
exit 2
|
|
60
|
+
fi
|
|
61
|
+
done
|
|
62
|
+
|
|
63
|
+
exit 0
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Test Runner Hook (PostToolUse - Edit/Write)
|
|
3
|
+
# Suggests running related tests when source files are modified.
|
|
4
|
+
# Does NOT auto-run tests (too slow) — just reminds which tests to run.
|
|
5
|
+
|
|
6
|
+
INPUT=$(cat)
|
|
7
|
+
|
|
8
|
+
FILE_PATH=$(echo "$INPUT" | python3 -c "
|
|
9
|
+
import sys, json
|
|
10
|
+
try:
|
|
11
|
+
data = json.load(sys.stdin)
|
|
12
|
+
inp = data.get('tool_input', {})
|
|
13
|
+
print(inp.get('file_path', ''))
|
|
14
|
+
except:
|
|
15
|
+
pass
|
|
16
|
+
" 2>/dev/null)
|
|
17
|
+
|
|
18
|
+
if [ -z "$FILE_PATH" ]; then
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
EXT="${FILE_PATH##*.}"
|
|
23
|
+
|
|
24
|
+
# Only suggest for source files, not tests or configs
|
|
25
|
+
if echo "$FILE_PATH" | grep -qE '(Test|test|spec|__tests__)'; then
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
case "$EXT" in
|
|
30
|
+
cs)
|
|
31
|
+
if echo "$FILE_PATH" | grep -q "Glasswing"; then
|
|
32
|
+
echo "Run: dotnet test src/Glasswing.Tests/ --filter \"$(basename ${FILE_PATH%.cs})\""
|
|
33
|
+
elif echo "$FILE_PATH" | grep -q "Monarch"; then
|
|
34
|
+
echo "Run: dotnet test src/Monarch.Tests/ --filter \"$(basename ${FILE_PATH%.cs})\""
|
|
35
|
+
fi
|
|
36
|
+
;;
|
|
37
|
+
ts|tsx)
|
|
38
|
+
if echo "$FILE_PATH" | grep -q "glasswing-client"; then
|
|
39
|
+
echo "Run: cd src/glasswing-client && npx vitest run --reporter=verbose"
|
|
40
|
+
elif echo "$FILE_PATH" | grep -q "monarch-client"; then
|
|
41
|
+
echo "Run: cd src/monarch-client && npx vitest run --reporter=verbose"
|
|
42
|
+
fi
|
|
43
|
+
;;
|
|
44
|
+
esac
|
|
45
|
+
|
|
46
|
+
exit 0
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# UAT Reminder Hook for Glasswing-and-Monarch
|
|
3
|
+
# Fires on the Stop event to remind about UAT after feature implementation
|
|
4
|
+
#
|
|
5
|
+
# This checks if recent conversation context suggests a feature was being
|
|
6
|
+
# implemented and reminds the user to run UAT before marking it complete.
|
|
7
|
+
|
|
8
|
+
echo "Reminder: If you just completed a feature implementation, run UAT before marking it done."
|
|
9
|
+
echo "Use: 'Use gm-uat-generator to create UAT checklist for [Feature ID]'"
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
|
|
2
|
+
## Claude Kit Workflow
|
|
3
|
+
|
|
4
|
+
This project uses [Claude Kit](https://github.com/Christopher-Waters/claude-kit) — a standardized set of agents, hooks, MCP servers, and workflows installed via `npx @chris1807/claude-kit init`.
|
|
5
|
+
|
|
6
|
+
### Agent Pipeline
|
|
7
|
+
|
|
8
|
+
When given a task, Claude Code can delegate through specialized agents:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
You (give task)
|
|
12
|
+
├── manager → orchestrates workflow, delegates to agents below
|
|
13
|
+
├── Explore → finds relevant files
|
|
14
|
+
├── Plan → designs the approach
|
|
15
|
+
├── mockup → creates HTML screen mockups before implementation
|
|
16
|
+
├── backend / frontend / legacy → implements code
|
|
17
|
+
├── deployer → commits, pushes, triggers CD pipeline
|
|
18
|
+
├── db-admin → queries/fixes MongoDB data
|
|
19
|
+
├── devops-tracker → creates/updates Azure DevOps work items
|
|
20
|
+
├── test-runner → runs xUnit, Vitest, Playwright tests
|
|
21
|
+
├── build-validator → confirms builds pass
|
|
22
|
+
├── lint-checker → runs ESLint and dotnet format
|
|
23
|
+
├── uat-generator → generates UAT checklists from requirements
|
|
24
|
+
├── security-auditor → scans for secrets, vulnerabilities
|
|
25
|
+
├── api-tester → tests API endpoints with curl
|
|
26
|
+
├── azure-ops → manages Azure infrastructure
|
|
27
|
+
└── reviewer → reviews code quality
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Sensitive Data Policy
|
|
31
|
+
|
|
32
|
+
**NEVER query, display, or expose sensitive PII fields from the database — even if the values are encrypted.** This includes TIN, SSN, EIN, TaxId, BankAccountNumber, RoutingNumber, and any `Encrypted*` variants. Even encrypted/hashed values must not appear in output, logs, or summaries. When querying collections that may contain sensitive fields, always use explicit inclusion projections listing only the non-sensitive fields needed. If a user requests access to sensitive data, direct them to use the application UI.
|
|
33
|
+
|
|
34
|
+
### Automated Hooks
|
|
35
|
+
|
|
36
|
+
These run automatically — no action needed:
|
|
37
|
+
|
|
38
|
+
| When | What Happens |
|
|
39
|
+
|------|-------------|
|
|
40
|
+
| **Before any Bash command** | Sensitive data blocker prevents database queries that reference TIN, SSN, or other PII fields |
|
|
41
|
+
| **Before any MCP database tool** | Sensitive data MCP blocker prevents MCP database queries that reference PII fields |
|
|
42
|
+
| **After any Bash/MCP/Read/Grep command** | Sensitive data output blocker scans results for PII field names and blocks exposure |
|
|
43
|
+
| **Before any file write** | Secret blocker scans for hardcoded credentials and blocks them |
|
|
44
|
+
| **Before any file edit** | Protected files guard warns/blocks edits to production configs |
|
|
45
|
+
| **After any file edit** | Auto-formatter runs (dotnet format for .cs, eslint --fix for .ts) |
|
|
46
|
+
| **After any file edit** | Test suggestions appear for related test files |
|
|
47
|
+
| **When Claude stops** | UAT reminder if a feature was implemented |
|
|
48
|
+
| **When Claude stops** | Self-improvement prompt to save learnings to memory |
|
|
49
|
+
|
|
50
|
+
### MCP Servers Available
|
|
51
|
+
|
|
52
|
+
| Server | What It Does |
|
|
53
|
+
|--------|-------------|
|
|
54
|
+
| **Azure DevOps** | Work items, pipelines, repos, wiki |
|
|
55
|
+
| **Playwright** | Browser testing (navigate, click, fill, screenshot) |
|
|
56
|
+
| **MongoDB** | Direct database queries and updates |
|
|
57
|
+
| **Microsoft Teams** | Send/read team messages and notifications |
|
|
58
|
+
| **Stripe** | Payment management (when configured) |
|
|
59
|
+
| **Azure** | 40+ Azure services via CLI |
|
|
60
|
+
|
|
61
|
+
### Memory System
|
|
62
|
+
|
|
63
|
+
Claude maintains persistent memory across sessions in `~/.claude/projects/.../memory/`. This includes:
|
|
64
|
+
- **User preferences** — how you like to work
|
|
65
|
+
- **Feedback patterns** — what to do and what to avoid (self-improving)
|
|
66
|
+
- **Project context** — decisions, priorities, blockers
|
|
67
|
+
- **References** — URLs, test accounts, external resources
|
|
68
|
+
|
|
69
|
+
### Development Workflow
|
|
70
|
+
|
|
71
|
+
1. **Pick a work item** from Azure DevOps (or describe what you need)
|
|
72
|
+
2. **Claude implements** using `/implement AB#<id>` (auto-creates branch)
|
|
73
|
+
3. **Hooks guard** against secrets and bad patterns automatically
|
|
74
|
+
4. **PR merges** into `develop` → deploys to Dev environment
|
|
75
|
+
5. **Create a release** using `/create-release <N>` to group work items
|
|
76
|
+
6. **Deploy the release** using `/deploy-release 23 staging` then `/deploy-release 23 production`
|
|
77
|
+
7. **Test** using Playwright MCP for browser testing
|
|
78
|
+
8. **Track** work items using the devops-tracker agent
|
|
79
|
+
9. **Learn** — Claude saves what worked for next time
|
|
80
|
+
|
|
81
|
+
### Branching Strategy
|
|
82
|
+
|
|
83
|
+
#### Target Branch-to-Environment Mapping
|
|
84
|
+
|
|
85
|
+
All projects should converge to this standard. Each long-lived branch maps to an Azure subscription and environment:
|
|
86
|
+
|
|
87
|
+
| Branch | Azure Subscription | Environment | CD Pipeline Trigger |
|
|
88
|
+
|---|---|---|---|
|
|
89
|
+
| `develop` | Dev | Development | Auto on merge |
|
|
90
|
+
| `staging` | Staging | Staging | Auto on merge |
|
|
91
|
+
| `main` | Production | Production | Auto on merge (with approval gate) |
|
|
92
|
+
|
|
93
|
+
> **Note:** Some projects are not yet in sync — they may use `master` instead of `main`, or lack a `staging` branch. Until a project is migrated, the deployer and `/implement` use the **current branch** dynamically and do not assume branch names.
|
|
94
|
+
|
|
95
|
+
#### Promotion Flow
|
|
96
|
+
|
|
97
|
+
Code flows through environments via PRs — never by direct push:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
feature/AB#1234-... ──PR──▸ develop ──PR──▸ staging ──PR──▸ main
|
|
101
|
+
(work branch) (Dev) (Staging) (Production)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- **develop → staging**: PR to promote all work ready for QA/stakeholder review
|
|
105
|
+
- **staging → main**: PR to promote to production. May cherry-pick individual commits if only some stories are ready (see Cherry-Pick Deployments below)
|
|
106
|
+
|
|
107
|
+
#### Release Management
|
|
108
|
+
|
|
109
|
+
Releases group work items together for coordinated deployment across environments. Releases are tracked in Azure DevOps as iterations (`Release #N`) and work items are tagged with `release-{N}`.
|
|
110
|
+
|
|
111
|
+
**Creating a release:**
|
|
112
|
+
```
|
|
113
|
+
/create-release 23
|
|
114
|
+
```
|
|
115
|
+
This creates a `Release #23` iteration, assigns the selected work items to it, and tags them with `release-23`.
|
|
116
|
+
|
|
117
|
+
**Deploying a release to an environment:**
|
|
118
|
+
```
|
|
119
|
+
/deploy-release 23 staging
|
|
120
|
+
/deploy-release 23 production
|
|
121
|
+
```
|
|
122
|
+
This finds all work items in Release #23, cherry-picks their commits into a release branch (`release/23-to-staging`), creates a PR targeting the environment branch, and links all work items.
|
|
123
|
+
|
|
124
|
+
**Selective deployment:** Since releases are deployed via cherry-pick, you can deploy a full release or a subset. If staging has 5 user stories but only 3 should go to production, create a release with just those 3 and deploy it.
|
|
125
|
+
|
|
126
|
+
**Release flow:**
|
|
127
|
+
```
|
|
128
|
+
/create-release 23 → Groups work items into Release #23
|
|
129
|
+
/deploy-release 23 staging → Cherry-picks Release #23 to staging
|
|
130
|
+
(QA/testing on staging)
|
|
131
|
+
/deploy-release 23 → Auto-detects next env (production), deploys
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### Cherry-Pick Deployments
|
|
135
|
+
|
|
136
|
+
Cherry-pick specific work items to an environment without a formal release:
|
|
137
|
+
```
|
|
138
|
+
/cherry-pick AB#1234 AB#1235 production
|
|
139
|
+
```
|
|
140
|
+
This finds commits for the specified work items, cherry-picks them into a branch (`cherry-pick/<date>-to-<environment>`), and creates a PR.
|
|
141
|
+
|
|
142
|
+
#### Promoting Environments
|
|
143
|
+
|
|
144
|
+
Promote all code from one environment to the next:
|
|
145
|
+
```
|
|
146
|
+
/promote staging production
|
|
147
|
+
/promote ← auto-detects source and target from current branch
|
|
148
|
+
```
|
|
149
|
+
This creates a PR from the source branch to the target branch with a summary of all included commits.
|
|
150
|
+
|
|
151
|
+
#### Rollbacks
|
|
152
|
+
|
|
153
|
+
Roll back a deployment on any environment:
|
|
154
|
+
```
|
|
155
|
+
/rollback AB#1234 production ← revert specific work items
|
|
156
|
+
/rollback last staging ← revert the most recent deployment
|
|
157
|
+
```
|
|
158
|
+
This creates a revert branch, reverts the specified commits, runs pre-flight checks, and creates a PR.
|
|
159
|
+
|
|
160
|
+
For emergency production rollbacks, the `/rollback` command already runs pre-flight checks and skips UAT. Treat the resulting PR as urgent and flag the user accordingly.
|
|
161
|
+
|
|
162
|
+
#### Deploying Changes
|
|
163
|
+
|
|
164
|
+
Commit, push, and deploy the current changes:
|
|
165
|
+
```
|
|
166
|
+
/deploy "Add payment export feature"
|
|
167
|
+
/deploy ← auto-generates commit message
|
|
168
|
+
```
|
|
169
|
+
This runs pre-flight checks, commits, pushes the current branch, and triggers the CD pipeline if on an environment branch.
|
|
170
|
+
|
|
171
|
+
#### Branch Naming Convention
|
|
172
|
+
|
|
173
|
+
When `/implement AB#<id>` is run, a branch is created off the current branch based on the Azure DevOps work item type:
|
|
174
|
+
|
|
175
|
+
| Work Item Type | Branch Prefix | Example |
|
|
176
|
+
|---|---|---|
|
|
177
|
+
| Feature | `feature/` | `feature/AB#1234-add-payment-export` |
|
|
178
|
+
| User Story | `story/` | `story/AB#1235-user-can-view-history` |
|
|
179
|
+
| Bug | `bugfix/` | `bugfix/AB#1236-fix-login-redirect` |
|
|
180
|
+
| Hot Fix | `hotfix/` | `hotfix/AB#1237-fix-crash-on-submit` |
|
|
181
|
+
| (other) | `work/` | `work/AB#1238-update-dependencies` |
|
|
182
|
+
|
|
183
|
+
Format: `{prefix}AB#{id}-{sanitized-title}` (title lowercased, special chars replaced with hyphens, max 50 chars)
|
|
184
|
+
|
|
185
|
+
> **Note:** The Azure DevOps work item type is "Hot Fix" (two words), but the branch prefix and PR label use `hotfix` (one word, lowercase).
|
|
186
|
+
|
|
187
|
+
#### PR Targeting
|
|
188
|
+
|
|
189
|
+
PRs always target the branch you were on when `/implement` was invoked. The base branch is captured dynamically at the start — no assumptions about branch names.
|
|
190
|
+
|
|
191
|
+
#### Hot Fix Workflow
|
|
192
|
+
|
|
193
|
+
Hot Fix work items follow the same automated checks (build, lint, tests, review) but skip manual UAT. An abbreviated confirmation is shown instead. Hot Fix PRs get a `hotfix` label. Hot Fixes target the current branch (which should be the project's production branch for production hot fixes).
|
|
194
|
+
|
|
195
|
+
#### Slash Commands Reference
|
|
196
|
+
|
|
197
|
+
All deployment and release operations are available as slash commands:
|
|
198
|
+
|
|
199
|
+
| Command | Usage | What It Does |
|
|
200
|
+
|---|---|---|
|
|
201
|
+
| `/implement` | `/implement AB#1234` | Summarize work item → approve plan → implement → PR |
|
|
202
|
+
| `/review` | `/review 142` | Automated code review on a PR |
|
|
203
|
+
| `/deploy` | `/deploy "commit message"` | Commit, push, trigger pipeline |
|
|
204
|
+
| `/create-release` | `/create-release 23` | Group work items into Release #23 |
|
|
205
|
+
| `/deploy-release` | `/deploy-release 23 staging` | Cherry-pick release to environment |
|
|
206
|
+
| `/add-to-release` | `/add-to-release 24 AB#4599` | Add work items to existing release |
|
|
207
|
+
| `/cherry-pick` | `/cherry-pick AB#1234 AB#1235 production` | Cherry-pick specific work items |
|
|
208
|
+
| `/promote` | `/promote staging production` | Promote all code between environments |
|
|
209
|
+
| `/rollback` | `/rollback AB#1234 production` | Revert commits on an environment |
|
|
210
|
+
| `/status` | `/status release 24` | Check release, pipeline, or work item status |
|
|
211
|
+
| `/cleanup-branches` | `/cleanup-branches` | Delete merged branches |
|
|
212
|
+
|
|
213
|
+
The CD pipeline is only triggered manually when pushing directly to an environment branch. For feature/work branches, the pipeline triggers on PR merge.
|
|
214
|
+
|
|
215
|
+
### Pipeline Configuration
|
|
216
|
+
|
|
217
|
+
Each project must define its environment chain and pipeline IDs so the slash commands (`/deploy`, `/promote`, `/deploy-release`) know which pipelines to trigger and what the promotion order is.
|
|
218
|
+
|
|
219
|
+
Add this section to your project's `CLAUDE.md`:
|
|
220
|
+
|
|
221
|
+
```markdown
|
|
222
|
+
## Pipeline Configuration
|
|
223
|
+
|
|
224
|
+
| Branch | Environment | Pipeline(s) |
|
|
225
|
+
|--------|------------|-------------|
|
|
226
|
+
| develop | Dev | My API (ID), My Client (ID) |
|
|
227
|
+
| staging | Staging | My API (ID), My Client (ID) |
|
|
228
|
+
| main | Production | My API (ID), My Client (ID) |
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Rules for slash commands:**
|
|
232
|
+
- `/deploy` triggers the pipeline(s) listed for the current branch. If the current branch is not in this table, no pipeline is triggered.
|
|
233
|
+
- `/promote` uses this table to determine the next environment (e.g., `develop` → `staging` → `main`).
|
|
234
|
+
- `/deploy-release` and `/cherry-pick` create PRs targeting environment branches listed here.
|
|
235
|
+
- The **order of rows** defines the promotion flow (top to bottom).
|
|
236
|
+
|
|
237
|
+
**Examples from actual projects:**
|
|
238
|
+
|
|
239
|
+
CSIPay (4 environments):
|
|
240
|
+
```markdown
|
|
241
|
+
| Branch | Environment | Pipeline(s) |
|
|
242
|
+
|--------|------------|-------------|
|
|
243
|
+
| Dev | Dev | CSIPay API (12), CSIPay Client (13) |
|
|
244
|
+
| QA | QA | CSIPay API (12), CSIPay Client (13) |
|
|
245
|
+
| Staging | Staging | CSIPay API (12), CSIPay Client (13) |
|
|
246
|
+
| master | Production | CSIPay API (12), CSIPay Client (13) |
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Glasswing and Monarch (1 environment currently):
|
|
250
|
+
```markdown
|
|
251
|
+
| Branch | Environment | Pipeline(s) |
|
|
252
|
+
|--------|------------|-------------|
|
|
253
|
+
| develop | Dev | CD - Development (28) |
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Environment Setup
|
|
257
|
+
|
|
258
|
+
Each team member needs to set their own environment variables (never commit these):
|
|
259
|
+
|
|
260
|
+
```bash
|
|
261
|
+
# MongoDB (required for db-admin agent)
|
|
262
|
+
export MONGODB_CONNECTION_STRING="mongodb+srv://..."
|
|
263
|
+
|
|
264
|
+
# Microsoft Teams (required for team notifications)
|
|
265
|
+
export TEAMS_TENANT_ID="..."
|
|
266
|
+
export TEAMS_CLIENT_ID="..."
|
|
267
|
+
export TEAMS_CLIENT_SECRET="..."
|
|
268
|
+
|
|
269
|
+
# Stripe (required when payment integration is active)
|
|
270
|
+
export STRIPE_SECRET_KEY="sk_test_..."
|
|
271
|
+
|
|
272
|
+
# Azure (use az login instead of env vars)
|
|
273
|
+
az login
|
|
274
|
+
```
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Standard Azure DevOps Pipeline Template (example)
|
|
2
|
+
#
|
|
3
|
+
# Multi-stage YAML pipeline that builds once and deploys to the correct
|
|
4
|
+
# environment based on the source branch.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# 1. Copy this file to your project root as azure-pipelines.yml
|
|
8
|
+
# 2. Replace all {{PLACEHOLDER}} values with your project-specific values
|
|
9
|
+
# 3. Remove stages you don't need (e.g., QA if your project doesn't have it)
|
|
10
|
+
# 4. Create a new pipeline in Azure DevOps pointing to this file
|
|
11
|
+
#
|
|
12
|
+
# Branch-to-environment mapping:
|
|
13
|
+
# develop → Dev
|
|
14
|
+
# staging → Staging
|
|
15
|
+
# main → Production
|
|
16
|
+
|
|
17
|
+
trigger:
|
|
18
|
+
branches:
|
|
19
|
+
include:
|
|
20
|
+
- develop
|
|
21
|
+
- staging
|
|
22
|
+
- main
|
|
23
|
+
paths:
|
|
24
|
+
include:
|
|
25
|
+
- "{{PROJECT_PATH}}/**" # e.g., Api/**, Client/**, src/**
|
|
26
|
+
|
|
27
|
+
pool:
|
|
28
|
+
vmImage: "windows-latest" # Use "ubuntu-latest" for Linux-based builds
|
|
29
|
+
|
|
30
|
+
variables:
|
|
31
|
+
buildConfiguration: "Release"
|
|
32
|
+
projectName: "{{PROJECT_NAME}}" # e.g., CompassAPI, CSIPayAPI
|
|
33
|
+
solutionFile: "{{SOLUTION_FILE}}" # e.g., CompassPOC.sln, CSIPay.sln
|
|
34
|
+
WebsitePhysicalPath: "{{PHYSICAL_PATH}}" # e.g., F:\Compass\Api
|
|
35
|
+
|
|
36
|
+
# Dev environment
|
|
37
|
+
devWebsiteName: "{{DEV_WEBSITE_NAME}}" # e.g., dev.api.compass.caresolutions.com
|
|
38
|
+
devAppPoolName: "{{DEV_APP_POOL}}" # e.g., dev.api.compass.com
|
|
39
|
+
|
|
40
|
+
# Staging environment
|
|
41
|
+
stagingWebsiteName: "{{STAGING_WEBSITE_NAME}}" # e.g., staging.api.compass.caresolutions.com
|
|
42
|
+
stagingAppPoolName: "{{STAGING_APP_POOL}}" # e.g., staging.api.compass.com
|
|
43
|
+
|
|
44
|
+
# Production environment
|
|
45
|
+
prodWebsiteName: "{{PROD_WEBSITE_NAME}}" # e.g., api.compass.caresolutions.com
|
|
46
|
+
prodAppPoolName: "{{PROD_APP_POOL}}" # e.g., api.compass.com
|
|
47
|
+
|
|
48
|
+
stages:
|
|
49
|
+
# ── Build ──────────────────────────────────────────────
|
|
50
|
+
- stage: Build
|
|
51
|
+
displayName: "Build"
|
|
52
|
+
jobs:
|
|
53
|
+
- job: BuildJob
|
|
54
|
+
displayName: "Build and Publish"
|
|
55
|
+
steps:
|
|
56
|
+
- script: |
|
|
57
|
+
dotnet build $(solutionFile) --configuration $(buildConfiguration)
|
|
58
|
+
dotnet publish $(solutionFile) --configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)
|
|
59
|
+
displayName: "dotnet build and publish"
|
|
60
|
+
|
|
61
|
+
- task: ArchiveFiles@2
|
|
62
|
+
displayName: "Zip Published Files"
|
|
63
|
+
inputs:
|
|
64
|
+
rootFolderOrFile: "$(Build.ArtifactStagingDirectory)"
|
|
65
|
+
includeRootFolder: false
|
|
66
|
+
archiveType: "zip"
|
|
67
|
+
archiveFile: "$(Build.ArtifactStagingDirectory)/$(projectName).zip"
|
|
68
|
+
|
|
69
|
+
- publish: $(Build.ArtifactStagingDirectory)/$(projectName).zip
|
|
70
|
+
artifact: drop
|
|
71
|
+
|
|
72
|
+
# ── Dev ────────────────────────────────────────────────
|
|
73
|
+
- stage: Dev
|
|
74
|
+
displayName: "Deploy to Dev"
|
|
75
|
+
dependsOn: "Build"
|
|
76
|
+
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop'))
|
|
77
|
+
jobs:
|
|
78
|
+
- deployment: DeployDev
|
|
79
|
+
displayName: "Deploy to Dev"
|
|
80
|
+
environment:
|
|
81
|
+
name: "{{DEV_ENVIRONMENT_NAME}}" # e.g., Dev
|
|
82
|
+
resourceType: VirtualMachine
|
|
83
|
+
strategy:
|
|
84
|
+
runOnce:
|
|
85
|
+
deploy:
|
|
86
|
+
steps:
|
|
87
|
+
- task: DownloadPipelineArtifact@2
|
|
88
|
+
inputs:
|
|
89
|
+
artifact: "drop"
|
|
90
|
+
path: "$(Build.ArtifactStagingDirectory)"
|
|
91
|
+
|
|
92
|
+
- task: IISWebAppManagementOnMachineGroup@0
|
|
93
|
+
displayName: "Configure IIS"
|
|
94
|
+
inputs:
|
|
95
|
+
IISDeploymentType: "IISWebsite"
|
|
96
|
+
ActionIISWebsite: "CreateOrUpdateWebsite"
|
|
97
|
+
WebsiteName: "$(devWebsiteName)"
|
|
98
|
+
WebsitePhysicalPath: "$(WebsitePhysicalPath)"
|
|
99
|
+
WebsitePhysicalPathAuth: "WebsiteUserPassThrough"
|
|
100
|
+
AddBinding: false
|
|
101
|
+
CreateOrUpdateAppPoolForWebsite: true
|
|
102
|
+
AppPoolNameForWebsite: "$(devAppPoolName)"
|
|
103
|
+
DotNetVersionForWebsite: "No Managed Code"
|
|
104
|
+
PipeLineModeForWebsite: "Integrated"
|
|
105
|
+
AppPoolIdentityForWebsite: "ApplicationPoolIdentity"
|
|
106
|
+
|
|
107
|
+
- task: IISWebAppDeploymentOnMachineGroup@0
|
|
108
|
+
displayName: "Deploy to IIS"
|
|
109
|
+
inputs:
|
|
110
|
+
WebsiteName: "$(devWebsiteName)"
|
|
111
|
+
Package: "$(Build.ArtifactStagingDirectory)/$(projectName).zip"
|
|
112
|
+
TakeAppOfflineFlag: true
|
|
113
|
+
XmlVariableSubstitution: true
|
|
114
|
+
|
|
115
|
+
# ── Staging ────────────────────────────────────────────
|
|
116
|
+
- stage: Staging
|
|
117
|
+
displayName: "Deploy to Staging"
|
|
118
|
+
dependsOn: "Build"
|
|
119
|
+
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/staging'))
|
|
120
|
+
jobs:
|
|
121
|
+
- deployment: DeployStaging
|
|
122
|
+
displayName: "Deploy to Staging"
|
|
123
|
+
environment:
|
|
124
|
+
name: "{{STAGING_ENVIRONMENT_NAME}}" # e.g., Staging
|
|
125
|
+
resourceType: VirtualMachine
|
|
126
|
+
strategy:
|
|
127
|
+
runOnce:
|
|
128
|
+
deploy:
|
|
129
|
+
steps:
|
|
130
|
+
- task: DownloadPipelineArtifact@2
|
|
131
|
+
inputs:
|
|
132
|
+
artifact: "drop"
|
|
133
|
+
path: "$(Build.ArtifactStagingDirectory)"
|
|
134
|
+
|
|
135
|
+
- task: IISWebAppManagementOnMachineGroup@0
|
|
136
|
+
displayName: "Configure IIS"
|
|
137
|
+
inputs:
|
|
138
|
+
IISDeploymentType: "IISWebsite"
|
|
139
|
+
ActionIISWebsite: "CreateOrUpdateWebsite"
|
|
140
|
+
WebsiteName: "$(stagingWebsiteName)"
|
|
141
|
+
WebsitePhysicalPath: "$(WebsitePhysicalPath)"
|
|
142
|
+
WebsitePhysicalPathAuth: "WebsiteUserPassThrough"
|
|
143
|
+
AddBinding: false
|
|
144
|
+
CreateOrUpdateAppPoolForWebsite: true
|
|
145
|
+
AppPoolNameForWebsite: "$(stagingAppPoolName)"
|
|
146
|
+
DotNetVersionForWebsite: "No Managed Code"
|
|
147
|
+
PipeLineModeForWebsite: "Integrated"
|
|
148
|
+
AppPoolIdentityForWebsite: "ApplicationPoolIdentity"
|
|
149
|
+
|
|
150
|
+
- task: IISWebAppDeploymentOnMachineGroup@0
|
|
151
|
+
displayName: "Deploy to IIS"
|
|
152
|
+
inputs:
|
|
153
|
+
WebsiteName: "$(stagingWebsiteName)"
|
|
154
|
+
Package: "$(Build.ArtifactStagingDirectory)/$(projectName).zip"
|
|
155
|
+
TakeAppOfflineFlag: true
|
|
156
|
+
XmlVariableSubstitution: true
|
|
157
|
+
|
|
158
|
+
# ── Production ─────────────────────────────────────────
|
|
159
|
+
- stage: Production
|
|
160
|
+
displayName: "Deploy to Production"
|
|
161
|
+
dependsOn: "Build"
|
|
162
|
+
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
|
|
163
|
+
jobs:
|
|
164
|
+
- deployment: DeployProd
|
|
165
|
+
displayName: "Deploy to Production"
|
|
166
|
+
environment:
|
|
167
|
+
name: "{{PROD_ENVIRONMENT_NAME}}" # e.g., Production
|
|
168
|
+
resourceType: VirtualMachine
|
|
169
|
+
strategy:
|
|
170
|
+
runOnce:
|
|
171
|
+
deploy:
|
|
172
|
+
steps:
|
|
173
|
+
- task: DownloadPipelineArtifact@2
|
|
174
|
+
inputs:
|
|
175
|
+
artifact: "drop"
|
|
176
|
+
path: "$(Build.ArtifactStagingDirectory)"
|
|
177
|
+
|
|
178
|
+
- task: IISWebAppManagementOnMachineGroup@0
|
|
179
|
+
displayName: "Configure IIS"
|
|
180
|
+
inputs:
|
|
181
|
+
IISDeploymentType: "IISWebsite"
|
|
182
|
+
ActionIISWebsite: "CreateOrUpdateWebsite"
|
|
183
|
+
WebsiteName: "$(prodWebsiteName)"
|
|
184
|
+
WebsitePhysicalPath: "$(WebsitePhysicalPath)"
|
|
185
|
+
WebsitePhysicalPathAuth: "WebsiteUserPassThrough"
|
|
186
|
+
AddBinding: false
|
|
187
|
+
CreateOrUpdateAppPoolForWebsite: true
|
|
188
|
+
AppPoolNameForWebsite: "$(prodAppPoolName)"
|
|
189
|
+
DotNetVersionForWebsite: "No Managed Code"
|
|
190
|
+
PipeLineModeForWebsite: "Integrated"
|
|
191
|
+
AppPoolIdentityForWebsite: "ApplicationPoolIdentity"
|
|
192
|
+
|
|
193
|
+
- task: IISWebAppDeploymentOnMachineGroup@0
|
|
194
|
+
displayName: "Deploy to IIS"
|
|
195
|
+
inputs:
|
|
196
|
+
WebsiteName: "$(prodWebsiteName)"
|
|
197
|
+
Package: "$(Build.ArtifactStagingDirectory)/$(projectName).zip"
|
|
198
|
+
TakeAppOfflineFlag: true
|
|
199
|
+
XmlVariableSubstitution: true
|