Compare commits

..

1 Commits

Author SHA1 Message Date
Christian Heusel
f77b767971 feat: record against which repo a package was built
Currently releasing a package into a repository it was not built against
would just work, which happened a few times by accident so far:

  $ pkgctl build --staging cowfortune
  # this pushes to extra
  $ pkgctl release cowfortune

We therefore now record against which repo a package was built against
and error out accordingly if this mismatches the repo we want to release
into.

Fixes #179

Component: pkgctl build
Component: pkgctl release
Signed-off-by: Christian Heusel <christian@heusel.eu>
2024-06-10 01:20:23 +02:00
13 changed files with 61 additions and 94 deletions

View File

@@ -1,15 +0,0 @@
# EditorConfig configuration for devtools
# https://editorconfig.org
# Top-most EditorConfig file
root = true
# Unix-style newlines without trailing whitespaces, but with a newline
# ending every file, utf-8 charset, set indent to tabs
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
charset = utf-8
indent_style = tab
tab_width = 4

View File

@@ -1,6 +1,6 @@
SHELL=/bin/bash -o pipefail SHELL=/bin/bash -o pipefail
V=1.2.1 V=1.2.0
BUILDTOOLVER ?= $(V) BUILDTOOLVER ?= $(V)
PREFIX = /usr/local PREFIX = /usr/local

View File

@@ -15,8 +15,6 @@ Description
Build packages in clean chroot environment, offering various options Build packages in clean chroot environment, offering various options
and functionalities to customize the package building process. and functionalities to customize the package building process.
By default, chroot environments are located in '/var/lib/archbuild/'.
Build Options Build Options
------------- -------------

View File

@@ -140,7 +140,7 @@ for _pkgname in "${pkgname[@]}"; do
bsdtar tf "$TEMPDIR/$oldpkg" | sort > "$TEMPDIR/filelist-$_pkgname-old" bsdtar tf "$TEMPDIR/$oldpkg" | sort > "$TEMPDIR/filelist-$_pkgname-old"
bsdtar tf "$pkgfile" | sort > "$TEMPDIR/filelist-$_pkgname" bsdtar tf "$pkgfile" | sort > "$TEMPDIR/filelist-$_pkgname"
diff --side-by-side --suppress-common-lines --width="$COLUMNS" --color=auto "$TEMPDIR/filelist-$_pkgname-old" "$TEMPDIR/filelist-$_pkgname" sdiff -s "$TEMPDIR/filelist-$_pkgname-old" "$TEMPDIR/filelist-$_pkgname"
find-libprovides "$TEMPDIR/$oldpkg" 2>/dev/null | sort > "$TEMPDIR/libraries-$_pkgname-old" find-libprovides "$TEMPDIR/$oldpkg" 2>/dev/null | sort > "$TEMPDIR/libraries-$_pkgname-old"
find-libprovides "$pkgfile" 2>/dev/null | sort > "$TEMPDIR/libraries-$_pkgname" find-libprovides "$pkgfile" 2>/dev/null | sort > "$TEMPDIR/libraries-$_pkgname"

View File

@@ -7,6 +7,8 @@ _DEVTOOLS_LIBRARY_DIR=${_DEVTOOLS_LIBRARY_DIR:-@pkgdatadir@}
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
# shellcheck source=src/lib/util/srcinfo.sh # shellcheck source=src/lib/util/srcinfo.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/srcinfo.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/srcinfo.sh
# shellcheck source=src/lib/state.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/state.sh
source /usr/share/makepkg/util/util.sh source /usr/share/makepkg/util/util.sh
@@ -234,6 +236,9 @@ declare -a uploads
declare -a commit_arches declare -a commit_arches
declare -a skip_arches declare -a skip_arches
BUILD_STATE_DIR=$(get_state_folder "build-state")
state_file=
for _arch in "${arch[@]}"; do for _arch in "${arch[@]}"; do
if [[ -n $commit_arch && ${_arch} != "$commit_arch" ]]; then if [[ -n $commit_arch && ${_arch} != "$commit_arch" ]]; then
skip_arches+=("$_arch") skip_arches+=("$_arch")
@@ -247,6 +252,12 @@ for _arch in "${arch[@]}"; do
skip_arches+=("$_arch") skip_arches+=("$_arch")
continue 2 continue 2
fi fi
state_file="${BUILD_STATE_DIR}/$(basename "${pkgfile}").txt"
if [[ -f "${state_file}" ]] && [[ $(cat "${state_file}") != "${repo}" ]]; then
error "%s was not built against '%s', aborting" "${pkgfile}" "${repo}"
exit 1
fi
uploads+=("$pkgfile") uploads+=("$pkgfile")
done done

View File

@@ -165,7 +165,7 @@ pkgctl_aur_drop_from_repo() {
warning 'Did not find %s in any repository, please delete manually' "${pkgbase}" warning 'Did not find %s in any repository, please delete manually' "${pkgbase}"
else else
msg2 " repo: ${pkgrepo}" msg2 " repo: ${pkgrepo}"
pkgctl_db_remove --noconfirm "${pkgrepo}" "${pkgbase}" pkgctl_db_remove "${pkgrepo}" "${pkgbase}"
fi fi
popd >/dev/null popd >/dev/null

View File

@@ -63,7 +63,7 @@ pkgctl_auth_login() {
esac esac
done done
personal_access_token_url="https://${GITLAB_HOST}/-/user_settings/personal_access_tokens?name=pkgctl+token&scopes=api,write_repository" personal_access_token_url="https://${GITLAB_HOST}/-/profile/personal_access_tokens?name=pkgctl+token&scopes=api,write_repository"
cat <<- _EOF_ cat <<- _EOF_
Logging into ${BOLD}${GITLAB_HOST}${ALL_OFF} Logging into ${BOLD}${GITLAB_HOST}${ALL_OFF}

View File

@@ -12,6 +12,8 @@ source "${_DEVTOOLS_LIBRARY_DIR}"/lib/common.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/update.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/db/update.sh
# shellcheck source=src/lib/release.sh # shellcheck source=src/lib/release.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/release.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/release.sh
# shellcheck source=src/lib/state.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/state.sh
# shellcheck source=src/lib/util/git.sh # shellcheck source=src/lib/util/git.sh
source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh source "${_DEVTOOLS_LIBRARY_DIR}"/lib/util/git.sh
# shellcheck source=src/lib/util/srcinfo.sh # shellcheck source=src/lib/util/srcinfo.sh
@@ -55,7 +57,6 @@ pkgctl_build_usage() {
-o, --offload Build on a remote server and transfer artifacts afterwards -o, --offload Build on a remote server and transfer artifacts afterwards
-c, --clean Recreate the chroot before building -c, --clean Recreate the chroot before building
--inspect WHEN Spawn an interactive shell to inspect the chroot (never, always, failure) --inspect WHEN Spawn an interactive shell to inspect the chroot (never, always, failure)
--offline MODE Run a part of the build process offline (build, check)
-w, --worker SLOT Name of the worker slot, useful for concurrent builds (disables automatic names) -w, --worker SLOT Name of the worker slot, useful for concurrent builds (disables automatic names)
--nocheck Do not run the check() function in the PKGBUILD --nocheck Do not run the check() function in the PKGBUILD
@@ -80,8 +81,8 @@ pkgctl_build_usage() {
EXAMPLES EXAMPLES
$ ${COMMAND} $ ${COMMAND}
$ ${COMMAND} --rebuild --staging --release --message 'libyay 0.42 rebuild' libfoo libbar $ ${COMMAND} --rebuild --staging --message 'libyay 0.42 rebuild' libfoo libbar
$ ${COMMAND} --pkgver=1.42 --release --db-update $ ${COMMAND} --pkgver 1.42 --release --db-update
_EOF_ _EOF_
} }
@@ -130,6 +131,7 @@ pkgctl_build() {
local PKGVER= local PKGVER=
local PKGREL= local PKGREL=
local MESSAGE= local MESSAGE=
local BUILD_STATE_DIR=
local paths=() local paths=()
local BUILD_ARCH=() local BUILD_ARCH=()
@@ -199,10 +201,6 @@ pkgctl_build() {
EDIT=1 EDIT=1
shift shift
;; ;;
--offline)
MAKECHROOT_OPTIONS+=("-o" "$2")
shift 2
;;
-o|--offload) -o|--offload)
OFFLOAD=1 OFFLOAD=1
shift shift
@@ -309,6 +307,8 @@ pkgctl_build() {
fi fi
fi fi
BUILD_STATE_DIR=$(get_state_folder "build-state")
# assign default worker slot # assign default worker slot
if [[ -z ${WORKER_SLOT} ]] && ! WORKER_SLOT="$(tty | sed 's|/dev/pts/||')"; then if [[ -z ${WORKER_SLOT} ]] && ! WORKER_SLOT="$(tty | sed 's|/dev/pts/||')"; then
WORKER_SLOT=$(( RANDOM % $(nproc) + 1 )) WORKER_SLOT=$(( RANDOM % $(nproc) + 1 ))
@@ -486,25 +486,26 @@ pkgctl_build() {
# shellcheck disable=SC2119 # shellcheck disable=SC2119
write_srcinfo_file write_srcinfo_file
# test-install (some of) the produced packages # shellcheck disable=2119
if [[ ${INSTALL_TO_HOST} == auto ]] || [[ ${INSTALL_TO_HOST} == all ]]; then load_makepkg_config
# shellcheck disable=2119
load_makepkg_config
# this is inspired by print_all_package_names from libmakepkg # this is inspired by print_all_package_names from libmakepkg
local version pkg_architecture pkg pkgfile local version pkg_architecture pkg pkgfile
version=$(get_full_version) version=$(get_full_version)
for pkg in "${pkgname[@]}"; do for pkg in "${pkgname[@]}"; do
pkg_architecture=$(get_pkg_arch "$pkg") pkg_architecture=$(get_pkg_arch "$pkg")
pkgfile=$(realpath "$(printf "%s/%s-%s-%s%s\n" "${PKGDEST:-.}" "$pkg" "$version" "$pkg_architecture" "$PKGEXT")") pkgpath=$(realpath "$(printf "%s\n" "${PKGDEST:-.}")")
pkgfile=$(printf "%s-%s-%s%s\n" "$pkg" "$version" "$pkg_architecture" "$PKGEXT")
# check if we install all packages or if the (split-)package is already installed # check if we install all packages or if the (split-)package is already installed
if [[ ${INSTALL_TO_HOST} == all ]] || ( [[ ${INSTALL_TO_HOST} == auto ]] && pacman -Qq -- "$pkg" &>/dev/null ); then if [[ ${INSTALL_TO_HOST} == all ]] || ( [[ ${INSTALL_TO_HOST} == auto ]] && pacman -Qq -- "$pkg" &>/dev/null ); then
INSTALL_HOST_PACKAGES+=("$pkgfile") INSTALL_HOST_PACKAGES+=("${pkgpath}/${pkgfile}")
fi fi
done
fi # save against which repo we have built the package
printf "%s" "${pkgrepo}" > "${BUILD_STATE_DIR}/${pkgfile}.txt"
done
# release the build # release the build
if (( RELEASE )); then if (( RELEASE )); then

View File

@@ -120,8 +120,6 @@ print_workdir_error() {
} }
_setup_workdir=false _setup_workdir=false
# Ensure that there is no outside value for WORKDIR leaking in
unset WORKDIR
setup_workdir() { setup_workdir() {
[[ -z ${WORKDIR:-} ]] && WORKDIR=$(mktemp -d --tmpdir "${0##*/}.XXXXXXXXXX") [[ -z ${WORKDIR:-} ]] && WORKDIR=$(mktemp -d --tmpdir "${0##*/}.XXXXXXXXXX")
_setup_workdir=true _setup_workdir=true

View File

@@ -271,7 +271,6 @@ pkgctl_repo_configure() {
if [[ -n $GPGKEY ]]; then if [[ -n $GPGKEY ]]; then
git config commit.gpgsign true git config commit.gpgsign true
git config user.signingKey "${GPGKEY}" git config user.signingKey "${GPGKEY}"
git config gpg.format openpgp
fi fi
# set default git exclude # set default git exclude

18
src/lib/state.sh Normal file
View File

@@ -0,0 +1,18 @@
#!/hint/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
[[ -z ${DEVTOOLS_INCLUDE_STATE_SH:-} ]] || return 0
DEVTOOLS_INCLUDE_STATE_SH=1
set -e
readonly XDG_DEVTOOLS_STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/devtools"
get_state_folder() {
local foldername=$1
local path="${XDG_DEVTOOLS_STATE_DIR}/${foldername}"
mkdir --parents -- "$path"
printf '%s' "${path}"
}

View File

@@ -284,7 +284,7 @@ nvchecker_check_error() {
local errors local errors
if ! errors=$(jq --raw-output --exit-status \ if ! errors=$(jq --raw-output --exit-status \
'select((.level == "error") and (.error != null)) | "\(.event)" + if .error then ": \(.error)" else "" end' \ 'select(.level == "error") | "\(.event)" + if .error then ": \(.error)" else "" end' \
<<< "${result}"); then <<< "${result}"); then
return 0 return 0
fi fi

View File

@@ -40,8 +40,6 @@ bindmounts_ro=()
bindmounts_rw=() bindmounts_rw=()
bindmounts_tmpfs=() bindmounts_tmpfs=()
offline_options=()
copy=$USER copy=$USER
[[ -n ${SUDO_USER:-} ]] && copy=$SUDO_USER [[ -n ${SUDO_USER:-} ]] && copy=$SUDO_USER
[[ -z "$copy" || $copy = root ]] && copy=copy [[ -z "$copy" || $copy = root ]] && copy=copy
@@ -82,7 +80,6 @@ usage() {
echo ' Useful for maintaining multiple copies' echo ' Useful for maintaining multiple copies'
echo " Default: $copy" echo " Default: $copy"
echo '-n Run namcap on the package' echo '-n Run namcap on the package'
echo '-o Run given step offline'
echo '-C Run checkpkg on the package' echo '-C Run checkpkg on the package'
echo '-T Build in a temporary directory' echo '-T Build in a temporary directory'
echo '-U Run makepkg as a specified user' echo '-U Run makepkg as a specified user'
@@ -108,7 +105,7 @@ sync_chroot() {
"Locking clean chroot [%s]" "$chrootdir/root" "Locking clean chroot [%s]" "$chrootdir/root"
stat_busy "Synchronizing chroot copy [%s] -> [%s]" "$chrootdir/root" "$copy" stat_busy "Synchronizing chroot copy [%s] -> [%s]" "$chrootdir/root" "$copy"
if is_btrfs "$chrootdir" && is_subvolume "$chrootdir/root" && ! mountpoint -q "$copydir"; then if is_btrfs "$chrootdir" && ! mountpoint -q "$copydir"; then
subvolume_delete_recursive "$copydir" || subvolume_delete_recursive "$copydir" ||
die "Unable to delete subvolume %s" "$copydir" die "Unable to delete subvolume %s" "$copydir"
btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null || btrfs subvolume snapshot "$chrootdir/root" "$copydir" >/dev/null ||
@@ -206,7 +203,6 @@ EOF
declare -p SOURCE_DATE_EPOCH 2>/dev/null || true declare -p SOURCE_DATE_EPOCH 2>/dev/null || true
declare -p BUILDTOOL 2>/dev/null declare -p BUILDTOOL 2>/dev/null
declare -p BUILDTOOLVER 2>/dev/null declare -p BUILDTOOLVER 2>/dev/null
declare -p offline_options
printf '_chrootbuild "$@" || exit\n' printf '_chrootbuild "$@" || exit\n'
if (( run_namcap )); then if (( run_namcap )); then
@@ -226,52 +222,14 @@ _chrootbuild() {
# shellcheck source=/dev/null # shellcheck source=/dev/null
. /etc/profile . /etc/profile
# for in_array
. /usr/share/makepkg/util.sh
# Beware, there are some stupid arbitrary rules on how you can # Beware, there are some stupid arbitrary rules on how you can
# use "$" in arguments to commands with "sudo -i". ${foo} or # use "$" in arguments to commands with "sudo -i". ${foo} or
# ${1} is OK, but $foo or $1 isn't. # ${1} is OK, but $foo or $1 isn't.
# https://bugzilla.sudo.ws/show_bug.cgi?id=765 # https://bugzilla.sudo.ws/show_bug.cgi?id=765
# Run prepare
sudo --preserve-env=SOURCE_DATE_EPOCH \ sudo --preserve-env=SOURCE_DATE_EPOCH \
--preserve-env=BUILDTOOL \ --preserve-env=BUILDTOOL \
--preserve-env=BUILDTOOLVER \ --preserve-env=BUILDTOOLVER \
-iu builduser bash -c 'cd /startdir; makepkg --nobuild "$@"' -bash "$@" -iu builduser bash -c 'cd /startdir; makepkg "$@"' -bash "$@"
if in_array "build" "${offline_options[@]}"; then
msg "building offline"
# Build offline
unshare -n -- sudo --preserve-env=SOURCE_DATE_EPOCH \
--preserve-env=BUILDTOOL \
--preserve-env=BUILDTOOLVER \
-iu builduser \
bash -c 'cd /startdir; makepkg --noprepare --noextract --nocheck "$@"' -bash "$@"
else
sudo --preserve-env=SOURCE_DATE_EPOCH \
--preserve-env=BUILDTOOL \
--preserve-env=BUILDTOOLVER \
-iu builduser \
bash -c 'cd /startdir; makepkg --noprepare --noextract --nocheck "$@"' -bash "$@"
fi
if in_array "check" "${offline_options[@]}"; then
msg "check offline"
# Run tests online
unshare -n -- sudo --preserve-env=SOURCE_DATE_EPOCH \
--preserve-env=BUILDTOOL \
--preserve-env=BUILDTOOLVER \
-iu builduser \
bash -c 'cd /startdir; makepkg --noprepare --noextract --nobuild "$@"' -bash "$@"
else
sudo --preserve-env=SOURCE_DATE_EPOCH \
--preserve-env=BUILDTOOL \
--preserve-env=BUILDTOOLVER \
-iu builduser \
bash -c 'cd /startdir; makepkg --noprepare --noextract --nobuild "$@"' -bash "$@"
fi
ret=$? ret=$?
case $ret in case $ret in
0|14) 0|14)
@@ -335,7 +293,7 @@ move_products() {
} }
# }}} # }}}
while getopts 'hcur:I:l:nCTD:o:d:U:x:t:' arg; do while getopts 'hcur:I:l:nCTD:d:U:x:t:' arg; do
case "$arg" in case "$arg" in
c) clean_first=1 ;; c) clean_first=1 ;;
D) bindmounts_ro+=("--bind-ro=$OPTARG") ;; D) bindmounts_ro+=("--bind-ro=$OPTARG") ;;
@@ -346,7 +304,6 @@ while getopts 'hcur:I:l:nCTD:o:d:U:x:t:' arg; do
I) install_pkgs+=("$OPTARG") ;; I) install_pkgs+=("$OPTARG") ;;
l) copy="$OPTARG" ;; l) copy="$OPTARG" ;;
n) run_namcap=1; makepkg_args+=(--install) ;; n) run_namcap=1; makepkg_args+=(--install) ;;
o) offline_options+=("$OPTARG") ;;
C) run_checkpkg=1 ;; C) run_checkpkg=1 ;;
T) temp_chroot=1; copy+="-$$" ;; T) temp_chroot=1; copy+="-$$" ;;
U) makepkg_user="$OPTARG" ;; U) makepkg_user="$OPTARG" ;;