Overengineer release script

This commit is contained in:
ChillerDragon 2023-03-16 16:43:53 +01:00
parent 9b264eb45d
commit 18f5c146b4
10 changed files with 225 additions and 13 deletions

1
.gitignore vendored
View file

@ -3,3 +3,4 @@ dist/
__pycache__/
*.pyc
*.egg-info
.env

View file

@ -14,11 +14,11 @@ pylint:
stage: lint
script:
- pip install -r requirements/dev.txt
- pylint src/
- pylint twnet_parser/
types:
stage: lint
script:
- pip install -r requirements/dev.txt
- mypy src/
- mypy twnet_parser/

View file

@ -47,8 +47,14 @@ mypy src/
## package and release
```bash
# manual
pip install -r requirements/dev.txt
version=0.0.2
sed "s/^version =.*/version = $version/" setup.cfg
python -m build
git tag -a v0.0.1 -m '# version 0.0.1'
git tag -a "v$version" -m "# version $version"
python -m twine upload dist/*
# or use the interactive convience script
./scripts/release.sh
```

203
scripts/release.sh Executable file
View file

@ -0,0 +1,203 @@
#!/bin/bash
if [ ! -f ./scripts/run_tests.sh ]
then
echo "Error: ./scripts/run_tests.sh not found"
exit 1
fi
if [ ! -f setup.cfg ]
then
echo "Error: setup.cfg not found"
exit 1
fi
if ! git diff-index --quiet --cached HEAD --
then
echo "Error: dirty git working tree"
exit 1
fi
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
if ! latest_tag="$(git tag | sort -V | tail -n1)"
then
echo "Error: failed to get latest tag"
exit 1
fi
echo ""
echo ""
echo ""
git tag | sort -V
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
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
if [[ "$( (git tag;echo v0.0.2) | sort -V | tail -n1)" != "$tag_name" ]]
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
echo "[*] updating version in setup.cfg ..."
# can safely be ran multiple times
sed -i "s/^version =.*/version = ${tag_name:1}/" setup.cfg
echo "[*] wiping old dist ..."
[[ -d dist ]] && rm -rf dist
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
if ! git add setup.cfg
then
echo "Error: git add failed"
exit 1
fi
if [ "$(git diff HEAD --name-only)" != "setup.cfg" ]
then
echo "Error: unexpected files would be included in the commit"
git diff HEAD --name-only | grep -v '^setup.cfg$' | awk '{ print " " $0 }'
exit 1
fi
if ! git commit -m "Release ${tag_name:1}"
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
python -m twine upload -u __token__ -p "$pypi_token" dist/*

8
scripts/run_tests.sh Executable file
View file

@ -0,0 +1,8 @@
#!/bin/bash
# TODO: use yq to parse .gitlab-ci.yaml and auto run whatever the CI does
pytest . || exit 1
pylint twnet_parser/ || exit 1
mypy twnet_parser/ || exit 1

View file

@ -16,11 +16,6 @@ classifiers =
License :: OSI Approved :: BSD License
Operating System :: OS Independent
[options]
package_dir =
= src
packages = find:
python_requires = >=3.6
[files]
packages = twnet_parser
[options.packages.find]
where = src

View file

@ -1,4 +1,4 @@
from src.packet import parse
from twnet_parser.packet import *
# TODO: uncomment and adjust ack/size when 0.6 is done

View file

@ -1,5 +1,4 @@
from src.packet import parse
from twnet_parser.packet import *
# # packet = parse(b'\x10\x10\x00\x04\x9a\xcb9\xc9') # 0.6 close
def test_parse_7_close():