From 32d182be92bd1a279ddd8daae48cf09373748e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Fri, 29 Sep 2023 16:39:21 +0200 Subject: [PATCH] Add APT repository preparation and upload scripts Build an apt/deb repository on builds and store locally on the build server. Also push it to development infra instantly. Push to staging if it's a release. And store locally for manual push to production later --- ci/buildserver-build.sh | 18 ++++++++ ci/buildserver-config.sh | 18 ++++++++ ci/prepare-apt-repository.sh | 59 +++++++++++++++++++++++++ ci/publish-linux-repositories.sh | 76 ++++++++++++++++++++++++++++++++ 4 files changed, 171 insertions(+) create mode 100644 ci/buildserver-config.sh create mode 100755 ci/prepare-apt-repository.sh create mode 100755 ci/publish-linux-repositories.sh diff --git a/ci/buildserver-build.sh b/ci/buildserver-build.sh index a8f17460e7d6..b8a0807d77ff 100755 --- a/ci/buildserver-build.sh +++ b/ci/buildserver-build.sh @@ -21,6 +21,8 @@ UPLOAD_DIR="$SCRIPT_DIR/upload" BRANCHES_TO_BUILD=("origin/main") +source "$SCRIPT_DIR/buildserver-config.sh" + # Ask for the passphrase to the signing keys case "$(uname -s)" in Darwin*|MINGW*|MSYS_NT*) @@ -42,6 +44,21 @@ case "$(uname -s)" in ;; esac +function publish_linux_repositories { + local artifact_dir=$1 + local version=$2 + local deb_repo_dir="$SCRIPT_DIR/deb/$version" + + "$SCRIPT_DIR/prepare-apt-repository.sh" "$artifact_dir" "$version" "$deb_repo_dir" + + "$SCRIPT_DIR/publish-linux-repositories.sh" --dev "$version" "$deb_repo_dir" + # If this is a release build, also push to staging. + # Publishing to production is done manually. + if [[ $version != *"-dev-"* ]]; then + "$SCRIPT_DIR/publish-linux-repositories.sh" --staging "$version" "$deb_repo_dir" + fi +} + # Uploads whatever matches the first argument to the Linux build server function upload_sftp { echo "Uploading Mullvad VPN installers to app-build-linux:upload/" @@ -210,6 +227,7 @@ function build_ref { fi fi + publish_linux_repositories "$artifact_dir" "$version" (cd "$artifact_dir" && upload "$version") || return 1 # shellcheck disable=SC2216 yes | rm -r "$artifact_dir" diff --git a/ci/buildserver-config.sh b/ci/buildserver-config.sh new file mode 100644 index 000000000000..eef67d84d63b --- /dev/null +++ b/ci/buildserver-config.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# +# Buildserver configuration. Runtime values are defined here instead of +# the scripts where they are used. + +# Which gpg key to sign things with +export CODE_SIGNING_KEY_FINGERPRINT="A1198702FC3E0A09A9AE5B75D5A1D4F266DE8DDF" + +# Debian codenames we support. +SUPPORTED_DEB_CODENAMES=("sid" "testing" "bookworm" "bullseye") +# Ubuntu codenames we support (latest two LTS + latest non-LTS) +SUPPORTED_DEB_CODENAMES+=("jammy" "focal" "lunar") +export SUPPORTED_DEB_CODENAMES + +# Servers to upload Linux deb/rpm repositories to +export DEV_LINUX_REPOSITORY_SERVERS=("se-got-cdn-001.devmole.eu" "se-got-cdn-002.devmole.eu") +export STAGING_LINUX_REPOSITORY_SERVERS=("se-got-cdn-001.stagemole.eu" "se-got-cdn-002.stagemole.eu") +export PRODUCTION_LINUX_REPOSITORY_SERVERS=("se-got-cdn-111.mullvad.net" "se-mma-cdn-101.mullvad.net") diff --git a/ci/prepare-apt-repository.sh b/ci/prepare-apt-repository.sh new file mode 100755 index 000000000000..784a6c92f87d --- /dev/null +++ b/ci/prepare-apt-repository.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# +# Usage: ./prepare-apt-repository.sh +# +# Will create a deb repository in and add all .deb files from +# matching to the repository. + +set -eu + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source "$SCRIPT_DIR/buildserver-config.sh" + +artifact_dir=$1 +version=$2 +repo_dir=$3 + +function generate_repository_configuration { + local codename=$1 + + echo -e "Origin: repository.mullvad.net +Label: Mullvad apt repository +Description: Mullvad package repository for Debian/Ubuntu +Codename: $codename +Architectures: amd64 arm64 +Components: main +SignWith: $CODE_SIGNING_KEY_FINGERPRINT" +} + +function generate_deb_distributions_content { + local distributions="" + for codename in "${SUPPORTED_DEB_CODENAMES[@]}"; do + distributions+=$(generate_repository_configuration "$codename")$'\n'$'\n' + distributions+=$(generate_repository_configuration "$codename"-testing)$'\n'$'\n' + done + echo "$distributions" +} + +function add_deb_to_repo { + local deb_path=$1 + local codename=$2 + echo "Adding $deb_path to repository $codename" + reprepro -V --basedir "$repo_dir" --component main includedeb "$codename" "$deb_path" +} + +echo "Generating deb repository into $repo_dir/" +mkdir -p "$repo_dir/conf" + +echo "Writing repository configuration to $repo_dir/conf/distributions" +generate_deb_distributions_content > "$repo_dir/conf/distributions" +echo "" + +for deb_path in "$artifact_dir"/MullvadVPN-"$version"*.deb; do + for codename in "${SUPPORTED_DEB_CODENAMES[@]}"; do + add_deb_to_repo "$deb_path" "$codename" + echo "" + done + echo "" +done diff --git a/ci/publish-linux-repositories.sh b/ci/publish-linux-repositories.sh new file mode 100755 index 000000000000..a87c35959aee --- /dev/null +++ b/ci/publish-linux-repositories.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +# +# Usage: ./publish-linux-repositories.sh [--production/--staging] +# +# Rsyncs a locally prepared and stored apt repository to the dev/staging/production +# repository servers. + +set -eu + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source "$SCRIPT_DIR/buildserver-config.sh" + +while [ "$#" -gt 0 ]; do + case "$1" in + "--production") + repository_servers=("${PRODUCTION_LINUX_REPOSITORY_SERVERS[@]}") + ;; + "--staging") + repository_servers=("${STAGING_LINUX_REPOSITORY_SERVERS[@]}") + ;; + "--dev") + repository_servers=("${DEV_LINUX_REPOSITORY_SERVERS[@]}") + ;; + -*) + echo "Unknown option \"$1\"" >&2 + exit 1 + ;; + *) + if [[ -z ${version+x} ]]; then + version=$1 + elif [[ -z ${deb_repo_dir+x} ]]; then + deb_repo_dir=$1 + else + echo "Too many arguments" >&2 + exit 1 + fi + ;; + esac + shift +done + +if [[ -z ${version+x} ]]; then + echo "Please give the release version as an argument to this script" >&2 + exit 1 +fi +if [[ -z ${deb_repo_dir+x} ]]; then + echo "Please specify the deb repository directory as an argument to this script" >&2 + exit 1 +fi +if [[ -z ${repository_servers+x} ]]; then + echo "Pass either --dev, --staging or --production to select target servers" >&2 + exit 1 +fi + +function rsync_repo { + local local_repo_dir=$1 + local remote_repo_dir=$2 + + for server in "${repository_servers[@]}"; do + echo "Syncing to $server:$remote_repo_dir" + rsync -av --delete --mkpath --rsh='ssh -p 1122' \ + "$local_repo_dir"/ \ + build@"$server":"$remote_repo_dir" + done +} + +if [[ ! -d "$deb_repo_dir" ]]; then + echo "$deb_repo_dir does not exist" >&2 + exit 1 +fi + +rsync_repo "$deb_repo_dir" "deb/beta" +if [[ $version != *"-beta"* ]]; then + rsync_repo "$deb_repo_dir" "deb/stable" +fi