@atlashub/smartstack-cli 1.35.0 → 1.36.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/skills/_shared.md +7 -7
- package/templates/skills/application/steps/step-04-backend.md +17 -17
- package/templates/skills/application/steps/step-05-frontend.md +4 -1
- package/templates/skills/application/templates-backend.md +8 -8
- package/templates/skills/application/templates-frontend.md +8 -8
- package/templates/skills/gitflow/_shared.md +188 -53
- package/templates/skills/gitflow/phases/abort.md +28 -16
- package/templates/skills/gitflow/phases/cleanup.md +13 -9
- package/templates/skills/gitflow/phases/status.md +16 -17
- package/templates/skills/gitflow/steps/step-commit.md +11 -5
- package/templates/skills/gitflow/steps/step-finish.md +43 -33
- package/templates/skills/gitflow/steps/step-init.md +7 -2
- package/templates/skills/gitflow/steps/step-merge.md +24 -10
- package/templates/skills/gitflow/steps/step-pr.md +42 -28
- package/templates/skills/gitflow/steps/step-start.md +19 -13
- package/templates/skills/gitflow/templates/config.json +7 -4
- package/templates/skills/ralph-loop/SKILL.md +57 -11
- package/templates/skills/ralph-loop/steps/step-00-init.md +170 -30
- package/templates/skills/ralph-loop/steps/step-01-task.md +243 -40
- package/templates/skills/ralph-loop/steps/step-02-execute.md +142 -24
- package/templates/skills/ralph-loop/steps/step-03-commit.md +140 -36
- package/templates/skills/ralph-loop/steps/step-04-check.md +128 -44
- package/templates/skills/ralph-loop/steps/step-05-report.md +175 -88
|
@@ -13,16 +13,15 @@ Display complete GitFlow state including branches, worktrees, remotes, and pendi
|
|
|
13
13
|
|
|
14
14
|
## EXECUTION:
|
|
15
15
|
|
|
16
|
-
### 1. Repository Info
|
|
16
|
+
### 1. Load Config and Repository Info
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
REMOTE_URL=$(git remote get-url origin 2>/dev/null || echo "No remote")
|
|
19
|
+
# Load GitFlow config (sets GF_* variables)
|
|
20
|
+
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
REPO_NAME="$GF_PROJECT_NAME"
|
|
23
|
+
CURRENT=$(git rev-parse --abbrev-ref HEAD)
|
|
24
|
+
GIT_PROVIDER="$GF_PROVIDER"
|
|
26
25
|
```
|
|
27
26
|
|
|
28
27
|
### 2. Branch Status
|
|
@@ -30,27 +29,27 @@ REMOTE_URL=$(git remote get-url origin 2>/dev/null || echo "No remote")
|
|
|
30
29
|
```bash
|
|
31
30
|
git fetch origin --quiet
|
|
32
31
|
|
|
33
|
-
# Main branches
|
|
34
|
-
MAIN_LOCAL=$(git rev-parse --short
|
|
35
|
-
MAIN_REMOTE=$(git rev-parse --short origin
|
|
36
|
-
DEVELOP_LOCAL=$(git rev-parse --short
|
|
37
|
-
DEVELOP_REMOTE=$(git rev-parse --short origin
|
|
32
|
+
# Main branches (from config)
|
|
33
|
+
MAIN_LOCAL=$(git rev-parse --short $GF_MAIN_BRANCH 2>/dev/null || echo "N/A")
|
|
34
|
+
MAIN_REMOTE=$(git rev-parse --short origin/$GF_MAIN_BRANCH 2>/dev/null || echo "N/A")
|
|
35
|
+
DEVELOP_LOCAL=$(git rev-parse --short $GF_DEVELOP_BRANCH 2>/dev/null || echo "N/A")
|
|
36
|
+
DEVELOP_REMOTE=$(git rev-parse --short origin/$GF_DEVELOP_BRANCH 2>/dev/null || echo "N/A")
|
|
38
37
|
|
|
39
38
|
# Divergence
|
|
40
|
-
DEVELOP_AHEAD=$(git rev-list --count origin
|
|
39
|
+
DEVELOP_AHEAD=$(git rev-list --count origin/$GF_MAIN_BRANCH..origin/$GF_DEVELOP_BRANCH 2>/dev/null || echo "0")
|
|
41
40
|
```
|
|
42
41
|
|
|
43
42
|
### 3. Active Branches
|
|
44
43
|
|
|
45
44
|
```bash
|
|
46
|
-
# Feature branches
|
|
47
|
-
FEATURES=$(git branch -r | grep "origin
|
|
45
|
+
# Feature branches (using prefixes from config)
|
|
46
|
+
FEATURES=$(git branch -r | grep "origin/${GF_FEATURE_PREFIX}" | sed 's/origin\///')
|
|
48
47
|
|
|
49
48
|
# Release branches
|
|
50
|
-
RELEASES=$(git branch -r | grep "origin
|
|
49
|
+
RELEASES=$(git branch -r | grep "origin/${GF_RELEASE_PREFIX}" | sed 's/origin\///')
|
|
51
50
|
|
|
52
51
|
# Hotfix branches
|
|
53
|
-
HOTFIXES=$(git branch -r | grep "origin
|
|
52
|
+
HOTFIXES=$(git branch -r | grep "origin/${GF_HOTFIX_PREFIX}" | sed 's/origin\///')
|
|
54
53
|
```
|
|
55
54
|
|
|
56
55
|
### 4. Worktree Status
|
|
@@ -28,20 +28,26 @@ Validate changes, check EF Core migrations, and create commit with proper messag
|
|
|
28
28
|
|
|
29
29
|
### 0. Pre-commit Guards
|
|
30
30
|
|
|
31
|
+
**0.0 Load Config:**
|
|
32
|
+
```bash
|
|
33
|
+
# Load GitFlow config (sets GF_* variables)
|
|
34
|
+
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
|
|
35
|
+
```
|
|
36
|
+
|
|
31
37
|
**0.1 Branch Protection:**
|
|
32
38
|
```bash
|
|
33
39
|
CURRENT=$(git rev-parse --abbrev-ref HEAD)
|
|
34
40
|
|
|
35
41
|
# BLOCK: main
|
|
36
|
-
[[ "$CURRENT" == "
|
|
37
|
-
echo "⛔ COMMIT BLOCKED -
|
|
42
|
+
[[ "$CURRENT" == "$GF_MAIN_BRANCH" ]] && {
|
|
43
|
+
echo "⛔ COMMIT BLOCKED - $GF_MAIN_BRANCH is protected"
|
|
38
44
|
echo "→ Use: /gitflow start hotfix <name>"
|
|
39
45
|
STOP
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
# WARNING: develop
|
|
43
|
-
[[ "$CURRENT" == "
|
|
44
|
-
echo "⚠️ Direct commits to
|
|
49
|
+
[[ "$CURRENT" == "$GF_DEVELOP_BRANCH" ]] && {
|
|
50
|
+
echo "⚠️ Direct commits to $GF_DEVELOP_BRANCH are discouraged"
|
|
45
51
|
# Offer RESCUE TO FEATURE
|
|
46
52
|
}
|
|
47
53
|
```
|
|
@@ -52,7 +58,7 @@ git fetch origin --quiet
|
|
|
52
58
|
STAGED=$(git diff --cached --name-only | wc -l)
|
|
53
59
|
MODIFIED=$(git diff --name-only | wc -l)
|
|
54
60
|
UNTRACKED=$(git ls-files --others --exclude-standard | wc -l)
|
|
55
|
-
LOCAL_COMMITS=$(git rev-list --count origin
|
|
61
|
+
LOCAL_COMMITS=$(git rev-list --count origin/$GF_DEVELOP_BRANCH..HEAD 2>/dev/null || echo "0")
|
|
56
62
|
|
|
57
63
|
# If there are changes or commits, offer rescue
|
|
58
64
|
[ "$STAGED" -gt 0 ] || [ "$MODIFIED" -gt 0 ] || [ "$LOCAL_COMMITS" -gt 0 ] && {
|
|
@@ -16,9 +16,12 @@ Create tags for releases/hotfixes, merge back to develop, clean up worktree and
|
|
|
16
16
|
|
|
17
17
|
## EXECUTION SEQUENCE:
|
|
18
18
|
|
|
19
|
-
### 1. Determine Branch Context
|
|
19
|
+
### 1. Load Config and Determine Branch Context
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
+
# Load GitFlow config (sets GF_* variables)
|
|
23
|
+
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
|
|
24
|
+
|
|
22
25
|
# Get current or specified branch
|
|
23
26
|
BRANCH=${1:-$(git rev-parse --abbrev-ref HEAD)}
|
|
24
27
|
BRANCH_TYPE=$(echo $BRANCH | cut -d'/' -f1)
|
|
@@ -27,8 +30,8 @@ BRANCH_NAME=$(echo $BRANCH | cut -d'/' -f2)
|
|
|
27
30
|
# Validate branch type
|
|
28
31
|
case "$BRANCH_TYPE" in
|
|
29
32
|
feature|release|hotfix) ;;
|
|
30
|
-
|
|
31
|
-
echo "❌ Cannot finish
|
|
33
|
+
$GF_MAIN_BRANCH|$GF_DEVELOP_BRANCH)
|
|
34
|
+
echo "❌ Cannot finish $GF_MAIN_BRANCH or $GF_DEVELOP_BRANCH branch"
|
|
32
35
|
STOP
|
|
33
36
|
;;
|
|
34
37
|
*)
|
|
@@ -46,12 +49,12 @@ git fetch origin
|
|
|
46
49
|
# Check if branch was merged
|
|
47
50
|
case "$BRANCH_TYPE" in
|
|
48
51
|
feature)
|
|
49
|
-
MERGED=$(git branch -r --merged origin
|
|
50
|
-
TARGET="
|
|
52
|
+
MERGED=$(git branch -r --merged origin/$GF_DEVELOP_BRANCH | grep "$BRANCH" | wc -l)
|
|
53
|
+
TARGET="$GF_DEVELOP_BRANCH"
|
|
51
54
|
;;
|
|
52
55
|
release|hotfix)
|
|
53
|
-
MERGED=$(git branch -r --merged origin
|
|
54
|
-
TARGET="
|
|
56
|
+
MERGED=$(git branch -r --merged origin/$GF_MAIN_BRANCH | grep "$BRANCH" | wc -l)
|
|
57
|
+
TARGET="$GF_MAIN_BRANCH"
|
|
55
58
|
;;
|
|
56
59
|
esac
|
|
57
60
|
|
|
@@ -74,8 +77,8 @@ esac
|
|
|
74
77
|
|
|
75
78
|
```bash
|
|
76
79
|
if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
|
|
77
|
-
# Get version
|
|
78
|
-
VERSION
|
|
80
|
+
# Get version from config (already loaded)
|
|
81
|
+
VERSION="$GF_VERSION"
|
|
79
82
|
|
|
80
83
|
# For hotfix, increment patch
|
|
81
84
|
if [ "$BRANCH_TYPE" = "hotfix" ]; then
|
|
@@ -95,8 +98,8 @@ if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
|
|
|
95
98
|
}
|
|
96
99
|
|
|
97
100
|
# Create tag on main
|
|
98
|
-
git checkout
|
|
99
|
-
git pull origin
|
|
101
|
+
git checkout $GF_MAIN_BRANCH
|
|
102
|
+
git pull origin $GF_MAIN_BRANCH
|
|
100
103
|
git tag -a "$TAG_NAME" -m "$BRANCH_TYPE: $BRANCH_NAME"
|
|
101
104
|
git push origin "$TAG_NAME"
|
|
102
105
|
|
|
@@ -108,13 +111,13 @@ fi
|
|
|
108
111
|
|
|
109
112
|
```bash
|
|
110
113
|
if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
|
|
111
|
-
echo "Merging $TAG_NAME back to
|
|
114
|
+
echo "Merging $TAG_NAME back to $GF_DEVELOP_BRANCH..."
|
|
112
115
|
|
|
113
|
-
git checkout
|
|
114
|
-
git pull origin
|
|
116
|
+
git checkout $GF_DEVELOP_BRANCH
|
|
117
|
+
git pull origin $GF_DEVELOP_BRANCH
|
|
115
118
|
|
|
116
119
|
# Merge with merge commit (preserve history)
|
|
117
|
-
git merge
|
|
120
|
+
git merge $GF_MAIN_BRANCH -m "Merge $TAG_NAME back to $GF_DEVELOP_BRANCH"
|
|
118
121
|
|
|
119
122
|
# Handle conflicts
|
|
120
123
|
CONFLICTS=$(git diff --name-only --diff-filter=U | wc -l)
|
|
@@ -125,48 +128,55 @@ if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
|
|
|
125
128
|
# Options: resolve, abort
|
|
126
129
|
}
|
|
127
130
|
|
|
128
|
-
git push origin
|
|
131
|
+
git push origin $GF_DEVELOP_BRANCH
|
|
129
132
|
|
|
130
133
|
# CRITICAL: Verify push and update tracking refs
|
|
131
|
-
git fetch origin
|
|
134
|
+
git fetch origin $GF_DEVELOP_BRANCH:refs/remotes/origin/$GF_DEVELOP_BRANCH --force --quiet
|
|
132
135
|
LOCAL_SHA=$(git rev-parse HEAD)
|
|
133
|
-
REMOTE_SHA=$(git rev-parse origin
|
|
136
|
+
REMOTE_SHA=$(git rev-parse origin/$GF_DEVELOP_BRANCH)
|
|
134
137
|
if [ "$LOCAL_SHA" = "$REMOTE_SHA" ]; then
|
|
135
138
|
echo "✅ Push verified - local/remote in sync"
|
|
136
139
|
else
|
|
137
140
|
echo "⚠️ Push verification FAILED"
|
|
138
141
|
echo " Local: $LOCAL_SHA"
|
|
139
142
|
echo " Remote: $REMOTE_SHA"
|
|
140
|
-
echo " → Try: git push origin
|
|
143
|
+
echo " → Try: git push origin $GF_DEVELOP_BRANCH --force-with-lease"
|
|
141
144
|
fi
|
|
142
145
|
|
|
143
|
-
echo "✅ Merged back to
|
|
146
|
+
echo "✅ Merged back to $GF_DEVELOP_BRANCH"
|
|
144
147
|
fi
|
|
145
148
|
```
|
|
146
149
|
|
|
147
|
-
### 5. Update Version (Release
|
|
150
|
+
### 5. Update Version (Release and Hotfix)
|
|
148
151
|
|
|
149
152
|
```bash
|
|
150
|
-
if [ "$BRANCH_TYPE" = "release" ]; then
|
|
151
|
-
# Increment minor version for next development
|
|
153
|
+
if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
|
|
152
154
|
MAJOR=$(echo $VERSION | cut -d'.' -f1)
|
|
153
155
|
MINOR=$(echo $VERSION | cut -d'.' -f2)
|
|
154
|
-
|
|
156
|
+
PATCH=$(echo $VERSION | cut -d'.' -f3)
|
|
157
|
+
|
|
158
|
+
if [ "$BRANCH_TYPE" = "release" ]; then
|
|
159
|
+
# Release: increment minor, reset patch
|
|
160
|
+
NEXT_VERSION="$MAJOR.$((MINOR + 1)).0"
|
|
161
|
+
else
|
|
162
|
+
# Hotfix: increment patch (patch was already bumped for the tag, bump again for next dev)
|
|
163
|
+
NEXT_VERSION="$MAJOR.$MINOR.$((PATCH + 2))"
|
|
164
|
+
fi
|
|
155
165
|
|
|
156
|
-
# Update config
|
|
157
|
-
sed -i "s/\"current\": \"
|
|
166
|
+
# Update config (using resolved config path)
|
|
167
|
+
sed -i "s/\"current\": \".*\"/\"current\": \"$NEXT_VERSION\"/" "$GF_CONFIG_FILE"
|
|
158
168
|
|
|
159
169
|
# Update source files
|
|
160
170
|
# csproj, package.json, etc.
|
|
161
171
|
|
|
162
172
|
git add -A
|
|
163
173
|
git commit -m "chore: bump version to $NEXT_VERSION for development"
|
|
164
|
-
git push origin
|
|
174
|
+
git push origin $GF_DEVELOP_BRANCH
|
|
165
175
|
|
|
166
176
|
# CRITICAL: Verify push and update tracking refs
|
|
167
|
-
git fetch origin
|
|
177
|
+
git fetch origin $GF_DEVELOP_BRANCH:refs/remotes/origin/$GF_DEVELOP_BRANCH --force --quiet
|
|
168
178
|
LOCAL_SHA=$(git rev-parse HEAD)
|
|
169
|
-
REMOTE_SHA=$(git rev-parse origin
|
|
179
|
+
REMOTE_SHA=$(git rev-parse origin/$GF_DEVELOP_BRANCH)
|
|
170
180
|
if [ "$LOCAL_SHA" = "$REMOTE_SHA" ]; then
|
|
171
181
|
echo "✅ Push verified - local/remote in sync"
|
|
172
182
|
else
|
|
@@ -182,14 +192,14 @@ fi
|
|
|
182
192
|
### 6. Clean Up Worktree
|
|
183
193
|
|
|
184
194
|
```bash
|
|
185
|
-
# Find worktree for this branch
|
|
186
|
-
WORKTREE_PATH=$(git worktree list | grep "
|
|
195
|
+
# Find worktree for this branch (use --porcelain for reliable parsing)
|
|
196
|
+
WORKTREE_PATH=$(git worktree list --porcelain | grep -B2 "branch refs/heads/$BRANCH" | grep "^worktree " | sed 's/^worktree //')
|
|
187
197
|
|
|
188
198
|
if [ -n "$WORKTREE_PATH" ] && [ -d "$WORKTREE_PATH" ]; then
|
|
189
199
|
echo "Removing worktree: $WORKTREE_PATH"
|
|
190
200
|
|
|
191
|
-
# Make sure we're not in the worktree
|
|
192
|
-
cd $(git rev-parse --show-toplevel)
|
|
201
|
+
# Make sure we're not in the worktree directory
|
|
202
|
+
cd "$GF_DEVELOP_PATH" 2>/dev/null || cd "$(git rev-parse --show-toplevel)"
|
|
193
203
|
|
|
194
204
|
git worktree remove "$WORKTREE_PATH" --force 2>/dev/null || {
|
|
195
205
|
rm -rf "$WORKTREE_PATH"
|
|
@@ -452,6 +452,7 @@ mkdir -p "$DEVELOP_PATH/.claude/gitflow/{plans,logs,cache,backup}"
|
|
|
452
452
|
"version": "2.0.0",
|
|
453
453
|
"repository": {
|
|
454
454
|
"name": "{PROJECT_NAME}",
|
|
455
|
+
"rootFolder": "{ROOT_FOLDER}",
|
|
455
456
|
"nameVariants": {
|
|
456
457
|
"pascalCaseDot": "{PascalCase.Dot}",
|
|
457
458
|
"pascalCase": "{PascalCase}",
|
|
@@ -459,7 +460,7 @@ mkdir -p "$DEVELOP_PATH/.claude/gitflow/{plans,logs,cache,backup}"
|
|
|
459
460
|
"snakeCase": "{snake_case}",
|
|
460
461
|
"displayName": "{Display Name}"
|
|
461
462
|
},
|
|
462
|
-
"
|
|
463
|
+
"defaultBranch": "main",
|
|
463
464
|
"remoteUrl": "{REPO_URL}"
|
|
464
465
|
},
|
|
465
466
|
"git": {
|
|
@@ -494,7 +495,8 @@ mkdir -p "$DEVELOP_PATH/.claude/gitflow/{plans,logs,cache,backup}"
|
|
|
494
495
|
"efcore": {
|
|
495
496
|
"enabled": true,
|
|
496
497
|
"validateOnCommit": true,
|
|
497
|
-
"blockDestructive": true
|
|
498
|
+
"blockDestructive": true,
|
|
499
|
+
"migrationNaming": "{context}_v{version}_{sequence}_{Description}"
|
|
498
500
|
},
|
|
499
501
|
"workflow": {
|
|
500
502
|
"push": {
|
|
@@ -504,6 +506,9 @@ mkdir -p "$DEVELOP_PATH/.claude/gitflow/{plans,logs,cache,backup}"
|
|
|
504
506
|
"autoLabels": true,
|
|
505
507
|
"requireReview": true
|
|
506
508
|
}
|
|
509
|
+
},
|
|
510
|
+
"language": {
|
|
511
|
+
"code": "{GF_LANG}"
|
|
507
512
|
}
|
|
508
513
|
}
|
|
509
514
|
```
|
|
@@ -16,19 +16,33 @@ Run through review checklist and merge the pull request with appropriate strateg
|
|
|
16
16
|
|
|
17
17
|
## EXECUTION SEQUENCE:
|
|
18
18
|
|
|
19
|
-
### 1. Load PR Context
|
|
19
|
+
### 1. Load Config and PR Context
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
+
# Load GitFlow config (sets GF_* variables)
|
|
23
|
+
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
|
|
24
|
+
|
|
22
25
|
CURRENT=$(git rev-parse --abbrev-ref HEAD)
|
|
23
|
-
GIT_PROVIDER
|
|
26
|
+
GIT_PROVIDER="$GF_PROVIDER"
|
|
27
|
+
|
|
28
|
+
# Try loading persisted PR state first
|
|
29
|
+
CONFIG_DIR=$(dirname "$GF_CONFIG_FILE")
|
|
30
|
+
PR_STATE_FILE="$CONFIG_DIR/cache/pr-state.json"
|
|
31
|
+
if [ -f "$PR_STATE_FILE" ]; then
|
|
32
|
+
PR_NUMBER=$(grep -oP '"pr_number":\s*"\K[^"]+' "$PR_STATE_FILE" | head -1)
|
|
33
|
+
TARGET_BRANCH=$(grep -oP '"target_branch":\s*"\K[^"]+' "$PR_STATE_FILE" | head -1)
|
|
34
|
+
echo "✓ Loaded PR state from cache: PR #$PR_NUMBER → $TARGET_BRANCH"
|
|
35
|
+
fi
|
|
24
36
|
|
|
25
|
-
#
|
|
26
|
-
if [ "$
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
# Fallback: query provider if no cached state
|
|
38
|
+
if [ -z "$PR_NUMBER" ]; then
|
|
39
|
+
if [ "$GIT_PROVIDER" = "github" ]; then
|
|
40
|
+
PR_NUMBER=$(gh pr list --head "$CURRENT" --json number --jq '.[0].number')
|
|
41
|
+
PR_STATUS=$(gh pr view $PR_NUMBER --json state,mergeable,reviews --jq '.')
|
|
42
|
+
elif [ "$GIT_PROVIDER" = "azuredevops" ]; then
|
|
43
|
+
PR_NUMBER=$(az repos pr list --source-branch "$CURRENT" --query "[0].pullRequestId" -o tsv)
|
|
44
|
+
PR_STATUS=$(az repos pr show --id $PR_NUMBER --query "{status:status,mergeStatus:mergeStatus}")
|
|
45
|
+
fi
|
|
32
46
|
fi
|
|
33
47
|
|
|
34
48
|
[ -z "$PR_NUMBER" ] && {
|
|
@@ -125,7 +139,7 @@ case "$BRANCH_TYPE" in
|
|
|
125
139
|
release|hotfix)
|
|
126
140
|
MERGE_STRATEGY="merge"
|
|
127
141
|
DELETE_BRANCH=true
|
|
128
|
-
MERGE_BACK="
|
|
142
|
+
MERGE_BACK="$GF_DEVELOP_BRANCH"
|
|
129
143
|
;;
|
|
130
144
|
esac
|
|
131
145
|
```
|
|
@@ -16,23 +16,21 @@ Create a pull request with proper target, title, and description based on branch
|
|
|
16
16
|
|
|
17
17
|
## EXECUTION SEQUENCE:
|
|
18
18
|
|
|
19
|
-
### 1. Detect
|
|
19
|
+
### 1. Load Config and Detect Provider
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
[[ "$
|
|
22
|
+
# Load GitFlow config (sets GF_* variables)
|
|
23
|
+
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
|
|
24
|
+
|
|
25
|
+
GIT_PROVIDER="$GF_PROVIDER"
|
|
26
|
+
|
|
27
|
+
# Extract Azure DevOps details if needed
|
|
28
|
+
if [ "$GIT_PROVIDER" = "azuredevops" ]; then
|
|
29
|
+
[[ "$GF_REMOTE_URL" =~ dev\.azure\.com/([^/]+)/([^/]+)/_git/([^/]+) ]] && {
|
|
30
30
|
AZURE_ORG="${BASH_REMATCH[1]}"
|
|
31
31
|
AZURE_PROJECT="${BASH_REMATCH[2]}"
|
|
32
32
|
AZURE_REPO="${BASH_REMATCH[3]}"
|
|
33
33
|
}
|
|
34
|
-
else
|
|
35
|
-
GIT_PROVIDER="unknown"
|
|
36
34
|
fi
|
|
37
35
|
```
|
|
38
36
|
|
|
@@ -42,10 +40,10 @@ fi
|
|
|
42
40
|
CURRENT=$(git rev-parse --abbrev-ref HEAD)
|
|
43
41
|
|
|
44
42
|
case "$CURRENT" in
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*)
|
|
43
|
+
${GF_FEATURE_PREFIX}*) TARGET_BRANCH="$GF_DEVELOP_BRANCH" ;;
|
|
44
|
+
${GF_RELEASE_PREFIX}*) TARGET_BRANCH="$GF_MAIN_BRANCH" ;;
|
|
45
|
+
${GF_HOTFIX_PREFIX}*) TARGET_BRANCH="$GF_MAIN_BRANCH" ;;
|
|
46
|
+
*) TARGET_BRANCH="$GF_DEVELOP_BRANCH" ;;
|
|
49
47
|
esac
|
|
50
48
|
```
|
|
51
49
|
|
|
@@ -90,16 +88,26 @@ EXISTING_PR=$(gh pr list --head "$CURRENT" --json number --jq '.[0].number' 2>/d
|
|
|
90
88
|
### 4. Run Pre-PR Checks
|
|
91
89
|
|
|
92
90
|
```bash
|
|
93
|
-
# Build check
|
|
91
|
+
# Build check (multi-runtime detection)
|
|
94
92
|
echo "Running build check..."
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
# Migration check
|
|
101
|
-
echo "Checking migrations..."
|
|
102
|
-
dotnet ef migrations list 2>&1 || echo "No migrations or EF Core not configured"
|
|
93
|
+
if [ -f "*.sln" ] || ls *.csproj 2>/dev/null | head -1 > /dev/null; then
|
|
94
|
+
dotnet build --no-restore 2>&1 || {
|
|
95
|
+
echo "❌ .NET build failed. Fix before creating PR."
|
|
96
|
+
STOP
|
|
97
|
+
}
|
|
98
|
+
# Migration check
|
|
99
|
+
echo "Checking migrations..."
|
|
100
|
+
dotnet ef migrations list 2>&1 || echo "No migrations or EF Core not configured"
|
|
101
|
+
elif [ -f "package.json" ]; then
|
|
102
|
+
npm run build 2>&1 || {
|
|
103
|
+
echo "❌ npm build failed. Fix before creating PR."
|
|
104
|
+
STOP
|
|
105
|
+
}
|
|
106
|
+
elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
|
|
107
|
+
echo "Python project detected — skipping build check"
|
|
108
|
+
else
|
|
109
|
+
echo "⚠️ No known build system detected — skipping build check"
|
|
110
|
+
fi
|
|
103
111
|
```
|
|
104
112
|
|
|
105
113
|
### 5. Generate PR Content
|
|
@@ -112,7 +120,7 @@ BRANCH_TYPE=$(echo $CURRENT | cut -d'/' -f1)
|
|
|
112
120
|
case "$BRANCH_TYPE" in
|
|
113
121
|
feature) TITLE="feat: $BRANCH_NAME" ;;
|
|
114
122
|
hotfix) TITLE="fix: $BRANCH_NAME" ;;
|
|
115
|
-
release) TITLE="release: v$
|
|
123
|
+
release) TITLE="release: v$GF_VERSION" ;;
|
|
116
124
|
esac
|
|
117
125
|
```
|
|
118
126
|
|
|
@@ -187,13 +195,19 @@ fi
|
|
|
187
195
|
### 8. Store PR Info
|
|
188
196
|
|
|
189
197
|
```bash
|
|
190
|
-
#
|
|
198
|
+
# Persist PR info for merge step (uses config path for portability)
|
|
199
|
+
CONFIG_DIR=$(dirname "$GF_CONFIG_FILE")
|
|
200
|
+
cat > "$CONFIG_DIR/cache/pr-state.json" << EOF
|
|
191
201
|
{
|
|
192
|
-
"pr_number": $PR_NUMBER,
|
|
202
|
+
"pr_number": "$PR_NUMBER",
|
|
193
203
|
"pr_url": "$PR_URL",
|
|
204
|
+
"source_branch": "$CURRENT",
|
|
194
205
|
"target_branch": "$TARGET_BRANCH",
|
|
195
|
-
"git_provider": "$GIT_PROVIDER"
|
|
206
|
+
"git_provider": "$GIT_PROVIDER",
|
|
207
|
+
"created_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
196
208
|
}
|
|
209
|
+
EOF
|
|
210
|
+
echo "✓ PR state saved to $CONFIG_DIR/cache/pr-state.json"
|
|
197
211
|
```
|
|
198
212
|
|
|
199
213
|
### 9. Summary
|
|
@@ -31,18 +31,22 @@ Create a new feature/release/hotfix branch with optional worktree setup.
|
|
|
31
31
|
|
|
32
32
|
## EXECUTION SEQUENCE:
|
|
33
33
|
|
|
34
|
-
### 1. Analyze Context
|
|
34
|
+
### 1. Load Config and Analyze Context
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
+
# Load GitFlow config (sets GF_* variables)
|
|
38
|
+
# See _shared.md → READ_GITFLOW_CONFIG for all variables
|
|
39
|
+
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
|
|
40
|
+
|
|
37
41
|
CURRENT_BRANCH=$(git branch --show-current)
|
|
38
42
|
git fetch origin --quiet
|
|
39
43
|
|
|
40
|
-
# Version
|
|
41
|
-
VERSION
|
|
44
|
+
# Version from config
|
|
45
|
+
VERSION="$GF_VERSION"
|
|
42
46
|
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "none")
|
|
43
47
|
|
|
44
48
|
# Develop ahead of main?
|
|
45
|
-
DEVELOP_AHEAD=$(git rev-list --count origin
|
|
49
|
+
DEVELOP_AHEAD=$(git rev-list --count origin/$GF_MAIN_BRANCH..origin/$GF_DEVELOP_BRANCH 2>/dev/null || echo "0")
|
|
46
50
|
|
|
47
51
|
# Working directory status
|
|
48
52
|
DIRTY=$(git status --porcelain | wc -l)
|
|
@@ -129,17 +133,17 @@ esac
|
|
|
129
133
|
|
|
130
134
|
### 6. Create Branch and Worktree
|
|
131
135
|
|
|
132
|
-
**Read worktree mode from config:**
|
|
136
|
+
**Read worktree mode from config (already loaded by read_gitflow_config):**
|
|
133
137
|
```bash
|
|
134
|
-
WORKTREE_MODE
|
|
138
|
+
WORKTREE_MODE="$GF_WORKTREE_MODE"
|
|
135
139
|
```
|
|
136
140
|
|
|
137
|
-
**Mode: organized**
|
|
141
|
+
**Mode: organized (uses absolute paths from config)**
|
|
138
142
|
```bash
|
|
139
143
|
case "$branch_type" in
|
|
140
|
-
feature) WORKTREE_PATH="
|
|
141
|
-
release) WORKTREE_PATH="
|
|
142
|
-
hotfix) WORKTREE_PATH="
|
|
144
|
+
feature) WORKTREE_PATH="$GF_FEATURES_PATH/$BRANCH_NAME" ;;
|
|
145
|
+
release) WORKTREE_PATH="$GF_RELEASES_PATH/v$VERSION" ;;
|
|
146
|
+
hotfix) WORKTREE_PATH="$GF_HOTFIXES_PATH/$BRANCH_NAME" ;;
|
|
143
147
|
esac
|
|
144
148
|
|
|
145
149
|
mkdir -p "$(dirname $WORKTREE_PATH)"
|
|
@@ -181,13 +185,15 @@ API_DIR=$(find "$WORKTREE_PATH" -type d -name "*.Api" -path "*/src/*" | head -1)
|
|
|
181
185
|
WEB_DIR=$(find "$WORKTREE_PATH" -type d -name "*-web" -path "*/web/*" | head -1)
|
|
182
186
|
|
|
183
187
|
# Generate unique ports based on branch name hash (to avoid conflicts between worktrees)
|
|
184
|
-
|
|
188
|
+
# Use shasum (portable across macOS/Linux/Windows Git Bash) with md5sum fallback
|
|
189
|
+
HASH=$(echo "$BRANCH_NAME" | shasum 2>/dev/null || echo "$BRANCH_NAME" | md5sum 2>/dev/null || echo "$BRANCH_NAME" | cksum)
|
|
190
|
+
HASH=$(echo "$HASH" | cut -c1-4)
|
|
185
191
|
HASH_NUM=$((16#$HASH % 100))
|
|
186
192
|
API_PORT=$((5200 + HASH_NUM))
|
|
187
193
|
WEB_PORT=$((5300 + HASH_NUM))
|
|
188
194
|
|
|
189
|
-
# Project
|
|
190
|
-
PROJECT_NAME=$(
|
|
195
|
+
# Project name from config (not from pwd)
|
|
196
|
+
PROJECT_NAME=$(echo "$GF_PROJECT_NAME" | tr '[:upper:]' '[:lower:]')
|
|
191
197
|
DB_NAME=$(echo "${PROJECT_NAME}_${branch_type}_${BRANCH_NAME}" | cut -c1-63)
|
|
192
198
|
```
|
|
193
199
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"version": "2.0.0",
|
|
3
3
|
"repository": {
|
|
4
4
|
"name": "",
|
|
5
|
+
"rootFolder": "",
|
|
5
6
|
"nameVariants": {
|
|
6
7
|
"pascalCaseDot": "",
|
|
7
8
|
"pascalCase": "",
|
|
@@ -13,7 +14,7 @@
|
|
|
13
14
|
"remoteUrl": ""
|
|
14
15
|
},
|
|
15
16
|
"git": {
|
|
16
|
-
"provider": "
|
|
17
|
+
"provider": "",
|
|
17
18
|
"branches": {
|
|
18
19
|
"main": "main",
|
|
19
20
|
"develop": "develop"
|
|
@@ -28,9 +29,11 @@
|
|
|
28
29
|
"enabled": true,
|
|
29
30
|
"mode": "organized",
|
|
30
31
|
"structure": {
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
32
|
+
"main": "",
|
|
33
|
+
"develop": "",
|
|
34
|
+
"features": "",
|
|
35
|
+
"releases": "",
|
|
36
|
+
"hotfixes": ""
|
|
34
37
|
}
|
|
35
38
|
},
|
|
36
39
|
"versioning": {
|