5858
5959MODULE_DIR=" $( dirname " $( realpath " $0 " ) " ) "
6060
61- source $MODULE_DIR /lib/helper.sh
61+ source $MODULE_DIR /lib/helpers.sh
62+ source $MODULE_DIR /lib/styles.sh
6263
6364NOW=" $( date +' %B %d, %Y' ) "
6465
@@ -71,373 +72,6 @@ PUSH_DEST="origin"
7172
7273JSON_FILES=($VER_FILE )
7374
74- # Show credits & help
75- usage () {
76- local SCRIPT_VER SCRIPT_AUTH_EMAIL SCRIPT_AUTH_NAME SCRIPT_HOME
77- # NPM environment variables are fetched with cross-platform tool cross-env
78- SCRIPT_VER=` cd $MODULE_DIR && npm run get-pkg-ver -s`
79- SCRIPT_AUTH_NAME=` cd $MODULE_DIR && npm run get-pkg-auth -s`
80- SCRIPT_AUTH_EMAIL=` cd $MODULE_DIR && npm run get-pkg-email -s`
81- SCRIPT_NAME=` cd $MODULE_DIR && npm run get-pkg-name -s`
82- SCRIPT_HOME=` cd $MODULE_DIR && npm run get-pkg-page -s`
83-
84- echo -e " ${GREEN} " \
85- " _ _ ___ ___ ___ _ _ __ __ ___ " \
86- " \n| | || __>| . \ ___ | . >| | || \ \| . \ " \
87- " \n| ' || _> | /|___|| . \| ' || || _/ " \
88- " \n|__/ |___>|_\_\ |___/\___/|_|_|_||_| " \
89- " \n\t\t\t${LIGHTGRAY} ${BOLD} Version: $S_WARN ${SCRIPT_VER} "
90-
91- echo -e " ${S_NORM}${BOLD} Description:${RESET} " \
92- " \nThis script automates bumping the git software project's version automatically." \
93- " \nIt does several things that are typically required for releasing a Git repository, like git tagging, automatic updating of CHANGELOG.md, and incrementing the version number in various JSON files."
94-
95- echo -e " \n${S_NORM}${BOLD} Usage:${RESET} " \
96- " \n${SCRIPT_NAME} [-v <version number>] [-m <release message>] [-j <file1>] [-j <file2>].. [-n] [-p] [-h]" 1>&2 ;
97-
98- echo -e " \n${S_NORM}${BOLD} Options:${RESET} "
99- echo -e " $S_WARN -v$S_NORM <version number>\tSpecify a manual version number"
100- echo -e " $S_WARN -m$S_NORM <release message>\tCustom release message."
101- echo -e " $S_WARN -f$S_NORM <filename.json>\tUpdate version number inside JSON files." \
102- " \n\t\t\tFor multiple files, add a separate -f option for each one, for example:" \
103- " \n\t\t\t${S_NORM} ver-bump -f src/plugin/package.json -f composer.json"
104- echo -e " $S_WARN -p$S_NORM \t\t\tPush release branch to ORIGIN. "
105- echo -e " $S_WARN -h$S_NORM \t\t\tShow this help message. \n"
106-
107- echo -e " ${S_NORM}${BOLD} Credits:${S_LIGHT} " \
108- " \n${SCRIPT_AUTH_NAME} <${SCRIPT_AUTH_EMAIL} > ${RESET} " \
109- " \n${SCRIPT_HOME} \n"
110- }
111-
112- # If there are no commits in repo, quit, because you can't tag with zero commits.
113- check-commits-exist () {
114- git rev-parse HEAD & > /dev/null
115- if [ ! " $? " -eq 0 ]; then
116- echo -e " \n${I_STOP} ${S_ERROR} Your current branch doesn't have any commits yet. Can't tag without at least one commit." >&2
117- echo
118- exit 1
119- fi
120- }
121-
122- get-commit-msg () {
123- echo Bumped $( [ -n " ${V_PREV} " ] && echo " ${V_PREV} –>" || echo " to " ) " $V_USR_INPUT "
124- }
125-
126- exit_abnormal () {
127- usage # Show help
128- exit 1
129- }
130-
131- # Process script options
132- process-arguments () {
133- local OPTIONS OPTIND OPTARG
134-
135- # Get positional parameters
136- while getopts " :v:p:m:f:hbn" OPTIONS; do # Note: Adding the first : before the flags takes control of flags and prevents default error msgs.
137- case " $OPTIONS " in
138- h )
139- # Show help
140- exit_abnormal
141- ;;
142- v )
143- # User has supplied a version number
144- V_USR_SUPPLIED=$OPTARG
145- ;;
146- m )
147- REL_NOTE=$OPTARG
148- # Custom release note
149- echo -e " \n${S_LIGHT} Option set: ${S_NOTICE} Release note:" ${S_NORM} " '" $REL_NOTE " '"
150- ;;
151- f )
152- FLAG_JSON=true
153- echo -e " \n${S_LIGHT} Option set: ${S_NOTICE} JSON file via [-f]: <${S_NORM}${OPTARG}${S_LIGHT} >"
154- # Store JSON filenames(s)
155- JSON_FILES+=($OPTARG )
156- ;;
157- p )
158- FLAG_PUSH=true
159- PUSH_DEST=${OPTARG} # Replace default with user input
160- echo -e " \n${S_LIGHT} Option set: ${S_NOTICE} Pushing to <${S_NORM}${PUSH_DEST}${S_LIGHT} >, as the last action in this script."
161- ;;
162- n )
163- FLAG_NOCOMMIT=true
164- echo -e " \n${S_LIGHT} Option set: ${S_NOTICE} Disable commit after tagging."
165- ;;
166- b )
167- FLAG_NOBRANCH=true
168- echo -e " \n${S_LIGHT} Option set: ${S_NOTICE} Disable committing to new branch."
169- ;;
170- \? )
171- echo -e " \n${I_ERROR}${S_ERROR} Invalid option: ${S_WARN} -$OPTARG " >&2
172- echo
173- exit_abnormal
174- ;;
175- : )
176- echo -e " \n${I_ERROR}${S_ERROR} Option ${S_WARN} -$OPTARG ${S_ERROR} requires an argument." >&2
177- echo
178- exit_abnormal
179- ;;
180- esac
181- done
182- }
183-
184- # Suggests version from VERSION file, or grabs from user supplied -v <version>.
185- # If none is set, suggest default from options.
186-
187- # - If <package.json> doesn't exist, warn + exit
188- # - If -v specified, set version from that
189- # - Else,
190- # - Grab from package.json
191- # - Suggest incremented number
192- # - Give prompt to user to modify
193- # - Set global
194-
195- # According to SemVer 2.0.0, given a version number MAJOR.MINOR.PATCH, suggest incremented value:
196- # — MAJOR version when you make incompatible API changes,
197- # — MINOR version when you add functionality in a backwards compatible manner, and
198- # — PATCH version when you make backwards compatible bug fixes.
199- process-version () {
200-
201- # If a version number is supplied by the user with [-v <version number>], then use it
202- if [ -n " $V_USR_SUPPLIED " ]; then
203- echo -e " \n${S_NOTICE} You selected version using [-v]:" " ${S_WARN}${V_USR_SUPPLIED} "
204- V_USR_INPUT=" ${V_USR_SUPPLIED} "
205- else
206- if [ -f $VER_FILE ] && [ -s $VER_FILE ]; then
207- local IS_NO=0
208-
209- # Get the existing version number
210- V_PREV=$( sed -n ' s/.*"version":.*"\(.*\)"\(,\)\{0,1\}/\1/p' $VER_FILE )
211-
212- if [ -n " $V_PREV " ]; then
213-
214- echo -e " \n${S_NOTICE} Current version read from <${S_QUESTION}${VER_FILE}${S_NOTICE} > file: ${S_QUESTION} $V_PREV "
215-
216- V_PREV_LIST=(` echo $V_PREV | tr ' .' ' ' ` )
217- V_MAJOR=${V_PREV_LIST[0]} ; V_MINOR=${V_PREV_LIST[1]} ; V_PATCH=${V_PREV_LIST[2]} ;
218-
219- is_number $V_MAJOR ; (( IS_NO = $? ))
220- is_number $V_MINOR ; (( IS_NO = $? && $IS_NO ))
221-
222- # If major & minor are numbers, then proceed to increment patch
223- if [ $IS_NO = 1 ]; then
224- is_number $V_PATCH ;
225- [ $? == 1 ] && V_PATCH=$(( V_PATCH + 1 )) # Increment
226- V_SUGGEST=" $V_MAJOR .$V_MINOR .$V_PATCH "
227- else
228- # If patch not a number, do nothing
229- echo -e " \n${I_WARN} ${S_WARN} Warning: ${S_QUESTION}${V_PREV}${S_WARN} doesn't look like a SemVer compatible version number!\n"
230- fi
231-
232- else
233- echo -e " \n${I_WARN} ${S_ERROR} Warning: <${S_QUESTION}${VER_FILE}${S_WARN} > doesn't contain a 'version' field!\n"
234- fi
235- else
236- echo -ne " \n${S_WARN} Warning: <${S_QUESTION}${VER_FILE}${S_WARN} > "
237-
238- if [ ! -f $VER_FILE ]; then
239- echo " was not found!" ;
240- elif [ ! -s $VER_FILE ]; then
241- echo " is empty!" ;
242- fi
243- fi
244-
245- # Confirm it with user
246- echo -ne " \n${S_QUESTION} Enter a new version number or press <enter> to use [${S_NORM} $V_SUGGEST ${S_QUESTION} ]: "
247- echo -ne " $S_WARN "
248- read V_USR_INPUT
249-
250- if [ " $V_USR_INPUT " = " " ]; then
251- V_USR_INPUT=" ${V_SUGGEST} "
252- fi
253- fi
254- }
255-
256- # Only tag if tag doesn't already exist
257- check-tag-exists () {
258- TAG_CHECK_EXISTS=` git tag -l v" $V_USR_INPUT " `
259- if [ -n " $TAG_CHECK_EXISTS " ]; then
260- echo -e " \n${I_STOP} ${S_ERROR} Error: A release with that tag version number already exists!\n"
261- exit 0
262- fi
263- }
264-
265- # $1 : version
266- # $2 : release note
267- tag () {
268- if [ -z " $2 " ]; then
269- # Default release note
270- git tag -a " v$1 " -m " Tag version $1 ."
271- else
272- # Custom release note
273- git tag -a " v$1 " -m " $2 "
274- fi
275- echo -e " \n${I_OK} ${S_NOTICE} Added GIT tag"
276- }
277-
278- # Change `version:` value in JSON files, like packager.json, composer.json, etc
279- bump-json-files () {
280- # if [ "$FLAG_JSON" != true ]; then return; fi
281-
282- JSON_PROCESSED=( ) # holds filenames after they've been changed
283-
284- for FILE in " ${JSON_FILES[@]} " ; do
285- if [ -f $FILE ]; then
286- # Get the existing version number
287- V_OLD=$( sed -n ' s/.*"version":.*"\(.*\)"\(,\)\{0,1\}/\1/p' $FILE )
288-
289- if [ " $V_OLD " = " $V_USR_INPUT " ]; then
290- echo -e " \n${I_ERROR} ${S_WARN} File <${S_QUESTION} $FILE ${S_WARN} > already contains version ${S_NORM} $V_OLD "
291- else
292- # Write to output file
293- FILE_MSG=` sed -i .temp " s/\" version\" :\(.*\)\" $V_OLD \" /\" version\" :\1\" $V_USR_INPUT \" /g" $FILE 2>&1 `
294-
295- if [ " $? " -eq 0 ]; then
296- echo -e " \n${I_OK} ${S_NOTICE} Updated file <${S_NORM} $FILE ${S_NOTICE} > from ${S_QUESTION} $V_OLD ${S_NOTICE} -> ${S_QUESTION} $V_USR_INPUT "
297- rm -f ${FILE} .temp
298- # Add file change to commit message:
299- GIT_MSG+=" Updated $FILE , "
300- else
301- echo -e " \n${I_STOP} ${S_ERROR} Error\n$PUSH_MSG \n"
302- fi
303- fi
304-
305- JSON_PROCESSED+=($FILE )
306- else
307- echo -e " \n${S_WARN} File <${S_NORM} $FILE ${S_WARN} > not found."
308- fi
309- done
310- # Stage files that were changed:
311- [ -n " ${JSON_PROCESSED} " ] && git add " ${JSON_PROCESSED[@]} "
312- }
313-
314- # Handle VERSION file - for backward compatibility
315- do-versionfile () {
316- if [ -f VERSION ]; then
317- GIT_MSG+=" Updated VERSION, "
318- echo $V_USR_INPUT > VERSION # Overwrite file
319- # Stage file for commit
320- git add VERSION
321-
322- echo -e " \n${I_OK} ${S_NOTICE} Updated [${S_NORM} VERSION${S_NOTICE} ] file." \
323- " \n${I_WARN} ${S_ERROR} Deprecation warning: using a <${S_NORM} VERSION${S_ERROR} > file is deprecated since v0.2.0 — support will be removed in future versions."
324- fi
325- }
326-
327- # Dump git log history to CHANGELOG.md
328- do-changelog () {
329-
330- # Log latest commits to CHANGELOG.md:
331- # Get latest commits since last versio
332- LOG_MSG=` git log --pretty=format:" - %s" $( [ -n " $V_PREV " ] && echo " v${V_PREV} ...HEAD" ) 2>&1 `
333- if [ ! " $? " -eq 0 ]; then
334- echo -e " \n${I_STOP} ${S_ERROR} Error getting commit history since last version bump for logging to CHANGELOG.\n\n$LOG_MSG \n"
335- exit 1
336- fi
337-
338- [ -f CHANGELOG.md ] && ACTION_MSG=" Updated" || ACTION_MSG=" Created"
339- # Add info to commit message for later:
340- GIT_MSG+=" ${ACTION_MSG} CHANGELOG.md, "
341-
342- # Add heading
343- echo " ## $V_USR_INPUT ($NOW )" > tmpfile
344-
345- # Log the bumping commit:
346- # - The final commit is done after do-changelog(), so we need to create the log entry for it manually:
347- echo " - ${GIT_MSG} $( get-commit-msg) " >> tmpfile
348- # Add previous commits
349- [ -n " $LOG_MSG " ] && echo " $LOG_MSG " >> tmpfile
350-
351- echo -en " \n" >> tmpfile
352-
353- if [ -f CHANGELOG.md ]; then
354- # Append existing log
355- cat CHANGELOG.md >> tmpfile
356- else
357- echo -e " \n${S_WARN} A [${S_NORM} CHANGELOG.md${S_WARN} ] file was not found."
358- fi
359-
360- mv tmpfile CHANGELOG.md
361-
362- # User prompts
363- echo -e " \n${I_OK} ${S_NOTICE}${ACTION_MSG} [${S_NORM} CHANGELOG.md${S_NOTICE} ] file"
364- # Pause & allow user to open and edit the file:
365- echo -en " \n${S_QUESTION} Make adjustments to [${S_NORM} CHANGELOG.md${S_QUESTION} ] if required now. Press <enter> to continue."
366- read
367-
368- # Stage log file, to commit later
369- git add CHANGELOG.md
370- }
371-
372- #
373- check-branch-exist () {
374- [ " $FLAG_NOBRANCH " = true ] && return
375-
376- BRANCH_MSG=` git rev-parse --verify " ${REL_PREFIX}${V_USR_INPUT} " 2>&1 `
377- if [ " $? " -eq 0 ]; then
378- echo -e " \n${I_STOP} ${S_ERROR} Error: Branch <${S_NORM}${REL_PREFIX}${V_USR_INPUT}${S_ERROR} > already exists!\n"
379- exit 1
380- fi
381- }
382-
383- #
384- do-branch () {
385- [ " $FLAG_NOBRANCH " = true ] && return
386-
387- echo -e " \n${S_NOTICE} Creating new release branch..."
388-
389- BRANCH_MSG=` git branch " ${REL_PREFIX}${V_USR_INPUT} " 2>&1 `
390- if [ ! " $? " -eq 0 ]; then
391- echo -e " \n${I_STOP} ${S_ERROR} Error\n$BRANCH_MSG \n"
392- exit 1
393- else
394- BRANCH_MSG=` git checkout " ${REL_PREFIX}${V_USR_INPUT} " 2>&1 `
395- echo -e " \n${I_OK} ${S_NOTICE}${BRANCH_MSG} "
396- fi
397-
398- # REL_PREFIX
399- }
400-
401- # Stage & commit all files modified by this script
402- do-commit () {
403- [ " $FLAG_NOCOMMIT " = true ] && return
404-
405- GIT_MSG+=" $( get-commit-msg) "
406- echo -e " \n${S_NOTICE} Committing..."
407- COMMIT_MSG=` git commit -m " ${GIT_MSG} " 2>&1 `
408- if [ ! " $? " -eq 0 ]; then
409- echo -e " \n${I_STOP} ${S_ERROR} Error\n$COMMIT_MSG \n"
410- exit 1
411- else
412- echo -e " \n${I_OK} ${S_NOTICE} $COMMIT_MSG "
413- fi
414- }
415-
416- # Pushes files + tags to remote repo. Changes are staged by earlier functions
417- do-push () {
418- [ " $FLAG_NOCOMMIT " = true ] && return
419-
420- if [ " $FLAG_PUSH " = true ]; then
421- CONFIRM=" Y"
422- else
423- echo -ne " \n${S_QUESTION} Push tags to <${S_NORM}${PUSH_DEST}${S_QUESTION} >? [${S_NORM} N/y${S_QUESTION} ]: "
424- read CONFIRM
425- fi
426-
427- case " $CONFIRM " in
428- [yY][eE][sS]|[yY] )
429- echo -e " \n${S_NOTICE} Pushing files + tags to <${S_NORM}${PUSH_DEST}${S_NOTICE} >..."
430- PUSH_MSG=` git push " ${PUSH_DEST} " v" $V_USR_INPUT " 2>&1 ` # Push new tag
431- if [ ! " $? " -eq 0 ]; then
432- echo -e " \n${I_STOP} ${S_WARN} Warning\n$PUSH_MSG "
433- # exit 1
434- else
435- echo -e " \n${I_OK} ${S_NOTICE} $PUSH_MSG "
436- fi
437- ;;
438- esac
439- }
440-
44175# ### Initiate Script ###########################
44276
44377# Process and prepare
0 commit comments