#!/bin/bash

# Launch sbuild from jenkins
# Input:
#  .dsc source package in current directory
#  JOB_NAME=$pkg-binaries or PACKAGE=pkg
#  architecture=amd64/arm64/...
#  distribution=foo (caveat: sbuild -d foo-pgdg will be called)
#  optionally: DEB_BUILD_OPTIONS
#  optionally: PG_SUPPORTED_VERSIONS (defaults to pgdg)
#  optionally: autopkgtest=skip
#  optionally: BACKPORTS=true
#  optionally: BUILD_DIR
#  optionally: wrap= (disables newpid-netns)
#  optionally: binnmu_reason=text binnmu_version=version
#  optionally: NODE_USAGE=exclusive (defaults to shared)
#  optionally: upload=extension-only (defaults to "all")
# Output:
#  .changes and .deb in current directory
#  autopkgtest.xml in current directory
# Requirements:
#  schroot $foo-pgdg-$arch-sbuild
#  gid sbuild (for sbuild as such and for /var/lock/sbuild-package)
#  adt-sbuild available in chroot (in pgdg-buildenv package)
#  /var/tmp bind mount in schroot fstab for retrieving adt-run summary
#  sbuild needs to pass through DEB_* variables (default)
#  "deb" resolves to some debian mirror
#  newpid (and newpid-netns) is installed on host and netns-setup was run

set -eu

error () {
  echo "Error: $@" >&2
  exit 1
}

# read pgapt config
for dir in . .. $HOME/apt.postgresql.org; do
  test -f $dir/pgapt.conf || continue
  . $dir/pgapt.conf
  break
done
chroot="chroot:${distribution:=sid}$REPO_DIST_SUFFIX-${architecture:=amd64}-sbuild"
set_dist_vars $distribution

# find dsc to build
if [ -z "${PACKAGE:-}" ]; then
  PACKAGE="${JOB_NAME%%-binaries*}"
fi
set -- ${PACKAGE}_*.dsc
DSC="$1"
[ "${2:-}" ] && error "There is more than one \${PACKAGE}_*.dsc in $PWD"

# exit early if package is arch:all only and we are not on amd64
if [ "$architecture" != "amd64" ] && grep -Eq '^Architecture: all$' $DSC; then
  echo "Package is arch:all only and we are not on amd64" # needs https://issues.jenkins-ci.org/browse/JENKINS-59730 fixed first: "###" "NOT BUILT" "###"
  adtsummary2junit /dev/null > autopkgtest.xml
  exit
fi

# check if chroot exists
schroot -l | grep -q $chroot || \
  error "There is no schroot definition for $chroot"

# decide if we should build arch:all packages
case $architecture in
  amd64)
    ARCH_ALL="--arch-all" ;; # always build arch:all binaries here
  *)
    ARCH_ALL="--no-arch-all"
    if [ "${autopkgtest:-}" != "skip" ] && grep -Eq '^Testsuite: .*autopkgtest' $DSC; then
      echo "Package has Testsuite: autopkgtest, will build arch:all binaries even on $architecture. We'll throw them away at the end."
      ARCH_ALL="--arch-all"
      FILTER_ARCH_ALL="true"
    fi ;;
esac

# build options and profiles
# the arrays need to have names different from the plain variables because we want to export them
BUILD_PROFILES=(${DEB_BUILD_PROFILES:-} pgdg $distribution)
BUILD_OPTIONS=(${DEB_BUILD_OPTIONS:-})

case $PACKAGE in
  postgresql-?.?|postgresql-[1-9]?|postgresql-[1-9]???) # 9.x, 15, 15ee
    case $distribution in
      # enable cassert on sid
      sid) BUILD_PROFILES+=(pkg.postgresql.cassert) ;;
    esac
    ;;
esac

if [ "${build_tweak:-}" ]; then
  echo "Applying build tweak:"
  echo "$build_tweak"
  set -x
  eval "$build_tweak"
  set +x
fi

case ${NODE_USAGE:=shared} in
  shared) BUILD_OPTIONS+=("parallel=2") ;;
  exclusive) BUILD_OPTIONS+=("parallel=$(nproc)") ;;
  *) echo "Invalid NODE_USAGE=$NODE_USAGE setting"; exit 1 ;;
esac

export DEB_BUILD_PROFILES=${BUILD_PROFILES[@]}
export DEB_BUILD_OPTIONS=${BUILD_OPTIONS[@]}

# resolve alternative build-dependencies on dists other than sid
case $distribution in
	sid) ;;
	*) RESOLVE_ALTERNATIVES="--resolve-alternatives --build-dep-resolver=aptitude" ;;
esac

# enable backports
if [ "$HAS_BACKPORTS" ] && [ "${BACKPORTS:-}" ] && [ "$BACKPORTS" != "false" ]; then
  BPOREPO="$mirror_backports"
fi

# auto-update debian/control from debian/control.in (pg_buildext updatecontrol)
export PG_UPDATECONTROL=yes

for version in $PG_SUPPORTED_VERSIONS; do
  case $version in [1-9]*)
    # extra build dependencies
    ADD_DEPENDS="${ADD_DEPENDS:-} --add-depends=postgresql-server-dev-$version"
    if grep -q 'Build-Depends: .*postgresql-all' $DSC; then
      ADD_DEPENDS="$ADD_DEPENDS --add-depends=postgresql-$version"
    fi
    ;;
  esac
done

for pkg in ${EXTRA_PACKAGES:-}; do
  ADD_DEPENDS="${ADD_DEPENDS:-} --add-depends=$pkg"
done

# prepare temp file for adt-run results
if [ "${autopkgtest:-}" != "skip" ]; then
  ADT_TEMP_DIR=$(mktemp -d /var/tmp/$PACKAGE.XXXXXX)
  chgrp sbuild "$ADT_TEMP_DIR"
  chmod 3775 "$ADT_TEMP_DIR" # allow jenkins to create files
  export DEB_ADT_SUMMARY="$ADT_TEMP_DIR/adt_summary"
  trap "rm -rf $ADT_TEMP_DIR" EXIT
  FINISHED_BUILD_COMMAND='adt-sbuild %SBUILD_BUILD_DIR %SBUILD_PKGBUILD_DIR'
fi

# lock against concurrent apt-get update/upgrade operations on the source chroot
LOCKDIR="/var/lock/sbuild-package"
if ! test -d $LOCKDIR; then
  mkdir -p $LOCKDIR
  chgrp sbuild $LOCKDIR
  chmod 3775 $LOCKDIR
fi
umask 002

# build package and run autopkgtests inside the chroot
(
  echo "Building $PACKAGE (PG_SUPPORTED_VERSIONS=$PG_SUPPORTED_VERSIONS)"
  set -x
  : "Acquiring node lock (run only one job in parallel when exclusive)"
  flock --$NODE_USAGE 8
  : "Acquiring chroot lock"
  flock --shared 9 # lock against concurrent source chroot upgrades
  ${wrap-newpid-netns} \
  sbuild --verbose --batch \
    -d $distribution$REPO_DIST_SUFFIX --arch $architecture ${ARCH_ALL:-} ${RESOLVE_ALTERNATIVES:-} \
    --build-path "/build/${BUILD_DIR:-$PACKAGE-$distribution-$architecture}" \
    ${BPOREPO:+--extra-repository="$BPOREPO"} \
    ${EXTRA_REPOSITORY:+--extra-repository="$EXTRA_REPOSITORY"} \
    ${EXTRA_REPOSITORY_KEY:+--extra-repository-key="$EXTRA_REPOSITORY_KEY"} \
    ${binnmu_reason:+--make-binNMU="$binnmu_reason" --binNMU="$binnmu_version" -m "$MAILING_LIST"} \
    ${FINISHED_BUILD_COMMAND:+--finished-build-commands="$FINISHED_BUILD_COMMAND"} \
    --no-run-lintian \
    ${ADD_DEPENDS:-} \
    ${ADD_DEPENDS:+--chroot-setup-commands="/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -h$PGDG_MIRROR -st -v'$PG_SUPPORTED_VERSIONS' $distribution"} \
    $DSC
) 8> $LOCKDIR/node.lock 9> $LOCKDIR/$distribution-$architecture.lock

# remove arch:all packages that were only built for autopkgtests
if [ "${FILTER_ARCH_ALL:-}" ]; then
  sed -i -e '/_all\.deb$/d' *.changes
fi

if [ "${upload:-all}" = "all" ]; then
  # add build log to changes file
  log=$(echo *_$architecture.build)
  xz < $log > $log.xz
  changestool *.changes add $log.xz

  # on amd64, add the source to the changes file
  case $architecture in
    amd64)
      changestool *.changes adddsc $DSC
      ;;
  esac
else
  # when building for PG devel, remove buildinfo so we don't overwrite the one
  # from the main "pgdg" build
  sed -i -e '/\.buildinfo$/d' *.changes
fi

# rename Ubuntu's .ddebs to .deb
if grep -q '\.ddeb$' *.changes; then
  for ddeb in $(grep -ho '[^ ]*\.ddeb$' *.changes | sort -u); do
    mv -v $ddeb ${ddeb%.ddeb}.deb
  done
  sed -i -e 's/\.ddeb$/.deb/' *.changes
fi

# convert autopkgtest results to junit xml format
if [ "${DEB_ADT_SUMMARY:-}" ]; then
  if [ -s "$DEB_ADT_SUMMARY" ]; then
    adtsummary2junit $DEB_ADT_SUMMARY > autopkgtest.xml
  else
    echo "$DEB_ADT_SUMMARY was not created, something went wrong with the autopkgtest run"
    exit 1
  fi
else
  adtsummary2junit /dev/null > autopkgtest.xml
fi
