diff --git a/Jenkinsfile b/Jenkinsfile index 3dca96e3b4895f2b08450c83df639675fec6613b..9429210b502cd1e641bdbd7a66338c3b56d432c7 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,3 +1,20 @@ +// Copyright (C) 2021 Savoir-faire Linux Inc. +// +// Author: Maxim Cournoyer <maxim.cournoyer@savoirfairelinux.com> +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// // Packaging validation for supported GNU/Linux systems. // // Note: To work on this script without having to push a commit each @@ -102,10 +119,7 @@ See https://wiki.savoirfairelinux.com/wiki/Jenkins.jami.net#Configuration_client stage('Generate release tarball') { steps { - // Note: sourcing .bashrc is necessary to setup the - // environment variables used by Guix. - sh '''#!/usr/bin/env bash - test -f $HOME/.bashrc && . $HOME/.bashrc + sh '''#!/usr/bin/env -S bash -l make portable-release-tarball .tarball-version ''' stash(includes: '*.tar.gz, .tarball-version', @@ -143,7 +157,7 @@ See https://wiki.savoirfairelinux.com/wiki/Jenkins.jami.net#Configuration_client unstash 'release-tarball' catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') { - sh """ + sh """#!/usr/bin/env -S bash -l echo Building on node \$NODE_NAME tar xf *.tar.gz --strip-components=1 make ${target} @@ -179,7 +193,16 @@ See https://wiki.savoirfairelinux.com/wiki/Jenkins.jami.net#Configuration_client echo "Failed to unstash ${target}, skipping..." return } - echo "Deploying packages for ${target}..." + } + + def distributionsText = sh( + script: 'find packages/* -maxdepth 1 -type d -print0' + + '| xargs -0 -n1 basename -z', + returnStdout: true).trim() + def distributions = distributionsText.split("\0") + + distributions.each { distribution -> + echo "Deploying ${distribution} packages..." sh """scripts/deploy-packages.sh \ --distribution=${target} \ --keyid="${RING_PUBLIC_KEY_FINGERPRINT}" \ diff --git a/Makefile b/Makefile index bd7fe50874bb0f3c7bd415a6b5a161d7fb6816cb..67915118d2f3ce056f600831a7e1d2e28bc3a834 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ # -*- mode: makefile; -*- # Copyright (C) 2016-2021 Savoir-faire Linux Inc. # +# Author: Maxim Cournoyer <maxim.cournoyer@savoirfairelinux.com> +# # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or @@ -42,7 +44,11 @@ else $(warning Using version from the .tarball-version file: $(TARBALL_VERSION)) RELEASE_VERSION:=$(TARBALL_VERSION) endif -RELEASE_TARBALL_FILENAME:=jami_$(RELEASE_VERSION).tar.gz +RELEASE_TARBALL_FILENAME := jami_$(RELEASE_VERSION).tar.gz + +# Export for consumption in child processes. +export RELEASE_VERSION +export RELEASE_TARBALL_FILENAME # Debian versions DEBIAN_VERSION:=$(RELEASE_VERSION)~dfsg1-1 @@ -88,15 +94,18 @@ release-tarball: rm -f "$(RELEASE_TARBALL_FILENAME)" tarballs.manifest $(MAKE) "$(RELEASE_TARBALL_FILENAME)" +# Predicate to check if the 'guix' command is available. +has-guix-p: + command -v guix > /dev/null 2>&1 || \ + (echo 'guix' is required to build the '$@' target && exit 1) + # The bundled tarballs included in the release tarball depend on what # is available on the host. To ensure it can be shared across all # different GNU/Linux distributions, generate it in a minimal # container. Wget uses GnuTLS, which looks up its certs from # /etc/ssl/certs. guix-share-tarball-arg = $${TARBALLS:+"--share=$$TARBALLS"} -portable-release-tarball: - command -v guix > /dev/null 2>&1 || \ - (echo 'guix' is required to build the '$@' target && exit 1) && \ +portable-release-tarball: has-guix-p guix environment --container --network \ --preserve=TARBALLS $(guix-share-tarball-arg) \ --expose=/usr/bin/env \ @@ -235,6 +244,40 @@ endef $(foreach target,$(DISTRIBUTIONS),\ $(eval $(call make-docker-package-target,$(target)))) +# +# Guix-generated Debian packages (deb packs) targets. +# +SUPPORTED_GNU_ARCHS = x86_64 i686 +DEB_PACK_TARGETS = + +define guix-pack-command +guix pack -C xz -f deb -m $(CURDIR)/guix/guix-pack-manifest.scm -v3 \ + -S /usr/bin/jami-qt=bin/jami-qt \ + -S /usr/share/applications/jami-qt.desktop=share/applications/jami-qt.desktop \ + -S /usr/share/icons/hicolor/scalable/apps/jami.svg=share/icons/hicolor/scalable/apps/jami.svg \ + -S /usr/share/icons/hicolor/48x48/apps/jami.png=share/icons/hicolor/48x48/apps/jami.png \ + -S /usr/share/metainfo/jami-qt.appdata.xml=share/metainfo/jami-qt.appdata.xml \ + --postinst-file=$(CURDIR)/guix/guix-pack-deb.postinst +endef + +# Arg1: the GNU architecture type (e.g., x86_64, i686, powerpcle, etc.) +define define-deb-pack-rule +deb-file-name := packages/guix-deb-pack/jami-$(RELEASE_VERSION)-$(1).deb +DEB_PACK_TARGETS += deb-pack-$(subst _,-,$(1)) +.PHONY: deb-pack-$(subst _,-,$(1)) +deb-pack-$(subst _,-,$(1)): $$(deb-file-name) +$$(deb-file-name): has-guix-p $(RELEASE_TARBALL_FILENAME) + output=$$$$($(guix-pack-command) --system=$(1)-linux $$(GUIX_PACK_ARGS)) && \ + mkdir -p "$$$$(dirname "$$@")" && \ + cp --reflink=auto "$$$$output" "$$@" + chmod +w "$$@" +endef + +$(foreach arch,$(SUPPORTED_GNU_ARCHS),\ + $(eval $(call define-deb-pack-rule,$(arch)))) + +PACKAGE-TARGETS += $(DEB_PACK_TARGETS) + package-all: $(PACKAGE-TARGETS) .PHONY: list-package-targets diff --git a/guix/guix-pack-deb.postinst b/guix/guix-pack-deb.postinst new file mode 100644 index 0000000000000000000000000000000000000000..4c6c8ca6801b29caa6db24745bb7abe266ee7e55 --- /dev/null +++ b/guix/guix-pack-deb.postinst @@ -0,0 +1,97 @@ +#!/bin/sh +# Copyright (C) 2021 Savoir-faire Linux Inc. +# +# Author: Maxim Cournoyer <maxim.cournoyer@savoirfairelinux.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +set -e + +# Fingerprint: A295D773307D25A33AE72F2F64CD5FA175348F84 +jami_key="\ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2 + +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 +4sRdAfS333T4Uifq4uOu +=s2aQ +-----END PGP PUBLIC KEY BLOCK-----" + +# System paths and generated variables. +apt_file=/etc/apt/sources.list.d/jami.list +update_manager_path=/etc/update-manager/release-upgrades.d/ +jami_update_manager_id=jami +jami_update_manager_cfg=${jami_update_manager_id}.cfg +update_manager_cfg_path=$update_manager_path/$jami_update_manager_cfg +jami_repo_url=https://dl.jami.net/nightly/guix-deb-pack + +case "$1" in + configure) + command -v apt-key > /dev/null \ + || (echo 'could not run postinst: apt-key is missing' && exit 1) + + # Add the key to the trusted keyring. + echo "$jami_key" | apt-key add - > /dev/null 2>&1 + + # Additionally, if update manager is installed we inform it about + # the repository so it doesn't get scrapped after system updates + if [ -d /etc/update-manager ]; then + mkdir -p "$update_manager_path" + cat > "$update_manager_cfg_path" <<EOF +# Added by Jami to prevent disabling of Jami repository sources on +# distribution release upgrade. +[ThirdPartyMirrors] +jami/${jami_update_manager_id}=${jami_repo_url} +EOF + fi + + # Add an entry for the package repository. + test -f "$apt_file" && cp "$apt_file" "${apt_file}.bak" + echo "deb $jami_repo_url jami main" > "$apt_file" + ;; +esac + +# Local Variables: +# mode: sh +# End: diff --git a/guix/guix-pack-manifest.scm b/guix/guix-pack-manifest.scm new file mode 100644 index 0000000000000000000000000000000000000000..ec3e6a237a425def5944925cc8c70ac904aaab74 --- /dev/null +++ b/guix/guix-pack-manifest.scm @@ -0,0 +1,120 @@ +;;; Copyright (C) 2021 Savoir-faire Linux Inc. +;;; +;;; Author: Maxim Cournoyer <maxim.cournoyer@savoirfairelinux.com> +;;; +;;; This program is free software: you can redistribute it and/or modify +;;; it under the terms of the GNU General Public License as published by +;;; the Free Software Foundation, either version 3 of the License, or +;;; (at your option) any later version. +;;; +;;; This program is distributed in the hope that it will be useful, +;;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with this program. If not, see <http://www.gnu.org/licenses/>. +;;; +;;; This GNU Guix manifest is used along the Makefile to build the +;;; latest Jami as a Guix pack. + +(use-modules (gnu packages certs) + (gnu packages jami) + (gnu packages python) + (guix base32) + (guix packages) + (guix transformations) + (guix store) + (guix utils)) + +;;; XXX: Below is a rather strenuous way to specify something that +;;; would have been nicer if it could have been specified via: +;;; +;;; --with-source=libring=$(RELEASE_TARBALL_FILENAME) \ +;;; --with-source=libringclient=$(RELEASE_TARBALL_FILENAME) \ +;;; --with-source=jami-qt=$(RELEASE_TARBALL_FILENAME) in the Makefile. +;;; +;;; The above doesn't currently rewrite the dependency graph +;;; recursively, hence why it is not sufficient. + +(define %release-version (getenv "RELEASE_VERSION")) + +(define %release-file-name (getenv "RELEASE_TARBALL_FILENAME")) + +(unless %release-version + (error "RELEASE_VERSION environment variable is not set")) + +(unless %release-file-name + (error "RELEASE_TARBALL_FILENAME environment variable is not set")) + +;;; Add the source tarball to the store and retrieve its hash. The +;;; hash is useful to turn the origin record into a fixed-output +;;; derivation, which means the Jami packages will only get built once +;;; for a given source tarball. +(define %release-file-hash + (with-store store + (let ((source (add-to-store store (basename %release-file-name) #f + "sha256" %release-file-name))) + (bytevector->nix-base32-string (query-path-hash store source))))) + +(define %jami-sources/latest + (origin + (inherit (@@ (gnu packages jami) %jami-sources)) + (uri %release-file-name) + (sha256 %release-file-hash))) + +(define (with-latest-sources name) + (options->transformation + `((with-source . ,(format #f "~a@~a=~a" name + %release-version %release-file-name))))) + +(define libring/latest ((with-latest-sources "libring") libring)) + +(define with-libring/latest + (package-input-rewriting `((,libring . ,libring/latest)))) + +(define libringclient/latest ((with-latest-sources "libringclient") + (with-libring/latest libringclient))) + +(define libringclient/latest+libwrap + (package/inherit libringclient/latest + (arguments + (substitute-keyword-arguments (package-arguments libringclient/latest) + ((#:configure-flags flags ''()) + `(cons "-DENABLE_LIBWRAP=true" + (delete "-DENABLE_LIBWRAP=false" ,flags))))))) + +(define with-libringclient/latest+libwrap + (package-input-rewriting + `((,libringclient . ,libringclient/latest+libwrap)))) + +;;; Bundling the TLS certificates with Jami enables a fully +;;; functional, configuration-free experience, useful in the context +;;; of Guix packs. +(define jami-qt-with-certs + (package/inherit jami-qt + (inputs (cons `("nss-certs" ,nss-certs) + (package-inputs jami-qt))) + (native-inputs (cons `("python" ,python) + (package-native-inputs jami-qt))) + (arguments + (substitute-keyword-arguments (package-arguments jami-qt) + ((#:phases phases '%standard-phases) + `(modify-phases ,phases + (add-after 'qt-wrap 'wrap-ssl-cert-dir + (lambda* (#:key inputs outputs #:allow-other-keys) + (let* ((out (assoc-ref outputs "out")) + (wrapper (string-append out "/bin/jami-qt")) + (nss-certs (assoc-ref inputs "nss-certs"))) + (substitute* wrapper + (("^exec.*" exec-line) + (string-append "export SSL_CERT_DIR=" + nss-certs + "/etc/ssl/certs\n" + exec-line)))))))))))) + +(define jami-qt-with-certs/latest + ((with-latest-sources "jami-qt") + (with-libringclient/latest+libwrap jami-qt-with-certs))) + +(packages->manifest (list jami-qt-with-certs/latest)) diff --git a/guix/manifest.scm b/guix/manifest.scm index c20c580a8c87cd739bc08f44f204499c8fb4e36c..cf000c3bbda6105e2ee4298b9bbdd7d0181edd6d 100644 --- a/guix/manifest.scm +++ b/guix/manifest.scm @@ -94,8 +94,8 @@ "yasm" ;; For libringclient (LRC) and the Qt client. - "qtbase" - "qtbase:debug" + "qtbase@5" + "qtbase@5:debug" ;; Shared by the GNOME and Qt clients. "qrencode" diff --git a/packaging/rules/debian/jami-all.postinst b/packaging/rules/debian/jami-all.postinst index 572889d794edadc598c2e3660e5636839884ea36..e2267b10c0023e25f2e7964f2c242852c4673ab9 100755 --- a/packaging/rules/debian/jami-all.postinst +++ b/packaging/rules/debian/jami-all.postinst @@ -70,9 +70,6 @@ HUFCGSHO3/kzxSlkE1PBUX3IZ8PSFijyopBnWUhlSXuyRjte8OR7Fl/Rlf0IaOD1 -----END PGP PUBLIC KEY BLOCK-----" # System paths and generated variables -# In general: you will not need to modify these variables. -# WARNING: When modifying the paths, keep in mind that the corresponding -# postrm paths should be modified as well APT_FILE="/etc/apt/sources.list.d/jami-main.list" UPDATE_MANAGER_PATH="/etc/update-manager/release-upgrades.d/" JAMI_UPDATE_MANAGER_ID="jami-main" @@ -153,10 +150,9 @@ EOF # Additionally, if update manager is installed we inform it about # the repository so it doesn't get scrapped after system updates - if [ -d /etc/update-manager -a ! -f $UPDATE_MANAGER_CFG_PATH ] + if [ -d /etc/update-manager ] then mkdir -p $UPDATE_MANAGER_PATH - # FIXME As soon as we change the repo name use jami (this line +5) cat > $UPDATE_MANAGER_CFG_PATH <<EOF # Added by Jami to prevent disabling of Jami repository sources on # distribution release upgrade. diff --git a/scripts/deploy-packages.sh b/scripts/deploy-packages.sh index 3847840bb097638ea5ae9e4a9b200d4265e0221a..e6046f3444f897500ac4d12bd01c9178d4eb086e 100755 --- a/scripts/deploy-packages.sh +++ b/scripts/deploy-packages.sh @@ -273,19 +273,14 @@ function deploy() function package() { - if [[ "${DISTRIBUTION:0:6}" == "debian" \ - || "${DISTRIBUTION:0:6}" == "ubuntu" \ - || "${DISTRIBUTION:0:8}" == "raspbian" ]]; then + if [[ $DISTRIBUTION =~ debian|ubuntu|raspbian|guix-deb-pack ]]; then package_deb - elif [[ "${DISTRIBUTION:0:6}" == "fedora" \ - || "${DISTRIBUTION:0:4}" == "rhel" \ - || "${DISTRIBUTION:0:13}" == "opensuse-leap" \ - || "${DISTRIBUTION:0:19}" == "opensuse-tumbleweed" ]]; then + elif [[ $DISTRIBUTION =~ fedora|rhel|opensuse ]]; then package_rpm - elif [[ "${DISTRIBUTION:0:4}" == "snap" ]]; then + elif [[ $DISTRIBUTION =~ snap ]]; then package_snap else - echo "ERROR: Distribution '${DISTRIBUTION}' is unsupported" + echo "error: Distribution \"$DISTRIBUTION\" is not supported" fi }