diff options
| author | David Lönnhager <david.l@mullvad.net> | 2025-03-20 15:09:41 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2025-03-20 15:09:41 +0100 |
| commit | f9c44d63533bcaaa91435b92abec1ba8cea25925 (patch) | |
| tree | d10bc627761d75f73a7dd73f70a671f3df9daf9c | |
| parent | e5b0413051697ef6bfec7518b05a07537dbc31f5 (diff) | |
| parent | 45c92e37b9fd0c1f40e817d49b5de19e4922aa39 (diff) | |
| download | mullvadvpn-f9c44d63533bcaaa91435b92abec1ba8cea25925.tar.xz mullvadvpn-f9c44d63533bcaaa91435b92abec1ba8cea25925.zip | |
Merge branch 'add-upload-option-build-sh'
| -rw-r--r-- | Cargo.lock | 2 | ||||
| -rwxr-xr-x | ci/buildserver-upload.sh | 29 | ||||
| -rw-r--r-- | installer-downloader/Cargo.toml | 3 | ||||
| -rwxr-xr-x | installer-downloader/build.sh | 98 |
4 files changed, 117 insertions, 15 deletions
diff --git a/Cargo.lock b/Cargo.lock index 5d4adf2281..dbf52a96cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2022,7 +2022,7 @@ dependencies = [ [[package]] name = "installer-downloader" -version = "1.0.0" +version = "0.1.0" dependencies = [ "anyhow", "async-trait", diff --git a/ci/buildserver-upload.sh b/ci/buildserver-upload.sh index fde7c192b8..f09ae11ea0 100755 --- a/ci/buildserver-upload.sh +++ b/ci/buildserver-upload.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -eu -shopt -s nullglob +shopt -s nullglob globstar CODE_SIGNING_KEY_FINGERPRINT="A1198702FC3E0A09A9AE5B75D5A1D4F266DE8DDF" @@ -23,35 +23,42 @@ function rsync_upload { while true; do sleep 10 - for checksums_path in *.sha256; do + for checksums_path in **/*.sha256; do sleep 1 + checksums_dir=$(dirname "$checksums_path") + checksums_filename=$(basename "$checksums_path") + # Parse the platform name and version out of the filename of the checksums file. - platform="$(echo "$checksums_path" | cut -d + -f 1)" - version="$(echo "$checksums_path" | cut -d + -f 3,4 | sed 's/\.sha256//')" - if ! sha256sum --quiet -c "$checksums_path"; then + platform="$(echo "$checksums_filename" | cut -d + -f 1)" + version="$(echo "$checksums_filename" | cut -d + -f 3,4 | sed 's/\.sha256//')" + if ! (cd "$checksums_dir" && sha256sum --quiet -c "$checksums_filename"); then echo "Failed to verify checksums for $version" continue fi - if [[ $version == *"-dev-"* ]]; then + if [[ "$platform" == "installer-downloader" ]]; then + upload_path="desktop/installer-downloader" + elif [[ $version == *"-dev-"* ]]; then upload_path="$platform/builds" else upload_path="$platform/releases" fi - files=$(awk '{print $2}' < "$checksums_path") - for file in $files; do + readarray -t files < <(cut -f 2- -d ' ' < "$checksums_path" | sed 's/^\*\(.*\)/\1/') + for filename in "${files[@]}"; do + file="$checksums_dir/$filename" + file_upload_dir="$upload_path/$version" - if [[ $platform == "desktop" && ! $file == MullvadVPN-* ]]; then + if [[ $platform == "desktop" && ! $filename == MullvadVPN-* ]]; then file_upload_dir="$file_upload_dir/additional-files" - elif [[ $platform == "android" && ! $file =~ MullvadVPN-"$version"(.apk|.play.apk|.play.aab) ]]; then + elif [[ $platform == "android" && ! $filename =~ MullvadVPN-"$version"(.apk|.play.apk|.play.aab) ]]; then file_upload_dir="$file_upload_dir/additional-files" fi rsync_upload "$file" "$file_upload_dir/" || continue - if [[ $file == MullvadVPN-* ]]; then + if [[ $filename == MullvadVPN-* || $filename == Install* ]]; then rm -f "$file.asc" gpg -u $CODE_SIGNING_KEY_FINGERPRINT --pinentry-mode loopback --sign --armor --detach-sign "$file" rsync_upload "$file.asc" "$file_upload_dir/" || continue diff --git a/installer-downloader/Cargo.toml b/installer-downloader/Cargo.toml index b88ed18a0c..98a6182b86 100644 --- a/installer-downloader/Cargo.toml +++ b/installer-downloader/Cargo.toml @@ -1,7 +1,8 @@ [package] name = "installer-downloader" description = "A secure minimal web installer for the Mullvad app" -version = "1.0.0" +version = "0.1.0" +publish = false authors.workspace = true repository.workspace = true license.workspace = true diff --git a/installer-downloader/build.sh b/installer-downloader/build.sh index efa060ae22..08a4d28d74 100755 --- a/installer-downloader/build.sh +++ b/installer-downloader/build.sh @@ -28,15 +28,19 @@ CARGO_TARGET_DIR=${CARGO_TARGET_DIR:-"../target"} export CARGO_TARGET_DIR # Temporary build directory -BUILD_DIR="./build" +BUILD_DIR="$SCRIPT_DIR/build" # Successfully built (and signed) artifacts -DIST_DIR="../dist" +DIST_DIR="$SCRIPT_DIR/../dist" BUNDLE_NAME="MullvadVPNInstaller" BUNDLE_ID="net.mullvad.$BUNDLE_NAME" FILENAME="Install Mullvad VPN" +# When --upload is passed, git verify-tag looks for a signed tag with the prefix below. +# The signed tag must be named $TAG_PREFIX/<version>. +TAG_PREFIX="desktop/installer-downloader/" + rm -rf "$BUILD_DIR" mkdir -p "$BUILD_DIR" @@ -45,6 +49,9 @@ mkdir -p "$DIST_DIR" # Whether to sign and notarized produced binaries SIGN="false" +# Whether to upload signed binaries +UPLOAD="false" + # Temporary keychain to store the .p12 in. # This is automatically created/replaced when signing on macOS. SIGN_KEYCHAIN_PATH="$HOME/Library/Keychains/mv-metadata-keychain-db" @@ -55,6 +62,9 @@ while [[ "$#" -gt 0 ]]; do --sign) SIGN="true" ;; + --upload) + UPLOAD="true" + ;; *) log_error "Unknown parameter: $1" exit 1 @@ -63,6 +73,11 @@ while [[ "$#" -gt 0 ]]; do shift done +if [[ "$UPLOAD" == "true" && "$SIGN" != "true" ]]; then + log_error "'--upload' requires '--sign' to be specified" + exit 1 +fi + # Check that we have the correct environment set for signing function assert_can_sign { if [[ "$(uname -s)" == "Darwin" ]]; then @@ -305,6 +320,76 @@ function dist_windows_app { mv "$BUILD_DIR/$FILENAME.exe" "$DIST_DIR/" } +# Upload whatever matches the first argument to the Linux build server +# Arguments: +# - local file +# - version +function upload_sftp { + local local_path=$1 + local version=$2 + echo "Uploading \"$local_path\" to app-build-linux:upload/installer-downloader/$version" + sftp app-build-linux <<EOF +mkdir upload/installer-downloader +mkdir upload/installer-downloader/$version +chmod 770 upload/installer-downloader +chmod 770 upload/installer-downloader/$version +cd upload/installer-downloader/$version +put "$local_path" +bye +EOF +} + +# Upload latest build and checksum in the dist directory to Linux build server +# The artifacts MUST have been built already +# The working directory MUST be $DIST_DIR +# +# Arguments: +# - version +function upload { + local version=$1 + local files=( "$FILENAME."* ) + + local checksums_path + checksums_path="installer-downloader+$(hostname)+$version.sha256" + + sha256sum "${files[@]}" > "$checksums_path" + + for file in "${files[@]}"; do + upload_sftp "$file" "$version" || return 1 + done + upload_sftp "$checksums_path" "$version" || return 1 +} + +# Check if the current commit has a signed tag +# +# Arguments: +# - version +function verify_version_tag { + local version=$1 + + local expect_tag="${TAG_PREFIX}${version}" + log_info "Current commit must have tag: $expect_tag" + + local tag + set +e + tag=$(git describe --exact-match --tags) + local describe_exit=$? + set -e + + if [[ $describe_exit -ne 0 ]]; then + log_error "'git describe' failed for the current commit (no tag?). Expected tag $expect_tag" + exit 1 + fi + + if [[ "$tag" != "$expect_tag" ]]; then + log_error "Unexpected tag found for current commit. Expected $expect_tag. Found: $tag" + exit 1 + fi + + log_info "Verifying tag $tag..." + git verify-tag "$tag" +} + function main { if [[ "$SIGN" != "false" ]]; then assert_can_sign @@ -327,6 +412,15 @@ function main { build_executable dist_windows_app fi + + if [[ "$UPLOAD" == "true" ]]; then + local version + version=$(product_version) + + verify_version_tag "$version" + + (cd "$DIST_DIR" && upload "$version") || return 1 + fi } main |
