rgb-cln/tools/build-release.sh

283 lines
11 KiB
Bash
Executable File

#! /bin/sh
set -e
# When run inside docker (from below), we do build and drop result in /release
if [ "$1" = "--inside-docker" ]; then
echo "Inside docker: starting build"
VER="$2"
PLTFM="$3"
git clone /src /build
cd /build
pip3 install -r plugins/clnrest/requirements.txt
./configure
make VERSION="$VER"
make install DESTDIR=/"$VER-$PLTFM" RUST_PROFILE=release
cd /"$VER-$PLTFM" && tar cvfz /release/clightning-"$VER-$PLTFM".tar.gz -- *
echo "Inside docker: build finished"
exit 0
fi
FORCE_UNCLEAN=false
VERIFY_RELEASE=false
DOCKER_PUSH=false
ALL_TARGETS="bin-Fedora-28-amd64 bin-Ubuntu docker sign"
# ALL_TARGETS="bin-Fedora-28-amd64 bin-Ubuntu tarball deb docker sign"
for arg; do
case "$arg" in
--force-version=*)
FORCE_VERSION=${arg#*=}
;;
--force-unclean)
FORCE_UNCLEAN=true
;;
--force-mtime=*)
FORCE_MTIME=${arg#*=}
;;
--verify)
VERIFY_RELEASE=true
;;
--push)
DOCKER_PUSH=true
;;
--help)
echo "Usage: [--force-version=<ver>] [--force-unclean] [--force-mtime=YYYY-MM-DD] [--verify] [TARGETS]"
echo Known targets: "$ALL_TARGETS"
echo "Example: tools/build-release.sh"
echo "Example: tools/build-release.sh --force-version=v23.05 --force-unclean --force-mtime=2023-05-01 bin-Fedora-28-amd64 bin-Ubuntu sign"
echo "Example: tools/build-release.sh --verify"
echo "Example: tools/build-release.sh --force-version=v23.05 --force-unclean --force-mtime=2023-05-01 --verify"
echo "Example: tools/build-release.sh --push docker"
echo "Example: tools/build-release.sh --force-version=v23.05 --force-unclean --force-mtime=2023-05-01 --push docker"
exit 0
;;
-*)
echo "Unknown arg $arg" >&2
exit 1
;;
*)
break
;;
esac
shift
done
echo "Verify Release: $VERIFY_RELEASE"
echo "Force mTime: $FORCE_MTIME"
echo "Force Unclean: $FORCE_UNCLEAN"
VERSION=$(git tag --points-at HEAD)
echo "Tagged Version: $VERSION"
VERSION=${FORCE_VERSION:-$VERSION}
echo "Version: $VERSION"
if [ "$VERSION" = "" ]; then
echo "No tagged version at HEAD?" >&2
exit 1
fi
# `status --porcelain -u no` suppressed modified! Bug reported...
if [ "$(git diff --name-only)" != "" ] && ! $FORCE_UNCLEAN; then
echo "Not a clean git directory" >&2
exit 1
fi
# Skip 'v' here in $VERSION
MTIME=${FORCE_MTIME:-$(sed -n "s/^## \\[.*${VERSION#v}\\] - \\([-0-9]*\\).*/\\1/p" < CHANGELOG.md)}
echo "mTime: $MTIME"
if [ -z "$MTIME" ]; then
echo "No date found for $VERSION in CHANGELOG.md" >&2
exit 1
fi
if [ "$VERIFY_RELEASE" = "true" ]; then
if [ -f "SHA256SUMS-$VERSION.asc" ] && [ -f "SHA256SUMS-$VERSION" ]; then
ALL_TARGETS="bin-Ubuntu"
else
echo "Unable to verify. File SHA256SUMS-$VERSION or SHA256SUMS-$VERSION.asc not found in the root."
exit 1
fi
fi
if [ "$#" = 0 ]; then
TARGETS=" $ALL_TARGETS "
else
TARGETS=" $* "
fi
RELEASEDIR="$(pwd)/release"
BARE_VERSION="$(echo "${VERSION}" | sed 's/^v//g')"
TARBALL="${RELEASEDIR}/lightningd_${BARE_VERSION}.orig.tar.bz2"
DATE=$(date +%Y%m%d%H%M%S)
echo "Targets: $TARGETS"
echo "Release Directory: $RELEASEDIR"
echo "Tarball File: $TARBALL"
echo "Current Timestamp: $DATE"
# submodcheck needs to know if we have lowdown
./configure --reconfigure
# If it's a completely clean directory, we need submodules!
make submodcheck
mkdir -p "$RELEASEDIR"
echo "Creating Zip File"
# delete zipfile if exists
[ -f "$RELEASEDIR/clightning-$VERSION.zip" ] && rm "$RELEASEDIR/clightning-$VERSION.zip"
mkdir "$RELEASEDIR/clightning-$VERSION"
# git archive won't go into submodules :(; We use tar to copy
git ls-files -z --recurse-submodules | tar --null --files-from=- -c -f - | (cd "$RELEASEDIR/clightning-$VERSION" && tar xf -)
# tar can set dates on files, but zip cares about dates in directories!
# We set to local time (not "$MTIME 00:00Z") because zip uses local time!
find "$RELEASEDIR/clightning-$VERSION" -print0 | xargs -0r touch --no-dereference --date="$MTIME"
# Seriously, we can have differing permissions, too. Normalize.
# Directories become drwxr-xr-x
find "$RELEASEDIR/clightning-$VERSION" -type d -print0 | xargs -0r chmod 755
# Executables become -rwxr-xr-x
find "$RELEASEDIR/clightning-$VERSION" -type f -perm -100 -print0 | xargs -0r chmod 755
# Non-executables become -rw-r--r--
find "$RELEASEDIR/clightning-$VERSION" -type f ! -perm -100 -print0 | xargs -0r chmod 644
# zip -r doesn't have a deterministic order, and git ls-files does.
LANG=C git ls-files --recurse-submodules | sed "s@^@clightning-$VERSION/@" | (cd release && zip -@ -X "clightning-$VERSION.zip")
rm -r "$RELEASEDIR/clightning-$VERSION"
echo "Zip File Created"
for target in $TARGETS; do
platform=${target#bin-}
[ "$platform" != "$target" ] || continue
case $platform in
Fedora-28-amd64)
echo "Building Fedora Image"
DOCKERFILE=contrib/docker/Dockerfile.builder.fedora
TAG=fedora
docker build -f $DOCKERFILE -t $TAG .
docker run --rm=true -v "$(pwd)":/src:ro -v "$RELEASEDIR":/release $TAG /src/tools/build-release.sh --inside-docker "$VERSION" "$platform"
docker run --rm=true -w /build $TAG rm -rf /"$VERSION-$platform" /build
echo "Fedora Image Built"
;;
Ubuntu)
for d in focal jammy; do
# Capitalize the first letter of distro
D=$(echo "$d" | awk '{print toupper(substr($0,1,1))substr($0,2)}')
echo "Building Ubuntu $D Image"
docker run --rm -v "$(pwd)":/build -e FORCE_MTIME="$MTIME" -e FORCE_VERSION="$VERSION" -ti cl-repro-"$d"
echo "Ubuntu $D Image Built"
done
;;
*)
echo "No Dockerfile for $platform" >&2
exit 1
esac
done
if [ -z "${TARGETS##* docker *}" ]; then
echo "Building Docker Images"
DOCKER_USER="elementsproject"
PLATFORMS="amd64 arm64v8"
for d in $PLATFORMS; do
TMPDIR="$(mktemp -d /tmp/lightningd-docker-"$d".XXXXXX)"
SRCDIR="$(pwd)"
echo "Bundling $d image in ${TMPDIR}"
git clone --recursive . "${TMPDIR}"
(
cd "${TMPDIR}"
if ! $FORCE_UNCLEAN; then
git checkout "v${BARE_VERSION}"
fi
cp "${SRCDIR}/Dockerfile" "${TMPDIR}/"
case "$d" in
"arm32v7")
TARBALL_ARCH="arm-linux-gnueabihf"
PLATFORM="linux/arm/v7"
;;
"arm64v8")
TARBALL_ARCH="aarch64-linux-gnu"
PLATFORM="linux/arm64"
;;
"amd64")
TARBALL_ARCH="x86_64-linux-gnu"
PLATFORM="linux/amd64"
;;
esac
if $DOCKER_PUSH; then
docker buildx build --push --platform $PLATFORM --build-arg TARBALL_ARCH=$TARBALL_ARCH -t "$DOCKER_USER"/lightningd:"$VERSION"-"$d" -f Dockerfile "${TMPDIR}"
echo "Docker Image for $PLATFORM Built and Uploaded on Dockerhub."
else
docker buildx build --load --platform $PLATFORM --build-arg TARBALL_ARCH=$TARBALL_ARCH -t "$DOCKER_USER"/lightningd:"$VERSION"-"$d" -f Dockerfile "${TMPDIR}"
echo "Docker Image for $PLATFORM Built. Ready to Upload on Dockerhub."
fi
)
rm -rf "${TMPDIR}"
done
echo "Creating a multi-platform image tagged as $VERSION"
docker manifest create --amend "$DOCKER_USER"/lightningd:"$VERSION" "$DOCKER_USER"/lightningd:"$VERSION"-amd64 "$DOCKER_USER"/lightningd:"$VERSION"-arm64v8
docker manifest annotate "$DOCKER_USER"/lightningd:"$VERSION" "$DOCKER_USER"/lightningd:"$VERSION"-amd64 --os linux --arch amd64
docker manifest annotate "$DOCKER_USER"/lightningd:"$VERSION" "$DOCKER_USER"/lightningd:"$VERSION"-arm64v8 --os linux --arch arm64 --variant v8
# FIXME: Throws ERROR: failed to solve: debian:bullseye-slim: no match for platform in manifest
# docker buildx create --use
# docker buildx build --push --platform linux/amd64,linux/arm64v8 -t "$DOCKER_USER/lightningd:"$VERSION"-$d" .
echo "Creating a multi-platform image tagged as latest"
# Remove the old image
docker rmi "$DOCKER_USER"/lightningd:latest
# Remove the old manifest
docker manifest rm "$DOCKER_USER"/lightningd:latest
docker manifest create "$DOCKER_USER"/lightningd:latest "$DOCKER_USER"/lightningd:"$VERSION"-amd64 "$DOCKER_USER"/lightningd:"$VERSION"-arm64v8
docker manifest annotate "$DOCKER_USER"/lightningd:latest "$DOCKER_USER"/lightningd:"$VERSION"-amd64 --os linux --arch amd64
docker manifest annotate "$DOCKER_USER"/lightningd:latest "$DOCKER_USER"/lightningd:"$VERSION"-arm64v8 --os linux --arch arm64 --variant v8
if $DOCKER_PUSH; then
docker manifest push "$DOCKER_USER"/lightningd:"$VERSION"
echo "Pushed a multi-platform image tagged as $VERSION"
docker manifest push "$DOCKER_USER"/lightningd:latest
echo "Pushed a multi-platform image tagged as latest"
else
echo "Docker Images Built. Ready to Upload on Dockerhub."
fi
fi
if [ -z "${TARGETS##* sign *}" ]; then
echo "Signing Release"
cd release/
sha256sum clightning-"$VERSION"* > SHA256SUMS
gpg -sb --armor -o SHA256SUMS.asc"$(gpgconf --list-options gpg | awk -F: '$1 == "default-key" {print $10}' | tr -d '"')" SHA256SUMS
cd ..
echo "Release Signed"
fi
if [ "$VERIFY_RELEASE" = "true" ]; then
echo "Verifying Release"
sumfile="SHA256SUMS-${VERSION}"
# Ensure that the release captains checksum exists at the desired location.
if [ ! -f "$sumfile" ]; then
echo "Can not find release captains checksum file \"$sumfile\"".
echo "You can download it from the repository at:"
echo "https://github.com/ElementsProject/lightning/releases/tag/$VERSION"
echo "Place it under the project root as \"$sumfile\"."
exit 1
fi
sumfile="$(pwd)/${sumfile}"
cd release/
# Check that the release captains sum matches. Ignore missing entries as we
# do not have a repro build for Fedora. Strictly this is not necessary here
# as we compare our checksums with the release captains checksums later, but
# it gives a direct hint which specific checksums don't match if so.
sha256sum --check --ignore-missing "${sumfile}"
# Creating SHA256SUMS, except Fedora (copy that from theirs)
grep 'Fedora-28-amd64' "$sumfile" > SHA256SUMS
sha256sum clightning-"$VERSION"* | grep -v 'bin-Fedora-28-amd64' >> SHA256SUMS
# compare our and release captain's SHA256SUMS contents
if cmp -s SHA256SUMS "$sumfile"; then
echo "SHA256SUMS are Identical"
else
echo "Error: SHA256SUMS do NOT Match"
exit 1
fi
# verify release captain signature
gpg --verify "../SHA256SUMS-$VERSION.asc"
# create ASCII-armored detached signature
gpg -sb --armor < SHA256SUMS > SHA256SUMS.new
echo "Verified Successfully! Signature Updated in release/SHA256SUMS.new"
fi
echo "Building release script finished!!"