Compare commits

...

19 Commits

Author SHA1 Message Date
Levente Polyak
aff81d34fd Version 20200407 2020-04-07 19:46:10 +02:00
Levente Polyak
5b1123e11f offload-build: retrieve the PKGBUILD in case makepkg changes it via pkgver
Building a package may change the PKGBUILD during update_pkgver. Let's
retrieve the PKGBUILD after building to ensure we have the very same
file as the one we used to build the package. Otherwise this may lead to
the inability to distribute the package during commitpkg in case the
expected and the actual hashsum mismatch.
2020-03-09 23:27:03 +01:00
Levente Polyak
a0f79fcce0 makerepropkg: prioritize downloading .zst packages over legacy format
First try a .zst location before falling back to legacy variants. This
should slightly speed up downloading of dependencies, especially over
time as .zst packages are or will be the dominant format.

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2020-03-09 23:27:03 +01:00
Eli Schwartz
94b0413e13 arch-nspawn: fix up host_mirrors cachedir handling
This was incorrectly implemented in commit
0067176529, which added the host_mirrors
root directory as a cachedir, when we actually want to use the pool/*
subdirectories (the same ones installed on the build server's
/etc/pacman.conf).

Signed-off-by: Eli Schwartz <eschwartz@archlinux.org>
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2020-02-27 14:50:27 +01:00
Eli Schwartz
e963b6da9e makechrootpkg: use the chroot database to find checkpkg packages
We don't want to check against the current version known to the host
system, because that will be incorrect in a wide variety of situations,
including:
- the build host hasn't done a full system upgrade yet
- we're building against staging, and want to see the delta between
  different staging versions
- we're building against extra, but the host runs testing which carries
  changes we don't want to visualize right now
- the chroot has a configured database not available to the host, and
  the package is only available there

Essentially, it's rarely 100% correct to run checkpkg on the host, but
we already have a database we *know* is correct, and that is the one we
just built the package against. So let's use that.

This also fixes a bug in the current logic, where in order to try
downloading fresh databases, we work in a non-cached temporary working
database to download the package files, but then let checkpkg default to
comparing packages in the system database. Since we are explicitly
trying to compare against packages that differ from the host's pacman
database, we need to pass the package files as options to checkpkg,
using the additional modes added in commit c14338c0fe

Signed-off-by: Eli Schwartz <eschwartz@archlinux.org>
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2020-02-27 14:50:19 +01:00
Eli Schwartz
b2cbb8628e checkpkg: fix support for http:// url comparisons
Broken in commit c14338c0fe.

Signed-off-by: Eli Schwartz <eschwartz@archlinux.org>
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2020-02-27 14:50:14 +01:00
Eli Schwartz
6d273f79c3 zsh-completion: update for new makerepropkg options
Thanks to anthraxx for the guidance.

Original-patch-by: Levente Polyak <anthraxx@archlinux.org>
Signed-off-by: Eli Schwartz <eschwartz@archlinux.org>
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2020-02-27 14:50:05 +01:00
Eli Schwartz
51842a1676 makerepropkg: support checking multiple split packages
By specifying multiple package files, we assume they are all from the
same PKGBUILD, and try to check them all against the produced artifacts.
Since the buildinfo should be comparable for all of them, we simply use
the first one passed on the command line.

Signed-off-by: Eli Schwartz <eschwartz@archlinux.org>
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2020-02-27 14:49:54 +01:00
Eli Schwartz
53fe5c67a1 makerepropkg: add support to check unreproducible packages using diffoscope
Signed-off-by: Eli Schwartz <eschwartz@archlinux.org>
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2020-02-27 14:49:48 +01:00
Eli Schwartz
21d9984acc makerepropkg: fix wonky indent
Signed-off-by: Eli Schwartz <eschwartz@archlinux.org>
Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2020-02-27 14:49:33 +01:00
Levente Polyak
cb6484fe45 Version 20200213 2020-02-13 01:53:45 +01:00
Levente Polyak
bcb1b4a163 offload-build: handle user specific makepkg.conf on the remote host
This ensures we take user specific config values for PKGDEST into
account when printing the package list. This is required as devtools
archbuild_cmd puts packages potentially into the user defined PKGDEST
which the package list would otherwise miss.
2020-02-12 00:05:00 +01:00
Levente Polyak
57fb44b976 offload-build: take makepkg.conf from devtools for appropriate packagelist
This fixes an issue with the usage of makepkg --packagelist to get the
produced artifacts filenames according to the PKGEXT used in devtools'
makepkg.conf instead of the one defined in pacman.

One goal we want to preserve is that devtools configuration should be
self contained and not require any editing of non owned files like
the host /etc/makepkg.conf to produce expected results.

Additionally modify the archbuild_cmd override for multilib builds to
use an independent variable and not fiddle with the actual arch
variable to select the appropriate cmd.
2020-02-11 01:42:17 +01:00
Levente Polyak
9b4d8ae930 offload-build: convert to in-prog so we can perform pre-processing 2020-02-10 23:02:41 +01:00
Levente Polyak
4c206ab549 makerepropkg: take makepkg.conf from devtools pkgdatadir location
This ensures we use the same configuration for reproducing packages as
we use for building them via devtools.
One example of why we care about this are the COMPRESS* settings that
may differ from the guest's pacman shipped makepkg.conf that affect the
reproducibility of packages.
2020-02-10 23:02:16 +01:00
Eli Schwartz
4c08847bfa makerepropkg: correctly reproduce a pkgfile with any compression type
We don't want the default PKGEXT in the current version of devtools, we
want the PKGEXT we *know* the input file used.

Signed-off-by: Levente Polyak <anthraxx@archlinux.org>
2019-12-27 18:54:26 +01:00
Levente Polyak
74d7a70915 Version 20191227 2019-12-27 16:06:30 +01:00
Robin Broda
5eacb475cd makerepopkg: fix zstd extension (.zstd -> .zst) 2019-12-27 16:05:14 +01:00
Robin Broda
bcda211dd8 makepkg.conf: change default compression method to zstd 2019-12-27 16:04:56 +01:00
10 changed files with 92 additions and 59 deletions

1
.gitignore vendored
View File

@@ -11,6 +11,7 @@ lddd
makechrootpkg makechrootpkg
makerepropkg makerepropkg
mkarchroot mkarchroot
offload-build
rebuildpkgs rebuildpkgs
zsh_completion zsh_completion
find-libdeps find-libdeps

View File

@@ -1,4 +1,4 @@
V=20191212 V=20200407
PREFIX = /usr/local PREFIX = /usr/local
MANDIR = $(PREFIX)/share/man MANDIR = $(PREFIX)/share/man
@@ -17,12 +17,12 @@ IN_PROGS = \
makerepropkg \ makerepropkg \
mkarchroot \ mkarchroot \
makechrootpkg \ makechrootpkg \
offload-build \
rebuildpkgs \ rebuildpkgs \
sogrep sogrep
BINPROGS = \ BINPROGS = \
$(IN_PROGS) \ $(IN_PROGS)
offload-build \
CONFIGFILES = \ CONFIGFILES = \
makepkg-x86_64.conf \ makepkg-x86_64.conf \

View File

@@ -69,7 +69,9 @@ host_mirrors=($($pacconf_cmd --repo extra Server 2> /dev/null | sed -r 's#(.*/)e
for host_mirror in "${host_mirrors[@]}"; do for host_mirror in "${host_mirrors[@]}"; do
if [[ $host_mirror == *file://* ]]; then if [[ $host_mirror == *file://* ]]; then
host_mirror=$(echo "$host_mirror" | sed -r 's#file://(/.*)/\$repo/os/\$arch#\1#g') host_mirror=$(echo "$host_mirror" | sed -r 's#file://(/.*)/\$repo/os/\$arch#\1#g')
in_array "$host_mirror" "${cache_dirs[@]}" || cache_dirs+=("$host_mirror") for m in "$host_mirror"/pool/*/; do
in_array "$m" "${cache_dirs[@]}" || cache_dirs+=("$m")
done
fi fi
done done

View File

@@ -95,8 +95,10 @@ for _pkgname in "${pkgname[@]}"; do
if (( $# )); then if (( $# )); then
case $1 in case $1 in
*://*)
pkgurl=$1 ;;
/*|*/*) /*|*/*)
pkgurl=file://$(readlink -m "$1") ;; pkgurl=$(readlink -m "$1") ;;
*.pkg.tar*) *.pkg.tar*)
pkgurl=$1 ;; pkgurl=$1 ;;
'') '')

View File

@@ -7,12 +7,12 @@ makerepropkg - Rebuild a package to see if it is reproducible
Synopsis Synopsis
-------- --------
makerepropkg [OPTIONS] <package_file> makerepropkg [OPTIONS] <package_file>...
Description Description
----------- -----------
Given the path to a built pacman package, attempt to rebuild it using the Given the path to a built pacman package(s), attempt to rebuild it using the
PKGBUILD in the current directory. The package will be built in an environment PKGBUILD in the current directory. The package will be built in an environment
as closely matching the environment of the initial package as possible, by as closely matching the environment of the initial package as possible, by
building up a chroot to match the information exposed in the package's building up a chroot to match the information exposed in the package's
@@ -20,12 +20,19 @@ linkman:BUILDINFO[5] manifest. On success, the resulting package will be
compared to the input package, and makerepropkg will report whether the compared to the input package, and makerepropkg will report whether the
artifacts are identical. artifacts are identical.
When given multiple packages, additional package files are assumed to be split
packages and will be treated as additional artifacts to compare during the
verification step.
This implements a verifier for pacman/libalpm packages in accordance with the This implements a verifier for pacman/libalpm packages in accordance with the
link:https://reproducible-builds.org/[Reproducible Builds] project. link:https://reproducible-builds.org/[Reproducible Builds] project.
Options Options
------- -------
*-d*::
If packages are not reproducible, compare them using diffoscope.
*-c*:: *-c*::
Set the pacman cache directory. Set the pacman cache directory.

View File

@@ -366,11 +366,7 @@ if arch-nspawn "$copydir" \
"${bindmounts_ro[@]}" "${bindmounts_rw[@]}" \ "${bindmounts_ro[@]}" "${bindmounts_rw[@]}" \
/chrootbuild "${makepkg_args[@]}" /chrootbuild "${makepkg_args[@]}"
then then
pkgnames=() mapfile -t pkgnames < <(sudo -u "$makepkg_user" bash -c 'source PKGBUILD; printf "%s\n" "${pkgname[@]}"')
for pkgfile in "$copydir"/pkgdest/*; do
pkgfile=${pkgfile##*/};
pkgnames+=("${pkgfile%-*-*-*}");
done
move_products move_products
else else
(( ret += 1 )) (( ret += 1 ))
@@ -388,29 +384,29 @@ else
if (( run_checkpkg )); then if (( run_checkpkg )); then
msg "Running checkpkg" msg "Running checkpkg"
# sync off-site databases for up-to-date queries mapfile -t remotepkgs < <(pacman --config "$copydir"/etc/pacman.conf \
trap 'rm -rf $dbpath; cleanup' EXIT INT TERM QUIT --dbpath "$copydir"/var/lib/pacman \
dbpath=$(mktemp -d --tmpdir makechrootpkg-database.XXXXXXXXXX) -Sddp "${pkgnames[@]}")
mkdir -p "$dbpath"
pacman -Sy --dbpath "$dbpath" --logfile /dev/null
# query current package locations if ! wait $!; then
remotepkgs=($(pacman -Sddp --dbpath "$dbpath" --logfile /dev/null "${pkgnames[@]}"))
if (( $? )); then
warning "Skipped checkpkg due to missing repo packages" warning "Skipped checkpkg due to missing repo packages"
exit 0 exit 0
fi fi
# download package files if any non-local location exists # download package files if any non-local location exists
for remotepkg in "${remotepkgs[@]}"; do for remotepkg in "${remotepkgs[@]}"; do
[[ $remotepkg == file://* ]] && continue if [[ $remotepkg != file://* ]]; then
msg2 "Downloading current versions" msg2 "Downloading current versions"
pacman --noconfirm -Swdd --dbpath "$dbpath" --logfile /dev/null "${pkgnames[@]}" arch-nspawn "$copydir" pacman --noconfirm -Swdd "${pkgnames[@]}"
break mapfile -t remotepkgs < <(pacman --config "$copydir"/etc/pacman.conf \
--dbpath "$copydir"/var/lib/pacman \
-Sddp "${pkgnames[@]}")
break
fi
done done
msg2 "Checking packages" msg2 "Checking packages"
sudo -u "$makepkg_user" checkpkg --rmdir --warn sudo -u "$makepkg_user" checkpkg --rmdir --warn "${remotepkgs[@]/#file:\/\//}"
fi fi
true true
fi fi

View File

@@ -132,7 +132,7 @@ DBGSRCDIR="/usr/src/debug"
COMPRESSGZ=(gzip -c -f -n) COMPRESSGZ=(gzip -c -f -n)
COMPRESSBZ2=(bzip2 -c -f) COMPRESSBZ2=(bzip2 -c -f)
COMPRESSXZ=(xz -c -z -) COMPRESSXZ=(xz -c -z -)
COMPRESSZST=(zstd -c -z -q -) COMPRESSZST=(zstd -c -T0 --ultra -20 -)
COMPRESSLRZ=(lrzip -q) COMPRESSLRZ=(lrzip -q)
COMPRESSLZO=(lzop -q) COMPRESSLZO=(lzop -q)
COMPRESSZ=(compress -c -f) COMPRESSZ=(compress -c -f)
@@ -143,7 +143,7 @@ COMPRESSLZ=(lzip -c -f)
# EXTENSION DEFAULTS # EXTENSION DEFAULTS
######################################################################### #########################################################################
# #
PKGEXT='.pkg.tar.xz' PKGEXT='.pkg.tar.zst'
SRCEXT='.src.tar.gz' SRCEXT='.src.tar.gz'
# vim: set ft=sh ts=2 sw=2 et: # vim: set ft=sh ts=2 sw=2 et:

View File

@@ -29,6 +29,7 @@ declare -a buildenv buildopts installed installpkgs
archiveurl='https://archive.archlinux.org/packages' archiveurl='https://archive.archlinux.org/packages'
buildroot=/var/lib/archbuild/reproducible buildroot=/var/lib/archbuild/reproducible
chroot=testenv chroot=testenv
diffoscope=0
parse_buildinfo() { parse_buildinfo() {
local line var val local line var val
@@ -59,7 +60,7 @@ get_pkgfile() {
local pkgname=${pkgfilebase%-*-*-*} local pkgname=${pkgfilebase%-*-*-*}
local pkgfile ext local pkgfile ext
for ext in .xz .zstd ''; do for ext in .zst .xz ''; do
pkgfile=${pkgfilebase}.pkg.tar${ext} pkgfile=${pkgfilebase}.pkg.tar${ext}
for c in "${cache_dirs[@]}"; do for c in "${cache_dirs[@]}"; do
@@ -94,19 +95,21 @@ package, including the .PKGINFO as well as the buildinfo.
For more details see https://reproducible-builds.org/ For more details see https://reproducible-builds.org/
OPTIONS OPTIONS
-d Run diffoscope if the package is unreproducible
-c <dir> Set pacman cache -c <dir> Set pacman cache
-M <file> Location of a makepkg config file -M <file> Location of a makepkg config file
-h Show this usage message -h Show this usage message
__EOF__ __EOF__
} }
while getopts 'M:c:h' arg; do while getopts 'dM:c:h' arg; do
case "$arg" in case "$arg" in
M) archroot_args+=(-M "$OPTARG") ;; d) diffoscope=1 ;;
c) cache_dirs+=("$OPTARG") ;; M) archroot_args+=(-M "$OPTARG") ;;
h) usage; exit 0 ;; c) cache_dirs+=("$OPTARG") ;;
*|?) usage; exit 1 ;; h) usage; exit 0 ;;
esac *|?) usage; exit 1 ;;
esac
done done
shift $((OPTIND - 1)) shift $((OPTIND - 1))
@@ -114,10 +117,13 @@ check_root
if [[ -n $1 ]]; then if [[ -n $1 ]]; then
pkgfile="$1" pkgfile="$1"
if ! bsdtar -tqf "${pkgfile}" .BUILDINFO >/dev/null 2>&1; then splitpkgs=("$@")
error "file is not a valid pacman package: '%s'" "${pkgfile}" for f in "${splitpkgs[@]}"; do
exit 1 if ! bsdtar -tqf "${f}" .BUILDINFO >/dev/null 2>&1; then
fi error "file is not a valid pacman package: '%s'" "${f}"
exit 1
fi
done
else else
error "no package file specified. Try '${BASH_SOURCE[0]##*/} -h' for more information. " error "no package file specified. Try '${BASH_SOURCE[0]##*/} -h' for more information. "
exit 1 exit 1
@@ -137,6 +143,7 @@ parse_buildinfo < <(bsdtar -xOqf "${pkgfile}" .BUILDINFO)
export SOURCE_DATE_EPOCH="${buildinfo[builddate]}" export SOURCE_DATE_EPOCH="${buildinfo[builddate]}"
PACKAGER="${buildinfo[packager]}" PACKAGER="${buildinfo[packager]}"
BUILDDIR="${buildinfo[builddir]}" BUILDDIR="${buildinfo[builddir]}"
PKGEXT=${pkgfile#${pkgfile%.pkg.tar*}}
# nuke and restore reproducible testenv # nuke and restore reproducible testenv
for copy in "${buildroot}"/*/; do for copy in "${buildroot}"/*/; do
@@ -152,15 +159,14 @@ for fname in "${installed[@]}"; do
exit 1 exit 1
fi fi
done done
printf '%s\n' "${allpkgfiles[@]}" | mkarchroot -U "${archroot_args[@]}" "${buildroot}"/root - || exit 1 printf '%s\n' "${allpkgfiles[@]}" | mkarchroot -M @pkgdatadir@/makepkg-x86_64.conf -U "${archroot_args[@]}" "${buildroot}"/root - || exit 1
# use makechrootpkg to prep the build directory # use makechrootpkg to prep the build directory
makechrootpkg -r "${buildroot}" -l "${chroot}" -- --packagelist || exit 1 makechrootpkg -r "${buildroot}" -l "${chroot}" -- --packagelist || exit 1
# set detected makepkg.conf options # set detected makepkg.conf options
{ {
for var in PACKAGER BUILDDIR; do for var in PACKAGER BUILDDIR PKGEXT; do
printf '%s=%s\n' "${var}" "${!var@Q}" printf '%s=%s\n' "${var}" "${!var@Q}"
done done
printf 'OPTIONS=(%s)\n' "${buildopts[*]@Q}" printf 'OPTIONS=(%s)\n' "${buildopts[*]@Q}"
@@ -173,18 +179,26 @@ arch-nspawn "${buildroot}/${chroot}" \
--bind="${PWD}:/startdir" \ --bind="${PWD}:/startdir" \
--bind="${SRCDEST}:/srcdest" \ --bind="${SRCDEST}:/srcdest" \
/chrootbuild -C --noconfirm --log --holdver --skipinteg /chrootbuild -C --noconfirm --log --holdver --skipinteg
ret=$?
if (( $? == 0 )); then if (( ${ret} == 0 )); then
msg2 "built succeeded! built packages can be found in ${buildroot}/${chroot}/pkgdest" msg2 "built succeeded! built packages can be found in ${buildroot}/${chroot}/pkgdest"
msg "comparing artifacts..." msg "comparing artifacts..."
if cmp -s "${pkgfile}" "${buildroot}/${chroot}/pkgdest/${pkgfile##*/}"; then
msg2 "Package successfully reproduced!" for pkgfile in "${splitpkgs[@]}"; do
exit 0 comparefiles=("${pkgfile}" "${buildroot}/${chroot}/pkgdest/${pkgfile##*/}")
else if cmp -s "${comparefiles[@]}"; then
warning "Package is not reproducible. :(" msg2 "Package '%s' successfully reproduced!" "${pkgfile}"
sha256sum "${pkgfile}" "${buildroot}/${chroot}/pkgdest/${pkgfile##*/}" else
fi ret=1
warning "Package '%s' is not reproducible. :(" "${pkgfile}"
sha256sum "${comparefiles[@]}"
if (( diffoscope )); then
diffoscope "${comparefiles[@]}"
fi
fi
done
fi fi
# the package either failed to build, or was unreproducible # return failure from chrootbuild, or the reproducibility status
exit 1 exit ${ret}

View File

@@ -74,18 +74,20 @@ while (( $# )); do
done done
# multilib must be handled specially # multilib must be handled specially
archbuild_arch="${arch}"
if [[ $repo = multilib* ]]; then if [[ $repo = multilib* ]]; then
arch= archbuild_arch=
fi fi
archbuild_cmd=("${repo}${arch:+-$arch}-build" "$@") archbuild_cmd=("${repo}${archbuild_arch:+-$archbuild_arch}-build" "$@")
trap 'rm -rf $SRCPKGDEST' EXIT INT TERM QUIT trap 'rm -rf $TEMPDIR' EXIT INT TERM QUIT
# Use a source-only tarball as an intermediate to transfer files. This # Use a source-only tarball as an intermediate to transfer files. This
# guarantees the checksums are okay, and guarantees that all needed files are # guarantees the checksums are okay, and guarantees that all needed files are
# transferred, including local sources, install scripts, and changelogs. # transferred, including local sources, install scripts, and changelogs.
export SRCPKGDEST=$(mktemp -d) export TEMPDIR=$(mktemp -d --tmpdir offload-build.XXXXXXXXXX)
export SRCPKGDEST=${TEMPDIR}
makepkg --source || die "unable to make source package" makepkg --source || die "unable to make source package"
# Temporary cosmetic workaround makepkg if SRCDEST is set somewhere else # Temporary cosmetic workaround makepkg if SRCDEST is set somewhere else
@@ -108,14 +110,22 @@ mapfile -t files < <(
printf "%s\n" "" "-> build complete" && printf "%s\n" "" "-> build complete" &&
printf "\t%s\n" "$temp"/* printf "\t%s\n" "$temp"/*
} >&2 && } >&2 &&
makepkg --packagelist makepkg_user_config="${XDG_CONFIG_HOME:-$HOME/.config}/pacman/makepkg.conf" &&
makepkg_config="/usr/share/devtools/makepkg-'"${arch}"'.conf" &&
if [[ -f /usr/share/devtools/makepkg-'"${repo}"'-'"${arch}"'.conf ]]; then
makepkg_config="/usr/share/devtools/makepkg-'"${repo}"'-'"${arch}"'.conf"
fi &&
makepkg --config <(cat "${makepkg_user_config}" "${makepkg_config}" 2>/dev/null) --packagelist &&
printf "%s\n" "${temp}/PKGBUILD"
') ')
if (( ${#files[@]} )); then if (( ${#files[@]} )); then
printf '%s\n' '' '-> copying files...' printf '%s\n' '' '-> copying files...'
load_makepkg_config load_makepkg_config
scp "${files[@]/#/$server:}" "${PKGDEST:-${PWD}}/" scp "${files[@]/#/$server:}" "${TEMPDIR}/"
mv "${TEMPDIR}"/*.pkg.tar* "${PKGDEST:-${PWD}}/"
mv "${TEMPDIR}/PKGBUILD" "${PWD}/"
else else
exit 1 exit 1
fi fi

View File

@@ -94,10 +94,11 @@ _offload_build_args=(
) )
_makerepropkg_args=( _makerepropkg_args=(
'-d[Run diffoscope if the package is unreproducible]'
'-c[Set pacman cache]:pacman_cache:_files -/' '-c[Set pacman cache]:pacman_cache:_files -/'
'-M[Location of a makepkg config file]:makepkg_config:_files -g "*.conf(.)"' '-M[Location of a makepkg config file]:makepkg_config:_files -g "*.conf(.)"'
'-h[Display usage]' '-h[Display usage]'
'1:working_dir:_files -g "*.pkg.tar.*(.)"' '*:working_dir:_files -g "*.pkg.tar.*(.)"'
) )
_devtools_completions_all_packages() { _devtools_completions_all_packages() {