-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathgit_tag.sh
More file actions
executable file
·298 lines (257 loc) · 11.2 KB
/
Copy pathgit_tag.sh
File metadata and controls
executable file
·298 lines (257 loc) · 11.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
#!/bin/bash
set -e
VersionFile=./skills/xjb-coding/SKILL.md
SyncFile=./skills/xjb-coding/.auto_coding/start_coding.md
PluginJsonFile=./.claude-plugin/plugin.json
CodexPluginJsonFile=./.codex-plugin/plugin.json
# SKILL.md 顶部样式:
# > **SkillName**:`xjb_coding`
# > **Version**:v0.0.1
# 中文冒号「:」 + backtick 包裹 SkillName + 裸 vX.X.X 包裹 Version。
ProductName=$(grep -E '^> \*\*SkillName\*\*:' "$VersionFile" | head -1 | sed -E 's/.*`([^`]+)`.*/\1/')
CURRENT_VERSION=$(grep -E '^> \*\*Version\*\*:' "$VersionFile" | head -1 | sed -E 's/.*:(v[0-9]+\.[0-9]+\.[0-9]+).*/\1/')
NEXT_VERSION=""
OS_TYPE="Unknown"
GetOSType() {
uNames=`uname -s`
osName=${uNames: 0: 4}
if [ "$osName" == "Darw" ] # Darwin
then
OS_TYPE="Darwin"
elif [ "$osName" == "Linu" ] # Linux
then
OS_TYPE="Linux"
elif [ "$osName" == "MING" ] # MINGW, windows, git-bash
then
OS_TYPE="Windows"
else
OS_TYPE="Unknown"
fi
}
GetOSType
function to_run() {
if [ -z "$1" ]; then
baseStr=$(echo ${CURRENT_VERSION} | cut -d'.' -f1) # Get the base version (v0)
base=${baseStr//v/} # Get the base version (0)
major=$(echo ${CURRENT_VERSION} | cut -d'.' -f2) # Get the major version (0)
minor=$(echo ${CURRENT_VERSION}| cut -d'.' -f3) # Get the minor version (1)
minor=$((minor+1)) # Increment the minor version
if ((minor==1000)); then # Check if minor version is 100
minor=0 # Reset minor version to 0
major=$((major+1)) # Increment major version
fi
if ((major==1000)); then # Check if major version is 100
major=0 # Reset major version to 0
base=$((base+1)) # Increment base version
fi
NEXT_VERSION="v${base}.${major}.${minor}"
return 0
elif [ "$1" == "custom" ]; then
echo "============================ ${ProductName} ============================"
echo " 1、release [-${ProductName}-]"
echo " current version [-${CURRENT_VERSION}-]"
echo "======================================================================"
read -p "$(echo -e "please input version string [example;v0.0.1]")" inputString
if [[ "$inputString" =~ ^v.* ]]; then
NEXT_VERSION=${inputString}
else
NEXT_VERSION=v${inputString}
fi
return 0
else
return 1
fi
}
function get_pre_del_version_no {
local v_str=$1
baseStr=$(echo $v_str | cut -d'.' -f1) # Get the base version (v0)
base=${baseStr//v/} # Get the base version (0)
major=$(echo $v_str | cut -d'.' -f2) # Get the major version (0)
minor=$(echo $v_str | cut -d'.' -f3) # Get the minor version (1)
if ((minor>0)); then # Check if minor version is more than 0
minor=$((minor-1)) # Decrement the minor version
else
minor=999 # Reset minor version to 99
if ((major>0)); then # Check if major version is more than 0
major=$((major-1)) # Decrement major version
else
major=999 # Reset major version to 99
if ((base>0)); then # Check if base version is more than 0
base=$((base-1)) # Decrement base version
else
echo "Error: Version cannot be decremented."
exit 1
fi
fi
fi
pre_v_no="${base}.${major}.${minor}"
echo $pre_v_no
}
function git_handle_ready() {
bash scripts/update_upstreams.sh --check
echo "Current Version With ${CURRENT_VERSION}"
echo "Next Version With ${NEXT_VERSION}"
local plain_version="${NEXT_VERSION#v}"
# SKILL.md:`> **Version**:vX.X.X` (中文冒号,无引号)
sed -i -e "s/^\(> \*\*Version\*\*:\)v[0-9.]*/\1${NEXT_VERSION}/" "$VersionFile"
# SKILL.md YAML frontmatter:`version: X.X.X`(hermes skills 必需字段)
sed -i -e "s/^version: [0-9.]*/version: ${plain_version}/" "$VersionFile"
# start_coding.md:`> **版本**:vX.X.X <任意后缀>`(后缀无关,只替换版本号本身;
# 旧模式硬编码「 通用版」后缀,footer 改文案后 sed 静默不匹配,曾致版本停在 v0.0.10)
if [ -f "$SyncFile" ]; then
sed -i -e "s/^\(> \*\*版本\*\*:\)v[0-9.]*/\1${NEXT_VERSION}/" "$SyncFile"
fi
# plugin.json:`"version": "X.X.X"` —— Claude Code / Codex plugin 更新检测的字段(无 v 前缀)
if [ -f "$PluginJsonFile" ]; then
sed -i -e "s/\"version\": \"[0-9.]*\"/\"version\": \"${plain_version}\"/" "$PluginJsonFile"
fi
if [ -f "$CodexPluginJsonFile" ]; then
sed -i -e "s/\"version\": \"[^\"]*\"/\"version\": \"${plain_version}\"/" "$CodexPluginJsonFile"
fi
if [[ $OS_TYPE == "Darwin" ]]; then
rm -f "${VersionFile}-e" "${SyncFile}-e" "${PluginJsonFile}-e" "${CodexPluginJsonFile}-e" 2>/dev/null || true
fi
}
function find_prev_release_commit() {
git log --fixed-strings --grep='Release:--:' --format='%H' -n 1 HEAD || true
}
function gen_changelog_if_possible() {
local del_version_no="$1"
local out_dir out_file prev_release_sha range_end range
out_dir="changelog"
mkdir -p "${out_dir}"
out_file="${out_dir}/${NEXT_VERSION}.md"
prev_release_sha="$(find_prev_release_commit)"
range_end="HEAD"
if [ -z "${prev_release_sha}" ]; then
# 没有历史 release marker:从仓库首提交到当前 HEAD
prev_release_sha="$(git rev-list --max-parents=0 HEAD | tail -n 1)"
range="${prev_release_sha}..${range_end}"
echo "[changelog] no previous Release marker found, use range ${range}"
local prev_label="root(${prev_release_sha:0:7})"
else
range="${prev_release_sha}..${range_end}"
echo "[changelog] previous Release marker: ${prev_release_sha}"
local prev_label="${prev_release_sha:0:7}"
fi
local commit_count
commit_count="$(git rev-list --count "${range}" 2>/dev/null || echo 0)"
{
echo "## ${NEXT_VERSION} ChangeLog"
echo
echo "- Release:--: ${NEXT_VERSION}_$(date -u +"%Y-%m-%d_%H:%M:%S")_UTC"
echo "- Range: ${range}"
echo "- Commits: ${commit_count}"
echo
echo "### commit infos"
echo
if [[ "${commit_count}" == "0" ]]; then
echo "- (no commits between releases)"
echo "- (no file changes)"
else
# 概览(总增删行/文件数)
# 例如: " 3 files changed, 10 insertions(+), 2 deletions(-)"
local shortstat
shortstat="$(git diff --shortstat "${range}" 2>/dev/null || true)"
if [ -n "${shortstat}" ]; then
echo "- ${shortstat}"
else
echo "- (no file changes)"
fi
echo
# 文件级统计(不输出具体 diff 内容)
echo '```'
git diff --stat "${range}" 2>/dev/null || true
echo '```'
fi
echo
echo "### commit messages"
echo
if [[ "${commit_count}" == "0" ]]; then
echo "- (no commits between releases)"
else
git log --reverse --date=short --pretty=format:"- %ad %h %s" "${range}" || true
fi
echo
} > "${out_file}"
echo "[changelog] wrote ${out_file}"
if [ -n "${del_version_no}" ]; then
local pre_file="${out_dir}/v${del_version_no}.md"
if [ -f "${pre_file}" ]; then
if git ls-files --error-unmatch "${pre_file}" >/dev/null 2>&1; then
git rm -f "${pre_file}"
else
rm -f "${pre_file}" 2>/dev/null || true
fi
echo "[changelog] removed ${pre_file}"
fi
fi
}
# run_release_step 记录当前步骤再执行;&& 链中途失败不会触发 set -e,靠它指出停在哪一步。
function run_release_step() {
last_release_step="$*"
"$@"
}
function git_handle_push() {
local current_version_no=${CURRENT_VERSION//v/}
local next_version_no=${NEXT_VERSION//v/}
local pre_del_version_no=$(get_pre_del_version_no "$current_version_no")
echo "Pre Del Version With v"${pre_del_version_no}
# Standalone health gate (B): refuse to cut an aggregation tag if any
# submodule fails to build/tidy cleanly without go.work support.
if [ -x ./scripts/check_standalone.sh ]; then
./scripts/check_standalone.sh
fi
echo current_version_no: $current_version_no
echo next_version_no: $next_version_no
echo pre_del_version_no: $pre_del_version_no
if ! { run_release_step gen_changelog_if_possible "${pre_del_version_no}" \
&& run_release_step git add . \
&& run_release_step git commit -m "Release:--: v${next_version_no}_$(date -u +"%Y-%m-%d_%H:%M:%S")"_"UTC" \
&& run_release_step git tag v${next_version_no} \
&& run_release_step git tag -f latest v${next_version_no}; }; then
echo "[git_tag] ERROR: release v${next_version_no} stopped before push at: ${last_release_step}" >&2
echo "[git_tag] nothing was pushed; inspect git status / git log -1 / git tag, fix the cause, then rerun." >&2
exit 1
fi
local push_failed_remotes=""
for remote in $(git remote)
do
echo "Pushing to ${remote}..."
if ! { run_release_step git push --delete ${remote} latest \
&& run_release_step git push ${remote} \
&& run_release_step git push ${remote} latest \
&& run_release_step git push ${remote} v${next_version_no}; }; then
echo "[git_tag] ERROR: push to ${remote} stopped at: ${last_release_step}" >&2
push_failed_remotes="${push_failed_remotes} ${remote}"
fi
done
git tag -d v${pre_del_version_no}
if [ -n "${push_failed_remotes}" ]; then
echo "[git_tag] ERROR: release v${next_version_no} is committed and tagged locally, but push failed for:${push_failed_remotes}" >&2
echo "[git_tag] retry each failed remote in order, starting from the step that failed:" >&2
echo "[git_tag] git push --delete <remote> latest (skip when the remote has no latest tag)" >&2
echo "[git_tag] git push <remote>" >&2
echo "[git_tag] git push <remote> latest" >&2
echo "[git_tag] git push <remote> v${next_version_no}" >&2
echo "[git_tag] verify: git ls-remote <remote> refs/heads/main refs/tags/latest refs/tags/v${next_version_no}" >&2
exit 1
fi
}
handle_input(){
if [[ $1 == "-get_pre_del_tag_name" ]]; then
pre_tag=$(get_pre_del_version_no "${CURRENT_VERSION}")
echo "Pre Del Tag With " "$pre_tag"
elif [ -z "$1" ] || [ "$1" == "auto" ]; then
if to_run "$1"; then
git_handle_ready
git_handle_push
echo "Complated"
else
echo "Invalid argument normal"
fi
else
echo "Invalid argument"
fi
}
handle_input "$@"