@atlashub/smartstack-cli 4.37.0 → 4.39.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/dist/mcp-entry.mjs +3 -17
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/efcore/migration.md +20 -59
- package/templates/agents/efcore/rebase-snapshot.md +107 -58
- package/templates/agents/efcore/squash.md +134 -71
- package/templates/agents/gitflow/cleanup.md +17 -6
- package/templates/project/claude-md/infrastructure.CLAUDE.md.template +1 -1
- package/templates/skills/application/references/migration-checklist-troubleshooting.md +3 -15
- package/templates/skills/application/steps/step-06-migration.md +0 -4
- package/templates/skills/application/templates-seed.md +33 -27
- package/templates/skills/dev-start/SKILL.md +192 -41
- package/templates/skills/efcore/SKILL.md +55 -12
- package/templates/skills/efcore/references/database-operations.md +2 -3
- package/templates/skills/efcore/references/seed-methods.md +1 -1
- package/templates/skills/efcore/references/shared-init-functions.md +8 -8
- package/templates/skills/efcore/references/sql-objects-injection.md +12 -54
- package/templates/skills/efcore/references/zero-downtime-patterns.md +2 -0
- package/templates/skills/gitflow/phases/cleanup.md +33 -3
- package/templates/skills/gitflow/references/commit-migration-validation.md +4 -0
|
@@ -58,7 +58,7 @@ the .NET SDK may not be found even if `dotnet-ef` is. Use `$USERPROFILE` first o
|
|
|
58
58
|
```bash
|
|
59
59
|
detect_efcore_project() {
|
|
60
60
|
# Find project with EF Core reference
|
|
61
|
-
CSPROJ=$(find
|
|
61
|
+
CSPROJ=$(find src-name "*.csproj" -exec grep -l "Microsoft.EntityFrameworkCore" {} \; | head -1)
|
|
62
62
|
|
|
63
63
|
if [ -z "$CSPROJ" ]; then
|
|
64
64
|
echo "ERROR: No EF Core project found"
|
|
@@ -70,8 +70,8 @@ detect_efcore_project() {
|
|
|
70
70
|
MIGRATIONS_DIR="$PROJECT_DIR/Persistence/Migrations"
|
|
71
71
|
|
|
72
72
|
# Find startup and infrastructure projects
|
|
73
|
-
STARTUP_PROJECT=$(find
|
|
74
|
-
INFRA_PROJECT=$(find
|
|
73
|
+
STARTUP_PROJECT=$(find src-name "*.Api.csproj" -o -name "*Web.csproj" | head -1)
|
|
74
|
+
INFRA_PROJECT=$(find src-name "*Infrastructure.csproj" | head -1)
|
|
75
75
|
[ -z "$INFRA_PROJECT" ] && INFRA_PROJECT="$CSPROJ"
|
|
76
76
|
|
|
77
77
|
echo "Project: $PROJECT_NAME"
|
|
@@ -84,7 +84,7 @@ detect_efcore_project() {
|
|
|
84
84
|
```bash
|
|
85
85
|
detect_dbcontext() {
|
|
86
86
|
# Priority 1: SmartStack.Domain exists → SmartStack source project (Core only)
|
|
87
|
-
if find
|
|
87
|
+
if find src-type d -name "SmartStack.Domain" | grep -q .; then
|
|
88
88
|
DBCONTEXT="CoreDbContext"
|
|
89
89
|
DBCONTEXT_TYPE="core"
|
|
90
90
|
SCHEMA="core"
|
|
@@ -94,7 +94,7 @@ detect_dbcontext() {
|
|
|
94
94
|
fi
|
|
95
95
|
|
|
96
96
|
# Priority 2: Client project with SmartStack NuGet → BOTH contexts
|
|
97
|
-
if find
|
|
97
|
+
if find src-name "*.csproj" -exec grep -ql "PackageReference.*SmartStack" {} \; 2>/dev/null; then
|
|
98
98
|
DBCONTEXT="CoreDbContext"
|
|
99
99
|
DBCONTEXT_TYPE="both"
|
|
100
100
|
SCHEMA="core"
|
|
@@ -105,8 +105,8 @@ detect_dbcontext() {
|
|
|
105
105
|
fi
|
|
106
106
|
|
|
107
107
|
# Priority 3: Scan for DbContext in code
|
|
108
|
-
CORE_CTX=$(find
|
|
109
|
-
EXT_CTX=$(find
|
|
108
|
+
CORE_CTX=$(find src-name "*.cs" -exec grep -l "CoreDbContext" {} \; 2>/dev/null | head -1)
|
|
109
|
+
EXT_CTX=$(find src-name "*.cs" -exec grep -l "ExtensionsDbContext" {} \; 2>/dev/null | head -1)
|
|
110
110
|
|
|
111
111
|
if [ -n "$CORE_CTX" ] && [ -n "$EXT_CTX" ]; then
|
|
112
112
|
DBCONTEXT="CoreDbContext"
|
|
@@ -137,7 +137,7 @@ detect_dbcontext() {
|
|
|
137
137
|
|
|
138
138
|
```bash
|
|
139
139
|
detect_environment() {
|
|
140
|
-
API_DIR=$(find
|
|
140
|
+
API_DIR=$(find src-type d -name "*.Api" | head -1)
|
|
141
141
|
[ -z "$API_DIR" ] && API_DIR="src/SmartStack.Api"
|
|
142
142
|
|
|
143
143
|
# Priority: --env flag > appsettings.Local.json > error
|
|
@@ -1,61 +1,19 @@
|
|
|
1
|
-
# SQL Objects
|
|
1
|
+
# SQL Objects Management
|
|
2
2
|
|
|
3
|
-
EF Core does NOT generate DDL for
|
|
4
|
-
SQL source scripts are in `Persistence/SqlObjects/` (Embedded Resources).
|
|
5
|
-
After a migration/squash/rebase, they must be re-injected into the consolidated migration.
|
|
3
|
+
EF Core does NOT generate DDL for TVFs, views, and stored procedures.
|
|
4
|
+
SQL source scripts are in `Persistence/SqlObjects/` (Embedded Resources, `CREATE OR ALTER`).
|
|
6
5
|
|
|
7
|
-
##
|
|
6
|
+
## Automatic Startup Deployment
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
# Check if SqlObjects folder exists with .sql files
|
|
11
|
-
SQL_OBJECTS_DIR="$INFRA_PROJECT_DIR/Persistence/SqlObjects"
|
|
12
|
-
SQL_FILES=$(find "$SQL_OBJECTS_DIR" -name "*.sql" 2>/dev/null | wc -l)
|
|
8
|
+
SQL objects are applied **automatically at application startup** via `SqlObjectHelper.ApplyAllAsync(dbContext)` in `SmartStackExtensions.InitializeSmartStackAsync()`, right after `MigrateAsync()`.
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
echo ""
|
|
16
|
-
echo "Found $SQL_FILES SQL object(s) in SqlObjects/"
|
|
17
|
-
echo "Injecting SqlObjectHelper.ApplyAll(migrationBuilder) into migration..."
|
|
10
|
+
**No migration injection is needed.** To add or modify a SQL object:
|
|
18
11
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
fi
|
|
24
|
-
if ! echo "$MIGRATION_FILE" | grep -qE '\.cs$'; then
|
|
25
|
-
echo "ERROR: Invalid migration file path (not .cs): $MIGRATION_FILE"
|
|
26
|
-
exit 1
|
|
27
|
-
fi
|
|
12
|
+
1. Create or edit the `.sql` file in `Persistence/SqlObjects/{Functions,Views,StoredProcedures}/`
|
|
13
|
+
2. Ensure it uses `CREATE OR ALTER` (idempotent)
|
|
14
|
+
3. Ensure `.csproj` has `<EmbeddedResource Include="Persistence\SqlObjects\**\*.sql" />`
|
|
15
|
+
4. Restart the application — the SQL object is deployed automatically
|
|
28
16
|
|
|
29
|
-
|
|
30
|
-
if ! grep -q "using SmartStack.Infrastructure.Persistence.SqlObjects;" "$MIGRATION_FILE"; then
|
|
31
|
-
sed -i '1s/^/using SmartStack.Infrastructure.Persistence.SqlObjects;\n/' "$MIGRATION_FILE"
|
|
32
|
-
fi
|
|
17
|
+
## Legacy Note
|
|
33
18
|
|
|
34
|
-
|
|
35
|
-
sed -i '/protected override void Up/,/^ }/ {
|
|
36
|
-
/^ }/ i\
|
|
37
|
-
\ // Apply SQL objects (TVF, Views, SP) from embedded resources\
|
|
38
|
-
\ SqlObjectHelper.ApplyAll(migrationBuilder);
|
|
39
|
-
}' "$MIGRATION_FILE"
|
|
40
|
-
|
|
41
|
-
# Verify injection succeeded (fallback to manual step if sed pattern didn't match)
|
|
42
|
-
if ! grep -q "SqlObjectHelper.ApplyAll" "$MIGRATION_FILE"; then
|
|
43
|
-
echo "WARNING: Automatic injection failed (indentation pattern may differ)"
|
|
44
|
-
echo ""
|
|
45
|
-
echo "MANUAL STEP REQUIRED: Add these lines inside the Up() method before the closing brace:"
|
|
46
|
-
echo ' using SmartStack.Infrastructure.Persistence.SqlObjects;'
|
|
47
|
-
echo ' ...'
|
|
48
|
-
echo ' SqlObjectHelper.ApplyAll(migrationBuilder);'
|
|
49
|
-
echo ""
|
|
50
|
-
echo "File: $MIGRATION_FILE"
|
|
51
|
-
else
|
|
52
|
-
echo " SqlObjectHelper.ApplyAll(migrationBuilder) injected"
|
|
53
|
-
fi
|
|
54
|
-
find "$SQL_OBJECTS_DIR" -name "*.sql" -exec basename {} \; | while read f; do
|
|
55
|
-
echo " - $f"
|
|
56
|
-
done
|
|
57
|
-
else
|
|
58
|
-
echo ""
|
|
59
|
-
echo "No SQL objects found in SqlObjects/ - skipping injection"
|
|
60
|
-
fi
|
|
61
|
-
```
|
|
19
|
+
Older migrations may still contain `SqlObjectHelper.ApplyAll(migrationBuilder)` calls. These are harmless (idempotent) but no longer required. New migrations should NOT include this call.
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Zero-downtime migration patterns for EF Core. Use when a migration contains destructive operations (column rename, type change, column drop) that could cause downtime during deployment.
|
|
3
3
|
|
|
4
4
|
These patterns apply to production deployments where the application runs continuously. For development environments, standard migrations are sufficient.
|
|
5
|
+
|
|
6
|
+
> **Exception to "no raw SQL" rule:** `migrationBuilder.Sql(...)` is authorized ONLY for data backfill operations within zero-downtime migration patterns (e.g., `UPDATE ... SET NewCol = OldCol`). Never use it for DDL (CREATE/ALTER/DROP) — those must go through EF Core Fluent API or `SqlObjects/`.
|
|
5
7
|
</overview>
|
|
6
8
|
|
|
7
9
|
<when_to_use>
|
|
@@ -60,9 +60,21 @@ while read -r line; do
|
|
|
60
60
|
continue
|
|
61
61
|
fi
|
|
62
62
|
|
|
63
|
+
# Skip permanent branches
|
|
64
|
+
[[ "$WT_BRANCH" == "$GF_MAIN_BRANCH" ]] || [[ "$WT_BRANCH" == "$GF_DEVELOP_BRANCH" ]] && {
|
|
65
|
+
VALID+=("$WT_PATH:$WT_BRANCH")
|
|
66
|
+
continue
|
|
67
|
+
}
|
|
68
|
+
|
|
63
69
|
# Check if branch still exists on remote
|
|
64
70
|
REMOTE_EXISTS=$(git branch -r --list "origin/$WT_BRANCH" | wc -l)
|
|
65
|
-
|
|
71
|
+
|
|
72
|
+
# Check if branch is merged into develop or main
|
|
73
|
+
MERGED_INTO_DEVELOP=$(git branch --merged "$GF_DEVELOP_BRANCH" | grep -c "$WT_BRANCH" 2>/dev/null || echo 0)
|
|
74
|
+
MERGED_INTO_MAIN=$(git branch --merged "$GF_MAIN_BRANCH" | grep -c "$WT_BRANCH" 2>/dev/null || echo 0)
|
|
75
|
+
|
|
76
|
+
# Stale if: no remote OR already merged
|
|
77
|
+
if [ "$REMOTE_EXISTS" -eq 0 ] || [ "$MERGED_INTO_DEVELOP" -gt 0 ] || [ "$MERGED_INTO_MAIN" -gt 0 ]; then
|
|
66
78
|
STALE+=("$WT_PATH:$WT_BRANCH")
|
|
67
79
|
continue
|
|
68
80
|
fi
|
|
@@ -166,10 +178,14 @@ AskUserQuestion:
|
|
|
166
178
|
# Remove orphaned
|
|
167
179
|
for item in "${ORPHANED[@]}"; do
|
|
168
180
|
WT_PATH=$(echo "$item" | cut -d':' -f1)
|
|
181
|
+
WT_BRANCH=$(echo "$item" | cut -d':' -f2)
|
|
169
182
|
git worktree remove "$WT_PATH" --force 2>/dev/null || rm -rf "$WT_PATH"
|
|
183
|
+
# Delete remote branch if exists
|
|
184
|
+
git push origin --delete "$WT_BRANCH" 2>/dev/null
|
|
185
|
+
git branch -D "$WT_BRANCH" 2>/dev/null
|
|
170
186
|
done
|
|
171
187
|
|
|
172
|
-
# Prune
|
|
188
|
+
# Prune stale worktree references
|
|
173
189
|
git worktree prune
|
|
174
190
|
|
|
175
191
|
# Remove stale
|
|
@@ -178,15 +194,29 @@ for item in "${STALE[@]}"; do
|
|
|
178
194
|
WT_BRANCH=$(echo "$item" | cut -d':' -f2)
|
|
179
195
|
|
|
180
196
|
git worktree remove "$WT_PATH" --force 2>/dev/null || rm -rf "$WT_PATH"
|
|
197
|
+
# Delete remote branch if exists
|
|
198
|
+
git push origin --delete "$WT_BRANCH" 2>/dev/null
|
|
181
199
|
git branch -D "$WT_BRANCH" 2>/dev/null
|
|
182
200
|
done
|
|
201
|
+
|
|
202
|
+
# Final prune after all removals
|
|
203
|
+
git worktree prune
|
|
183
204
|
```
|
|
184
205
|
|
|
185
206
|
**Branches:**
|
|
186
207
|
```bash
|
|
187
|
-
# Delete merged branches
|
|
208
|
+
# Delete merged branches (local + remote)
|
|
188
209
|
for branch in "${MERGED_BRANCHES[@]}"; do
|
|
189
210
|
git branch -d "$branch"
|
|
211
|
+
git push origin --delete "$branch" 2>/dev/null
|
|
212
|
+
done
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Empty parent directories:**
|
|
216
|
+
```bash
|
|
217
|
+
# Clean up empty worktree parent directories
|
|
218
|
+
for dir in "$GF_FEATURES_DIR" "$GF_RELEASES_DIR" "$GF_HOTFIXES_DIR"; do
|
|
219
|
+
[ -d "$dir" ] && [ -z "$(ls -A "$dir" 2>/dev/null)" ] && rm -rf "$dir"
|
|
190
220
|
done
|
|
191
221
|
```
|
|
192
222
|
|
|
@@ -47,3 +47,7 @@ if [ "$HAS_MIGRATIONS" = "true" ]; then
|
|
|
47
47
|
}
|
|
48
48
|
fi
|
|
49
49
|
```
|
|
50
|
+
|
|
51
|
+
## SQL Objects Note
|
|
52
|
+
|
|
53
|
+
SQL objects (TVFs, views, stored procedures) are applied **automatically at application startup** via `SqlObjectHelper.ApplyAllAsync()`. No injection into migrations is needed. Migrations no longer need to contain `SqlObjectHelper.ApplyAll(migrationBuilder)` calls.
|