2023-03-16 15:43:53 +00:00
|
|
|
#!/bin/bash
|
|
|
|
|
2023-06-01 08:40:26 +00:00
|
|
|
YELLOW="\e[0;33m"
|
|
|
|
RESET="\e[0m"
|
|
|
|
|
2023-03-16 15:43:53 +00:00
|
|
|
if [ ! -f ./scripts/run_tests.sh ]
|
|
|
|
then
|
|
|
|
echo "Error: ./scripts/run_tests.sh not found"
|
|
|
|
exit 1
|
|
|
|
fi
|
2023-04-06 16:11:49 +00:00
|
|
|
if [ ! -f pyproject.toml ]
|
2023-03-16 15:43:53 +00:00
|
|
|
then
|
2023-04-06 16:11:49 +00:00
|
|
|
echo "Error: pyproject.toml not found"
|
2023-03-16 15:43:53 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2023-04-02 17:37:27 +00:00
|
|
|
function warn_todos() {
|
|
|
|
local todos=0
|
|
|
|
todos="$(grep -nri TODO twnet_parser | wc -l)"
|
|
|
|
if [ "$todos" == "0" ]
|
|
|
|
then
|
|
|
|
return
|
|
|
|
fi
|
|
|
|
echo "<============ TODOS"
|
|
|
|
echo "..."
|
|
|
|
grep --color=always -nri TODO twnet_parser | tail -n2
|
|
|
|
echo "<============ TODOS"
|
|
|
|
echo "Warning: there are $todos open todos!"
|
|
|
|
echo " doing a major release with open todos"
|
|
|
|
echo " is not recommended!"
|
|
|
|
echo "Do you really want to continue? [y/N]"
|
|
|
|
read -r -n1 yn
|
|
|
|
if ! [[ "$yn" =~ [yY] ]]
|
|
|
|
then
|
|
|
|
echo "aborting ..."
|
|
|
|
exit 0
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
2023-03-16 15:43:53 +00:00
|
|
|
if ! git diff-index --quiet --cached HEAD --
|
|
|
|
then
|
|
|
|
echo "Error: dirty git working tree"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2023-03-16 15:59:59 +00:00
|
|
|
if [ "$(git rev-parse --abbrev-ref HEAD)" != "master" ]
|
|
|
|
then
|
|
|
|
echo "Error: can only release from master branch"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2023-03-16 15:43:53 +00:00
|
|
|
echo "This script will create a git tag, git commit and a pypi release"
|
|
|
|
echo "Do you really want to run that? [y/N]"
|
|
|
|
read -r -n1 yn
|
|
|
|
if ! [[ "$yn" =~ [yY] ]]
|
|
|
|
then
|
|
|
|
echo "aborting ..."
|
|
|
|
exit 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ ! -f .env ]
|
|
|
|
then
|
|
|
|
(
|
|
|
|
echo "# get it from https://pypi.org/manage/account/token/"
|
|
|
|
echo 'PYPI_TOKEN='
|
|
|
|
) > .env
|
|
|
|
fi
|
|
|
|
if ! pypi_token="$(grep PYPI_TOKEN= .env | cut -d'=' -f2-)"
|
|
|
|
then
|
|
|
|
echo "Error: failed to load env file"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if [ "$pypi_token" == "" ]
|
|
|
|
then
|
|
|
|
echo "Error: pypi token unset check your .env file"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ ! -x "$(command -v twine)" ]
|
|
|
|
then
|
|
|
|
echo "Error: command twine not found. Make sure to run:"
|
|
|
|
echo ""
|
|
|
|
echo " pip install -r requirements/dev.txt"
|
|
|
|
echo ""
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2023-06-01 08:40:26 +00:00
|
|
|
function commits_since_last_tag() {
|
|
|
|
git log "$(git describe --tags --abbrev=0)..HEAD" --pretty=format:'%s'
|
|
|
|
}
|
|
|
|
|
|
|
|
function list_api_breaking_commits() {
|
|
|
|
printf '%b' "$YELLOW"
|
|
|
|
if commits_since_last_tag | grep -F '!: '
|
|
|
|
then
|
|
|
|
printf '%b' "$RESET"
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
printf '%b' "$RESET"
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2023-03-16 15:43:53 +00:00
|
|
|
if ! latest_tag="$(git tag | sort -V | tail -n1)"
|
|
|
|
then
|
|
|
|
echo "Error: failed to get latest tag"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
echo ""
|
|
|
|
echo ""
|
|
|
|
echo ""
|
2023-03-18 09:07:51 +00:00
|
|
|
echo "==================================================================="
|
|
|
|
echo "current tag names:"
|
|
|
|
git tag | sort -V | awk '{ print " " $0 }'
|
|
|
|
echo "==================================================================="
|
2023-03-18 09:01:24 +00:00
|
|
|
echo "How to pick a tag name?"
|
|
|
|
echo " - change lib user facing api -> at least minor version bump"
|
2023-03-19 10:41:49 +00:00
|
|
|
echo " - adding a feature or a new api -> does NOT require a minor bump"
|
2023-03-18 09:01:24 +00:00
|
|
|
echo " - change internal (local variables etc) api -> patch version bump"
|
|
|
|
echo " - drastic user affecting change -> major version bump"
|
|
|
|
echo "Only a patch version change should NEVER break a users code"
|
2023-03-18 09:07:51 +00:00
|
|
|
echo "==================================================================="
|
2023-06-01 08:40:26 +00:00
|
|
|
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
if list_api_breaking_commits
|
|
|
|
then
|
|
|
|
echo ""
|
|
|
|
echo "=!= Found api breaking commits! See list above ^^^ =!="
|
|
|
|
echo "=!= Do at least a minor version jump due to breaking changes =!="
|
|
|
|
echo "=!= https://www.conventionalcommits.org/en/v1.0.0/ =!="
|
|
|
|
echo "==================================================================="
|
|
|
|
fi
|
|
|
|
|
2023-03-16 15:43:53 +00:00
|
|
|
read -r -p "tag name: " -i "$latest_tag" -e tag_name
|
|
|
|
if [ "$tag_name" == "" ]
|
|
|
|
then
|
|
|
|
echo "Error: tag name can not be empty"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if [ "$tag_name" == "$latest_tag" ]
|
|
|
|
then
|
|
|
|
echo "Error: please use a new tag version"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if [ "$(git tag -l "$tag_name")" != "" ]
|
|
|
|
then
|
|
|
|
echo "Error: tag already exists"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if [ "${tag_name::1}" != "v" ]
|
|
|
|
then
|
|
|
|
echo "Error: tag has to start with a v"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if [[ "$tag_name" =~ ^v([0-9]+)\.[0-9]+\.[0-9]+$ ]]
|
|
|
|
then
|
|
|
|
major="${BASH_REMATCH[1]}"
|
|
|
|
if [[ "$latest_tag" =~ ^v([0-9]+)\.[0-9]+\.[0-9]+$ ]]
|
|
|
|
then
|
|
|
|
latest_major="${BASH_REMATCH[1]}"
|
|
|
|
diff="$((major - latest_major))"
|
|
|
|
if [[ "$diff" -gt "1" ]]
|
|
|
|
then
|
|
|
|
echo "Error: new major version is $diff bigger than current"
|
|
|
|
echo " can only jump 1 major version at a time max"
|
|
|
|
echo " $latest_tag -> $tag_name"
|
|
|
|
exit 1
|
|
|
|
elif [[ "$diff" -lt "0" ]]
|
|
|
|
then
|
|
|
|
echo "Error: new major version is $diff smaller than current"
|
|
|
|
echo " can only increase or stay equal"
|
|
|
|
echo " $latest_tag -> $tag_name"
|
|
|
|
exit 1
|
|
|
|
fi
|
2023-04-02 17:37:27 +00:00
|
|
|
if [ "$diff" == "1" ]
|
|
|
|
then
|
|
|
|
warn_todos
|
|
|
|
fi
|
2023-03-16 15:43:53 +00:00
|
|
|
else
|
|
|
|
echo "Error: failed to parse latest tag"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
echo "Error: tag has to match vMAJOR.MINOR.PATCH format"
|
|
|
|
exit 1
|
|
|
|
fi
|
2023-03-18 09:09:24 +00:00
|
|
|
if [[ "$( (git tag;echo "$tag_name") | sort -V | tail -n1)" != "$tag_name" ]]
|
2023-03-16 15:43:53 +00:00
|
|
|
then
|
|
|
|
echo "Error: the tag name you entered '$tag_name' does not seem to be the latest"
|
|
|
|
echo " instead '$( (git tag;echo v0.0.2) | sort -V | tail -n1)' is the latest"
|
|
|
|
echo " ensure a new release has the latest semantic version"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if ! commit="$(git log -n 1 --pretty=format:"%h %s")"
|
|
|
|
then
|
|
|
|
echo "Error: failed to get commit"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
echo "====================================================="
|
|
|
|
echo "commit: $commit"
|
|
|
|
echo "tag: $tag_name (superseding: $latest_tag)"
|
|
|
|
echo "====================================================="
|
|
|
|
echo "Is that info correct? [y/N]"
|
|
|
|
read -r -n1 yn
|
|
|
|
if ! [[ "$yn" =~ [yY] ]]
|
|
|
|
then
|
|
|
|
echo "aborting ..."
|
|
|
|
exit 0
|
|
|
|
fi
|
|
|
|
|
|
|
|
if ! ./scripts/run_tests.sh
|
|
|
|
then
|
|
|
|
echo "Error: tests failed aborting ..."
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2023-04-07 07:27:49 +00:00
|
|
|
# Do not update setup.cfg
|
2023-04-06 15:56:25 +00:00
|
|
|
# if the build fails anyways
|
|
|
|
if ! python -m build
|
|
|
|
then
|
|
|
|
echo "Error: build failed"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2023-04-07 07:27:49 +00:00
|
|
|
echo "[*] updating version in setup.cfg ..."
|
2023-03-16 15:43:53 +00:00
|
|
|
# can safely be ran multiple times
|
2023-04-07 07:27:49 +00:00
|
|
|
sed -i "s/^version =.*/version = ${tag_name:1}/" setup.cfg
|
2023-03-16 15:43:53 +00:00
|
|
|
|
|
|
|
echo "[*] wiping old dist ..."
|
|
|
|
[[ -d dist ]] && rm -rf dist
|
|
|
|
|
2023-04-07 07:27:49 +00:00
|
|
|
# Try build again after setup.cfg update
|
2023-03-16 15:43:53 +00:00
|
|
|
if ! python -m build
|
|
|
|
then
|
|
|
|
echo "Error: build failed"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ ! -f dist/twnet_parser-"${tag_name:1}".tar.gz ]
|
|
|
|
then
|
|
|
|
echo "Error: build did not generate expected file"
|
|
|
|
echo " dist/twnet_parser-${tag_name:1}.tar.gz"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if ! pip install dist/twnet_parser-"${tag_name:1}".tar.gz
|
|
|
|
then
|
|
|
|
echo "Error: local test install of package failed"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if ! python -c "import twnet_parser"
|
|
|
|
then
|
|
|
|
echo "Error: local test import failed"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2023-04-06 17:07:41 +00:00
|
|
|
rm -rf /tmp/twnet_parser_test
|
|
|
|
mkdir -p /tmp/twnet_parser_test
|
2023-04-06 17:12:17 +00:00
|
|
|
cp -r tests /tmp/twnet_parser_test || exit 1
|
2023-04-06 17:07:41 +00:00
|
|
|
cp dist/twnet_parser-"${tag_name:1}".tar.gz /tmp/twnet_parser_test/
|
|
|
|
(
|
|
|
|
deactivate &>/dev/null
|
|
|
|
cd /tmp/twnet_parser_test || exit 1
|
|
|
|
python -m venv venv
|
2023-04-06 17:43:29 +00:00
|
|
|
# shellcheck disable=SC1091
|
2023-04-06 17:07:41 +00:00
|
|
|
source venv/bin/activate
|
|
|
|
if ! pip install twnet_parser-"${tag_name:1}".tar.gz
|
|
|
|
then
|
|
|
|
echo "Error: local test install of package failed (venv)"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if ! python -c "import twnet_parser"
|
|
|
|
then
|
|
|
|
echo "Error: local test import failed (venv)"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
if ! python -c "import twnet_parser.packet"
|
|
|
|
then
|
|
|
|
echo "Error: local test import twnet_parser.packet failed (venv)"
|
|
|
|
exit 1
|
|
|
|
fi
|
2023-04-06 17:12:17 +00:00
|
|
|
pip install pytest
|
|
|
|
python -m pytest tests || exit 1
|
2023-04-06 17:07:41 +00:00
|
|
|
) || {
|
|
|
|
echo "[*] venv install tests failed.";
|
|
|
|
exit 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
echo "[*] venv tests passed."
|
|
|
|
|
2023-04-07 07:27:49 +00:00
|
|
|
if ! git add setup.cfg
|
2023-03-16 15:43:53 +00:00
|
|
|
then
|
|
|
|
echo "Error: git add failed"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2023-04-07 07:27:49 +00:00
|
|
|
if [ "$(git diff HEAD --name-only)" != "setup.cfg" ]
|
2023-03-16 15:43:53 +00:00
|
|
|
then
|
|
|
|
echo "Error: unexpected files would be included in the commit"
|
2023-04-07 07:27:49 +00:00
|
|
|
git diff HEAD --name-only | grep -v '^setup.cfg$' | awk '{ print " " $0 }'
|
2023-03-16 15:43:53 +00:00
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2023-07-13 11:00:44 +00:00
|
|
|
if ! git commit -m "chore: release ${tag_name:1}"
|
2023-03-16 15:43:53 +00:00
|
|
|
then
|
|
|
|
echo "Error: git commit failed"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if ! git tag -a "$tag_name" -m "# version ${tag_name:1}"
|
|
|
|
then
|
|
|
|
echo "Error: creating the tag failed"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
2023-03-16 15:59:59 +00:00
|
|
|
if ! python -m twine upload -u __token__ -p "$pypi_token" dist/*
|
|
|
|
then
|
|
|
|
echo "Error: upload to pypi failed"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
git push origin master
|
|
|
|
git push origin "$tag_name"
|
2023-03-16 15:43:53 +00:00
|
|
|
|
2023-03-18 09:29:28 +00:00
|
|
|
echo "Create a release on gitlab with a changelog!"
|
|
|
|
echo "./scripts/gen_changelog.sh"
|
|
|
|
echo "https://gitlab.com/teeworlds-network/twnet_parser/-/releases/new?tag_name=$tag_name"
|
|
|
|
|