From 89e676cfe5e268a32cbc01f077b12ac106bfaafe Mon Sep 17 00:00:00 2001 From: Oleksii Ivanov Date: Mon, 8 Jan 2024 10:38:18 +0200 Subject: [PATCH] fix(workflows) fix prev_tag script --- .github/workflows/scripts/prev_tag-test.sh | 114 ++++++++++++++ .github/workflows/scripts/prev_tag.sh | 175 +++++++++++++++------ 2 files changed, 238 insertions(+), 51 deletions(-) create mode 100644 .github/workflows/scripts/prev_tag-test.sh diff --git a/.github/workflows/scripts/prev_tag-test.sh b/.github/workflows/scripts/prev_tag-test.sh new file mode 100644 index 0000000000..8da1a4c2b5 --- /dev/null +++ b/.github/workflows/scripts/prev_tag-test.sh @@ -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" diff --git a/.github/workflows/scripts/prev_tag.sh b/.github/workflows/scripts/prev_tag.sh index eaef18e421..0842564da4 100755 --- a/.github/workflows/scripts/prev_tag.sh +++ b/.github/workflows/scripts/prev_tag.sh @@ -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" \ No newline at end of file