Skip to content

Commit

Permalink
fix(workflows) fix prev_tag script
Browse files Browse the repository at this point in the history
  • Loading branch information
Oleksiivanov committed Jan 10, 2024
1 parent 3aa0282 commit 89e676c
Show file tree
Hide file tree
Showing 2 changed files with 238 additions and 51 deletions.
114 changes: 114 additions & 0 deletions .github/workflows/scripts/prev_tag-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#!/bin/bash

# Function to create a mock git repository
setup_mock_repo() {
mkdir temp_repo
cd temp_repo
git init
# Create a dummy commit to enable tagging
touch dummy.txt
git add dummy.txt
git commit -m "Initial commit"

# Add mock tags to simulate different scenarios
git tag 8.2.0
git tag 8.2.1
git tag 8.3.0-alpha1
git tag 8.3.0-rc1
git tag 8.3.0
git tag 8.3.1-rc1
git tag 8.3.1
git tag 8.3.2-rc1
git tag 8.3.2-rc2
git tag 8.3.2
git tag 8.3.3
git tag 8.4.0-alpha1
git tag 8.4.0-alpha2
git tag 8.4.0-alpha2-rc1
git tag 8.4.0-alpha2-rc2
git tag 8.4.0-alpha2-rc3
git tag 8.4.0-rc1
git tag 8.4.0-rc2
git tag 8.4.0-rc3
git tag 8.4.0
git tag 8.4.1-alpha1
git tag 8.4.2
git tag 8.4.2-alpha1
git tag 9.0.0-alpha1
git tag 9.0.0-alpha2-rc1
git tag 9.0.0-alpha2
git tag 9.0.0-alpha3-rc1
git tag 9.0.0-rc1
git tag 9.0.0
git tag 9.1.0
git tag 9.2.0-alpha2
git tag 9.2.0-rc2
}

# Function to clean up the mock repository
cleanup() {
cd ..
rm -rf temp_repo
}

# Initialize a variable to store test results
passed_tests_results=""
fail_test_results=""

# Function to run a single test case
run_test() {
input_tag=$1
expected_output=$2

output=$(bash ../prev_tag.sh $input_tag)
if [[ $output == *"$expected_output"* ]]; then
passed_tests_results+="Test passed for input $input_tag: Expected and got $expected_output\n"
else
fail_test_results+="Test failed for input $input_tag: Expected $expected_output, got $output\n"
fi
}

# Main test logic
setup_mock_repo
# input : arg 1 -> input tag, arg 2-> expected output
run_test "8.4.0" "8.3.0" # Normal release, next lower tag in the same minor series
run_test "8.3.0" "8.2.0"
run_test "8.3.3" "8.3.2" # Normal release, next lower tag
run_test "8.3.1" "8.3.0" # Normal release, next lower tag

run_test "8.4.0-alpha2" "8.4.0-alpha1" # Alpha version, next lower alpha tag
run_test "8.3.0-alpha1" "8.2.0" # First alpha of a new minor version

run_test "8.4.0-alpha2-rc3" "8.4.0-alpha2-rc2" # Alpha RC, next lower alpha RC tag
run_test "8.4.0-alpha2-rc2" "8.4.0-alpha2-rc1" # Alpha RC, next lower alpha RC tag
run_test "8.4.0-alpha2-rc1" "8.4.0-alpha1" # First alpha RC of a new alpha version
run_test "9.0.0-alpha2-rc1" "9.0.0-alpha1" # First alpha RC of a new alpha version
run_test "9.0.0-alpha3-rc1" "9.0.0-alpha2" # First alpha RC of a new alpha version
run_test "8.4.0-alpha1" "8.3.0" # First alpha of a new alpha version

run_test "8.4.1-alpha1" "8.4.0" # First alpha of a new alpha version
run_test "8.4.2-alpha1" "8.4.1" # First alpha of a new alpha version

run_test "8.3.2-rc1" "8.3.1" # RC for normal release, next lower normal tag
run_test "8.3.2-rc2" "8.3.2-rc1" # Next RC in series

run_test "8.4.0-rc1" "8.3.0" # RC for normal release, next lower normal tag
run_test "8.4.0-rc2" "8.4.0-rc1" # Next RC in series
run_test "8.4.0-rc3" "8.4.0-rc2" # Next RC in series

run_test "9.0.0" "8.4.0" # First release in a new major version
run_test "9.1.0" "9.0.0" # First release in a new minor version after a major version

run_test "9.2.0-alpha2" "9.1.0" # Missed alpha1
run_test "9.2.0-rc2" "9.1.0" # Missed rc1

# Invalid Tag Format
run_test "invalid-tag" "Release tag is invalid" # Invalid tag format
run_test "8.4" "Release tag is invalid" # Incomplete tag

# Clean up after tests
cleanup

# Output all test results at the end
echo -e "$passed_tests_results"
echo -e "$fail_test_results"
175 changes: 124 additions & 51 deletions .github/workflows/scripts/prev_tag.sh
Original file line number Diff line number Diff line change
@@ -1,61 +1,134 @@
if [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Release tag is valid" >&2
TYPE=NORMAL
elif [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+.*-rc[0-9]+$ ]]; then
echo "Release tag is valid (release candidate)" >&2
TYPE=RC
elif [[ $1 =~ [0-9]+\.[0-9]+\.[0-9]+-alpha[0-9]+$ ]]; then
echo "Release tag is valid (alpha)" >&2
TYPE=ALPHA
else
#!/bin/bash
# Rules for Determining Previous Tags
#
# Normal Versions:
# - For a regular release within a minor version (e.g., 8.3.3), the previous tag is the next lower tag in the same minor series (e.g., 8.3.2).
# - When it's the first release of a new minor version (e.g., 8.4.0), the previous tag is the base (x.0) tag of the preceding minor version (e.g., 8.3.0).
#
# Release Candidates (RC) for Normal Versions:
# - For the first RC of a new minor version (e.g., 8.4.0-rc1), the previous tag is the base (x.0) tag of the preceding minor version (e.g., 8.3.0).
# - For subsequent RC releases within the same minor version, the previous tag is the same as the previous RC release (e.g., 8.4.0-rc2).
#
# Alpha Versions:
# - When it's the first alpha release of a new minor version (e.g., 8.4.0-alpha1), the previous tag is the base (x.0) tag of the preceding minor version (e.g., 8.3.0).
# - For subsequent alpha releases within the same minor version, the previous tag is the same as the previous alpha release (e.g., 8.4.2-alpha2).
#
# Release Candidates (RC) for Alpha Versions:
# - For RC releases of alpha versions (e.g., 8.4.0-alpha2-rc1), the previous tag is the corresponding alpha tag (e.g., 8.4.0-alpha1).
#
# Major Version Releases:
# - For the first release of a new major version (e.g., 9.0.0), the previous tag is the base (x.0) tag of the highest minor version from the last major series (e.g., 8.9.0).
#
# Release Candidates (RC) for Major Versions:
# - For RC releases of a major version (e.g., 9.0.0-rc1), the previous tag is the base (x.0) tag of the highest minor version from the last major series (e.g., 8.9.0).

# Function to determine the previous tag based on the type and version
determine_prev_tag() {
local current_tag=$1
local type=$2
local major_minor=$(echo "$current_tag" | cut -d '.' -f 1,2)
local patch_version=$(echo "$current_tag" | cut -d '.' -f 3 | grep -oE "^[0-9]+")
local prev_major_minor=$(echo "$major_minor" | awk -F. '{$NF = $NF - 1;} 1' | sed 's/ /./g')

local prev_tag=""
local prev_tags=$(git --no-pager tag --sort=-v:refname)

case $type in
NORMAL)
# For a normal release, find the highest tag that is lower than the current tag in the same minor version series
prev_tag=$(echo "$prev_tags" | grep -E "^$major_minor\.[0-9]+$" | awk -v curTag="$current_tag" '$0 < curTag' | head -1)

# If no previous tag is found within the same minor version, default to the .0 tag of the previous minor version
[[ -z $prev_tag ]] && prev_tag="$prev_major_minor.0"
;;

RC)
# Remove the RC part from the current tag to find the base version
local base_version=$(echo "$current_tag" | sed 's/-rc[0-9]*$//')
# For regular RC releases, find the highest RC tag that is lower than the current tag in the same minor version series
prev_tag=$(echo "$prev_tags" | grep -E "^$major_minor\.[0-9]+-rc[0-9]+$" | awk -v curTag="$current_tag" '$0 < curTag' | head -1)
# If no previous RC is found within the same minor version, default to the .0 tag of the previous minor version
[[ -z $prev_tag ]] && prev_tag="$prev_major_minor.0"
;;

ALPHA)
if [[ $current_tag =~ -alpha[0-9]+-rc[0-9]+$ ]]; then
local alpha_version=$(echo "$current_tag" | sed 's/-rc[0-9]*$//')
local base_alpha=$(echo "$alpha_version" | sed 's/-alpha[0-9]*$//')

# Get the list of all RCs for the current alpha version
local rc_tags=$(echo "$prev_tags" | grep -E "^$alpha_version-rc[0-9]+$" | sort -rV)

if [[ -z $rc_tags ]]; then
# If no RCs found for the current alpha version, set the previous tag to the highest alpha version before the current alpha
prev_tag=$(echo "$prev_tags" | grep -E "^$base_alpha-alpha[0-9]+$" | sort -rV | awk -v curAlpha="$alpha_version" '$0 < curAlpha' | head -1)
else
# Find the immediate preceding RC for the current tag
prev_tag=$(echo "$rc_tags" | awk -v curTag="$current_tag" '$0 < curTag' | head -1)
if [[ -z $prev_tag ]]; then
# If no preceding RC found, it means the current tag is the first RC of the alpha version
# So, set the previous tag to the highest alpha version before the current alpha
prev_tag=$(echo "$prev_tags" | grep -E "^$base_alpha-alpha[0-9]+$" | sort -rV | awk -v curAlpha="$alpha_version" '$0 < curAlpha' | head -1)
fi
fi
elif [[ $current_tag =~ -alpha[0-9]+$ ]]; then
local alpha_base=$(echo "$current_tag" | sed 's/-alpha[0-9]*$//')

# Find the previous tag within the same major.minor version for alpha releases
prev_tag=$(echo "$prev_tags" | grep -E "^$major_minor\.[0-9]+-alpha[0-9]+$" | awk -v curTag="$current_tag" '$0 < curTag' | sort -rV | head -1)

if [[ -z $prev_tag ]]; then
# For the first alpha release of a new minor version, set the previous tag to the base tag of the preceding minor version
if [[ $patch_version == 0 ]]; then
prev_tag="$prev_major_minor.0"
else
# For subsequent alpha releases, find the last alpha release before the current tag
prev_tag="$major_minor.$((patch_version - 1))"
fi
fi
fi
;;
MAJOR)
local major=$(echo "$current_tag" | cut -d '.' -f 1)
local prev_major=$((major - 1))
prev_tag=$(echo "$prev_tags" | grep -E "^$prev_major\.[0-9]+\.0$" | head -1)
;;
esac

echo "$prev_tag"
}

# validation for tag format
if [[ ! $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+(-alpha[0-9]+)?(-rc[0-9]+)?$ ]]; then
echo "Release tag is invalid"
exit 1
fi
CUR_MINOR=$(echo "$1" | cut -d '.' -f 1,2)
PREV_MINOR=$(echo "$1" | cut -d '.' -f 1,2 | awk -F. '{$NF = $NF - 1;} 1' | sed 's/ /./g')

git fetch --tags -f 1>/dev/null
git pull --tags -f 1>/dev/null
PREV_TAGS=$(git --no-pager tag --sort=-creatordate)
NORMAL_PATTERN='^[0-9]+\.[0-9]+\.[0-9]+$'
RC_PATTERN='^[0-9]+\.[0-9]+\.[0-9]+.*-rc[0-9]+$'
ALPHA_PATTERN='^[0-9]+\.[0-9]+\.[0-9]+-alpha[0-9]+$'

# sanity check: the new tag must already exist
if [[ -z $(echo "$PREV_TAGS" | grep "$1") ]]; then
echo "Tag $1 does not exist" >&2
exit 1
# Determine the tag type
TYPE=""
if [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
TYPE="NORMAL"
[[ $1 =~ ^[0-9]+\.0\.0$ ]] && TYPE="MAJOR"
elif [[ $1 =~ -alpha[0-9]+(-rc[0-9]+)?$ ]]; then
TYPE="ALPHA"
elif [[ $1 =~ -rc[0-9]+$ ]]; then
TYPE="RC"
fi


echo "Current minor: $CUR_MINOR" >&2
echo "Previous minor: $PREV_MINOR" >&2
echo "Type: $TYPE" >&2

if [[ $TYPE == "NORMAL" ]]; then
# take last normal tag from current minor, if present - otherwise take last normal tag from previous minor
PREV_TAG=$(echo "$PREV_TAGS" | grep -E "$NORMAL_PATTERN" | grep "$CUR_MINOR" | head -2 | tail -1)
if [[ -z $PREV_TAG ]]; then
PREV_TAG=$(echo "$PREV_TAGS" | grep -E "$NORMAL_PATTERN" | grep "$PREV_MINOR" | head -1)
fi
elif [[ $TYPE == "RC" ]]; then
# take rc from current minor, if present - otherwise take last normal from previous minor
PREV_TAG=$(echo "$PREV_TAGS" | grep -E "$RC_PATTERN" | grep "$CUR_MINOR" | head -2 | tail -1)
if [[ -z $PREV_TAG ]]; then
PREV_TAG=$(echo "$PREV_TAGS" | grep -E "$NORMAL_PATTERN" | grep "$PREV_MINOR" | head -1)
fi
elif [[ $TYPE == "ALPHA" ]]; then
# take alpha from current minor, if present - otherwise take last normal tag from previous minor
PREV_TAG=$(echo "$PREV_TAGS" | grep -E "$ALPHA_PATTERN" | grep "$CUR_MINOR" | head -2 | tail -1)
if [[ -z $PREV_TAG ]]; then
PREV_TAG=$(echo "$PREV_TAGS" | grep -E "$NORMAL_PATTERN" | grep "$PREV_MINOR" | head -1)
fi
if [[ -z $TYPE ]]; then
echo "Invalid tag format"
exit 1
fi

if [[ -z $PREV_TAG ]]; then
echo "WARNING: No previous tag found for the given rules, taking the previous tag" >&2
PREV_TAG=$(echo "$PREV_TAGS" | head -2 | tail -1)
# Fetch and pull the tags from the repository
git fetch --tags -f 1>/dev/null
git pull --tags -f 1>/dev/null

# Determine the previous tag
prev_tag=$(determine_prev_tag "$1" "$TYPE")
if [[ -z $prev_tag ]]; then
echo "No previous tag found for the given rules"
exit 1
fi

echo "Previous tag: $PREV_TAG" >&2
echo $TYPE "$PREV_TAG"
echo "Previous tag: $prev_tag"

0 comments on commit 89e676c

Please sign in to comment.