@atlashub/smartstack-cli 1.17.0 → 1.19.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/package.json +1 -1
- package/templates/agents/efcore/db-deploy.md +5 -0
- package/templates/agents/efcore/db-reset.md +5 -0
- package/templates/agents/efcore/db-seed.md +5 -0
- package/templates/agents/efcore/db-status.md +5 -0
- package/templates/agents/efcore/migration.md +8 -0
- package/templates/agents/efcore/rebase-snapshot.md +9 -0
- package/templates/agents/efcore/squash.md +50 -20
- package/templates/commands/efcore/squash.md +24 -12
- package/templates/skills/efcore/SKILL.md +162 -0
- package/templates/skills/efcore/steps/db/step-deploy.md +208 -0
- package/templates/skills/efcore/steps/db/step-reset.md +259 -0
- package/templates/skills/efcore/steps/db/step-seed.md +244 -0
- package/templates/skills/efcore/steps/db/step-status.md +198 -0
- package/templates/skills/efcore/steps/migration/step-00-init.md +102 -0
- package/templates/skills/efcore/steps/migration/step-01-check.md +138 -0
- package/templates/skills/efcore/steps/migration/step-02-create.md +144 -0
- package/templates/skills/efcore/steps/migration/step-03-validate.md +203 -0
- package/templates/skills/efcore/steps/rebase-snapshot/step-00-init.md +173 -0
- package/templates/skills/efcore/steps/rebase-snapshot/step-01-backup.md +100 -0
- package/templates/skills/efcore/steps/rebase-snapshot/step-02-fetch.md +115 -0
- package/templates/skills/efcore/steps/rebase-snapshot/step-03-create.md +108 -0
- package/templates/skills/efcore/steps/rebase-snapshot/step-04-validate.md +157 -0
- package/templates/skills/efcore/steps/shared/step-00-init.md +266 -0
- package/templates/skills/efcore/steps/squash/step-00-init.md +141 -0
- package/templates/skills/efcore/steps/squash/step-01-backup.md +120 -0
- package/templates/skills/efcore/steps/squash/step-02-fetch.md +168 -0
- package/templates/skills/efcore/steps/squash/step-03-create.md +178 -0
- package/templates/skills/efcore/steps/squash/step-04-validate.md +174 -0
- package/templates/skills/gitflow/steps/step-commit.md +14 -2
- package/templates/skills/gitflow/steps/step-finish.md +26 -0
- package/templates/skills/gitflow/steps/step-merge.md +8 -3
- package/templates/skills/gitflow/steps/step-pr.md +10 -0
- package/templates/skills/gitflow/steps/step-start.md +12 -1
- package/templates/skills/gitflow/steps/step-sync.md +24 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: step-04-validate
|
|
3
|
+
description: Validate rebase-snapshot - build and test
|
|
4
|
+
next_step: null
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Step 4: Validate
|
|
8
|
+
|
|
9
|
+
## YOUR TASK:
|
|
10
|
+
|
|
11
|
+
Validate the rebased migration by building and generating a script.
|
|
12
|
+
|
|
13
|
+
**Previous step:** `step-03-create.md`
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## EXECUTION SEQUENCE:
|
|
18
|
+
|
|
19
|
+
### 1. Build Project
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
echo "Building project..."
|
|
23
|
+
|
|
24
|
+
dotnet build "$INFRA_PROJECT" --no-restore
|
|
25
|
+
|
|
26
|
+
if [ $? -ne 0 ]; then
|
|
27
|
+
echo ""
|
|
28
|
+
echo "ERROR: Build failed"
|
|
29
|
+
echo "Restoring from backup..."
|
|
30
|
+
cp "$BACKUP_DIR"/*.cs "$MIGRATIONS_DIR/"
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
echo "Build: OK"
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. Generate Script
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
echo ""
|
|
41
|
+
echo "Generating migration script..."
|
|
42
|
+
|
|
43
|
+
SCRIPT_FILE="$BACKUP_DIR/migration_script.sql"
|
|
44
|
+
|
|
45
|
+
dotnet ef migrations script \
|
|
46
|
+
--context "$DBCONTEXT" \
|
|
47
|
+
--project "$INFRA_PROJECT" \
|
|
48
|
+
--startup-project "$STARTUP_PROJECT" \
|
|
49
|
+
--idempotent \
|
|
50
|
+
--no-build \
|
|
51
|
+
-o "$SCRIPT_FILE"
|
|
52
|
+
|
|
53
|
+
if [ $? -ne 0 ]; then
|
|
54
|
+
echo ""
|
|
55
|
+
echo "ERROR: Script generation failed"
|
|
56
|
+
echo "Restoring from backup..."
|
|
57
|
+
cp "$BACKUP_DIR"/*.cs "$MIGRATIONS_DIR/"
|
|
58
|
+
exit 1
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
echo "Script: $SCRIPT_FILE"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 3. List Migrations
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
echo ""
|
|
68
|
+
echo "Migration list:"
|
|
69
|
+
|
|
70
|
+
dotnet ef migrations list \
|
|
71
|
+
--context "$DBCONTEXT" \
|
|
72
|
+
--project "$INFRA_PROJECT" \
|
|
73
|
+
--startup-project "$STARTUP_PROJECT" \
|
|
74
|
+
--no-build
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 4. Final Summary
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
FINAL_COUNT=$(find "$MIGRATIONS_DIR" -name "*.cs" 2>/dev/null | grep -v "Designer\|Snapshot" | wc -l)
|
|
81
|
+
|
|
82
|
+
echo ""
|
|
83
|
+
echo "==========================================="
|
|
84
|
+
echo "REBASE-SNAPSHOT COMPLETE"
|
|
85
|
+
echo "==========================================="
|
|
86
|
+
echo ""
|
|
87
|
+
echo "Branch: $CURRENT_BRANCH"
|
|
88
|
+
echo "Parent: $BASE_BRANCH"
|
|
89
|
+
echo "DbContext: $DBCONTEXT ($DBCONTEXT_TYPE)"
|
|
90
|
+
echo ""
|
|
91
|
+
echo "Changes:"
|
|
92
|
+
echo " - Snapshot reset to $BASE_BRANCH"
|
|
93
|
+
echo " - Removed: ${#BRANCH_MIGRATIONS[@]} branch migrations"
|
|
94
|
+
echo " - Created: 1 consolidated migration"
|
|
95
|
+
echo ""
|
|
96
|
+
echo "Result:"
|
|
97
|
+
echo " Migration: $MIGRATION_NAME"
|
|
98
|
+
echo " Total: $FINAL_COUNT migrations"
|
|
99
|
+
echo ""
|
|
100
|
+
echo "Backup: $BACKUP_DIR"
|
|
101
|
+
echo "Script: $SCRIPT_FILE"
|
|
102
|
+
echo ""
|
|
103
|
+
echo "==========================================="
|
|
104
|
+
echo ""
|
|
105
|
+
echo "Next steps:"
|
|
106
|
+
echo " /efcore db-reset # Reset local database"
|
|
107
|
+
echo " /efcore db-deploy # Apply migrations"
|
|
108
|
+
echo " /gitflow commit # Commit changes"
|
|
109
|
+
echo ""
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## OUTPUT FORMAT:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
REBASE-SNAPSHOT COMPLETE
|
|
118
|
+
========================
|
|
119
|
+
Branch: {current_branch}
|
|
120
|
+
Parent: {base_branch}
|
|
121
|
+
DbContext: {dbcontext} ({dbcontext_type})
|
|
122
|
+
|
|
123
|
+
Changes:
|
|
124
|
+
- Snapshot reset to {base_branch}
|
|
125
|
+
- Removed: {count} branch migrations
|
|
126
|
+
- Created: 1 consolidated migration
|
|
127
|
+
|
|
128
|
+
Result:
|
|
129
|
+
Migration: {migration_name}
|
|
130
|
+
Total: {final_count} migrations
|
|
131
|
+
|
|
132
|
+
Backup: {backup_dir}
|
|
133
|
+
Script: {backup_dir}/migration_script.sql
|
|
134
|
+
|
|
135
|
+
Next: /efcore db-reset, /efcore db-deploy, /gitflow commit
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## ERROR HANDLING:
|
|
141
|
+
|
|
142
|
+
| Error | Action |
|
|
143
|
+
|-------|--------|
|
|
144
|
+
| Build fails | Restore backup |
|
|
145
|
+
| Script fails | Restore backup |
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## SUCCESS CRITERIA:
|
|
150
|
+
|
|
151
|
+
- Build passes
|
|
152
|
+
- Script generates
|
|
153
|
+
- Summary displayed
|
|
154
|
+
|
|
155
|
+
## COMPLETION:
|
|
156
|
+
|
|
157
|
+
Rebase-snapshot complete. Use `/efcore db-reset` then `/efcore db-deploy` to apply.
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: step-00-init
|
|
3
|
+
description: Initialize EF Core context - detect project, DbContext, and environment
|
|
4
|
+
next_step: null
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Step 0: Initialize EF Core Context
|
|
8
|
+
|
|
9
|
+
## YOUR TASK:
|
|
10
|
+
|
|
11
|
+
Detect EF Core project structure, identify DbContext (Core vs Extensions), and load environment configuration.
|
|
12
|
+
|
|
13
|
+
**This step runs first for ALL EF Core commands.**
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## EXECUTION SEQUENCE:
|
|
18
|
+
|
|
19
|
+
### 1. Detect EF Core Project
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
detect_efcore_project() {
|
|
23
|
+
# Find project with EF Core reference
|
|
24
|
+
CSPROJ=$(find . -name "*.csproj" -exec grep -l "Microsoft.EntityFrameworkCore" {} \; | head -1)
|
|
25
|
+
|
|
26
|
+
if [ -z "$CSPROJ" ]; then
|
|
27
|
+
echo "ERROR: No EF Core project found"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
PROJECT_DIR=$(dirname "$CSPROJ")
|
|
32
|
+
PROJECT_NAME=$(basename "$CSPROJ" .csproj)
|
|
33
|
+
MIGRATIONS_DIR="$PROJECT_DIR/Persistence/Migrations"
|
|
34
|
+
|
|
35
|
+
# Find startup and infrastructure projects
|
|
36
|
+
STARTUP_PROJECT=$(find . -name "*.Api.csproj" -o -name "*Web.csproj" | head -1)
|
|
37
|
+
INFRA_PROJECT=$(find . -name "*Infrastructure.csproj" | head -1)
|
|
38
|
+
[ -z "$INFRA_PROJECT" ] && INFRA_PROJECT="$CSPROJ"
|
|
39
|
+
|
|
40
|
+
echo "Project: $PROJECT_NAME"
|
|
41
|
+
echo "Migrations: $MIGRATIONS_DIR"
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 2. Detect DbContext (Core vs Extensions)
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
detect_dbcontext() {
|
|
49
|
+
# Priority 1: SmartStack.Domain exists → CoreDbContext
|
|
50
|
+
if find . -type d -name "SmartStack.Domain" | grep -q .; then
|
|
51
|
+
DBCONTEXT="CoreDbContext"
|
|
52
|
+
DBCONTEXT_TYPE="core"
|
|
53
|
+
SCHEMA="core"
|
|
54
|
+
echo "DbContext: CoreDbContext (SmartStack.Domain found)"
|
|
55
|
+
return
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
# Priority 2: Client with SmartStack NuGet → ExtensionsDbContext
|
|
59
|
+
if find . -name "*.csproj" -exec grep -l "SmartStack\." {} \; | grep -qv "SmartStack\."; then
|
|
60
|
+
DBCONTEXT="ExtensionsDbContext"
|
|
61
|
+
DBCONTEXT_TYPE="extensions"
|
|
62
|
+
SCHEMA="extensions"
|
|
63
|
+
echo "DbContext: ExtensionsDbContext (SmartStack NuGet reference)"
|
|
64
|
+
return
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
# Priority 3: Scan for DbContext in code
|
|
68
|
+
CORE_CTX=$(find . -name "*.cs" -exec grep -l "CoreDbContext" {} \; 2>/dev/null | head -1)
|
|
69
|
+
EXT_CTX=$(find . -name "*.cs" -exec grep -l "ExtensionsDbContext" {} \; 2>/dev/null | head -1)
|
|
70
|
+
|
|
71
|
+
if [ -n "$CORE_CTX" ] && [ -z "$EXT_CTX" ]; then
|
|
72
|
+
DBCONTEXT="CoreDbContext"
|
|
73
|
+
DBCONTEXT_TYPE="core"
|
|
74
|
+
SCHEMA="core"
|
|
75
|
+
elif [ -z "$CORE_CTX" ] && [ -n "$EXT_CTX" ]; then
|
|
76
|
+
DBCONTEXT="ExtensionsDbContext"
|
|
77
|
+
DBCONTEXT_TYPE="extensions"
|
|
78
|
+
SCHEMA="extensions"
|
|
79
|
+
else
|
|
80
|
+
# Priority 4: Ask user
|
|
81
|
+
DBCONTEXT=""
|
|
82
|
+
DBCONTEXT_TYPE=""
|
|
83
|
+
SCHEMA=""
|
|
84
|
+
fi
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 3. Ask User if DbContext Unknown
|
|
89
|
+
|
|
90
|
+
**If `{dbcontext}` is empty after detection:**
|
|
91
|
+
|
|
92
|
+
```yaml
|
|
93
|
+
AskUserQuestion:
|
|
94
|
+
header: "DbContext"
|
|
95
|
+
question: "Which DbContext to use?"
|
|
96
|
+
options:
|
|
97
|
+
- label: "CoreDbContext"
|
|
98
|
+
description: "SmartStack entities (User, Role, Navigation...)"
|
|
99
|
+
- label: "ExtensionsDbContext"
|
|
100
|
+
description: "Client-specific entities"
|
|
101
|
+
- label: "Both"
|
|
102
|
+
description: "Run for both contexts"
|
|
103
|
+
multiSelect: false
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Set variables based on response:**
|
|
107
|
+
```javascript
|
|
108
|
+
if (answer === "CoreDbContext") {
|
|
109
|
+
DBCONTEXT = "CoreDbContext";
|
|
110
|
+
DBCONTEXT_TYPE = "core";
|
|
111
|
+
SCHEMA = "core";
|
|
112
|
+
} else if (answer === "ExtensionsDbContext") {
|
|
113
|
+
DBCONTEXT = "ExtensionsDbContext";
|
|
114
|
+
DBCONTEXT_TYPE = "extensions";
|
|
115
|
+
SCHEMA = "extensions";
|
|
116
|
+
} else {
|
|
117
|
+
// Both - will run commands twice
|
|
118
|
+
RUN_BOTH = true;
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 4. Detect Environment
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
detect_environment() {
|
|
126
|
+
API_DIR=$(find . -type d -name "*.Api" | head -1)
|
|
127
|
+
[ -z "$API_DIR" ] && API_DIR="src/SmartStack.Api"
|
|
128
|
+
|
|
129
|
+
# Priority: --env flag > appsettings.Local.json > error
|
|
130
|
+
if [ -n "$ENV_FLAG" ]; then
|
|
131
|
+
CONFIG_FILE="$API_DIR/appsettings.${ENV_FLAG}.json"
|
|
132
|
+
elif [ -f "$API_DIR/appsettings.Local.json" ]; then
|
|
133
|
+
CONFIG_FILE="$API_DIR/appsettings.Local.json"
|
|
134
|
+
SELECTED_ENV="Local"
|
|
135
|
+
else
|
|
136
|
+
echo "ERROR: No appsettings.Local.json found"
|
|
137
|
+
echo "Create one or use --env flag"
|
|
138
|
+
exit 1
|
|
139
|
+
fi
|
|
140
|
+
|
|
141
|
+
echo "Environment: $SELECTED_ENV"
|
|
142
|
+
echo "Config: $CONFIG_FILE"
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 5. Determine Base Branch (for squash/rebase)
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
determine_base_branch() {
|
|
150
|
+
CURRENT_BRANCH=$(git branch --show-current)
|
|
151
|
+
|
|
152
|
+
case "$CURRENT_BRANCH" in
|
|
153
|
+
feature/*)
|
|
154
|
+
BASE_BRANCH="develop"
|
|
155
|
+
BRANCH_TYPE="feature"
|
|
156
|
+
;;
|
|
157
|
+
release/*)
|
|
158
|
+
BASE_BRANCH="main"
|
|
159
|
+
BRANCH_TYPE="release"
|
|
160
|
+
;;
|
|
161
|
+
hotfix/*)
|
|
162
|
+
BASE_BRANCH="main"
|
|
163
|
+
BRANCH_TYPE="hotfix"
|
|
164
|
+
;;
|
|
165
|
+
develop)
|
|
166
|
+
BASE_BRANCH="main"
|
|
167
|
+
BRANCH_TYPE="develop"
|
|
168
|
+
;;
|
|
169
|
+
main|master)
|
|
170
|
+
echo "ERROR: Cannot run on main/master branch"
|
|
171
|
+
exit 1
|
|
172
|
+
;;
|
|
173
|
+
*)
|
|
174
|
+
BASE_BRANCH="develop"
|
|
175
|
+
BRANCH_TYPE="unknown"
|
|
176
|
+
;;
|
|
177
|
+
esac
|
|
178
|
+
|
|
179
|
+
echo "Branch: $CURRENT_BRANCH ($BRANCH_TYPE)"
|
|
180
|
+
echo "Base: $BASE_BRANCH"
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### 6. Block Production
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
block_production() {
|
|
188
|
+
# Check for production indicators
|
|
189
|
+
if grep -q '"Production"' "$CONFIG_FILE" 2>/dev/null; then
|
|
190
|
+
echo "BLOCKED: Production environment detected"
|
|
191
|
+
exit 1
|
|
192
|
+
fi
|
|
193
|
+
|
|
194
|
+
if [[ "$DATABASE_NAME" == *"prod"* ]] || [[ "$DATABASE_NAME" == *"production"* ]]; then
|
|
195
|
+
echo "BLOCKED: Production database detected"
|
|
196
|
+
exit 1
|
|
197
|
+
fi
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### 7. Display Summary
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
EF CORE CONTEXT
|
|
205
|
+
├── Project: {PROJECT_NAME}
|
|
206
|
+
├── DbContext: {DBCONTEXT} ({DBCONTEXT_TYPE})
|
|
207
|
+
├── Schema: {SCHEMA}
|
|
208
|
+
├── Migrations: {MIGRATIONS_DIR}
|
|
209
|
+
├── Environment:{SELECTED_ENV}
|
|
210
|
+
└── Branch: {CURRENT_BRANCH} → {BASE_BRANCH}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## STATE OUTPUT:
|
|
216
|
+
|
|
217
|
+
After this step, these variables are available:
|
|
218
|
+
|
|
219
|
+
| Variable | Example Value |
|
|
220
|
+
|----------|---------------|
|
|
221
|
+
| `{project_name}` | SmartStack.Infrastructure |
|
|
222
|
+
| `{dbcontext}` | CoreDbContext |
|
|
223
|
+
| `{dbcontext_type}` | core |
|
|
224
|
+
| `{schema}` | core |
|
|
225
|
+
| `{migrations_dir}` | src/SmartStack.Infrastructure/Persistence/Migrations |
|
|
226
|
+
| `{infra_project}` | src/SmartStack.Infrastructure/SmartStack.Infrastructure.csproj |
|
|
227
|
+
| `{startup_project}` | src/SmartStack.Api/SmartStack.Api.csproj |
|
|
228
|
+
| `{base_branch}` | develop |
|
|
229
|
+
| `{branch_type}` | feature |
|
|
230
|
+
| `{current_branch}` | feature/multitenant |
|
|
231
|
+
| `{selected_env}` | Local |
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## SUCCESS CRITERIA:
|
|
236
|
+
|
|
237
|
+
- EF Core project detected
|
|
238
|
+
- DbContext identified (or user prompted)
|
|
239
|
+
- Environment loaded
|
|
240
|
+
- No production environment
|
|
241
|
+
- All paths validated
|
|
242
|
+
|
|
243
|
+
## FAILURE MODES:
|
|
244
|
+
|
|
245
|
+
| Error | Resolution |
|
|
246
|
+
|-------|------------|
|
|
247
|
+
| No EF Core project | Check Microsoft.EntityFrameworkCore reference |
|
|
248
|
+
| No appsettings.Local.json | Create file or use --env flag |
|
|
249
|
+
| Production detected | Use different environment |
|
|
250
|
+
| Both DbContexts found | User will be prompted |
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## NEXT STEP:
|
|
255
|
+
|
|
256
|
+
Route to command-specific step based on `{command}`:
|
|
257
|
+
|
|
258
|
+
| Command | Next Step |
|
|
259
|
+
|---------|-----------|
|
|
260
|
+
| `db-status` | `../db/step-status.md` |
|
|
261
|
+
| `db-deploy` | `../db/step-deploy.md` |
|
|
262
|
+
| `db-reset` | `../db/step-reset.md` |
|
|
263
|
+
| `db-seed` | `../db/step-seed.md` |
|
|
264
|
+
| `migration` | `../migration/step-01-check.md` |
|
|
265
|
+
| `squash` | `../squash/step-01-backup.md` |
|
|
266
|
+
| `rebase-snapshot` | `../rebase-snapshot/step-01-backup.md` |
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: step-00-init
|
|
3
|
+
description: Initialize squash - verify prerequisites and get confirmation
|
|
4
|
+
next_step: step-01-backup.md
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Step 0: Initialize Squash
|
|
8
|
+
|
|
9
|
+
## YOUR TASK:
|
|
10
|
+
|
|
11
|
+
Verify prerequisites for squash operation and get user confirmation.
|
|
12
|
+
|
|
13
|
+
**Requires:** `steps/shared/step-00-init.md` completed (provides {dbcontext}, {base_branch}, etc.)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## EXECUTION SEQUENCE:
|
|
18
|
+
|
|
19
|
+
### 1. Verify Clean Working Directory
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
[ -n "$(git status --porcelain)" ] && {
|
|
23
|
+
echo "ERROR: Working directory not clean"
|
|
24
|
+
git status --short
|
|
25
|
+
exit 1
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 2. Identify Branch-Only Migrations
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Fetch parent branch
|
|
33
|
+
git fetch origin "$BASE_BRANCH" --quiet
|
|
34
|
+
|
|
35
|
+
# Get migrations from parent branch
|
|
36
|
+
BASE_MIGRATIONS=$(git ls-tree -r --name-only "origin/$BASE_BRANCH" -- "$MIGRATIONS_DIR" 2>/dev/null | grep "\.cs$" | grep -v "Designer\|Snapshot" || echo "")
|
|
37
|
+
|
|
38
|
+
# Get local migrations
|
|
39
|
+
LOCAL_MIGRATIONS=$(find "$MIGRATIONS_DIR" -name "*.cs" 2>/dev/null | grep -v "Designer\|Snapshot" | xargs -I{} basename {} 2>/dev/null || echo "")
|
|
40
|
+
|
|
41
|
+
# Find migrations unique to this branch
|
|
42
|
+
BRANCH_ONLY_MIGRATIONS=()
|
|
43
|
+
for mig in $LOCAL_MIGRATIONS; do
|
|
44
|
+
if ! echo "$BASE_MIGRATIONS" | grep -q "$(basename "$mig")"; then
|
|
45
|
+
BRANCH_ONLY_MIGRATIONS+=("$mig")
|
|
46
|
+
fi
|
|
47
|
+
done
|
|
48
|
+
|
|
49
|
+
MIGRATION_COUNT=${#BRANCH_ONLY_MIGRATIONS[@]}
|
|
50
|
+
BASE_MIGRATION_COUNT=$(echo "$BASE_MIGRATIONS" | grep -c "." || echo "0")
|
|
51
|
+
|
|
52
|
+
echo "Branch: $CURRENT_BRANCH"
|
|
53
|
+
echo "Parent: $BASE_BRANCH"
|
|
54
|
+
echo "Migrations to squash: $MIGRATION_COUNT (branch-only)"
|
|
55
|
+
echo "Migrations from parent: $BASE_MIGRATION_COUNT (preserved)"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 3. Check If Squash Needed
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
if [ "$MIGRATION_COUNT" -eq 0 ]; then
|
|
62
|
+
echo "No branch-specific migrations to squash."
|
|
63
|
+
echo "Nothing to do."
|
|
64
|
+
exit 0
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
if [ "$MIGRATION_COUNT" -eq 1 ]; then
|
|
68
|
+
echo "Only 1 migration on branch."
|
|
69
|
+
# Ask if user wants to continue anyway
|
|
70
|
+
fi
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 4. Display Summary
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
SQUASH PREVIEW
|
|
77
|
+
==============
|
|
78
|
+
Branch: {CURRENT_BRANCH}
|
|
79
|
+
Parent: {BASE_BRANCH}
|
|
80
|
+
DbContext: {DBCONTEXT} ({DBCONTEXT_TYPE})
|
|
81
|
+
|
|
82
|
+
Migrations to squash ({MIGRATION_COUNT}):
|
|
83
|
+
{for mig in BRANCH_ONLY_MIGRATIONS}
|
|
84
|
+
- {mig}
|
|
85
|
+
{endfor}
|
|
86
|
+
|
|
87
|
+
Migrations from parent ({BASE_MIGRATION_COUNT}):
|
|
88
|
+
(will be preserved)
|
|
89
|
+
|
|
90
|
+
Result: {BASE_MIGRATION_COUNT + 1} migrations total
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 5. User Confirmation
|
|
94
|
+
|
|
95
|
+
**If NOT auto_mode:**
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
AskUserQuestion:
|
|
99
|
+
header: "Squash"
|
|
100
|
+
question: "Squash {MIGRATION_COUNT} migrations from {CURRENT_BRANCH}?
|
|
101
|
+
|
|
102
|
+
The ModelSnapshot and migrations from {BASE_BRANCH} will be recovered.
|
|
103
|
+
Your {MIGRATION_COUNT} migrations will be consolidated into ONE.
|
|
104
|
+
|
|
105
|
+
This operation is DESTRUCTIVE but a backup will be created."
|
|
106
|
+
options:
|
|
107
|
+
- label: "Yes, squash"
|
|
108
|
+
description: "Consolidate on base of {BASE_BRANCH}"
|
|
109
|
+
- label: "View details"
|
|
110
|
+
description: "Show migrations to be squashed"
|
|
111
|
+
- label: "Cancel"
|
|
112
|
+
description: "Do nothing"
|
|
113
|
+
multiSelect: false
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
**Handle response:**
|
|
117
|
+
- "Yes, squash" → Continue to next step
|
|
118
|
+
- "View details" → Show full migration list, ask again
|
|
119
|
+
- "Cancel" → Exit
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## STATE OUTPUT:
|
|
124
|
+
|
|
125
|
+
| Variable | Description |
|
|
126
|
+
|----------|-------------|
|
|
127
|
+
| `{branch_only_migrations}` | Array of migrations to squash |
|
|
128
|
+
| `{migration_count}` | Number of migrations to squash |
|
|
129
|
+
| `{base_migration_count}` | Number of parent migrations |
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## SUCCESS CRITERIA:
|
|
134
|
+
|
|
135
|
+
- Working directory clean
|
|
136
|
+
- At least 1 branch-specific migration
|
|
137
|
+
- User confirmed (or auto_mode)
|
|
138
|
+
|
|
139
|
+
## NEXT STEP:
|
|
140
|
+
|
|
141
|
+
→ `step-01-backup.md`
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: step-01-backup
|
|
3
|
+
description: Create backup of all migration files
|
|
4
|
+
next_step: step-02-fetch.md
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Step 1: Backup
|
|
8
|
+
|
|
9
|
+
## YOUR TASK:
|
|
10
|
+
|
|
11
|
+
Create a complete backup of all migration files before destructive operations.
|
|
12
|
+
|
|
13
|
+
**Previous step:** `step-00-init.md`
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## EXECUTION SEQUENCE:
|
|
18
|
+
|
|
19
|
+
### 1. Create Backup Directory
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
|
23
|
+
BACKUP_DIR=".claude/gitflow/backup/migrations/squash_${TIMESTAMP}"
|
|
24
|
+
|
|
25
|
+
mkdir -p "$BACKUP_DIR"
|
|
26
|
+
echo "Backup directory: $BACKUP_DIR"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 2. Backup All Migration Files
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Backup all .cs files from migrations directory
|
|
33
|
+
cp "$MIGRATIONS_DIR"/*.cs "$BACKUP_DIR/" 2>/dev/null || {
|
|
34
|
+
echo "ERROR: No migration files found to backup"
|
|
35
|
+
exit 1
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# Count backed up files
|
|
39
|
+
BACKUP_COUNT=$(ls -1 "$BACKUP_DIR"/*.cs 2>/dev/null | wc -l)
|
|
40
|
+
echo "Backed up: $BACKUP_COUNT files"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 3. Create Backup Manifest
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cat > "$BACKUP_DIR/MANIFEST.md" << EOF
|
|
47
|
+
# Squash Backup Manifest
|
|
48
|
+
|
|
49
|
+
**Created:** $(date -Iseconds)
|
|
50
|
+
**Branch:** $CURRENT_BRANCH
|
|
51
|
+
**Parent:** $BASE_BRANCH
|
|
52
|
+
**DbContext:** $DBCONTEXT
|
|
53
|
+
|
|
54
|
+
## Files Backed Up
|
|
55
|
+
|
|
56
|
+
\`\`\`
|
|
57
|
+
$(ls -la "$BACKUP_DIR"/*.cs)
|
|
58
|
+
\`\`\`
|
|
59
|
+
|
|
60
|
+
## Migrations to Squash
|
|
61
|
+
|
|
62
|
+
$(for mig in "${BRANCH_ONLY_MIGRATIONS[@]}"; do echo "- $mig"; done)
|
|
63
|
+
|
|
64
|
+
## Restore Command
|
|
65
|
+
|
|
66
|
+
\`\`\`bash
|
|
67
|
+
cp "$BACKUP_DIR"/*.cs "$MIGRATIONS_DIR/"
|
|
68
|
+
\`\`\`
|
|
69
|
+
EOF
|
|
70
|
+
|
|
71
|
+
echo "Manifest created: $BACKUP_DIR/MANIFEST.md"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 4. Verify Backup
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Ensure critical files exist
|
|
78
|
+
SNAPSHOT_BACKUP=$(ls "$BACKUP_DIR"/*ModelSnapshot.cs 2>/dev/null | head -1)
|
|
79
|
+
|
|
80
|
+
if [ -z "$SNAPSHOT_BACKUP" ]; then
|
|
81
|
+
echo "WARNING: No ModelSnapshot in backup"
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
echo ""
|
|
85
|
+
echo "Backup complete:"
|
|
86
|
+
echo " Directory: $BACKUP_DIR"
|
|
87
|
+
echo " Files: $BACKUP_COUNT"
|
|
88
|
+
echo " Snapshot: $(basename "$SNAPSHOT_BACKUP" 2>/dev/null || echo 'N/A')"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## STATE OUTPUT:
|
|
94
|
+
|
|
95
|
+
| Variable | Value |
|
|
96
|
+
|----------|-------|
|
|
97
|
+
| `{backup_dir}` | `.claude/gitflow/backup/migrations/squash_{timestamp}` |
|
|
98
|
+
| `{backup_count}` | Number of files backed up |
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## RECOVERY:
|
|
103
|
+
|
|
104
|
+
If squash fails, restore with:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
cp "{BACKUP_DIR}"/*.cs "{MIGRATIONS_DIR}/"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## SUCCESS CRITERIA:
|
|
113
|
+
|
|
114
|
+
- Backup directory created
|
|
115
|
+
- All migration files copied
|
|
116
|
+
- Manifest created
|
|
117
|
+
|
|
118
|
+
## NEXT STEP:
|
|
119
|
+
|
|
120
|
+
→ `step-02-fetch.md`
|