|
| 1 | +#!/bin/bash |
| 2 | +set -eu |
| 3 | + |
| 4 | +check_command() { |
| 5 | + command -v "$1" >/dev/null 2>&1 |
| 6 | +} |
| 7 | + |
| 8 | +if ! check_command jq; then |
| 9 | + echo "jq not found. Install it from https://stedolan.github.io/jq" |
| 10 | + exit 1 |
| 11 | +fi |
| 12 | + |
| 13 | +OS_NAME=$(echo "$RUNNER_OS" | awk '{print tolower($0)}') |
| 14 | +ARCH_NAME=$(echo "$RUNNER_ARCH" | awk '{print tolower($0)}') |
| 15 | +MANIFEST_BASE_URL="${FLUTTER_STORAGE_BASE_URL:-https://storage.googleapis.com}/flutter_infra_release/releases" |
| 16 | +MANIFEST_JSON_PATH="releases_$OS_NAME.json" |
| 17 | +MANIFEST_URL="$MANIFEST_BASE_URL/$MANIFEST_JSON_PATH" |
| 18 | + |
| 19 | +filter_by_channel() { |
| 20 | + jq --arg channel "$1" '[.releases[] | select($channel == "any" or .channel == $channel)]' |
| 21 | +} |
| 22 | + |
| 23 | +filter_by_arch() { |
| 24 | + jq --arg arch "$1" '[.[] | select(.dart_sdk_arch == $arch or ($arch == "x64" and (has("dart_sdk_arch") | not)))]' |
| 25 | +} |
| 26 | + |
| 27 | +filter_by_version() { |
| 28 | + jq --arg version "$1" '.[].version |= gsub("^v"; "") | (if $version == "any" then .[0] else (map(select(.version == $version or (.version | startswith(($version | sub("\\.x$"; "")) + ".")) and .version != $version)) | .[0]) end)' |
| 29 | +} |
| 30 | + |
| 31 | +not_found_error() { |
| 32 | + echo "Unable to determine Flutter version for channel: $1 version: $2 architecture: $3" |
| 33 | +} |
| 34 | + |
| 35 | +transform_path() { |
| 36 | + if [ "$OS_NAME" = windows ]; then |
| 37 | + echo "$1" | sed -e 's/^\///' -e 's/\//\\/g' |
| 38 | + else |
| 39 | + echo "$1" |
| 40 | + fi |
| 41 | +} |
| 42 | + |
| 43 | +download_archive() { |
| 44 | + archive_url="$MANIFEST_BASE_URL/$1" |
| 45 | + archive_name=$(basename "$1") |
| 46 | + archive_local="$RUNNER_TEMP/$archive_name" |
| 47 | + |
| 48 | + curl --connect-timeout 15 --retry 5 "$archive_url" >"$archive_local" |
| 49 | + |
| 50 | + mkdir -p "$2" |
| 51 | + |
| 52 | + case "$archive_name" in |
| 53 | + *.zip) |
| 54 | + EXTRACT_PATH="$RUNNER_TEMP/_unzip_temp" |
| 55 | + unzip -q -o "$archive_local" -d "$EXTRACT_PATH" |
| 56 | + # Remove the folder again so that the move command can do a simple rename |
| 57 | + # instead of moving the content into the target folder. |
| 58 | + # This is a little bit of a hack since the "mv --no-target-directory" |
| 59 | + # linux option is not available here |
| 60 | + rm -r "$2" |
| 61 | + mv "$EXTRACT_PATH"/flutter "$2" |
| 62 | + rm -r "$EXTRACT_PATH" |
| 63 | + ;; |
| 64 | + *) |
| 65 | + tar xf "$archive_local" -C "$2" --strip-components=1 |
| 66 | + ;; |
| 67 | + esac |
| 68 | + |
| 69 | + rm "$archive_local" |
| 70 | +} |
| 71 | + |
| 72 | +CACHE_PATH="" |
| 73 | +CACHE_KEY="" |
| 74 | +PUB_CACHE_PATH="" |
| 75 | +PUB_CACHE_KEY="" |
| 76 | +PRINT_ONLY="" |
| 77 | +TEST_MODE=false |
| 78 | +ARCH="" |
| 79 | +VERSION="" |
| 80 | +VERSION_FILE="" |
| 81 | +GIT_SOURCE="" |
| 82 | + |
| 83 | +while getopts 'tc:k:d:l:pa:n:f:g:' flag; do |
| 84 | + case "$flag" in |
| 85 | + c) CACHE_PATH="$OPTARG" ;; |
| 86 | + k) CACHE_KEY="$OPTARG" ;; |
| 87 | + d) PUB_CACHE_PATH="$OPTARG" ;; |
| 88 | + l) PUB_CACHE_KEY="$OPTARG" ;; |
| 89 | + p) PRINT_ONLY=true ;; |
| 90 | + t) TEST_MODE=true ;; |
| 91 | + a) ARCH="$(echo "$OPTARG" | awk '{print tolower($0)}')" ;; |
| 92 | + n) VERSION="$OPTARG" ;; |
| 93 | + f) |
| 94 | + VERSION_FILE="$OPTARG" |
| 95 | + if [ -n "$VERSION_FILE" ] && ! check_command yq; then |
| 96 | + echo "yq not found. Install it from https://mikefarah.gitbook.io/yq" |
| 97 | + exit 1 |
| 98 | + fi |
| 99 | + ;; |
| 100 | + g) GIT_SOURCE="$OPTARG" ;; |
| 101 | + ?) exit 2 ;; |
| 102 | + esac |
| 103 | +done |
| 104 | + |
| 105 | +[ -z "$ARCH" ] && ARCH="$ARCH_NAME" |
| 106 | + |
| 107 | +if [ -n "$VERSION_FILE" ]; then |
| 108 | + if [ -n "$VERSION" ]; then |
| 109 | + echo "Cannot specify both a version and a version file" |
| 110 | + exit 1 |
| 111 | + fi |
| 112 | + |
| 113 | + VERSION="$(yq eval '.environment.flutter' "$VERSION_FILE")" |
| 114 | +fi |
| 115 | + |
| 116 | +ARR_CHANNEL=("${@:$OPTIND:1}") |
| 117 | +CHANNEL="${ARR_CHANNEL[0]:-}" |
| 118 | + |
| 119 | +[ -z "$CHANNEL" ] && CHANNEL=stable |
| 120 | +[ -z "$VERSION" ] && VERSION=any |
| 121 | +[ -z "$ARCH" ] && ARCH=x64 |
| 122 | +[ -z "$CACHE_PATH" ] && CACHE_PATH="$RUNNER_TOOL_CACHE/flutter/:channel:-:version:-:arch:" |
| 123 | +[ -z "$CACHE_KEY" ] && CACHE_KEY="flutter-:os:-:channel:-:version:-:arch:-:hash:" |
| 124 | +[ -z "$PUB_CACHE_KEY" ] && PUB_CACHE_KEY="flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" |
| 125 | +[ -z "$PUB_CACHE_PATH" ] && PUB_CACHE_PATH="default" |
| 126 | +[ -z "$GIT_SOURCE" ] && GIT_SOURCE="https://github.com/flutter/flutter.git" |
| 127 | + |
| 128 | +# `PUB_CACHE` is what Dart and Flutter looks for in the environment, while |
| 129 | +# `PUB_CACHE_PATH` is passed in from the action. |
| 130 | +# |
| 131 | +# If `PUB_CACHE` is set already, then it should continue to be used. Otherwise, satisfy it |
| 132 | +# if the action requests a custom path, or set to the Dart default values depending |
| 133 | +# on the operating system. |
| 134 | +if [ -z "${PUB_CACHE:-}" ]; then |
| 135 | + if [ "$PUB_CACHE_PATH" != "default" ]; then |
| 136 | + PUB_CACHE="$PUB_CACHE_PATH" |
| 137 | + elif [ "$OS_NAME" = "windows" ]; then |
| 138 | + PUB_CACHE="$LOCALAPPDATA\\Pub\\Cache" |
| 139 | + else |
| 140 | + PUB_CACHE="$HOME/.pub-cache" |
| 141 | + fi |
| 142 | +fi |
| 143 | + |
| 144 | +if [ "$TEST_MODE" = true ]; then |
| 145 | + RELEASE_MANIFEST=$(cat "$(dirname -- "${BASH_SOURCE[0]}")/test/$MANIFEST_JSON_PATH") |
| 146 | +else |
| 147 | + RELEASE_MANIFEST=$(curl --silent --connect-timeout 15 --retry 5 "$MANIFEST_URL") |
| 148 | +fi |
| 149 | + |
| 150 | +if [ "$CHANNEL" = "master" ] || [ "$CHANNEL" = "main" ]; then |
| 151 | + VERSION_MANIFEST="{\"channel\":\"$CHANNEL\",\"version\":\"$VERSION\",\"dart_sdk_arch\":\"$ARCH\",\"hash\":\"$CHANNEL\",\"sha256\":\"$CHANNEL\"}" |
| 152 | +else |
| 153 | + VERSION_MANIFEST=$(echo "$RELEASE_MANIFEST" | filter_by_channel "$CHANNEL" | filter_by_arch "$ARCH" | filter_by_version "$VERSION") |
| 154 | +fi |
| 155 | + |
| 156 | +case "$VERSION_MANIFEST" in |
| 157 | +*null*) |
| 158 | + not_found_error "$CHANNEL" "$VERSION" "$ARCH" |
| 159 | + exit 1 |
| 160 | + ;; |
| 161 | +esac |
| 162 | + |
| 163 | +expand_key() { |
| 164 | + version_channel=$(echo "$VERSION_MANIFEST" | jq -r '.channel') |
| 165 | + version_version=$(echo "$VERSION_MANIFEST" | jq -r '.version') |
| 166 | + version_arch=$(echo "$VERSION_MANIFEST" | jq -r '.dart_sdk_arch // "x64"') |
| 167 | + version_hash=$(echo "$VERSION_MANIFEST" | jq -r '.hash') |
| 168 | + version_sha_256=$(echo "$VERSION_MANIFEST" | jq -r '.sha256') |
| 169 | + |
| 170 | + expanded_key="${1/:channel:/$version_channel}" |
| 171 | + expanded_key="${expanded_key/:version:/$version_version}" |
| 172 | + expanded_key="${expanded_key/:arch:/$version_arch}" |
| 173 | + expanded_key="${expanded_key/:hash:/$version_hash}" |
| 174 | + expanded_key="${expanded_key/:sha256:/$version_sha_256}" |
| 175 | + expanded_key="${expanded_key/:os:/$OS_NAME}" |
| 176 | + |
| 177 | + echo "$expanded_key" |
| 178 | +} |
| 179 | + |
| 180 | +CACHE_KEY=$(expand_key "$CACHE_KEY") |
| 181 | +PUB_CACHE_KEY=$(expand_key "$PUB_CACHE_KEY") |
| 182 | +CACHE_PATH=$(expand_key "$(transform_path "$CACHE_PATH")") |
| 183 | +PUB_CACHE=$(expand_key "$(transform_path "$PUB_CACHE")") |
| 184 | + |
| 185 | +if [ "$PRINT_ONLY" = true ]; then |
| 186 | + version_info=$(echo "$VERSION_MANIFEST" | jq -j '.channel,":",.version,":",.dart_sdk_arch // "x64"') |
| 187 | + |
| 188 | + info_channel=$(echo "$version_info" | awk -F ':' '{print $1}') |
| 189 | + info_version=$(echo "$version_info" | awk -F ':' '{print $2}') |
| 190 | + info_architecture=$(echo "$version_info" | awk -F ':' '{print $3}') |
| 191 | + |
| 192 | + if [ "$TEST_MODE" = true ]; then |
| 193 | + echo "CHANNEL=$info_channel" |
| 194 | + echo "VERSION=$info_version" |
| 195 | + # VERSION_FILE is not printed, because it is essentially same as VERSION |
| 196 | + echo "ARCHITECTURE=$info_architecture" |
| 197 | + echo "CACHE-KEY=$CACHE_KEY" |
| 198 | + echo "CACHE-PATH=$CACHE_PATH" |
| 199 | + echo "PUB-CACHE-KEY=$PUB_CACHE_KEY" |
| 200 | + echo "PUB-CACHE-PATH=$PUB_CACHE" |
| 201 | + exit 0 |
| 202 | + fi |
| 203 | + |
| 204 | + { |
| 205 | + echo "CHANNEL=$info_channel" |
| 206 | + echo "VERSION=$info_version" |
| 207 | + # VERSION_FILE is not printed, because it is essentially same as VERSION |
| 208 | + echo "ARCHITECTURE=$info_architecture" |
| 209 | + echo "CACHE-KEY=$CACHE_KEY" |
| 210 | + echo "CACHE-PATH=$CACHE_PATH" |
| 211 | + echo "PUB-CACHE-KEY=$PUB_CACHE_KEY" |
| 212 | + echo "PUB-CACHE-PATH=$PUB_CACHE" |
| 213 | + } >>"${GITHUB_OUTPUT:-/dev/null}" |
| 214 | + |
| 215 | + exit 0 |
| 216 | +fi |
| 217 | + |
| 218 | +if [ ! -x "$CACHE_PATH/bin/flutter" ]; then |
| 219 | + if [ "$CHANNEL" = "master" ] || [ "$CHANNEL" = "main" ]; then |
| 220 | + git clone -b "$CHANNEL" "$GIT_SOURCE" "$CACHE_PATH" |
| 221 | + if [ "$VERSION" != "any" ]; then |
| 222 | + git config --global --add safe.directory "$CACHE_PATH" |
| 223 | + (cd "$CACHE_PATH" && git checkout "$VERSION") |
| 224 | + fi |
| 225 | + else |
| 226 | + archive_url=$(echo "$VERSION_MANIFEST" | jq -r '.archive') |
| 227 | + download_archive "$archive_url" "$CACHE_PATH" |
| 228 | + fi |
| 229 | +fi |
| 230 | + |
| 231 | +{ |
| 232 | + echo "FLUTTER_ROOT=$CACHE_PATH" |
| 233 | + echo "PUB_CACHE=$PUB_CACHE" |
| 234 | +} >>"${GITHUB_ENV:-/dev/null}" |
| 235 | + |
| 236 | +{ |
| 237 | + echo "$CACHE_PATH/bin" |
| 238 | + echo "$CACHE_PATH/bin/cache/dart-sdk/bin" |
| 239 | + echo "$PUB_CACHE/bin" |
| 240 | +} >>"${GITHUB_PATH:-/dev/null}" |
0 commit comments