Workflow#
Rules#
Assume that the root of the repository is
./
.3.5 <= Python version < 4
Variable reference#
Variable name |
Description |
---|---|
|
the name of the project as a Python module |
|
a relative path that corresponds project name |
|
the directory of the corresponding AUR package |
|
a valid PGP key used to sign commits |
|
development git branch |
|
the version identifier used in the git tag |
|
a variable of the Semantic Versioning document |
|
a variable of the Semantic Versioning document |
|
a variable of the Semantic Versioning document |
Sequence#
enable git signing
git config commit.gpgsign true git config user.signingkey ${gpg_signing_key}
setup a bare git repository serving static pages. Follow this blog post
if you need to publish a package on AUR follow the instructions
finish working on the development branch
cd ${project_directory}
check that the current branch is not
master
git branch --no-color --show-current # dev
if you need to publish a new asciinema video follow the instructions
commit
git add -A git commit git push
update version numbers
./setup.cfg
./docs/conf.py
./packages/*
if necessary update dependencies in
./requirements.txt
./requirements-dev.txt
./setup.cfg
and regenerate the pinned dependencies
make regenerate-freeze
Read the changelogs of the dependencies and decide what packages to update
run a final test
make uninstall-dev; make install-dev make doc make test make install cd ~ && python3 -c "import ${package_name}" && cd ${OLDPWD} make uninstall make clean
For each of these files update copyright years, emails and contributors
./README.md
./docs/conf.py
./docs/misc.rst
all changed Python source files
./packages/*
commit
git add -A make pre-commit git commit git push
update the documentation
make clean && make doc rm -rf ~/html && cp -aR docs/_build/html ~ git branch --delete --force docs git checkout --orphan docs rm -rf .mypy_cache .venv git rm --cached -r . git clean -f && git clean -f -d mv ~/html/{*,.buildinfo} . git add -A git commit --no-verify -m "New release" git push --force deploy-docs docs
merge the branches and tag the release
git checkout master git merge ${dev_branch}
tag the release.
git tag -s -a ${version_id}
Write a message like this. Use the infinitive tense
Release ${MAJOR}.${MINOR}.${PATCH} - Item 1 - Item 2 - [ ... ] - Item n
push the changes
git push git push --tags
upload the package to PyPI if applicable
make install-dev make clean make dist make upload
upload the package on the software page. Follow the instructions reported here
update downstream distribution packages. See the updating packages section
update other resources if applicable
Other steps#
Upstream packages#
AUR#
See also
An alternative to GitHub Pages [3]
create an Arch Linux virtual machine
create a bare repository
git init --bare ${project_directory} cd ${project_directory}
use this
post-receive
git hook#!/usr/bin/bash -l # # The MIT License (MIT) # # Copyright (c) 2008-present Tom Preston-Werner and Jekyll contributors # 2021 Franco Masotti # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. cleanup() { local ok='${1}' rm --recursive --force "${tmp_git_clone}" /dev/shm/"${PROJECT}" if [ "${ok}" != 'true' ]; then printf '\n%s\n%s\n%s %s\n\n' 'remember to run' '"git tag | xargs git tag -d; git update-ref HEAD -d"' 'before a new attempt with the same tag' "(${tag})" fi } set -euo pipefail . 'hooks/post-receive.conf' # Run cleanup on signal. trap cleanup EXIT # Check if last commit has a tag pointing to it. tag="$(git describe --exact-match)" || { printf '%s\n' 'error: tag not present'; exit 1; } # Check AUR dependencies. pacman -Qi ${AUR_DEPENDENCIES} 1>/dev/null 2>/dev/null || { printf '%s\n' 'error: AUR dependencies not met'; exit 1; } sha512_checksum="$(/usr/bin/curl ${BASE_URL}/${PROJECT}-${tag}/${PROJECT}-${tag}.tar.gz.SHA512SUM.txt | awk '{ print $1 }')" tmp_git_clone=""${HOME}"/tmp/${PROJECT}" ########### # Cleanup # ########### cleanup 'true' ######### # Clone # ######### git clone "${GIT_DIR}" "${tmp_git_clone}" unset GIT_DIR ######### # Build # ######### # Create a disposable directory because we need to clean the temporary repository later. mkdir /dev/shm/"${PROJECT}" pushd "${tmp_git_clone}"/packages/aur cp -aR PKGBUILD /dev/shm/"${PROJECT}" pushd /dev/shm/"${PROJECT}" # Replace SKIP with SHA512SUM. sed -i "s/sha512sums=('SKIP' 'SKIP'/sha512sums=('SKIP' '${sha512_checksum}'/" PKGBUILD # Build the package. makepkg -rsi --noconfirm makepkg --printsrcinfo > .SRCINFO ######## # Test # ######## # Run a command to test the package. pushd ~ eval ${TEST_COMMAND} popd ########### # Cleanup # ########### sudo pacman -Rnus --noconfirm "${ARCHLINUX_PACKAGE}" rm -rf pkg src *.tar.* popd popd ########## # Commit # ########## pushd "${tmp_git_clone}" # Push updated pkgbuild to an empty disposable git branch. # Put PKGBUILD and .SRCINFO git checkout --orphan packages-aur git rm -rf . mv /dev/shm/"${PROJECT}"/{PKGBUILD,.SRCINFO} . git add PKGBUILD .SRCINFO git commit -m "Updated PKGBUILD and .SRCINFO." # Update remotes. git remote add repo "${ORIGIN}" # Remove remote branch. git push repo --delete packages-aur || echo OK # Push the files. git push --set-upstream repo packages-aur popd
use this
configuration
# The MIT License (MIT) # # Copyright (c) 2008-present Tom Preston-Werner and Jekyll contributors # 2021 Franco Masotti # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # Example for fpyutils. TEST_COMMAND="python3 -c 'import fpyutils'" BASE_URL='https://blog.franco.net.eu.org/software' PROJECT='fpyutils' ARCHLINUX_PACKAGE='python-fpyutils' ORIGIN="gitea@franco.net.eu.org:frnmst/fpyutils.git" AUR_DEPENDENCIES=''
mark the hook as executable
chmod 700 .git/hooks/post-receive
add the
pacman
command to the ones not requiring password in the sudoers filevisudo build-user ALL=NOPASSWD: /bin/pacman
on the local repository (development machine) create a new remote called
packages-aur
which points to the Arch Linux virtual machinecreate a repository containing the AUR source. Add a normal
origin
remote and a gitaur
remote that to points tohttps://aur.archlinux.org/"$(basedir "${projects_aur_git_directory}")".git
Updating packages#
AUR#
git push --atomic packages-aur master ${MAJOR}.${MINOR}.${PATCH}
make clean
git branch -D packages-aur && git fetch --all && git checkout packages-aur
cp PKGBUILD .SRCINFO ${projects_aur_git_directory}
git checkout ${dev_branch}
cd ${projects_aur_git_directory}
git add PKGBUILD .SRCINFO
git commit -m "New release."
git push
git push aur
Asciinema#
create a new asciinema demo file
cd ./asciinema touch ${project_directory}_asciinema_${MAJOR}_${MINOR}_${PATCH}_demo.sh
edit the demo file
record and check the demo file
. .venv/bin/activate asciinema rec --command=./${project_directory}_asciinema_${MAJOR}_${MINOR}_${PATCH}_demo.sh ${project_directory}_asciinema_${MAJOR}_${MINOR}_${PATCH}.json asciinema play ${project_directory}_asciinema_${MAJOR}_${MINOR}_${PATCH}.json deactivate
upload
. .venv/bin/activate asciinema upload ${project_directory}_asciinema_${MAJOR}_${MINOR}_${PATCH}.json deactivate
edit the
./README.md
file with the new asciinema linkcommit
git add -A git commit git push
symlink to the previous relevant release
cd ./asciinema ln -s ${project_directory}_asciinema_${MAJOR}_${OLD_MINOR}_${OLD_PATCH}_demo.sh ${project_directory}_asciinema_${MAJOR}_${MINOR}_${PATCH}_demo.sh ln -s ${project_directory}_asciinema_${MAJOR}_${OLD_MINOR}_${OLD_PATCH}.json ${project_directory}_asciinema_${MAJOR}_${MINOR}_${PATCH}.json
commit
git add -A git commit git push
Files#
Makefile#
#
# Makefile
#
export PACKAGE_NAME=${project_python_module_name}
# See
# https://docs.python.org/3/library/venv.html#how-venvs-work
export VENV_CMD=. .venv/bin/activate
default: install-dev
doc:
$(VENV_CMD) \
&& $(MAKE) -C docs html \
&& deactivate
install:
pip3 install . --user
uninstall:
pip3 uninstall --verbose --yes $(PACKAGE_NAME)
install-dev:
python3 -m venv .venv
$(VENV_CMD) \
&& pip install --requirement requirements-freeze.txt \
&& deactivate
$(VENV_CMD) \
&& pre-commit install \
&& deactivate
$(VENV_CMD) \
&& pre-commit install --hook-type commit-msg \
&& deactivate
regenerate-freeze: uninstall-dev
python3 -m venv .venv
$(VENV_CMD) \
&& pip install --requirement requirements.txt --requirement requirements-dev.txt \
&& pip freeze --local > requirements-freeze.txt \
&& deactivate
uninstall-dev:
rm -rf .venv
update: install-dev
$(VENV_CMD) \
&& pre-commit autoupdate \
--repo https://github.com/pre-commit/pre-commit-hooks \
--repo https://github.com/PyCQA/bandit \
--repo https://github.com/pycqa/isort \
--repo https://codeberg.org/frnmst/licheck \
--repo https://codeberg.org/frnmst/md-toc \
--repo https://github.com/mgedmin/check-manifest \
--repo https://github.com/jorisroovers/gitlint \
&& deactivate
# --repo https://github.com/pre-commit/mirrors-mypy \
test:
$(VENV_CMD) \
&& python -m unittest $(PACKAGE_NAME).tests.tests --failfast --locals --verbose \
&& deactivate
pre-commit:
$(VENV_CMD) \
&& pre-commit run --all \
&& deactivate
dist:
# Create a reproducible archive at least on the wheel.
# See
# https://bugs.python.org/issue31526
# https://bugs.python.org/issue38727
# https://github.com/pypa/setuptools/issues/1468
# https://github.com/pypa/setuptools/issues/2133
# https://reproducible-builds.org/docs/source-date-epoch/
$(VENV_CMD) \
&& SOURCE_DATE_EPOCH=$$(git -c log.showSignature='false' log -1 --pretty=%ct) \
python -m build \
&& deactivate
$(VENV_CMD) \
&& twine check --strict dist/* \
&& deactivate
upload:
$(VENV_CMD) \
&& twine upload dist/* \
&& deactivate
clean:
rm -rf build dist *.egg-info tests/benchmark-results
# Remove all markdown files except the readmes.
find -regex ".*\.[mM][dD]" ! -name 'README.md' ! -name 'CONTRIBUTING.md' -type f -exec rm -f {} +
$(VENV_CMD) \
&& $(MAKE) -C docs clean \
&& deactivate
.PHONY: default doc install uninstall install-dev uninstall-dev update test pre-commit
Footnotes