aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>2021-12-30 00:52:26 +0100
committerDenis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>2021-12-30 02:33:47 +0100
commitfdac4cf8364c02760312a8c9650de24dba0007e5 (patch)
tree0dd858e0a277c6c9b84bca06e6edf806eb0a73f3
parent82bfee48f074c496347e77e277d63cd1c7c1155a (diff)
downloadvendor_replicant-release-scripts-fdac4cf8364c02760312a8c9650de24dba0007e5.tar.gz
vendor_replicant-release-scripts-fdac4cf8364c02760312a8c9650de24dba0007e5.tar.bz2
vendor_replicant-release-scripts-fdac4cf8364c02760312a8c9650de24dba0007e5.zip
Add script to copy the release patches to a remote build machine
This script makes a patch out of the latest commit from the following repositories: - ../vendor_replicant-release-scripts - ../vendor_replicant - ../manifest it then apply them inside the respective directories inside the replicant directory on another machine, with SSH and Rsync. When doing a release we typically need to change the Replicant version, and so that requires to add 1 patch to each of the repositories mentioned above. However in some cases, the Replicant directory is on another computer. This is for instance the case for people working on their laptop and building Replicant on another machine. The release process already takes care of that situation but it required to manually apply patches on the remote builder before tagging the source code. And the Replicant 6.0 0004 RC6 release failed because some patches were missing in the released (and signed) source code. So it's better to automate things to avoid forgetting patches for the next releases. Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
-rwxr-xr-xbuilder-patches.sh262
1 files changed, 262 insertions, 0 deletions
diff --git a/builder-patches.sh b/builder-patches.sh
new file mode 100755
index 0000000..4934a56
--- /dev/null
+++ b/builder-patches.sh
@@ -0,0 +1,262 @@
+#!/usr/bin/env sh
+# Copyright (C) 2021 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero 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 Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+# During the release process, we need patches in the manifest, in
+# vendor/replicant and vendor/replicant-release-scripts to change the
+# Replicant revision.
+
+# When the person who does the release uses a separate computer to
+# build Replicant, in some cases, it makes sense to develop the patch
+# locally and push them to the remote.
+
+local_repositories="\
+ ../vendor_replicant-release-scripts \
+ ../vendor_replicant \
+ ../manifest \
+"
+
+local_tmpdir="$(mktemp -d)"
+
+usage()
+{
+ echo "Usage:"
+ echo "$0 <machine> <replicant_dir> apply" \
+ " # Apply patches to the remote git repositories"
+ echo "$0 <machine> <replicant_dir> remove" \
+ "# Remove the last commit from the remote git repositories"
+ echo "$0 <machine> <replicant_dir> reset" \
+ " # run git reset --hard on the remote git repositories"
+ echo "$0 <machine> <replicant_dir> sync" \
+ " # run repo sync on the remote git repositories"
+ echo ""
+ echo "Remote repositories:"
+ for repository in ${local_repositories} ; do
+ echo "- $(basename ${repository} | sed 's#_#/#g')/"
+ done
+ exit 64 # EX_USAGE in sysexits.h
+}
+
+append_raw()
+{
+ variable="$1"
+ shift 1
+ values="$@"
+
+ if [ -z "$(eval echo \$${variable})" ] ; then
+ eval "${variable}=\"${values}\""
+ else
+ eval "${variable}=\"\$${variable}${values}\""
+ fi
+}
+
+append()
+{
+ variable="$1"
+ shift 1
+ values="$@"
+
+ if [ -z "$(eval echo \$${variable})" ] ; then
+ eval "${variable}=\"${values}\""
+ else
+ eval "${variable}=\"\$${variable} ${values}\""
+ fi
+}
+
+remote_commands=""
+queue_remote_commands()
+{
+ commands="$@"
+
+ if [ -z "${remote_commands}" ] ; then
+ append_raw remote_commands "${commands}"
+ else
+ append_raw remote_commands ";${commands}"
+ fi
+}
+
+apply_remote_commands()
+{
+ machine="$1"
+
+ ssh "${machine}" "${remote_commands}"
+ remote_commands=""
+}
+
+patches_for_remote=""
+queue_patches_for_remote()
+{
+ patches="$@"
+
+ if [ -z "${patches_for_remote}" ] ; then
+ append patches_for_remote "${patches}"
+ else
+ append patches_for_remote ";${patches}"
+ fi
+}
+
+send_and_apply_patches_to_remote()
+{
+ machine="$1"
+ replicant_dir="$2"
+
+ remote_tmpdir="$(mktemp -d --dry-run)"
+
+ for patch in ${patches_for_remote} ; do
+ append remote_tmpsubdirs "${remote_tmpdir}/$(dirname ${patch})"
+ append local_patches_paths "${local_tmpdir}/./${patch}"
+ queue_remote_commands \
+ "cd;cd ${replicant_dir}/$(dirname ${patch} | sed 's#_#/#g')"
+ # TODO: check if the patch is already applied
+ queue_remote_commands "git am ${remote_tmpdir}/${patch}"
+ done
+ queue_remove_remote_temporary_files "${remote_tmpdir}"
+
+ rsync -Rrav ${local_patches_paths} "${machine}:${remote_tmpdir}/"
+ apply_remote_commands "${machine}"
+ patches_for_remote=""
+}
+
+remove_local_temporary_files()
+{
+ tmpdirs="$@"
+
+ for tmpdir in ${tmpdirs} ; do
+ for patch in ${patches} ; do
+ rm -f "${tmpdir}/${patch}"
+ done
+
+ for repository_dir in ${repositories_dirs} ; do
+ rmdir "${tmpdir}/${repository_dir}/"
+ done
+
+ rmdir "${tmpdir}/"
+ done
+}
+
+queue_remove_remote_temporary_files()
+{
+ tmpdirs="$@"
+
+ for tmpdir in ${tmpdirs} ; do
+ for patch in ${patches} ; do
+ queue_remote_commands "rm -f ${tmpdir}/${patch}"
+ done
+
+ for repository_dir in ${repositories_dirs} ; do
+ queue_remote_commands \
+ "rmdir ${tmpdir}/${repository_dir}/"
+ done
+
+ queue_remote_commands "rmdir ${tmpdir}/"
+ done
+}
+
+apply_patches_to_remote()
+{
+ machine="$1"
+ replicant_dir="$2"
+
+ patches=""
+ repositories_dirs=""
+
+ for repository in ${local_repositories} ; do
+ patch="$(git -C ${repository} format-patch -1)"
+ destdir="${local_tmpdir}/$(basename ${repository})"
+
+ mkdir -p "${destdir}/"
+ mv -f "${repository}/${patch}" "${destdir}/"
+
+ append "patches" "$(basename ${repository})/${patch}"
+ append "repositories_dirs" "$(basename ${repository})"
+ done
+
+ queue_patches_for_remote "${patches}"
+ send_and_apply_patches_to_remote "${machine}" "${replicant_dir}"
+
+ remove_local_temporary_files "${local_tmpdir}"
+}
+
+apply_git_reset_hard_to_remote()
+{
+ machine="$1"
+ replicant_dir="$2"
+
+ patches=""
+ repositories_dirs=""
+
+ for repository in ${local_repositories} ; do
+ remote_git_dir="$(echo $(basename ${repository}) \
+ | sed 's#_#/#g')"
+ queue_remote_commands "cd;cd ${replicant_dir}"
+ queue_remote_commands "git -C ${remote_git_dir} reset --hard"
+ done
+ apply_remote_commands "${machine}"
+}
+
+remove_top_patches_from_remote()
+{
+ machine="$1"
+ replicant_dir="$2"
+
+ for repository in ${local_repositories} ; do
+ remote_git_dir="$(echo $(basename ${repository}) \
+ | sed 's#_#/#g')"
+ queue_remote_commands "cd;cd ${replicant_dir}"
+ queue_remote_commands \
+ "GIT_EDITOR='echo noop > ' \
+ git -C ${remote_git_dir} rebase -i HEAD~1"
+ done
+ apply_remote_commands "${machine}"
+}
+
+repo_sync_remote_repositories()
+{
+ machine="$1"
+ replicant_dir="$2"
+
+ for repository in ${local_repositories} ; do
+ append \
+ "remote_repositories_paths" \
+ "$(echo $(basename ${repository})| sed 's#_#/#g')"
+ done
+
+ queue_remote_commands "cd;cd ${replicant_dir}"
+ # When using repo sync, repo update itself automatically. But
+ # the updated repo doesn't work anymore withTrisquel 9 python3
+ # version.To workaround that issue, Replicant released a
+ # tarball (built with Guix) that includes a newer repo and all
+ # its dependencies (including python). And to work properly we
+ # need to source a script that setups the environment
+ # variables to make that repo work.
+ queue_remote_commands \
+ "[ -f /usr/local/bin/repo-env.sh ] && \
+ source /usr/local/bin/repo-env.sh"
+ queue_remote_commands "repo sync ${remote_repositories_paths}"
+
+ apply_remote_commands "${machine}"
+}
+
+if [ $# -ne 3 ] ; then
+ usage
+elif [ "$3" = "apply" ] ; then
+ apply_patches_to_remote "$1" "$2"
+elif [ "$3" = "remove" ] ; then
+ remove_top_patches_from_remote "$1" "$2"
+elif [ "$3" = "reset" ] ; then
+ apply_git_reset_hard_to_remote "$1" "$2"
+elif [ "$3" = "sync" ] ; then
+ repo_sync_remote_repositories "$1" "$2"
+fi