-
-
Save OleksandrKucherenko/9fb14f81a29b46886ccd63b774c5959f to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash | |
# shellcheck disable=SC2155 | |
## Copyright (C) 2017, Oleksandr Kucherenko | |
## Last revisit: 2023-09-30 | |
## Version: 2.0.2 | |
## License: MIT | |
## Fix: 2023-10-01, prefix for initial INIT_VERSION was not applied | |
## Fix: 2023-10-01, correct extraction of latest tag that match version pattern | |
## Added: 2023-09-30, @mrares prefix modification implemented | |
## Bug fixes: 2021-06-09, @slmingol changes applied | |
# For help: | |
# ./version-up.sh --help | |
# For developer / references: | |
# https://ryanstutorials.net/bash-scripting-tutorial/bash-functions.php | |
# http://tldp.org/LDP/abs/html/comparison-ops.html | |
# https://misc.flogisoft.com/bash/tip_colors_and_formatting | |
## display help | |
function help() { | |
echo 'usage: ./version-up.sh [-r|--release] [-a|--alpha] [-b|--beta] [-c|--release-candidate]' | |
echo ' [-m|--major] [-i|--minor] [-p|--patch] [-e|--revision] [-g|--git-revision]' | |
echo ' [--prefix root|sub-folder|any] [--stay] [--default] [--help]' | |
echo '' | |
echo 'Switches:' | |
echo ' --release switch stage to release, no suffix, -r' | |
echo ' --alpha switch stage to alpha, -a' | |
echo ' --beta switch stage to beta, -b' | |
echo ' --release-candidate switch stage to rc, -c' | |
echo ' --major increment MAJOR version part, -m' | |
echo ' --minor increment MINOR version part, -i' | |
echo ' --patch increment PATCH version part, -p' | |
echo ' --revision increment REVISION version part, -e' | |
echo ' --git-revision use git revision number as a revision part, -g' | |
echo ' --stay compose version.properties but do not do any increments, -s' | |
echo ' --default increment last found part of version, keeping the stage. Increment applied up to MINOR part.' | |
echo ' --apply run GIT command to apply version upgrade' | |
echo ' --prefix provide tag prefix or use on of the strategies: root, sub-folder (default), any_string' | |
echo '' | |
echo 'Version: [PREFIX]MAJOR.MINOR[.PATCH[.REVISION]][-STAGE]' | |
echo '' | |
echo 'Reference:' | |
echo ' https://semver.org/' | |
echo '' | |
echo 'Versions priority:' | |
echo ' 1.0.0-alpha < 1.0.0-beta < 1.0.0-rc < 1.0.0' | |
exit 0 | |
} | |
## find the monorepo root folder | |
function monorepo_root() { | |
# Navigate up from the script directory until we find the .git sub-folder to determine the monorepo root | |
local monorepoRootDir=$( | |
dir="$(dirname "${BASH_SOURCE[0]}")" | |
while [[ "$dir" != '/' && ! -d "$dir/.git" ]]; do dir="$(dirname "$dir")"; done | |
echo "$dir" | |
) | |
echo "$monorepoRootDir" | |
} | |
# https://stackoverflow.com/a/67449155 | |
function get_relative_path() { | |
local targetFilename=$(basename "$1") | |
local targetFolder=$(cd "$(dirname "$1")" && pwd) # absolute target folder path | |
local currentFolder=$(cd "$2" && pwd) # absolute source folder | |
local result=. | |
while [ "$currentFolder" != "$targetFolder" ]; do | |
if [[ "$targetFolder" =~ "$currentFolder"* ]]; then | |
local pointSegment=${targetFolder#${currentFolder}} | |
result=$result/${pointSegment#/} | |
break | |
fi | |
result="$result"/.. | |
currentFolder=$(dirname "$currentFolder") | |
done | |
result=$result/$targetFilename | |
echo "${result#./}" | |
} | |
## get monorepo sub-folder | |
function prefix_sub_folder() { | |
local tmpFileName="temp.file" | |
local repoDir=$(realpath "$(monorepo_root)") | |
local relativePath=$(get_relative_path "$(pwd)/$tmpFileName" "$repoDir") | |
# expected / at the end | |
echo "${relativePath/$tmpFileName/}" | |
} | |
## resolve income parameter into prefix | |
function prefix_strategy() { | |
local strategy=${1:-"sub-folder"} | |
local resolution="" | |
if [[ "$strategy" == "root" ]]; then | |
resolution="" | |
elif [[ "$strategy" == "sub-folder" ]]; then | |
resolution=$(prefix_sub_folder) | |
else | |
resolution="$strategy" | |
fi | |
echo "$resolution" | |
} | |
## calculate the prefix based on the strategy | |
function use_prefix() { | |
PREFIX=$(prefix_strategy "$1") | |
echo "Tag prefix: '$PREFIX'" | |
} | |
## get the highest version tag for all branches | |
function highest_tag() { | |
local gitTag=$(git tag --list 2>/dev/null | sort -V | tail -n1 2>/dev/null) | |
echo "$gitTag" | |
} | |
## extract current branch name | |
function current_branch() { | |
## expected: heads/{branch_name} | |
## expected: {branch_name} | |
local gitBranch=$(git rev-parse --abbrev-ref HEAD | cut -d"/" -f2) | |
echo "$gitBranch" | |
} | |
## get latest/head commit hash number | |
function head_hash() { | |
local commitHash=$(git rev-parse --verify HEAD) | |
echo "$commitHash" | |
} | |
## extract tag commit hash code, tag name provided by argument | |
function tag_hash() { | |
local tagHash=$(git log -1 --format=format:"%H" "$1" 2>/dev/null | tail -n1) | |
echo "$tagHash" | |
} | |
## extract prefix argument before the actual parsing of flags is done | |
function preparse_prefix_argument() { | |
local args=("$@") | |
local resolved_prefix=$(prefix_strategy) | |
# if --prefix provided, then required filtering of the tags by provided prefix pattern | |
if [[ "${args[*]}" =~ "--prefix" ]]; then | |
local prefix=$(echo "${args[*]}" | sed 's/.*--prefix \([^ ]*\).*/\1/') | |
resolved_prefix=$(prefix_strategy "$prefix") | |
fi | |
echo "$resolved_prefix" | |
} | |
## get latest tag in specified branch | |
# shellcheck disable=SC2001 | |
function latest_tag() { | |
local resolved_prefix=$(preparse_prefix_argument "$@") | |
# extract from git latest tag that started from number (OR from prefix and number) | |
local tag=$(git describe --tags --abbrev=0 --match="${resolved_prefix}[0-9]*" 2>/dev/null) | |
echo "$tag" | |
} | |
## get latest revision number | |
function latest_revision() { | |
local gitRevision=$(git rev-list --count HEAD 2>/dev/null) | |
echo "$gitRevision" | |
} | |
## parse first PART of the tage, extract PREFIX if any provided | |
# shellcheck disable=SC2001 | |
function parse_first() { | |
# extract into PREFIX variable all non digits chars from the beginning of the PARTS[0] | |
local prefix=$(echo "${PARTS[0]}" | sed 's#\([^0-9]*\)\(.*\)#\1#') | |
# leave only digits in the PARTS[0] | |
local clean_part=$(echo "${PARTS[0]}" | sed 's#\([^0-9]*\)\(.*\)#\2#') | |
PREFIX=$prefix | |
PARTS[0]=$clean_part | |
} | |
## parse last found tag, extract it PARTS | |
function parse_last() { | |
local position=$(($1 - 1)) | |
# two parts found only | |
# shellcheck disable=SC2206 | |
local segments=(${PARTS[$position]//-/ }) # split by - into array of strings | |
#echo ${segments[@]}, size: ${#segments} | |
# found NUMBER | |
PARTS[$position]=${segments[0]} | |
#echo ${PARTS[@]} | |
# found SUFFIX | |
if [[ ${#segments} -ge 1 ]]; then | |
PARTS[4]=${segments[1],,} #lowercase | |
#echo ${PARTS[@]}, ${SUBS[@]} | |
fi | |
} | |
## increment REVISION part, don't touch STAGE | |
function increment_revision() { | |
PARTS[3]=$((PARTS[3] + 1)) | |
IS_DIRTY=1 | |
} | |
## increment PATCH part, reset all others lower PARTS, don't touch STAGE | |
function increment_patch() { | |
PARTS[2]=$((PARTS[2] + 1)) | |
PARTS[3]=0 | |
IS_DIRTY=1 | |
} | |
## increment MINOR part, reset all others lower PARTS, don't touch STAGE | |
function increment_minor() { | |
PARTS[1]=$((PARTS[1] + 1)) | |
PARTS[2]=0 | |
PARTS[3]=0 | |
IS_DIRTY=1 | |
} | |
## increment MAJOR part, reset all others lower PARTS, don't touch STAGE | |
function increment_major() { | |
PARTS[0]=$((PARTS[0] + 1)) | |
PARTS[1]=0 | |
PARTS[2]=0 | |
PARTS[3]=0 | |
IS_DIRTY=1 | |
} | |
## increment the number only of last found PART: REVISION --> PATCH --> MINOR. don't touch STAGE | |
function increment_last_found() { | |
if [[ "${#PARTS[3]}" == 0 || "${PARTS[3]}" == "0" ]]; then | |
if [[ "${#PARTS[2]}" == 0 || "${PARTS[2]}" == "0" ]]; then | |
increment_minor | |
else | |
increment_patch | |
fi | |
else | |
increment_revision | |
fi | |
# stage part is not EMPTY | |
if [[ "${#PARTS[4]}" != 0 ]]; then | |
IS_SHIFT=1 | |
fi | |
} | |
## compose version from PARTS | |
function compose() { | |
local major="${PARTS[0]}" | |
local minor=".${PARTS[1]}" | |
local patch=".${PARTS[2]}" | |
local revision=".${PARTS[3]}" | |
local suffix="-${PARTS[4]}" | |
if [[ "${#patch}" == 1 ]]; then # if empty {patch} | |
patch="" | |
fi | |
if [[ "${#revision}" == 1 ]]; then # if empty {revision} | |
revision="" | |
fi | |
if [[ "${PARTS[3]}" == "0" ]]; then # if revision is ZERO | |
revision="" | |
fi | |
# shrink patch and revision | |
if [[ -z "${revision// /}" ]]; then | |
if [[ "${PARTS[2]}" == "0" ]]; then | |
patch="" | |
fi | |
else # revision is not EMPTY | |
if [[ "${#patch}" == 0 ]]; then | |
patch=".0" | |
fi | |
fi | |
# remove suffix if we don't have alpha/beta/rc | |
if [[ "${#suffix}" == 1 ]]; then | |
suffix="" | |
fi | |
echo "${PREFIX}${major}${minor}${patch}${revision}${suffix}" #full format | |
} | |
## print error message about conflict with existing tag and proposed tag | |
function error_conflict_tag() { | |
local red=$(tput setaf 1) | |
local end=$(tput sgr0) | |
local yellow=$(tput setaf 3) | |
echo -e "${red}ERROR:${end} " | |
echo -e "${red}ERROR:${end} Found conflict with existing tag ${yellow}$(compose)${end} / $PROPOSED_HASH" | |
echo -e "${red}ERROR:${end} Only manual resolving is possible now." | |
echo -e "${red}ERROR:${end} " | |
echo -e "${red}ERROR:${end} To Resolve try to add --revision or --patch modifier." | |
echo -e "${red}ERROR:${end} " | |
echo "" | |
} | |
## print help message how to apply changes manually | |
function help_manual_apply() { | |
echo 'To apply changes manually execute the command(s):' | |
echo -e "\033[90m" | |
echo " git tag $(compose)" | |
echo " git push origin $(compose)" | |
echo -e "\033[0m" | |
} | |
## save all support information into version.properties file | |
function publish_version_file() { | |
echo "# $(date)" >${VERSION_FILE} | |
{ | |
echo "snapshot.version=$(compose)" | |
echo "snapshot.lasttag=$TAG" | |
echo "snapshot.revision=$REVISION" | |
echo "snapshot.hightag=$TOP_TAG" | |
echo "snapshot.branch=$BRANCH" | |
echo '# end of file' | |
} >>"${VERSION_FILE}" | |
} | |
## apply changes to GIT repository, local changes only | |
function apply_git_changes() { | |
echo '' | |
echo "Applying git repository version up... no push, only local tag assignment!" | |
echo '' | |
git tag "$(compose)" | |
# confirm that tag applied | |
git --no-pager log \ | |
--pretty=format:"%h%x09%Cblue%cr%Cgreen%x09%an%Creset%x09%s%Cred%d%Creset" \ | |
-n 2 --date=short | nl -w2 -s" " | |
echo '' | |
echo '' | |
} | |
## print current state of the repository | |
function report_current_state() { | |
# do we have any GIT tag for parsing?! | |
echo "" | |
if [[ -z "${TAG// /}" ]]; then | |
TAG=$INIT_VERSION | |
echo "No tags found." | |
else | |
echo "Found tag: $TAG in branch '$BRANCH'" | |
fi | |
# print current revision number based on number of commits | |
echo "Current Revision: $REVISION" | |
echo "Current Branch : $BRANCH" | |
echo "Repository Dir : \"$(realpath "$(monorepo_root)")\"" | |
echo "Current Folder : \"$(prefix_sub_folder)\"" | |
echo "" | |
} | |
PREFIX=$(preparse_prefix_argument "$@") | |
# initial version used for repository without tags | |
INIT_VERSION="${PREFIX}0.0.0.0-alpha" | |
# do GIT data extracting, globals | |
TAG=$(latest_tag "$@") | |
REVISION=$(latest_revision) | |
BRANCH=$(current_branch) | |
TOP_TAG=$(highest_tag) | |
TAG_HASH=$(tag_hash "$TAG") | |
HEAD_HASH=$(head_hash) | |
PROPOSED_HASH="" | |
VERSION_FILE=version.properties | |
report_current_state | |
# if tag and branch commit hashes are different, then print info about that | |
#echo $HEAD_HASH vs $TAG_HASH | |
# shellcheck disable=SC2199 | |
if [[ "$@" == "" ]]; then | |
if [[ "$TAG_HASH" == "$HEAD_HASH" ]]; then | |
echo "Tag $TAG and HEAD are aligned. We will stay on the TAG version." | |
echo "" | |
NO_ARGS_VALUE='--stay' | |
else | |
PATTERN="^[0-9]+.[0-9]+(.[0-9]+)*(-(alpha|beta|rc))*$" | |
if [[ "$BRANCH" =~ $PATTERN ]]; then | |
echo "Detected version branch '$BRANCH'. We will auto-increment the last version PART." | |
echo "" | |
NO_ARGS_VALUE='--default' | |
else | |
echo "Detected branch name '$BRANCH' than does not match version pattern. We will increase MINOR." | |
echo "" | |
NO_ARGS_VALUE='--minor' | |
fi | |
fi | |
fi | |
# | |
# [PREFIX]{MAJOR}.{MINOR}[.{PATCH}[.{REVISION}][-(.*)] | |
# | |
# Suffix: alpha, beta, rc | |
# No Suffix --> {NEW_VERSION}-alpha | |
# alpha --> beta | |
# beta --> rc | |
# rc --> {VERSION} | |
# | |
# shellcheck disable=SC2206 | |
PARTS=(${TAG//./ }) | |
parse_first | |
parse_last ${#PARTS[@]} # array size as argument | |
#echo ${PARTS[@]} | |
# if no parameters than emulate --default parameter | |
# shellcheck disable=SC2199 | |
if [[ "$@" == "" ]]; then | |
# shellcheck disable=SC2086 | |
set -- ${NO_ARGS_VALUE} | |
fi | |
# parse input parameters | |
for i in "$@"; do | |
key="$i" | |
case $key in | |
-a | --alpha) # switched to ALPHA | |
PARTS[4]="alpha" | |
IS_SHIFT=1 | |
;; | |
-b | --beta) # switched to BETA | |
PARTS[4]="beta" | |
IS_SHIFT=1 | |
;; | |
-c | --release-candidate) # switched to RC | |
PARTS[4]="rc" | |
IS_SHIFT=1 | |
;; | |
-r | --release) # switched to RELEASE | |
PARTS[4]="" | |
IS_SHIFT=1 | |
;; | |
-p | --patch) # increment of PATCH | |
increment_patch | |
;; | |
-e | --revision) # increment of REVISION | |
increment_revision | |
;; | |
-g | --git-revision) # use git revision number as a revision part§ | |
PARTS[3]=$((REVISION)) | |
IS_DIRTY=1 | |
;; | |
-i | --minor) # increment of MINOR by default | |
increment_minor | |
;; | |
--default) # stay on the same stage, but increment only last found PART of version code | |
increment_last_found | |
;; | |
-m | --major) # increment of MAJOR | |
increment_major | |
;; | |
-s | --stay) # extract version info | |
IS_DIRTY=1 | |
NO_APPLY_MSG=1 | |
;; | |
--prefix) # version tag prefix provided | |
use_prefix "$2" | |
shift # expected one more argument with prefix name | |
;; | |
--apply) | |
DO_APPLY=1 | |
;; | |
-h | --help) | |
help | |
;; | |
esac | |
shift | |
done | |
# detected shift, but no increment | |
if [[ "$IS_SHIFT" == "1" ]]; then | |
# temporary disable stage shift | |
stage=${PARTS[4]} | |
PARTS[4]='' | |
# detect first run on repository, INIT_VERSION was used | |
if [[ "$(compose)" == "0.0" ]]; then | |
increment_minor | |
fi | |
PARTS[4]=$stage | |
fi | |
# no increment applied yet and no shift of state, do minor increase | |
if [[ "$IS_DIRTY$IS_SHIFT" == "" ]]; then | |
increment_minor | |
fi | |
# instruct user how to apply new TAG | |
echo -e "Proposed TAG: \033[32m$(compose)\033[0m" | |
echo '' | |
# is proposed tag in conflict with any other TAG | |
PROPOSED_HASH=$(tag_hash "$(compose)") | |
if [[ "${#PROPOSED_HASH}" -gt 0 && "$NO_APPLY_MSG" == "" ]]; then | |
error_conflict_tag | |
fi | |
if [[ "$NO_APPLY_MSG" == "" ]]; then | |
help_manual_apply | |
fi | |
# compose version override file | |
if [[ "$TAG" == "$INIT_VERSION" ]]; then | |
TAG='0.0' | |
fi | |
publish_version_file | |
# should we apply the changes | |
if [[ "$DO_APPLY" == "1" ]]; then | |
apply_git_changes | |
fi | |
# | |
# Major logic of the script - "on each run script propose future version of the product". | |
# | |
# - if no tags on project --> propose '0.1-alpha' | |
# - do multiple build iterations until you become satisfied with result | |
# - run 'version-up.sh --apply' to save result in GIT | |
# |
@OleksandrKucherenko This is really great. Could you provide a brief description of the development and release workflow that this script best fits? I'm eager to integrate something like this into an automated CI system, but need to first understand how best to use it.
How would you recommend a developer use the script vs an automated CI system use the script?
@OleksandrKucherenko This is really great. Could you provide a brief description of the development and release workflow that this script best fits? I'm eager to integrate something like this into an automated CI system, but need to first understand how best to use it.
How would you recommend a developer use the script vs an automated CI system use the script?
Is script documentation not enough?! OK... @nicknezis
- GIT repository enabled project required.
- Developer execute
version-up.sh
script for composingversion.properties
file. - Script is smart and depends on state of the git applies different version increment strategies on run.
- Developer also may customize script behavior by flags and force different version increments.
- Major scenario: developer may switch state of the project to alpha, beta, release candidate or release state. (also known as stage)
- Depends on type of modification developer may force "patch" part of the version modification, instead of default "feature" part. script is smart and depends on incremented part improves version number.
- when developer satisfied with state of the project, can be set a version git tag.
- when developer works in branch that has a version tag - script detects it and propose next version number based on that info.
Thank you. This is helpful. I'm sorry if my questions were a little bit nebulous.
Your description is very helpful. Some remaining questions for clarity.
- Does a developer run the script manually and generate the
version.properties
file with that file being checked into Git? Or does the script get called by the build tool/CI to dynamically generate the current version? (This is something I've seen in the Gradle Nebula Release plugin) - Does it work when releasing from branch as opposed to release from trunk?
- If a team of engineers are working on a repo, could they bump the version in their feature branches? Or would it have to be bumped after merging back into master? Based on some of the bullet points you mentioned, this seems like it might be covered which would be really cool.
Thanks again for the script and the answers. I really appreciate it. It's helpful in understanding before I recommend to a larger team for use.
- Does a developer run the script manually and generate the
version.properties
file with that file being checked into Git? Or does the script get called by the build tool/CI to dynamically generate the current version? (This is something I've seen in the Gradle Nebula Release plugin)
No, script is not a part of anything else. It's designed for manual and CI/CD execution. The dev should identify the best way to call it.
I usually do script execution as a first build step for CI/CD or local builds.
2. Does it work when releasing from branch as opposed to release from trunk?
- if you in master branch - script verify do we have any commits from last version tag or not, and based on this information decide which version to propose. (btw for new repositories we can have main instead of master!)
- we on master, new commit added after last version tag -> increase minor/feature segment of the version
- we on master, no new commits after last version tag -> "we are building specific version", script extract version from version tag
script work for trunk and for other branches.
3. If a team of engineers are working on a repo, could they bump the version in their feature branches? Or would it have to be bumped after merging back into master? Based on some of the bullet points you mentioned, this seems like it might be covered which would be really cool.
if you doing modification in branch - that treated as a "hot fix" for a specific version. Than developer should run script and make a decision which segment of the version should be modified...
master -- tag:1.0.0.0 --> commits --> HEAD
\----- branch --- version. 1.0.1.0 (developer decide to increase a patch segment)
I highly recommend to cherry-pick changes from release branches into main/master... that will keep master in good state
Hi
Thank you very much for this script, I think you should make a dedicated repo...
I've a question: does it work with prefix on TAG? I noticed that the MAGIOR doesn't increase If it has a prefix. For example:
./version-up.sh -m
Found tag: v2.14.1 in branch 'master'
Current Revision: 192
Current Branch: master
Proposed TAG: 1.0
To apply changes manually execute the command(s):
git tag 1.0
git push origin 1.0
If I understand correctly, expected output should be: Proposed TAG: v3.0
Hi
Thank you very much for this script, I think you should make a dedicated repo...
I've a question: does it work with prefix on TAG? I noticed that the MAGIOR doesn't increase If it has a prefix. For example:
./version-up.sh -m Found tag: v2.14.1 in branch 'master' Current Revision: 192 Current Branch: master Proposed TAG: 1.0 To apply changes manually execute the command(s): git tag 1.0 git push origin 1.0
If I understand correctly, expected output should be:
Proposed TAG: v3.0
Expected tag 2.14.1
but was v2.14.1
... you need to adjust the script for your version tag pattern.
You may check: https://stackoverflow.com/a/5719854/349681 - How to rename git tag
Thank you very much. Very nice job indeed.
Do you have any thoughts on the supported versioning scheme?
I'm considering expanding the script to support "official" Semantic Versioning 2.0.0 (as found on https://semver.org/spec/v2.0.0.html).
... or at least supporting the versioning scheme we use (v1.2.3-alpha.43 should be able to up into v1.2.3-alpha.44) - which doesn't seem to be supported at the moment.
Also please consider turning this gist into a repo :D
Thank you for this script. I added a couple of echo ''
to the apply condition to cleanup the output displayed when running the git --no-pager log ...
cmds. Otherwise my prompt started right at the end of the last log msg it displayed.
...
...
# should we apply the changes
if [[ "$DO_APPLY" == "1" ]]; then
echo ''
echo "Applying git repository version up... no push, only local tag assignment!"
echo ''
git tag $(compose)
# confirm that tag applied
git --no-pager log --pretty=format:"%h%x09%Cblue%cr%Cgreen%x09%an%Creset%x09%s%Cred%d%Creset" -n 2 --date=short | nl -w2 -s" "
echo ''
echo ''
fi
I suspect this might be a bug here where you're calculating the highest tag value:
## get highest version tag for all branches
function highest_tag(){
local TAG=$(git tag --list 2>/dev/null | tail -n1 2>/dev/null)
echo "$TAG"
}
I suspect this should be like so:
## get highest version tag for all branches
function highest_tag(){
local TAG=$(git tag --list 2>/dev/null | tail -n1 2>/dev/null | sort -V)
echo "$TAG"
}
For e.g.:
$ git tag --list | tail -10
0.0.70
0.0.71
0.0.72
0.0.73
0.0.74
0.0.75
0.0.76
0.0.77
0.0.8
0.0.9
But with my approach:
$ git tag --list | tail -10 | sort -V
0.0.8
0.0.9
0.0.70
0.0.71
0.0.72
0.0.73
0.0.74
0.0.75
0.0.76
0.0.77
I suspect this might be a bug here where you're calculating the highest tag value:
Thanks @slmingol for catching it. I will update the script shortly.
Script updated.
hi @OleksandrKucherenko can you create a parameter to output just the tag to be used ?
Im try in Makefile create a version to build my dockerimage with this tag but I cant with regular output of this script so I tried this bellow
VERSION=$(shell ./version-up.sh --patch --release | grep "TAG" | awk '{split($0, a, ":"); print a[2]}' | sed 's/\x1b\[[0-9;]*m//g' | sed -e 's/^[[:space:]]*//')
version: ## output to version
@echo $(VERSION)
make version
awk: syntax error at source line 1
context is
>>> {split(, <<<
awk: illegal statement at source line 1
awk: illegal statement at source line 1
Can you include a parameter to output only the calculated tag ?
I use a monorepo and so have different tags for different services, is there some hack I could use to make this work for me? (effectively I'd like to filter tags by prefix before using this tool)
@mrares let's assume you want to support tags in the following pattern:
# We have a workspace with subfolders, use this to print tree of the project:
# find . | sed -e "s/[^-][^\/]*\// |/g" -e "s/|\([^ ]\)/|-\1/"
#
.
|-.git
| |-branches
| |-info
| |-hooks
| |-refs
| |-objects
| |-logs
|-.husky
|-.idea
|-.scripts
|-.vscode
|-.yarn
| |-plugins
| |-releases
| |-sdks
|-clis
| |-gpt
|-packages
| |-arguments
| |-configuration
| |-gc
| |-telemetry
# $(pwd)/${version}
git tag packages/telemetry/v1.0.0
# something like this
export expected_tag="$(realpath --relative-to=${workspace_root_folder} "$(pwd)")/${version_tag}"
Can you confirm that this is a good way for you?
In my case this would be tagged telemetry-v1.0.0 but I can see the logic behind what you're proposing.
In my opinion this can be done by specifying a prefix to the command, so it ignores any tags that are not prefixed the same way (currently it searches for the latest tag, which will have the prefix let's say "telemetry"), if I could specify --prefix "arguments" then it will look for the latest tag prefixed arguments, and then operate further from there (it would generate the next tag for that)
@mrares just a hint, try chatgpt for updating the script - it solve such kind of tasks without any issues
@mrares just a hint, try chatgpt for updating the script - it solve such kind of tasks without any issues
?!
@mrares Updated version with the --prefix
approach implementation
Preview
prefix provided as user defined custom string:
sub-folder strategy in use: (default settings or can be forced by --prefix sub-folder
)
script try to propose tag based on sub-folder path (relative path to monorepo root dir):
force root directory logic:
version 2.0.0 released
@rafilkmp3 @mrares @slmingol @rasmusskovdk @vlauciani @nicknezis @sadortun @thuitaw @Br3nda
Changes:
- support for monorepo added
- sub-folder used as version tag prefix by default, developer should be in the module folder when calling the
version-up.sh
script --prefix
flag allows to change the strategy 'root' - use repo root folder logic, 'sub-folder' (default), any-text - prefix provided by developer- refactoring:
- more functionality placed into functions
- local variables are in lower/camel case
- global variables in UPPER case
- shellcheck proposed/found warnings/errors fixed
- tested on MacOs only
Known issues:
- empty prefix or root strategy may select the wrong tag for processing, used hungry wildcard that select 'telemetry-0.0.1' instead of '1.0.0.0' tag from images above... any suggestions how fix are welcome 🙏
@OleksandrKucherenko Thank you, --prefix
now works perfectly for my needs
migrated to GitHub Project - https://github.com/OleksandrKucherenko/e-bash
@OleksandrKucherenko small, yes, but It would give people a chance to open issues and submit PRs. You did an amazing job, but there Is still a few more improvement to do :)