You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by el...@apache.org on 2023/10/21 00:19:35 UTC

[superset] branch 2.1 updated (e946227d92 -> 68ff72061d)

This is an automated email from the ASF dual-hosted git repository.

elizabeth pushed a change to branch 2.1
in repository https://gitbox.apache.org/repos/asf/superset.git


    omit e946227d92 bump frontend version
    omit d153fb78a5 fix tests
    omit 7d55d236d3 chore: add latest-official docker tag (#25322)
     new 62613a875d chore: add latest-official docker tag (#25322)
     new 8d20fa11db fix tests and lint
     new 68ff72061d bump frontend version

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (e946227d92)
            \
             N -- N -- N   refs/heads/2.1 (68ff72061d)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 superset/models/helpers.py                          | 20 ++++++++++----------
 superset/sql_parse.py                               | 10 +++++-----
 tests/unit_tests/scripts/docker_build_push_test.py  | 16 ++++++++++++++++
 tests/unit_tests/scripts/tag_latest_release_test.py | 16 ++++++++++++++++
 4 files changed, 47 insertions(+), 15 deletions(-)


[superset] 02/03: fix tests and lint

Posted by el...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

elizabeth pushed a commit to branch 2.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 8d20fa11db3db6881189e34b53920bf5036980da
Author: Elizabeth Thompson <es...@gmail.com>
AuthorDate: Fri Oct 20 16:37:41 2023 -0700

    fix tests and lint
---
 requirements/development.txt |  2 --
 requirements/testing.txt     |  5 -----
 superset/models/helpers.py   | 20 ++++++++++----------
 superset/sql_parse.py        | 10 +++++-----
 4 files changed, 15 insertions(+), 22 deletions(-)

diff --git a/requirements/development.txt b/requirements/development.txt
index 47fe7a1737..aa92fcfda4 100644
--- a/requirements/development.txt
+++ b/requirements/development.txt
@@ -80,8 +80,6 @@ pure-sasl==0.6.2
     # via thrift-sasl
 pydruid==0.6.5
     # via apache-superset
-pygments==2.12.0
-    # via ipython
 pyhive[hive]==0.6.5
     # via apache-superset
 pyinstrument==4.0.2
diff --git a/requirements/testing.txt b/requirements/testing.txt
index ead36ba3f6..73f3447521 100644
--- a/requirements/testing.txt
+++ b/requirements/testing.txt
@@ -137,8 +137,3 @@ trino==0.319.0
     # via apache-superset
 websocket-client==1.2.0
     # via docker
-wrapt==1.12.1
-    # via astroid
-# The following packages are considered to be unsafe in a requirements file:
-# pip
-# setuptools
diff --git a/superset/models/helpers.py b/superset/models/helpers.py
index 795cc6faa3..ba6b15edbc 100644
--- a/superset/models/helpers.py
+++ b/superset/models/helpers.py
@@ -152,7 +152,7 @@ def convert_uuids(obj: Any) -> Any:
     if isinstance(obj, uuid.UUID):
         return str(obj)
 
-    if isinstance(obj, list):
+    if isinstance(obj, List):
         return [convert_uuids(el) for el in obj]
 
     if isinstance(obj, dict):
@@ -185,7 +185,7 @@ class ImportExportMixin:
     __mapper__: Mapper
 
     @classmethod
-    def _unique_constraints(cls) -> list[set[str]]:
+    def _unique_constraints(cls) -> List[Set[str]]:
         """Get all (single column and multi column) unique constraints"""
         unique = [
             {c.name for c in u.columns}
@@ -246,7 +246,7 @@ class ImportExportMixin:
         dict_rep: Dict[Any, Any],
         parent: Optional[Any] = None,
         recursive: bool = True,
-        sync: Optional[list[str]] = None,
+        sync: Optional[List[str]] = None,
         allow_reparenting: bool = False,
     ) -> Any:
         """Import obj from a dictionary"""
@@ -265,7 +265,7 @@ class ImportExportMixin:
         filters = []  # Using these filters to check if obj already exists
 
         # Remove fields that should not get imported
-        for k in list(dict_rep):
+        for k in List(dict_rep):
             if k not in export_fields and k not in parent_refs:
                 del dict_rep[k]
 
@@ -651,7 +651,7 @@ def clone_model(
     primary_keys = table.primary_key.columns.keys()
     data = {
         attr: getattr(target, attr)
-        for attr in list(table.columns.keys()) + (keep_relations or [])
+        for attr in List(table.columns.keys()) + (keep_relations or [])
         if attr not in primary_keys and attr not in ignore
     }
     data.update(kwargs)
@@ -1150,13 +1150,13 @@ class ExploreMixin:  # pylint: disable=too-many-public-methods
                 return utils.cast_to_boolean(value)
             return value
 
-        if isinstance(values, (list, tuple)):
+        if isinstance(values, (List, Tuple)):
             values = [handle_single_value(v) for v in values]  # type: ignore
         else:
             values = handle_single_value(values)
-        if is_list_target and not isinstance(values, (tuple, list)):
+        if is_list_target and not isinstance(values, (Tuple, List)):
             values = [values]  # type: ignore
-        elif not is_list_target and isinstance(values, (tuple, list)):
+        elif not is_list_target and isinstance(values, (Tuple, List)):
             values = values[0] if values else None
         return values
 
@@ -1407,7 +1407,7 @@ class ExploreMixin:  # pylint: disable=too-many-public-methods
         template_kwargs["removed_filters"] = removed_filters
         template_kwargs["applied_filters"] = applied_template_filters
         template_processor = self.get_template_processor(**template_kwargs)
-        prequeries: list[str] = []
+        prequeries: List[str] = []
         orderby = orderby or []
         need_groupby = bool(metrics is not None or groupby)
         metrics = metrics or []
@@ -1747,7 +1747,7 @@ class ExploreMixin:  # pylint: disable=too-many-public-methods
                         )
                     )
                 elif is_list_target:
-                    assert isinstance(eq, (tuple, list))
+                    assert isinstance(eq, (Tuple, List))
                     if len(eq) == 0:
                         raise QueryObjectValidationError(
                             _("Filter value list cannot be empty")
diff --git a/superset/sql_parse.py b/superset/sql_parse.py
index 216b4e8825..f705ad9679 100644
--- a/superset/sql_parse.py
+++ b/superset/sql_parse.py
@@ -18,7 +18,7 @@ import logging
 import re
 from dataclasses import dataclass
 from enum import Enum
-from typing import Any, cast, Iterator, List, Optional, Set, Tuple
+from typing import Any, cast, Iterator, List, Optional, Set, Tuple, Dict
 from urllib import parse
 
 import sqlparse
@@ -216,12 +216,12 @@ class ParsedQuery:
     def limit(self) -> Optional[int]:
         return self._limit
 
-    def _get_cte_tables(self, parsed: dict[str, Any]) -> list[dict[str, Any]]:
+    def _get_cte_tables(self, parsed: Dict[str, Any]) -> List[Dict[str, Any]]:
         if "with" not in parsed:
             return []
         return parsed["with"].get("cte_tables", [])
 
-    def _check_cte_is_select(self, oxide_parse: list[dict[str, Any]]) -> bool:
+    def _check_cte_is_select(self, oxide_parse: List[Dict[str, Any]]) -> bool:
         """
         Check if a oxide parsed CTE contains only SELECT statements
 
@@ -822,10 +822,10 @@ def extract_table_references(
         """
         Find all nodes in a SQL tree matching a given key.
         """
-        if isinstance(element, list):
+        if isinstance(element, List):
             for child in element:
                 yield from find_nodes_by_key(child, target)
-        elif isinstance(element, dict):
+        elif isinstance(element, Dict):
             for key, value in element.items():
                 if key == target:
                     yield value


[superset] 03/03: bump frontend version

Posted by el...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

elizabeth pushed a commit to branch 2.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 68ff72061de810118e6a4b65ac0c725d0bdfb401
Author: Elizabeth Thompson <es...@gmail.com>
AuthorDate: Fri Oct 20 16:39:58 2023 -0700

    bump frontend version
---
 superset-frontend/package-lock.json | 4 ++--
 superset-frontend/package.json      | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json
index adb7f27ae6..b38140b873 100644
--- a/superset-frontend/package-lock.json
+++ b/superset-frontend/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "superset",
-  "version": "2.1.1",
+  "version": "2.1.2",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "superset",
-      "version": "2.1.1",
+      "version": "2.1.2",
       "license": "Apache-2.0",
       "workspaces": [
         "packages/*",
diff --git a/superset-frontend/package.json b/superset-frontend/package.json
index 5cc84f7fe8..d58dad57ee 100644
--- a/superset-frontend/package.json
+++ b/superset-frontend/package.json
@@ -1,6 +1,6 @@
 {
   "name": "superset",
-  "version": "2.1.1",
+  "version": "2.1.2",
   "description": "Superset is a data exploration platform designed to be visual, intuitive, and interactive.",
   "keywords": [
     "big",


[superset] 01/03: chore: add latest-official docker tag (#25322)

Posted by el...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

elizabeth pushed a commit to branch 2.1
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 62613a875d61eaef1d5d51f719278669c5130469
Author: Elizabeth Thompson <es...@gmail.com>
AuthorDate: Wed Oct 18 16:59:30 2023 -0700

    chore: add latest-official docker tag (#25322)
---
 .github/workflows/docker-release.yml               |   3 +-
 .github/workflows/docker.yml                       |   2 +-
 .../workflows => scripts}/docker_build_push.sh     |  82 +++++++++++-
 scripts/tag_latest_release.sh                      | 140 +++++++++++++++------
 tests/unit_tests/fixtures/bash_mock.py             |  44 +++++++
 tests/unit_tests/scripts/docker_build_push_test.py |  60 +++++++++
 .../unit_tests/scripts/tag_latest_release_test.py  |  65 ++++++++++
 7 files changed, 354 insertions(+), 42 deletions(-)

diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml
index d082603be9..9e9119ab78 100644
--- a/.github/workflows/docker-release.yml
+++ b/.github/workflows/docker-release.yml
@@ -19,4 +19,5 @@ jobs:
           DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
           DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
         run: |
-          .github/workflows/docker_build_push.sh
+          GITHUB_RELEASE_TAG_NAME="${{ github.event.release.tag_name }}"
+          ./scripts/docker_build_push.sh "$GITHUB_RELEASE_TAG_NAME"
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index bd3fa3730c..8e62938baf 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -41,7 +41,7 @@ jobs:
           DOCKERHUB_USER: ${{ secrets.DOCKERHUB_USER }}
           DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }}
         run: |
-          .github/workflows/docker_build_push.sh
+          ./scripts/docker_build_push.sh
 
       - name: Build ephemeral env image
         if: github.event_name == 'pull_request'
diff --git a/.github/workflows/docker_build_push.sh b/scripts/docker_build_push.sh
similarity index 57%
rename from .github/workflows/docker_build_push.sh
rename to scripts/docker_build_push.sh
index b969813627..4aef8f2244 100755
--- a/.github/workflows/docker_build_push.sh
+++ b/scripts/docker_build_push.sh
@@ -17,6 +17,8 @@
 #
 set -eo pipefail
 
+GITHUB_RELEASE_TAG_NAME="$1"
+
 SHA=$(git rev-parse HEAD)
 REPO_NAME="apache/superset"
 
@@ -32,10 +34,27 @@ else
   LATEST_TAG="${REFSPEC}"
 fi
 
+
 if [[ "${REFSPEC}" == "master" ]]; then
-  LATEST_TAG="latest"
+  LATEST_TAG="master"
+fi
+
+# get the latest release tag
+if [ -n "${GITHUB_RELEASE_TAG_NAME}" ]; then
+  output=$(source ./scripts/tag_latest_release.sh "${GITHUB_RELEASE_TAG_NAME}" --dry-run) || true
+  SKIP_TAG=$(echo "${output}" | grep "SKIP_TAG" | cut -d'=' -f2)
+  if [[ "${SKIP_TAG}" == "SKIP_TAG::false" ]]; then
+    LATEST_TAG="latest"
+  fi
+fi
+
+if [[ "${TEST_ENV}" == "true" ]]; then
+  # don't run the build in test environment
+  echo "LATEST_TAG is ${LATEST_TAG}"
+  exit 0
 fi
 
+
 cat<<EOF
   Rolling with tags:
   - ${REPO_NAME}:${SHA}
@@ -43,6 +62,47 @@ cat<<EOF
   - ${REPO_NAME}:${LATEST_TAG}
 EOF
 
+if [ -z "${DOCKERHUB_TOKEN}" ]; then
+  # Skip if secrets aren't populated -- they're only visible for actions running in the repo (not on forks)
+  echo "Skipping Docker push"
+  # By default load it back
+  DOCKER_ARGS="--load"
+  ARCHITECTURE_FOR_BUILD="linux/amd64 linux/arm64"
+else
+  # Login and push
+  docker logout
+  docker login --username "${DOCKERHUB_USER}" --password "${DOCKERHUB_TOKEN}"
+  DOCKER_ARGS="--push"
+  ARCHITECTURE_FOR_BUILD="linux/amd64,linux/arm64"
+fi
+set -x
+
+# for the dev image, it's ok to tag master as latest-dev
+# for production, we only want to tag the latest official release as latest
+if [ "${LATEST_TAG}" = "master" ]; then
+  DEV_TAG="${REPO_NAME}:latest-dev"
+else
+  DEV_TAG="${REPO_NAME}:${LATEST_TAG}-dev"
+fi
+
+#
+# Build the dev image
+#
+docker buildx build --target dev \
+  $DOCKER_ARGS \
+  --cache-from=type=registry,ref=apache/superset:master-dev \
+  --cache-from=type=local,src=/tmp/superset \
+  --cache-to=type=local,ignore-error=true,dest=/tmp/superset \
+  -t "${REPO_NAME}:${SHA}-dev" \
+  -t "${REPO_NAME}:${REFSPEC}-dev" \
+  -t "${DEV_TAG}" \
+  --platform linux/amd64 \
+  --label "sha=${SHA}" \
+  --label "built_at=$(date)" \
+  --label "target=dev" \
+  --label "build_actor=${GITHUB_ACTOR}" \
+  .
+
 #
 # Build the "lean" image
 #
@@ -71,6 +131,26 @@ docker build --target lean \
   --label "build_actor=${GITHUB_ACTOR}" \
   .
 
+#
+# Build the "lean39" image
+#
+docker buildx build --target lean \
+  $DOCKER_ARGS \
+  --cache-from=type=local,src=/tmp/superset \
+  --cache-to=type=local,ignore-error=true,dest=/tmp/superset \
+  -t "${REPO_NAME}:${SHA}-py39" \
+  -t "${REPO_NAME}:${REFSPEC}-py39" \
+  -t "${REPO_NAME}:${LATEST_TAG}-py39" \
+  --platform linux/amd64 \
+  --build-arg PY_VER="3.9-slim-bullseye"\
+  --label "sha=${SHA}" \
+  --label "built_at=$(date)" \
+  --label "target=lean39" \
+  --label "build_actor=${GITHUB_ACTOR}" \
+  .
+
+
+for BUILD_PLATFORM in $ARCHITECTURE_FOR_BUILD; do
 #
 # Build the "websocket" image
 #
diff --git a/scripts/tag_latest_release.sh b/scripts/tag_latest_release.sh
index a5d50eaf9f..f2ee846a63 100755
--- a/scripts/tag_latest_release.sh
+++ b/scripts/tag_latest_release.sh
@@ -17,7 +17,7 @@
 #
 
 run_git_tag () {
-  if [ "$DRY_RUN" = "false" ] && [ "$SKIP_TAG" = "false" ]
+  if [[ "$DRY_RUN" == "false" ]] && [[ "$SKIP_TAG" == "false" ]]
   then
     git tag -a -f latest "${GITHUB_TAG_NAME}" -m "latest tag"
     echo "${GITHUB_TAG_NAME} has been tagged 'latest'"
@@ -25,7 +25,55 @@ run_git_tag () {
   exit 0
 }
 
-echo "::set-output name=SKIP_TAG::false"
+###
+# separating out git commands into functions so they can be mocked in unit tests
+###
+git_show_ref () {
+  if [[ "$TEST_ENV" == "true" ]]
+  then
+    if [[ "$GITHUB_TAG_NAME" == "does_not_exist" ]]
+        # mock return for testing only
+    then
+      echo ""
+    else
+      echo "2817aebd69dc7d199ec45d973a2079f35e5658b6 refs/tags/${GITHUB_TAG_NAME}"
+    fi
+  fi
+  result=$(git show-ref "${GITHUB_TAG_NAME}")
+  echo "${result}"
+}
+
+get_latest_tag_list () {
+  if [[ "$TEST_ENV" == "true" ]]
+  then
+    echo "(tag: 2.1.0, apache/2.1test)"
+  else
+    result=$(git show-ref --tags --dereference latest | awk '{print $2}' | xargs git show --pretty=tformat:%d -s | grep tag:)
+    echo "${result}"
+  fi
+}
+###
+
+split_string () {
+  local version="$1"
+  local delimiter="$2"
+  local components=()
+  local tmp=""
+  for (( i=0; i<${#version}; i++ )); do
+    local char="${version:$i:1}"
+    if [[ "$char" != "$delimiter" ]]; then
+      tmp="$tmp$char"
+    elif [[ -n "$tmp" ]]; then
+      components+=("$tmp")
+      tmp=""
+    fi
+  done
+  if [[ -n "$tmp" ]]; then
+    components+=("$tmp")
+  fi
+  echo "${components[@]}"
+}
+
 DRY_RUN=false
 
 # get params passed in with script when it was run
@@ -50,12 +98,14 @@ done
 
 if [ -z "${GITHUB_TAG_NAME}" ]; then
     echo "Missing tag parameter, usage: ./scripts/tag_latest_release.sh <GITHUB_TAG_NAME>"
+    echo "::set-output name=SKIP_TAG::true"
     exit 1
 fi
 
-if [ -z "$(git show-ref ${GITHUB_TAG_NAME})" ]; then
+if [ -z "$(git_show_ref)" ]; then
     echo "The tag ${GITHUB_TAG_NAME} does not exist. Please use a different tag."
-    exit 1
+    echo "::set-output name=SKIP_TAG::true"
+    exit 0
 fi
 
 # check that this tag only contains a proper semantic version
@@ -63,36 +113,41 @@ if ! [[ ${GITHUB_TAG_NAME} =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]
 then
   echo "This tag ${GITHUB_TAG_NAME} is not a valid release version. Not tagging."
   echo "::set-output name=SKIP_TAG::true"
-  exit 0
+  exit 1
 fi
 
 ## split the current GITHUB_TAG_NAME into an array at the dot
-IFS=$'.'
-THIS_TAG_NAME=(${GITHUB_TAG_NAME})  || echo 'not found'
+THIS_TAG_NAME=$(split_string "${GITHUB_TAG_NAME}" ".")
 
 # look up the 'latest' tag on git
-LATEST_TAG_LIST=$(git show-ref latest && git show --pretty=tformat:%d -s latest | grep tag:) || echo 'not found'
+LATEST_TAG_LIST=$(get_latest_tag_list) || echo 'not found'
 
 # if 'latest' tag doesn't exist, then set this commit to latest
 if [[ -z "$LATEST_TAG_LIST" ]]
 then
-  # move on to next task
   echo "there are no latest tags yet, so I'm going to start by tagging this sha as the latest"
   run_git_tag
+  exit 0
 fi
 
-## get all tags that use the same sha as the latest tag. split at comma.
-IFS=$','
-LATEST_TAGS=($LATEST_TAG_LIST)
+# remove parenthesis and tag: from the list of tags
+LATEST_TAGS_STRINGS=$(echo "$LATEST_TAG_LIST" | sed 's/tag: \([^,]*\)/\1/g' | tr -d '()')
 
-## loop over those tags and only take action on the one that isn't tagged 'latest'
-## that one will have the version number tag
-for (( i=0; i<${#LATEST_TAGS[@]}; i++ ))
+LATEST_TAGS=$(split_string "$LATEST_TAGS_STRINGS" ",")
+TAGS=($(split_string "$LATEST_TAGS" " "))
+
+# Initialize a flag for comparison result
+compare_result=""
+
+# Iterate through the tags of the latest release
+for tag in $TAGS
 do
-  if [[ ${LATEST_TAGS[$i]} != *"latest"* ]]
-  then
+  if [[ $tag == "latest" ]]; then
+    continue
+  else
     ## extract just the version from this tag
-    LATEST_RELEASE_TAG=$(echo "${LATEST_TAGS[$i]}" | sed -E -e 's/tag:|\(|\)|[[:space:]]*//g')
+    LATEST_RELEASE_TAG="$tag"
+    echo "LATEST_RELEASE_TAG: ${LATEST_RELEASE_TAG}"
 
     # check that this only contains a proper semantic version
     if ! [[ ${LATEST_RELEASE_TAG} =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]
@@ -101,28 +156,35 @@ do
       continue
     fi
     echo "The current release with the latest tag is version ${LATEST_RELEASE_TAG}"
-
-    ## remove the sha from the latest tag and split into an array- split at the dot
-    IFS=$'.'
-    LATEST_RELEASE_TAG_SPLIT=(${LATEST_RELEASE_TAG})
-
-    for (( j=0; j<${#THIS_TAG_NAME[@]}; j++ ))
-    do
-      ## if this value is greater than the latest release, then tag it, if it's lower, then stop, if it's
-      ## the same then move on to the next index
-      if [[ ${THIS_TAG_NAME[$j]} -gt ${LATEST_RELEASE_TAG_SPLIT[$j]} ]]
-      then
-        echo "This release tag ${GITHUB_TAG_NAME} is the latest. Tagging it"
-        run_git_tag
-
-      elif [[ ${THIS_TAG_NAME[$j]} -lt ${LATEST_RELEASE_TAG_SPLIT[$j]} ]]
-      then
-        continue
-      fi
+    # Split the version strings into arrays
+    THIS_TAG_NAME_ARRAY=($(split_string "$THIS_TAG_NAME" "."))
+    LATEST_RELEASE_TAG_ARRAY=($(split_string "$LATEST_RELEASE_TAG" "."))
+
+    # Iterate through the components of the version strings
+    for (( j=0; j<${#THIS_TAG_NAME_ARRAY[@]}; j++ )); do
+        echo "Comparing ${THIS_TAG_NAME_ARRAY[$j]} to ${LATEST_RELEASE_TAG_ARRAY[$j]}"
+        if [[ $((THIS_TAG_NAME_ARRAY[$j])) > $((LATEST_RELEASE_TAG_ARRAY[$j])) ]]; then
+            compare_result="greater"
+            break
+        elif [[ $((THIS_TAG_NAME_ARRAY[$j])) < $((LATEST_RELEASE_TAG_ARRAY[$j])) ]]; then
+            compare_result="lesser"
+            break
+        fi
     done
   fi
 done
 
-echo "This release tag ${GITHUB_TAG_NAME} is not the latest. Not tagging."
-# if you've gotten this far, then we don't want to run any tags in the next step
-echo "::set-output name=SKIP_TAG::true"
+# Determine the result based on the comparison
+if [[ -z "$compare_result" ]]; then
+    echo "Versions are equal"
+    echo "::set-output name=SKIP_TAG::true"
+elif [[ "$compare_result" == "greater" ]]; then
+    echo "This release tag ${GITHUB_TAG_NAME} is newer than the latest."
+    echo "::set-output name=SKIP_TAG::false"
+    # Add other actions you want to perform for a newer version
+elif [[ "$compare_result" == "lesser" ]]; then
+    echo "This release tag ${GITHUB_TAG_NAME} is older than the latest."
+    echo "This release tag ${GITHUB_TAG_NAME} is not the latest. Not tagging."
+    # if you've gotten this far, then we don't want to run any tags in the next step
+    echo "::set-output name=SKIP_TAG::true"
+fi
diff --git a/tests/unit_tests/fixtures/bash_mock.py b/tests/unit_tests/fixtures/bash_mock.py
new file mode 100644
index 0000000000..91194de6bf
--- /dev/null
+++ b/tests/unit_tests/fixtures/bash_mock.py
@@ -0,0 +1,44 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import subprocess
+
+
+class BashMock:
+    @staticmethod
+    def tag_latest_release(tag):
+        bash_command = f"./scripts/tag_latest_release.sh {tag} --dry-run"
+        result = subprocess.run(
+            bash_command,
+            shell=True,
+            capture_output=True,
+            text=True,
+            env={"TEST_ENV": "true"},
+        )
+        return result
+
+    @staticmethod
+    def docker_build_push(tag, branch):
+        bash_command = f"./scripts/docker_build_push.sh {tag}"
+        result = subprocess.run(
+            bash_command,
+            shell=True,
+            capture_output=True,
+            text=True,
+            env={"TEST_ENV": "true", "GITHUB_REF": f"refs/heads/{branch}"},
+        )
+        return result
diff --git a/tests/unit_tests/scripts/docker_build_push_test.py b/tests/unit_tests/scripts/docker_build_push_test.py
new file mode 100644
index 0000000000..4c5d1373b3
--- /dev/null
+++ b/tests/unit_tests/scripts/docker_build_push_test.py
@@ -0,0 +1,60 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+import re
+import subprocess
+from unittest import mock
+from unittest.mock import patch
+
+import pytest
+
+from tests.unit_tests.fixtures.bash_mock import BashMock
+
+original_run = subprocess.run
+
+
+def wrapped(*args, **kwargs):
+    return original_run(*args, **kwargs)
+
+
+@pytest.mark.parametrize(
+    "tag, expected_output, branch",
+    [
+        ("1.0.0", "LATEST_TAG is master", "master"),
+        ("2.1.0", "LATEST_TAG is master", "master"),
+        ("2.1.1", "LATEST_TAG is latest", "master"),
+        ("3.0.0", "LATEST_TAG is latest", "master"),
+        ("2.1.0rc1", "LATEST_TAG is 2.1.0", "2.1.0"),
+        ("", "LATEST_TAG is foo", "foo"),
+        ("2.1", "LATEST_TAG is 2.1", "2.1"),
+        ("does_not_exist", "LATEST_TAG is does-not-exist", "does_not_exist"),
+    ],
+)
+def test_tag_latest_release(tag, expected_output, branch):
+    with mock.patch(
+        "tests.unit_tests.fixtures.bash_mock.subprocess.run", wraps=wrapped
+    ) as subprocess_mock:
+        result = BashMock.docker_build_push(tag, branch)
+
+        subprocess_mock.assert_called_once_with(
+            f"./scripts/docker_build_push.sh {tag}",
+            shell=True,
+            capture_output=True,
+            text=True,
+            env={"TEST_ENV": "true", "GITHUB_REF": f"refs/heads/{branch}"},
+        )
+
+        assert re.search(expected_output, result.stdout, re.MULTILINE)
diff --git a/tests/unit_tests/scripts/tag_latest_release_test.py b/tests/unit_tests/scripts/tag_latest_release_test.py
new file mode 100644
index 0000000000..6dbb0eee4e
--- /dev/null
+++ b/tests/unit_tests/scripts/tag_latest_release_test.py
@@ -0,0 +1,65 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+import subprocess
+from unittest import mock
+from unittest.mock import patch
+
+import pytest
+
+from tests.unit_tests.fixtures.bash_mock import BashMock
+
+original_run = subprocess.run
+
+
+def wrapped(*args, **kwargs):
+    return original_run(*args, **kwargs)
+
+
+@pytest.mark.parametrize(
+    "tag, expected_output",
+    [
+        ("1.0.0", "This release tag 1.0.0 is older than the latest."),
+        ("2.1.0", "Versions are equal\n::set-output name=SKIP_TAG::true"),
+        ("2.1.1", "This release tag 2.1.1 is newer than the latest."),
+        ("3.0.0", "This release tag 3.0.0 is newer than the latest."),
+        ("2.1.0rc1", "This tag 2.1.0rc1 is not a valid release version. Not tagging."),
+        (
+            "",
+            "Missing tag parameter, usage: ./scripts/tag_latest_release.sh <GITHUB_TAG_NAME>",
+        ),
+        ("2.1", "This tag 2.1 is not a valid release version. Not tagging."),
+        (
+            "does_not_exist",
+            "The tag does_not_exist does not exist. Please use a different tag.\n::set-output name=SKIP_TAG::true",
+        ),
+    ],
+)
+def test_tag_latest_release(tag, expected_output):
+    with mock.patch(
+        "tests.unit_tests.fixtures.bash_mock.subprocess.run", wraps=wrapped
+    ) as subprocess_mock:
+        result = BashMock.tag_latest_release(tag)
+
+        subprocess_mock.assert_called_once_with(
+            f"./scripts/tag_latest_release.sh {tag} --dry-run",
+            shell=True,
+            capture_output=True,
+            text=True,
+            env={"TEST_ENV": "true"},
+        )
+
+        assert expected_output in result.stdout