kanidm/platform/debian/build_kanidm.sh
Jinna Kiisuo aa00ac94d0
Fix debian versioning (#2472)
* Make the ubuntu_docker_builder.sh script a bit easier to use

- Entrypoint that installs dependencies on launch
- Echo hint on how to build deb packages

* Change debian packaging version string format to fix sort order

The sort order is important so that newer packages are seen as an update
and get installed, instead of apt preferring the older versions!

With these changes, a package is generated as `kanidm_Ubuntu_22.04_1:1.1.0~rc.15-dev~202401311334+c8a9e2c_x86_64.deb`
with the version string `1:1.1.0~rc.15-dev~202401311334+c8a9e2c`

Deb package version string comparison is Complex:
https://man7.org/linux/man-pages/man7/deb-version.7.html

With the previous versioning scheme for dev packages, the git hash
ended up getting prioritized over the date string, see for example:
`dpkg --compare-versions 1.1.0-rc.15-dev-202401100453666448f lt 1.1.0-rc.15-dev-20240120072786916a3; echo $?`
-> 1 (comparison failure)

A simple schema change avoiding most dashes could rescue the hash trouble:
`dpkg --compare-versions 1.1.0~rc.15-dev-202401100453+666448f lt 1.1.0-rc.15-dev-202401200727+86916a3; echo $?`
-> 0 (comparison success)

.. But, the second problem is seeing a stable release as newer:
`dpkg --compare-versions 1.1.0~rc.15-dev~202401100453+666448f lt 1.1.0; echo $?`
-> 1 (comparison failure)

.. Which can be solved by forcing the entire dev portion to not be
interpreted as a debian version by substituting tildes:
`dpkg --compare-versions 1.1.0~rc.15-dev~202401100453+666448f lt 1.1.0; echo $?`
-> 0 (comparison success)

.. But, old schema versions still seem newer due to their debian
version:
`dpkg --compare-versions 1.1.0-rc.15-dev-202401100453666448f lt 1.1.0~rc.15-dev~202401200727+86916a3; echo $?`
-> 1 (comparison failure)

Thus, the only solution is to change the scheme and increment the epoch value once
to force all lesser default epoch versions to be seen as older:
`dpkg --compare-versions 1.1.0-rc.15-dev-202401100453666448f lt 1:1.1.0~rc.15-dev~202401200727+86916a3; echo $?`
-> 0 (comparison success)
`dpkg --compare-versions 1:1.1.0~rc.15-dev~202401200727+86916a3 lt 1:1.1.0; echo $?`
-> 0 (comparison success)

* Drop epoch field from deb filenames

GitHub Actions enforces NTFS compatible artifact filenames, ergo the
colon required for the epoch field is banned. The epoc is still in the
version field itself, just not in the filename.

---------

Co-authored-by: Jinna Kiisuo <jinna+git@nocturnal.fi>
2024-02-05 18:06:43 +10:00

150 lines
3.8 KiB
Bash
Executable file

#!/usr/bin/bash
# you can skip the dependency install by setting the env var SKIP_DEPS=1
set -e
if [ -z "${ARCH}" ]; then
ARCH="$(dpkg --print-architecture)"
fi
if [ "${ARCH}" != "$(dpkg --print-architecture)" ]; then
echo "${ARCH} != $(dpkg --print-architecture), cross-compiling!"
export PKG_CONFIG_ALLOW_CROSS=1
else
echo "Building for ${ARCH}"
fi
if [ -z "$1" ]; then
PACKAGE="kanidm"
else
PACKAGE="$1"
fi
if [ ! -d "./platform/debian/${PACKAGE}" ]; then
echo "Can't find packaging files for ${PACKAGE}"
exit 1
fi
echo "Building ${PACKAGE}"
SOURCE_DIR="$(cargo metadata --format-version 1 | jq -r .workspace_root)"
echo "Source dir ${SOURCE_DIR}"
if [ ! -d "${SOURCE_DIR}" ]; then
echo "Can't find source dir ${SOURCE_DIR}!"
exit 1
fi
BUILD_DIR="$(mktemp -d)"
if [ -z "${SKIP_DEPS}" ]; then
PACKAGING=1 ./scripts/install_ubuntu_dependencies.sh
else
echo "SKIP_DEPS configured, skipping install of rust and packages"
fi
if [ -f "${HOME}/.cargo/env" ]; then
# shellcheck disable=SC1091
source "${HOME}/.cargo/env"
else
echo "Couldn't find cargo env in ${HOME}/.cargo/env that seems weird?"
fi
# if we can't find cargo then need to update the path
if [ "$(which cargo | wc -l)" -eq 0 ]; then
if echo "$PATH" | grep -q '.cargo/bin'; then
echo "Updating path to include local cargo dir"
export PATH="$HOME/.cargo/bin:$PATH"
if [ "$(which cargo | wc -l)" -eq 0 ]; then
echo "Still couldn't find cargo, bailing!"
exit 1
fi
fi
fi
# this assumes the versions are in lock-step, which is fine at the moment.
# Debian is picky abour dashes in version strings, so a bit of conversion
# is needed for the first one to prevent interference.
KANIDM_VERSION="$(grep -ioE 'version.*' Cargo.toml | head -n1 | awk '{print $NF}' | tr -d '"' | sed -e 's/-/~/')"
# if we're in a github action, then it's easy to get the commit
if [ -n "${GITHUB_SHA}" ]; then
GIT_HEAD="${GITHUB_SHA}"
else
GIT_HEAD="$(git rev-parse HEAD)"
fi
# we only want the short commit
GIT_COMMIT="${GIT_HEAD:0:7}"
DATESTR="$(date +%Y%m%d%H%M)"
# Due to previous version schemes we need to increment epoch above the default 0,
# to supercede old versions before the change.
EPOCH=1
# GitHub Actions forces NTFS compatibility which disallows colons in filenames
# ergo, we do not include the epoch in the filename.
FILENAME="${KANIDM_VERSION}~${DATESTR}+${GIT_COMMIT}"
PACKAGE_VERSION="${EPOCH}:${FILENAME}"
echo "Deb package Version: ${PACKAGE_VERSION}"
echo "Updating package dir"
rm -rf "${BUILD_DIR:?}/*"
echo "Copying source files from ${SOURCE_DIR} to ${BUILD_DIR}"
rsync -a \
--exclude target \
"${SOURCE_DIR}/" \
"${BUILD_DIR}/"
echo "Copying the debian-specific build files"
cd "${BUILD_DIR}"
pwd
ls -la
rm -rf debian && mkdir -p debian
cp -R platform/debian/packaging/* debian/
if [ -d "platform/debian/${PACKAGE}/" ]; then
echo "Copying debian-specific files for ${PACKAGE}"
# shellcheck disable=SC2086
cp platform/debian/${PACKAGE}/* debian/
else
echo "No package-specific files were found"
fi
echo "Setting permissions on debian scripts"
find "./debian/" -name 'pre*' -ls -exec chmod 755 "{}" \;
find "./debian/" -name 'rules' -ls -exec chmod 755 "{}" \;
echo "Updating changelog"
sed -E \
"s/#DATE#/$(date -R)/" \
platform/debian/packaging/templates/changelog | \
sed -E "s/#VERSION#/${PACKAGE_VERSION}/" | \
sed -E "s/#GIT_COMMIT#/${GIT_COMMIT}/" | \
sed -E "s/#PACKAGE#/${PACKAGE}/" > debian/changelog
echo "Running clean"
# debian/rules clean
echo "Running build"
debian/rules build
echo "Packaging ${PACKAGE}"
fakeroot debian/rules binary
echo "Moving debs to target/"
mkdir -p "${SOURCE_DIR}/target/"
find ../ -maxdepth 1 -name '*.deb' -exec mv "{}" "${SOURCE_DIR}/target/" \;
echo "Done, packages:"
find "${SOURCE_DIR}/target/" -maxdepth 1 -name '*.deb'