summaryrefslogtreecommitdiffhomepage
path: root/ci/buildserver-build-android.sh
blob: 59381410b21f3361486e31307e8c7485ca843675 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env bash

# # Setup instructions before this script will work
#
# * Follow the instructions in ../README.md
# * Import and trust the GPG keys of everyone who the build server should trust code from
# * Ensure that the machine running this script is allowed to upload to releases.mullvad.net.

set -eu
shopt -s nullglob

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
BUILD_DIR="$SCRIPT_DIR/mullvadvpn-app"
LAST_BUILT_DIR="$SCRIPT_DIR/last-built"
UPLOAD_DIR="/home/upload/upload"
ANDROID_CREDENTIALS_DIR="$SCRIPT_DIR/credentials-android"

BRANCHES_TO_BUILD=("origin/main")
TAG_PATTERN_TO_BUILD="^android/"

function upload {
    version=$1

    files=( * )
    checksums_path="android+$(hostname)+$version.sha256"
    sha256sum "${files[@]}" > "$checksums_path"

    mv "${files[@]}" "$checksums_path" "$UPLOAD_DIR/"
}

function run_in_linux_container {
    ./building/container-run.sh linux "$@"
}

# Builds the app artifacts and move them to the passed in `artifact_dir`.
# Must pass `artifact_dir` to show where to move the built artifacts.
function build {
    ANDROID_CREDENTIALS_DIR=$ANDROID_CREDENTIALS_DIR \
        CARGO_TARGET_VOLUME_NAME="cargo-target-android" \
        CARGO_REGISTRY_VOLUME_NAME="cargo-registry-android" \
        ./building/containerized-build.sh android --app-bundle --enable-play-publishing || return 1

    mv dist/*.{aab,apk} "$artifact_dir" || return 1
}

# Checks out the passed git reference passed to the working directory.
# Returns an error code if the commit/tag at `ref` is not properly signed.
function checkout_ref {
    ref=$1
    if [[ $ref == "refs/tags/"* ]] && ! git verify-tag "$ref"; then
        echo "!!!"
        echo "[#] $ref is a tag, but it failed GPG verification!"
        echo "!!!"
        return 1
    elif [[ $ref == "refs/remotes/"* ]] && ! git verify-commit "$current_hash"; then
        echo "!!!"
        echo "[#] $ref is a branch, but it failed GPG verification!"
        echo "!!!"
        return 1
    fi

    # Clean our working dir and check out the code we want to build
    rm -r dist/ 2&>/dev/null || true
    git reset --hard
    git checkout "$ref"
    git submodule update
    git submodule update --init wireguard-go-rs/libwg/wireguard-go || true
    git clean -df
}

function build_ref {
    ref=$1
    tag=${2:-""}

    current_hash="$(git rev-parse "$ref^{commit}")"
    if [ -f "$LAST_BUILT_DIR/$current_hash" ]; then
        # This commit has already been built
        return 0
    fi

    echo ""
    echo "[#] $ref: $current_hash, building new packages."
    echo ""

    checkout_ref "$ref" || return 1

    # podman appends a trailing carriage return to the output. So we use `tr` to strip it
    local version=""
    version="$(run_in_linux_container 'stty -echo && cargo run -q --bin mullvad-version versionName' | tr -d "\r" || return 1)"

    local artifact_dir="dist/$version"
    mkdir -p "$artifact_dir"

    echo "Building Android app"
    artifact_dir=$artifact_dir build || return 1

    # If there is a tag for this commit then we append that to the produced artifacts
    # A version suffix should only be created if there is a tag for this commit and it is not a release build
    if [[ -n "$tag" && $version == *"-dev-"* ]]; then
        # Replace disallowed version characters in the tag with hyphens
        version_suffix="+${tag//[^0-9a-z_-]/-}"
        # Will only match paths that include *-dev-* which means release builds will not be included
        # Pipes all matching names and their new name to mv
        pushd "$artifact_dir"
        for original_file in MullvadVPN-*{.apk,.aab}; do
            new_file=$(echo "$original_file" | sed -nE "s/^(MullvadVPN-$version)(.*\.apk|.*\.aab)$/\1$version_suffix\2/p")
            mv "$original_file" "$new_file"
        done
        popd

        version="$version$version_suffix"
    fi

    (cd "$artifact_dir" && upload "$version") || return 1
    # shellcheck disable=SC2216
    yes | rm -r "$artifact_dir"

    touch "$LAST_BUILT_DIR/$current_hash"

    echo ""
    echo "Successfully finished building $version at $(date)"
    echo ""
}

cd "$BUILD_DIR"

while true; do
    # Delete all tags. So when fetching we only get the ones existing on the remote
    git tag | xargs git tag -d > /dev/null

    git fetch --prune --tags 2> /dev/null || continue

    # Only build android/* tags.
    # Tags can't include spaces so SC2207 isn't a problem here
    # shellcheck disable=SC2207
    tags=( $(git tag | grep "$TAG_PATTERN_TO_BUILD") )

    for tag in "${tags[@]}"; do
        build_ref "refs/tags/$tag" "$tag" || echo "Failed to build tag $tag"
    done

    for branch in "${BRANCHES_TO_BUILD[@]}"; do
        build_ref "refs/remotes/$branch" || echo "Failed to build branch $tag"
    done

    sleep 240
done