@neferbyte/cherry-release-cli 1.0.4 → 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.
Files changed (2) hide show
  1. package/bin/cherry-release +96 -37
  2. package/package.json +1 -1
@@ -3,12 +3,41 @@ set -e
3
3
 
4
4
  # ─── Constants ────────────────────────────────────────────────────────────────
5
5
 
6
- BRANCHES=(staging production)
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 "${BRANCHES[@]}"; do
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 "${BRANCHES[@]}"; do
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
- if [[ "$staging_count" -eq 0 && "$production_count" -eq 0 ]]; then
118
- echo -e "\n\033[1;32mNothing to promote.\033[0m staging and production are up to date."
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 "${BRANCHES[@]}"; do
175
+ for branch in staging production; do
126
176
  commits=(${COMMITS_FOR[$branch]})
127
177
  if [[ ${#commits[@]} -eq 0 ]]; then
128
178
  continue
@@ -155,45 +205,54 @@ echo -e "\n\033[1;32mAll pre-flight checks passed.\033[0m"
155
205
  # ─── Phase 2: Execution ──────────────────────────────────────────────────────
156
206
 
157
207
  # --- development ---
158
- step "Deploying to development"
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
- step "Deploying to staging (${#staging_commits[@]} commit(s))"
169
-
170
- git checkout staging
171
- git reset --hard origin/staging --quiet
172
- if [[ ${#staging_commits[@]} -gt 0 ]]; then
173
- for hash in "${staging_commits[@]}"; do
174
- git cherry-pick "$hash"
175
- done
176
- git push origin staging
221
+ if should_deploy "staging" "${#staging_commits[@]}"; then
222
+ step "Deploying to staging (${#staging_commits[@]} commit(s))"
223
+ git checkout staging
224
+ git reset --hard origin/staging --quiet
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
231
+ "$SCRIPT_DIR/cherry-release-version" patch
232
+ git push --follow-tags origin staging
233
+ echo -e " \033[1;32m✓\033[0m staging released"
234
+ else
235
+ echo -e "\n\033[1;34m→\033[0m Skipping staging (up to date)"
177
236
  fi
178
- "$SCRIPT_DIR/cherry-release-version" patch
179
- git push --follow-tags origin staging
180
- echo -e " \033[1;32m✓\033[0m staging released"
181
237
 
182
238
  # --- production ---
183
239
  production_commits=(${COMMITS_FOR[production]})
184
- step "Deploying to production (${#production_commits[@]} commit(s))"
185
-
186
- git checkout production
187
- git reset --hard origin/production --quiet
188
- if [[ ${#production_commits[@]} -gt 0 ]]; then
189
- for hash in "${production_commits[@]}"; do
190
- git cherry-pick "$hash"
191
- done
192
- git push origin production
240
+ if should_deploy "production" "${#production_commits[@]}"; then
241
+ step "Deploying to production (${#production_commits[@]} commit(s))"
242
+ git checkout production
243
+ git reset --hard origin/production --quiet
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
250
+ "$SCRIPT_DIR/cherry-release-version" patch
251
+ git push --follow-tags origin production
252
+ echo -e " \033[1;32m✓\033[0m production released"
253
+ else
254
+ echo -e "\n\033[1;34m→\033[0m Skipping production (up to date)"
193
255
  fi
194
- "$SCRIPT_DIR/cherry-release-version" patch
195
- git push --follow-tags origin production
196
- echo -e " \033[1;32m✓\033[0m production released"
197
256
 
198
257
  # ─── Phase 3: Cleanup ────────────────────────────────────────────────────────
199
258
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neferbyte/cherry-release-cli",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "Cherry-pick commits across environment branches and tag releases",
5
5
  "license": "MIT",
6
6
  "bin": {