Blueprints

post-receive git hook for AUR packages

  1. generate a bare repository on an Arch Linux instance

  2. add this file as hooks/post-receive

    Example for fpyutils

    #!/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
    
  3. add this file as hooks/post-receive.conf for the configuration

    Example for fpyutils

    # 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.
    
    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=''
    

Makefile

Example for fpyutils

#!/usr/bin/env make
#
# Makefile
#
# Copyright (C) 2017-2020 Franco Masotti (franco \D\o\T masotti {-A-T-} tutanota \D\o\T com)
#
# This file is part of fpyutils.
#
# fpyutils is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# fpyutils is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with fpyutils.  If not, see <http://www.gnu.org/licenses/>.
#

export PACKAGE_NAME=fpyutils

default: doc

doc: clean
        mkdir -p docs/_static && pipenv run $(MAKE) -C docs html

install:
        pip3 install . --user

uninstall:
        pip3 uninstall --verbose --yes $(PACKAGE_NAME)

install-dev:
        pipenv install --dev
        pipenv run pre-commit install
        pipenv graph
        pipenv check

uninstall-dev:
        rm -f Pipfile.lock
        pipenv --rm

update: install-dev
        pipenv run pre-commit autoupdate

test:
        pipenv run python -m unittest $(PACKAGE_NAME).tests.tests --failfast --locals --verbose

dist:
        pipenv run python setup.py sdist
        # Create a reproducible archve 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/
        SOURCE_DATE_EPOCH=$$(git -c log.showSignature='false' log -1 --pretty=%ct) pipenv run python setup.py bdist_wheel
        pipenv run twine check dist/*

upload:
        pipenv run twine upload dist/*

clean:
        rm -rf build dist *.egg-info
        pipenv run $(MAKE) -C docs clean

.PHONY: default doc install uninstall install-dev uninstall-dev update test clean