@neferbyte/cherry-release-cli 1.0.5 → 1.0.6
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/bin/cherry-release +80 -23
- package/package.json +1 -1
package/bin/cherry-release
CHANGED
|
@@ -3,12 +3,41 @@ set -e
|
|
|
3
3
|
|
|
4
4
|
# ─── Constants ────────────────────────────────────────────────────────────────
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
ALL_BRANCHES=(development staging production)
|
|
7
7
|
ORIGINAL_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
|
8
8
|
WORKTREE_DIR="/tmp/cherry-release-test"
|
|
9
9
|
WORKTREES_TO_CLEAN=()
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
11
11
|
|
|
12
|
+
# ─── Parse --force flag ──────────────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
FORCE_ALL=false
|
|
15
|
+
declare -A FORCE_BRANCH
|
|
16
|
+
for b in "${ALL_BRANCHES[@]}"; do FORCE_BRANCH[$b]=false; done
|
|
17
|
+
|
|
18
|
+
if [[ "$1" == "--force" ]]; then
|
|
19
|
+
shift
|
|
20
|
+
if [[ $# -eq 0 ]]; then
|
|
21
|
+
FORCE_ALL=true
|
|
22
|
+
else
|
|
23
|
+
for arg in "$@"; do
|
|
24
|
+
found=false
|
|
25
|
+
for b in "${ALL_BRANCHES[@]}"; do
|
|
26
|
+
if [[ "$arg" == "$b" ]]; then
|
|
27
|
+
FORCE_BRANCH[$b]=true
|
|
28
|
+
found=true
|
|
29
|
+
break
|
|
30
|
+
fi
|
|
31
|
+
done
|
|
32
|
+
if [[ "$found" == false ]]; then
|
|
33
|
+
echo -e "\033[1;31mError:\033[0m Unknown branch '$arg'. Valid branches: ${ALL_BRANCHES[*]}" >&2
|
|
34
|
+
exit 1
|
|
35
|
+
fi
|
|
36
|
+
done
|
|
37
|
+
shift $#
|
|
38
|
+
fi
|
|
39
|
+
fi
|
|
40
|
+
|
|
12
41
|
# ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
13
42
|
|
|
14
43
|
fail() {
|
|
@@ -24,6 +53,15 @@ check_ok() {
|
|
|
24
53
|
echo -e " \033[1;32m✓\033[0m $1"
|
|
25
54
|
}
|
|
26
55
|
|
|
56
|
+
should_deploy() {
|
|
57
|
+
local branch=$1
|
|
58
|
+
local commit_count=$2
|
|
59
|
+
[[ "$FORCE_ALL" == true ]] && return 0
|
|
60
|
+
[[ "${FORCE_BRANCH[$branch]}" == true ]] && return 0
|
|
61
|
+
[[ "$commit_count" -gt 0 ]] && return 0
|
|
62
|
+
return 1
|
|
63
|
+
}
|
|
64
|
+
|
|
27
65
|
cleanup() {
|
|
28
66
|
for wt in "${WORKTREES_TO_CLEAN[@]}"; do
|
|
29
67
|
if [[ -d "$wt" ]]; then
|
|
@@ -79,7 +117,7 @@ fi
|
|
|
79
117
|
check_ok "development can fast-forward to origin"
|
|
80
118
|
|
|
81
119
|
# 6. staging and production have no local-only commits ahead of origin
|
|
82
|
-
for branch in
|
|
120
|
+
for branch in staging production; do
|
|
83
121
|
local_ref=$(git rev-parse "$branch" 2>/dev/null || true)
|
|
84
122
|
remote_ref=$(git rev-parse "origin/$branch" 2>/dev/null || true)
|
|
85
123
|
|
|
@@ -96,7 +134,7 @@ check_ok "No local-only commits on staging/production"
|
|
|
96
134
|
|
|
97
135
|
# 7. Auto-discover commits to promote (per target branch)
|
|
98
136
|
declare -A COMMITS_FOR
|
|
99
|
-
for branch in
|
|
137
|
+
for branch in staging production; do
|
|
100
138
|
hashes=$(git cherry "origin/$branch" origin/development | grep '^+' | awk '{print $2}')
|
|
101
139
|
|
|
102
140
|
# Filter out version bump commits (commit-and-tag-version)
|
|
@@ -114,15 +152,27 @@ done
|
|
|
114
152
|
staging_count=$(echo "${COMMITS_FOR[staging]}" | wc -w | tr -d ' ')
|
|
115
153
|
production_count=$(echo "${COMMITS_FOR[production]}" | wc -w | tr -d ' ')
|
|
116
154
|
|
|
117
|
-
|
|
118
|
-
|
|
155
|
+
# Check if there's anything to do
|
|
156
|
+
has_work=false
|
|
157
|
+
for branch in "${ALL_BRANCHES[@]}"; do
|
|
158
|
+
count=0
|
|
159
|
+
[[ "$branch" == "staging" ]] && count=$staging_count
|
|
160
|
+
[[ "$branch" == "production" ]] && count=$production_count
|
|
161
|
+
if should_deploy "$branch" "$count"; then
|
|
162
|
+
has_work=true
|
|
163
|
+
break
|
|
164
|
+
fi
|
|
165
|
+
done
|
|
166
|
+
|
|
167
|
+
if [[ "$has_work" == false ]]; then
|
|
168
|
+
echo -e "\n\033[1;32mNothing to do.\033[0m All branches are up to date."
|
|
119
169
|
exit 0
|
|
120
170
|
fi
|
|
121
171
|
|
|
122
172
|
check_ok "Discovered commits to promote (staging: $staging_count, production: $production_count)"
|
|
123
173
|
|
|
124
174
|
# 8. Dry-run cherry-picks in temporary worktrees
|
|
125
|
-
for branch in
|
|
175
|
+
for branch in staging production; do
|
|
126
176
|
commits=(${COMMITS_FOR[$branch]})
|
|
127
177
|
if [[ ${#commits[@]} -eq 0 ]]; then
|
|
128
178
|
continue
|
|
@@ -155,24 +205,29 @@ echo -e "\n\033[1;32mAll pre-flight checks passed.\033[0m"
|
|
|
155
205
|
# ─── Phase 2: Execution ──────────────────────────────────────────────────────
|
|
156
206
|
|
|
157
207
|
# --- development ---
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
git checkout development
|
|
161
|
-
git pull --ff-only
|
|
162
|
-
"$SCRIPT_DIR/cherry-release-version" patch
|
|
163
|
-
git push --follow-tags origin development
|
|
164
|
-
echo -e " \033[1;32m✓\033[0m development released"
|
|
208
|
+
if should_deploy "development" "$staging_count"; then
|
|
209
|
+
step "Deploying to development"
|
|
210
|
+
git checkout development
|
|
211
|
+
git pull --ff-only
|
|
212
|
+
"$SCRIPT_DIR/cherry-release-version" patch
|
|
213
|
+
git push --follow-tags origin development
|
|
214
|
+
echo -e " \033[1;32m✓\033[0m development released"
|
|
215
|
+
else
|
|
216
|
+
echo -e "\n\033[1;34m→\033[0m Skipping development (up to date)"
|
|
217
|
+
fi
|
|
165
218
|
|
|
166
219
|
# --- staging ---
|
|
167
220
|
staging_commits=(${COMMITS_FOR[staging]})
|
|
168
|
-
if
|
|
221
|
+
if should_deploy "staging" "${#staging_commits[@]}"; then
|
|
169
222
|
step "Deploying to staging (${#staging_commits[@]} commit(s))"
|
|
170
223
|
git checkout staging
|
|
171
224
|
git reset --hard origin/staging --quiet
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
225
|
+
if [[ ${#staging_commits[@]} -gt 0 ]]; then
|
|
226
|
+
for hash in "${staging_commits[@]}"; do
|
|
227
|
+
git cherry-pick "$hash"
|
|
228
|
+
done
|
|
229
|
+
git push origin staging
|
|
230
|
+
fi
|
|
176
231
|
"$SCRIPT_DIR/cherry-release-version" patch
|
|
177
232
|
git push --follow-tags origin staging
|
|
178
233
|
echo -e " \033[1;32m✓\033[0m staging released"
|
|
@@ -182,14 +237,16 @@ fi
|
|
|
182
237
|
|
|
183
238
|
# --- production ---
|
|
184
239
|
production_commits=(${COMMITS_FOR[production]})
|
|
185
|
-
if
|
|
240
|
+
if should_deploy "production" "${#production_commits[@]}"; then
|
|
186
241
|
step "Deploying to production (${#production_commits[@]} commit(s))"
|
|
187
242
|
git checkout production
|
|
188
243
|
git reset --hard origin/production --quiet
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
244
|
+
if [[ ${#production_commits[@]} -gt 0 ]]; then
|
|
245
|
+
for hash in "${production_commits[@]}"; do
|
|
246
|
+
git cherry-pick "$hash"
|
|
247
|
+
done
|
|
248
|
+
git push origin production
|
|
249
|
+
fi
|
|
193
250
|
"$SCRIPT_DIR/cherry-release-version" patch
|
|
194
251
|
git push --follow-tags origin production
|
|
195
252
|
echo -e " \033[1;32m✓\033[0m production released"
|