├── .github ├── FUNDING.yaml └── workflows │ └── workflow.yaml ├── test └── pubspec.yaml ├── LICENSE ├── action.yaml ├── setup.sh └── README.md /.github/FUNDING.yaml: -------------------------------------------------------------------------------- 1 | github: [subosito] 2 | -------------------------------------------------------------------------------- /test/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_action_test 2 | 3 | environment: 4 | dart: ">=2.18.0 <3.0.0" 5 | flutter: 3.3.10 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Alif Rachmawadi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /action.yaml: -------------------------------------------------------------------------------- 1 | name: Set up Flutter 2 | description: Setup your runner with Flutter environment 3 | author: Alif Rachmawadi 4 | branding: 5 | icon: maximize 6 | color: blue 7 | 8 | inputs: 9 | channel: 10 | description: The Flutter build release channel 11 | required: false 12 | default: stable 13 | flutter-version: 14 | description: The Flutter version to make available on the path 15 | required: false 16 | default: "" 17 | flutter-version-file: 18 | description: The pubspec.yaml file with exact Flutter version defined 19 | required: false 20 | default: "" 21 | architecture: 22 | description: The architecture of Flutter SDK executable (x64 or arm64) 23 | required: false 24 | default: "${{ runner.arch }}" 25 | cache: 26 | description: Cache the Flutter SDK 27 | required: false 28 | default: "false" 29 | cache-key: 30 | description: Identifier for the Flutter SDK cache 31 | required: false 32 | default: "" 33 | cache-path: 34 | description: Flutter SDK cache path 35 | required: false 36 | default: "" 37 | pub-cache-key: 38 | description: Identifier for the Dart .pub-cache cache 39 | required: false 40 | default: "" 41 | pub-cache-path: 42 | description: Flutter pub cache path 43 | required: false 44 | default: default 45 | dry-run: 46 | description: If true, get outputs but do not install Flutter 47 | required: false 48 | default: "false" 49 | git-source: 50 | description: Git clone source 51 | required: false 52 | default: "https://github.com/flutter/flutter.git" 53 | 54 | outputs: 55 | CHANNEL: 56 | value: "${{ steps.flutter-action.outputs.CHANNEL }}" 57 | description: The selected Flutter release channel 58 | VERSION: 59 | value: "${{ steps.flutter-action.outputs.VERSION }}" 60 | description: The selected Flutter version 61 | ARCHITECTURE: 62 | value: "${{ steps.flutter-action.outputs.ARCHITECTURE }}" 63 | description: The selected Flutter CPU architecture 64 | CACHE-KEY: 65 | value: "${{ steps.flutter-action.outputs.CACHE-KEY }}" 66 | description: Key used to cache the Flutter SDK 67 | CACHE-PATH: 68 | value: "${{ steps.flutter-action.outputs.CACHE-PATH }}" 69 | description: Path to Flutter SDK 70 | PUB-CACHE-KEY: 71 | value: "${{ steps.flutter-action.outputs.PUB-CACHE-KEY }}" 72 | description: Key used to cache the pub dependencies 73 | PUB-CACHE-PATH: 74 | value: "${{ steps.flutter-action.outputs.PUB-CACHE-PATH }}" 75 | description: Path to pub cache 76 | GIT_SOURCE: 77 | value: "${{ steps.flutter-action.outputs.GIT_SOURCE }}" 78 | description: Git source of Flutter SDK repository to clone 79 | CACHE-HIT: 80 | value: "${{ steps.cache-flutter.outputs.cache-hit }}" 81 | description: "`true` if the flutter cache was a hit" 82 | PUB-CACHE-HIT: 83 | value: "${{ steps.cache-pub.outputs.cache-hit }}" 84 | description: "`true` if the pub cache was a hit" 85 | 86 | runs: 87 | using: composite 88 | steps: 89 | # This is a cross-platform composite action that needs yq in order to parse 90 | # the pubspec.yaml file. 91 | # It's not preinstalled on Windows runners. 92 | # See https://github.com/actions/runner-images/issues/7443#issuecomment-1514597691 93 | - name: Make yq tool available on Windows runners 94 | if: runner.os == 'Windows' && inputs.flutter-version-file != '' 95 | run: choco install yq 96 | shell: bash 97 | 98 | - name: Make setup script executable 99 | run: chmod +x "$GITHUB_ACTION_PATH/setup.sh" 100 | shell: bash 101 | 102 | - name: Set action inputs 103 | id: flutter-action 104 | shell: bash 105 | run: | 106 | $GITHUB_ACTION_PATH/setup.sh -p \ 107 | -n '${{ inputs.flutter-version }}' \ 108 | -f '${{ inputs.flutter-version-file }}' \ 109 | -a '${{ inputs.architecture }}' \ 110 | -k '${{ inputs.cache-key }}' \ 111 | -c '${{ inputs.cache-path }}' \ 112 | -l '${{ inputs.pub-cache-key }}' \ 113 | -d '${{ inputs.pub-cache-path }}' \ 114 | -g '${{ inputs.git-source }}' \ 115 | ${{ inputs.channel }} 116 | 117 | - name: Cache Flutter 118 | id: cache-flutter 119 | uses: actions/cache@v4 120 | if: ${{ inputs.cache == 'true' }} 121 | with: 122 | path: ${{ steps.flutter-action.outputs.CACHE-PATH }} 123 | key: ${{ steps.flutter-action.outputs.CACHE-KEY }} 124 | 125 | - name: Cache pub dependencies 126 | uses: actions/cache@v4 127 | id: cache-pub 128 | if: ${{ inputs.cache == 'true' }} 129 | with: 130 | path: ${{ steps.flutter-action.outputs.PUB-CACHE-PATH }} 131 | key: ${{ steps.flutter-action.outputs.PUB-CACHE-KEY }}-${{ hashFiles('**/pubspec.lock') }} 132 | 133 | - name: Run setup script 134 | shell: bash 135 | if: ${{ inputs.dry-run != 'true' && inputs.dry-run != true }} 136 | run: | 137 | $GITHUB_ACTION_PATH/setup.sh \ 138 | -n '${{ steps.flutter-action.outputs.VERSION }}' \ 139 | -a '${{ steps.flutter-action.outputs.ARCHITECTURE }}' \ 140 | -c '${{ steps.flutter-action.outputs.CACHE-PATH }}' \ 141 | -d '${{ steps.flutter-action.outputs.PUB-CACHE-PATH }}' \ 142 | ${{ steps.flutter-action.outputs.CHANNEL }} 143 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 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}" 241 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # flutter-action 2 | 3 | Flutter environment for use in GitHub Actions. It works on Linux, Windows, and 4 | macOS. 5 | 6 | Originally created by [Alif Rachmawadi]. Maintained by [Bartek Pacia]. 7 | 8 | The following sections show how to configure this action. 9 | 10 | ## Specifying Flutter version 11 | 12 | ### Use specific version and channel 13 | 14 | ```yaml 15 | steps: 16 | - name: Clone repository 17 | uses: actions/checkout@v4 18 | - name: Set up Flutter 19 | uses: subosito/flutter-action@v2 20 | with: 21 | channel: stable 22 | flutter-version: 3.19.0 23 | - run: flutter --version 24 | ``` 25 | 26 | ### Use version from pubspec.yaml 27 | 28 | This is inspired by [`actions/setup-go`](https://github.com/actions/setup-go). 29 | 30 | ```yaml 31 | steps: 32 | - name: Clone repository 33 | uses: actions/checkout@v4 34 | - name: Set up Flutter 35 | uses: subosito/flutter-action@v2 36 | with: 37 | channel: stable 38 | flutter-version-file: pubspec.yaml # path to pubspec.yaml 39 | - run: flutter --version 40 | ``` 41 | 42 | > [!IMPORTANT] 43 | > 44 | > For `flutter-version-file` to work, you need to have the exact Flutter version 45 | > defined in your pubspec.yaml: 46 | > 47 | > **Good** 48 | > 49 | > ```yaml 50 | > environment: 51 | > sdk: ">=3.3.0 <4.0.0" 52 | > flutter: 3.19.0 53 | > ``` 54 | > 55 | > **Bad** 56 | > 57 | > ```yaml 58 | > environment: 59 | > sdk: ">=3.3.0 <4.0.0" 60 | > flutter: ">= 3.19.0 <4.0.0" 61 | > ``` 62 | 63 | > [!NOTE] 64 | > 65 | > Using `flutter-version-file` requires [`yq`](https://github.com/mikefarah/yq), 66 | > which is not pre-installed in `windows` runners. Fortunately, since version 67 | > 2.18.0, this action installs `yq` automatically if `flutter-version-file` 68 | > is specified, so no action is required from you. 69 | 70 | ### Use latest release for particular channel 71 | 72 | ```yaml 73 | steps: 74 | - name: Clone repository 75 | uses: actions/checkout@v4 76 | - name: Set up Flutter 77 | uses: subosito/flutter-action@v2 78 | with: 79 | channel: stable # or: beta, master (or main) 80 | - run: flutter --version 81 | ``` 82 | 83 | ### Use latest release for particular version and/or channel 84 | 85 | ```yaml 86 | steps: 87 | - name: Clone repository 88 | uses: actions/checkout@v4 89 | - name: Set up Flutter 90 | uses: subosito/flutter-action@v2 91 | with: 92 | channel: dev 93 | flutter-version: 1.22.x 94 | - run: flutter --version 95 | ``` 96 | 97 | ### Use particular version on any channel 98 | 99 | ```yaml 100 | steps: 101 | - name: Clone repository 102 | uses: actions/checkout@v4 103 | - name: Set up Flutter 104 | uses: subosito/flutter-action@v2 105 | with: 106 | channel: any 107 | flutter-version: 3.x 108 | - run: flutter --version 109 | ``` 110 | 111 | ### Use particular git reference on master channel 112 | 113 | ```yaml 114 | steps: 115 | - name: Clone repository 116 | uses: actions/checkout@v4 117 | - name: Set up Flutter 118 | uses: subosito/flutter-action@v2 119 | with: 120 | channel: master 121 | flutter-version: 5b12b74 # tag, commit or branch 122 | - run: flutter --version 123 | ``` 124 | 125 | ### Use a Flutter mirror by set ENV 126 | 127 | You can get more infomation from [Flutter official docs](https://docs.flutter.dev/community/china). 128 | 129 | ```yaml 130 | steps: 131 | - name: Clone repository 132 | uses: actions/checkout@v4 133 | - name: Set up Flutter 134 | env: 135 | FLUTTER_STORAGE_BASE_URL: https://storage.flutter-io.cn 136 | uses: subosito/flutter-action@v2 137 | with: 138 | channel: master 139 | flutter-version: 5b12b74 # tag, commit or branch 140 | - run: flutter --version 141 | ``` 142 | 143 | ### Use alternative Flutter repository 144 | 145 | This action supports "alternative Flutters" in addition to the official 146 | [`flutter/flutter`](https://github.com/flutter/flutter), for example: 147 | - [Flock](https://github.com/join-the-flock/flock.git) 148 | - [a Flutter fork that supports 149 | HarmonyOS](https://gitee.com/harmonycommando_flutter/flutter.git) 150 | 151 | ```yaml 152 | steps: 153 | - name: Clone repository 154 | uses: actions/checkout@v4 155 | - name: Set up Flutter 156 | uses: subosito/flutter-action@v2 157 | with: 158 | channel: master 159 | flutter-version: 3.24.0 160 | git-source: https://github.com/join-the-flock/flock.git 161 | - run: flutter --version 162 | ``` 163 | 164 | > [!NOTE] 165 | > 166 | > This feature was implemented in 167 | > [#344](https://github.com/subosito/flutter-action/pull/334) and is available 168 | > since v2.18.0. 169 | 170 | ### Apply a patch 171 | 172 | Sometimes you find a bug in Flutter and you fix it yourself (you're a 173 | rockstar!), and then submit a patch/PR to Flutter repository. However, everyone 174 | knows that code review takes time, but your app needs the fix _now_. 175 | 176 | You can apply your patch like this: 177 | 178 | ```yaml 179 | steps: 180 | - name: Clone repository 181 | uses: actions/checkout@v4 182 | - uses: subosito/flutter-action@v2 183 | with: 184 | flutter-version: 3.22.2 185 | channel: stable 186 | - run: | 187 | flutter --version 188 | cd ${{ env.FLUTTER_ROOT }} 189 | curl https://patch-diff.githubusercontent.com/raw/flutter/flutter/pull/137874.patch | git apply 190 | git status 191 | ``` 192 | 193 | > [!NOTE] 194 | > 195 | > This was first discussed in [this issue](https://github.com/subosito/flutter-action/issues/310). 196 | 197 | ## Build targets 198 | 199 | Build **Android** APK and app bundle: 200 | 201 | ```yaml 202 | steps: 203 | - name: Clone repository 204 | uses: actions/checkout@v4 205 | - name: Set up Flutter 206 | uses: subosito/flutter-action@v2 207 | with: 208 | flutter-version: 3.24.0 209 | - run: flutter pub get 210 | - run: flutter test 211 | - run: flutter build apk 212 | - run: flutter build appbundle 213 | ``` 214 | 215 | ### Build for iOS 216 | 217 | > [!NOTE] 218 | > 219 | > Building for iOS requires a macOS runner. 220 | 221 | ```yaml 222 | jobs: 223 | main: 224 | runs-on: macos-latest 225 | steps: 226 | - name: Clone repository 227 | uses: actions/checkout@v4 228 | - name: Set up Flutter 229 | uses: subosito/flutter-action@v2 230 | with: 231 | channel: stable 232 | - run: flutter pub get 233 | - run: flutter test 234 | - run: flutter build ios --release --no-codesign 235 | ``` 236 | 237 | ### Build for the web 238 | 239 | ```yaml 240 | steps: 241 | - name: Clone repository 242 | uses: actions/checkout@v4 243 | - name: Set up Flutter 244 | uses: subosito/flutter-action@v2 245 | with: 246 | channel: stable 247 | - run: flutter pub get 248 | - run: flutter test 249 | - run: flutter build web 250 | ``` 251 | 252 | ### Build for Windows 253 | 254 | ```yaml 255 | jobs: 256 | main: 257 | runs-on: windows-latest 258 | steps: 259 | - name: Clone repository 260 | uses: actions/checkout@v4 261 | - name: Set up Flutter 262 | uses: subosito/flutter-action@v2 263 | with: 264 | channel: stable 265 | - run: flutter build windows 266 | ``` 267 | 268 | ### Build for Linux desktop 269 | 270 | ```yaml 271 | jobs: 272 | main: 273 | runs-on: ubuntu-latest 274 | steps: 275 | - name: Clone repository 276 | uses: actions/checkout@v4 277 | - name: Set up Flutter 278 | uses: subosito/flutter-action@v2 279 | with: 280 | channel: stable 281 | - run: | 282 | sudo apt-get update -y 283 | sudo apt-get install -y ninja-build libgtk-3-dev 284 | - run: flutter build linux 285 | ``` 286 | 287 | ### Build for macOS desktop 288 | 289 | > [!NOTE] 290 | > 291 | > Building for macOS requires a macOS runner. 292 | 293 | ```yaml 294 | jobs: 295 | main: 296 | runs-on: macos-latest 297 | steps: 298 | - name: Clone repository 299 | uses: actions/checkout@v4 300 | - name: Set up Flutter 301 | uses: subosito/flutter-action@v2 302 | with: 303 | channel: stable 304 | - run: flutter build macos 305 | ``` 306 | 307 | ## Caching 308 | 309 | Integration with [`actions/cache`](https://github.com/actions/cache): 310 | 311 | ```yaml 312 | steps: 313 | - name: Clone repository 314 | uses: actions/checkout@v4 315 | - name: Set up Flutter 316 | uses: subosito/flutter-action@v2 317 | with: 318 | channel: stable 319 | cache: true 320 | # optional parameters follow 321 | cache-key: "flutter-:os:-:channel:-:version:-:arch:-:hash:" # optional, change this to force refresh cache 322 | cache-path: "${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:" # optional, change this to specify the cache path 323 | pub-cache-key: "flutter-pub-:os:-:channel:-:version:-:arch:-:hash:" # optional, change this to force refresh cache of dart pub get dependencies 324 | pub-cache-path: "${{ runner.tool_cache }}/flutter/:channel:-:version:-:arch:" # optional, change this to specify the cache path 325 | - run: flutter --version 326 | ``` 327 | 328 | Note: `cache-key`, `pub-cache-key`, and `cache-path` have support for several 329 | dynamic values: 330 | 331 | - `:os:` 332 | - `:channel:` 333 | - `:version:` 334 | - `:arch:` 335 | - `:hash:` 336 | - `:sha256:` 337 | 338 | ### Using cache outputs 339 | 340 | > [!NOTE] 341 | > `PUB-CACHE-HIT` and `CACHE-HIT` directly use the `cache-hit` output from `actions/cache@v4`, which is the following: 342 | > - `cache-hit` - A string value to indicate an exact match was found for the key. 343 | > - If there's a cache hit, this will be 'true' or 'false' to indicate if there's an exact match for `key`. 344 | > - If there's a cache miss, this will be an empty string. 345 | 346 | Example usage (inspired by [actions/cache@v4](https://github.com/actions/cache/blob/c45d39173a637a28edbd526cb160189cc4e84f5a/README.md#skipping-steps-based-on-cache-hit) and [#346](https://github.com/subosito/flutter-action/pull/346)) to skip `melos bootstrap` if there was a pub cache hit: 347 | 348 | ``` 349 | steps: 350 | - name: Checkout repository 351 | uses: actions/checkout@v4 352 | 353 | - name: Set up Flutter 354 | uses: subosito/flutter-action@v2 355 | id: flutter-action 356 | with: 357 | channel: stable 358 | cache: true 359 | 360 | - name: Conditionally run melos bootstrap 361 | if: steps.flutter-action.outputs.PUB-CACHE-HIT != 'true' 362 | run: melos bootstrap 363 | 364 | - name: Continue with build 365 | run: flutter build apk 366 | ``` 367 | 368 | ## Outputs 369 | 370 | Use outputs from `flutter-action`: 371 | 372 | ```yaml 373 | steps: 374 | - name: Clone repository 375 | - uses: actions/checkout@v4 376 | - name: Set up Flutter 377 | uses: subosito/flutter-action@v2 378 | id: flutter-action 379 | with: 380 | channel: stable 381 | - name: Print outputs 382 | shell: bash 383 | run: | 384 | echo CACHE-PATH=${{ steps.flutter-action.outputs.CACHE-PATH }} 385 | echo CACHE-KEY=${{ steps.flutter-action.outputs.CACHE-KEY }} 386 | echo CHANNEL=${{ steps.flutter-action.outputs.CHANNEL }} 387 | echo VERSION=${{ steps.flutter-action.outputs.VERSION }} 388 | echo ARCHITECTURE=${{ steps.flutter-action.outputs.ARCHITECTURE }} 389 | echo PUB-CACHE-PATH=${{ steps.flutter-action.outputs.PUB-CACHE-PATH }} 390 | echo PUB-CACHE-KEY=${{ steps.flutter-action.outputs.PUB-CACHE-KEY }} 391 | echo CACHE-HIT=${{ steps.flutter-action.outputs.CACHE-HIT }} 392 | echo PUB-CACHE-HIT=${{ steps.flutter-action.outputs.PUB-CACHE-HIT }} 393 | ``` 394 | 395 | If you don't need to install Flutter and just want the outputs, you can use the 396 | `dry-run` option: 397 | 398 | ```yaml 399 | steps: 400 | - name: Clone repository 401 | - uses: actions/checkout@v4 402 | - name: Set up Flutter 403 | uses: subosito/flutter-action@v2 404 | id: flutter-action 405 | with: 406 | channel: stable 407 | dry-run: true 408 | - run: | 409 | echo CACHE-PATH=${{ steps.flutter-action.outputs.CACHE-PATH }} 410 | echo CACHE-KEY=${{ steps.flutter-action.outputs.CACHE-KEY }} 411 | echo CHANNEL=${{ steps.flutter-action.outputs.CHANNEL }} 412 | echo VERSION=${{ steps.flutter-action.outputs.VERSION }} 413 | echo ARCHITECTURE=${{ steps.flutter-action.outputs.ARCHITECTURE }} 414 | echo PUB-CACHE-PATH=${{ steps.flutter-action.outputs.PUB-CACHE-PATH }} 415 | echo PUB-CACHE-KEY=${{ steps.flutter-action.outputs.PUB-CACHE-KEY }} 416 | echo CACHE-HIT=${{ steps.flutter-action.outputs.CACHE-HIT }} 417 | echo PUB-CACHE-HIT=${{ steps.flutter-action.outputs.PUB-CACHE-HIT }} 418 | shell: bash 419 | ``` 420 | 421 | [Alif Rachmawadi]: https://github.com/subosito 422 | [Bartek Pacia]: https://github.com/bartekpacia 423 | -------------------------------------------------------------------------------- /.github/workflows/workflow.yaml: -------------------------------------------------------------------------------- 1 | name: test 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | - dev 9 | pull_request: 10 | paths: 11 | - setup.sh 12 | - action.yaml 13 | - .github/workflows/workflow.yaml 14 | jobs: 15 | lint_shellcheck: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - name: Clone repository 20 | uses: actions/checkout@v4 21 | - name: Run shellcheck 22 | uses: ludeeus/action-shellcheck@master 23 | 24 | test_channel: 25 | runs-on: ${{ matrix.operating-system }} 26 | 27 | strategy: 28 | matrix: 29 | operating-system: 30 | - ubuntu-latest 31 | - windows-latest 32 | - macos-latest 33 | - macos-13 34 | channel: [stable, beta, master] 35 | dry-run: [true, false] 36 | git-source: 37 | - https://github.com/flutter/flutter.git 38 | - https://github.com/Flutter-Foundation/flutter.git 39 | - https://gitee.com/harmonycommando_flutter/flutter.git 40 | include: 41 | - operating-system: ubuntu-latest 42 | channel: main 43 | 44 | steps: 45 | - name: Clone repository 46 | uses: actions/checkout@v4 47 | - id: flutter-action 48 | uses: ./ 49 | with: 50 | channel: ${{ matrix.channel }} 51 | dry-run: ${{ matrix.dry-run }} 52 | git-source: ${{ matrix.git-source }} 53 | - name: Echo outputs 54 | run: | 55 | echo RUNNER-OS=${{ runner.os }} 56 | echo RUNNER-ARCH=${{ runner.arch }} 57 | 58 | echo CACHE-PATH=${{ steps.flutter-action.outputs.CACHE-PATH }} 59 | echo CACHE-KEY=${{ steps.flutter-action.outputs.CACHE-KEY }} 60 | echo CHANNEL=${{ steps.flutter-action.outputs.CHANNEL }} 61 | echo VERSION=${{ steps.flutter-action.outputs.VERSION }} 62 | echo ARCHITECTURE=${{ steps.flutter-action.outputs.ARCHITECTURE }} 63 | shell: bash 64 | - run: dart --version 65 | if: ${{ matrix.dry-run != true }} 66 | shell: bash 67 | - run: flutter --version 68 | if: ${{ matrix.dry-run != true }} 69 | shell: bash 70 | - run: "! dart --version" 71 | if: ${{ matrix.dry-run == true }} 72 | shell: bash 73 | - run: "! flutter --version" 74 | if: ${{ matrix.dry-run == true }} 75 | shell: bash 76 | 77 | test_cache: 78 | runs-on: ${{ matrix.operating-system }} 79 | 80 | strategy: 81 | matrix: 82 | operating-system: 83 | [ubuntu-latest, windows-latest, macos-latest, macos-13] 84 | 85 | steps: 86 | - name: Clone repository 87 | uses: actions/checkout@v4 88 | - uses: ./ 89 | with: 90 | channel: stable 91 | flutter-version: 3.10.6 92 | cache: true 93 | - run: dart --version 94 | shell: bash 95 | - run: flutter --version 96 | shell: bash 97 | 98 | test_version_file: 99 | runs-on: ${{ matrix.operating-system }} 100 | 101 | strategy: 102 | matrix: 103 | operating-system: [ubuntu-latest] 104 | 105 | steps: 106 | - name: Clone repository 107 | uses: actions/checkout@v4 108 | - uses: ./ 109 | with: 110 | channel: stable 111 | flutter-version-file: test/pubspec.yaml 112 | - name: Verify Dart version 113 | run: dart --version | grep '2.18.6' 114 | shell: bash 115 | - name: Verify Flutter version 116 | run: flutter --version | grep '3.3.10' 117 | shell: bash 118 | 119 | test_print_output_x64: 120 | runs-on: ubuntu-latest 121 | 122 | # These calls to setup.sh sepcify the -t flag, which enables test mode. 123 | # Test mode uses hardcoded Flutter release manifests from test/ directory. 124 | 125 | steps: 126 | - name: Clone repository 127 | uses: actions/checkout@v4 128 | - run: ./setup.sh -t -p -f test/pubspec.yaml | grep '3.3.10' 129 | shell: bash 130 | - run: ./setup.sh -t -p | grep 'stable' 131 | shell: bash 132 | - run: ./setup.sh -t -p | grep '3.7.7' 133 | shell: bash 134 | - run: ./setup.sh -t -p | grep 'x64' 135 | shell: bash 136 | - run: ./setup.sh -t -p stable | grep 'stable' 137 | shell: bash 138 | - run: ./setup.sh -t -p beta | grep 'beta' 139 | shell: bash 140 | - run: ./setup.sh -t -p beta | grep '3.9.0-0.1.pre' 141 | shell: bash 142 | - run: ./setup.sh -t -p -n 3.3.10 stable | grep '3.3.10' 143 | shell: bash 144 | - run: ./setup.sh -t -p -n 3.3.1 stable | grep '3.3.1' 145 | shell: bash 146 | - run: ./setup.sh -t -p -n 2 stable | grep '2.10.5' 147 | shell: bash 148 | - run: ./setup.sh -t -p -n 2 beta | grep '2.13.0-0.4.pre' 149 | shell: bash 150 | - run: ./setup.sh -t -p -n 2 any | grep 'beta' 151 | shell: bash 152 | - run: ./setup.sh -t -p -n 2 any | grep '2.13.0-0.4.pre' 153 | shell: bash 154 | - run: ./setup.sh -t -p -n 3 any | grep 'beta' 155 | shell: bash 156 | - run: ./setup.sh -t -p -n 3 any | grep '3.9.0-0.1.pre' 157 | shell: bash 158 | - run: ./setup.sh -t -p -n 3 any | grep 'x64' 159 | shell: bash 160 | - run: ./setup.sh -t -p -n any stable | grep 'stable' 161 | shell: bash 162 | - run: ./setup.sh -t -p -n any stable | grep '3.7.7' 163 | shell: bash 164 | - run: ./setup.sh -t -p -n any stable | grep 'x64' 165 | shell: bash 166 | - run: ./setup.sh -t -p -n 1 stable | grep '1.22.6' 167 | shell: bash 168 | - run: ./setup.sh -t -p -n 0 any | grep 'beta' 169 | shell: bash 170 | - run: ./setup.sh -t -p -n 0 any | grep '0.11.13' 171 | shell: bash 172 | - run: ./setup.sh -t -p | grep 'flutter-linux-stable-3.7.7-x64-2ad6cd72c040113b47ee9055e722606a490ef0da' 173 | shell: bash 174 | - run: ./setup.sh -t -p stable | grep 'flutter-linux-stable-3.7.7-x64-2ad6cd72c040113b47ee9055e722606a490ef0da' 175 | shell: bash 176 | - run: ./setup.sh -t -p beta | grep 'flutter-linux-beta-3.9.0-0.1.pre-x64-f732038a8cf4562ce38a1d7debb30209ae3da896' 177 | shell: bash 178 | - run: ./setup.sh -t -p dev | grep 'flutter-linux-dev-2.13.0-0.1.pre-x64-13a2fb10b838971ce211230f8ffdd094c14af02c' 179 | shell: bash 180 | - run: ./setup.sh -t -p master | grep 'flutter-linux-master-any-x64-master' 181 | shell: bash 182 | - run: ./setup.sh -t -p -n 5b12b74 master | grep 'flutter-linux-master-5b12b74-x64-master' 183 | shell: bash 184 | - run: ./setup.sh -t -p -n 3.12.0-12.0.pre master | grep 'flutter-linux-master-3.12.0-12.0.pre-x64-master' 185 | shell: bash 186 | - run: ./setup.sh -t -p -n stable master | grep 'flutter-linux-master-stable-x64-master' 187 | shell: bash 188 | - run: ./setup.sh -t -p -n 2 any | grep 'flutter-linux-beta-2.13.0-0.4.pre-x64-25caf1461b8f643092a9f6f5b224453b5c057d10' 189 | shell: bash 190 | - run: ./setup.sh -t -p -n 1 any | grep 'flutter-linux-beta-1.26.0-17.8.pre-x64-044f2cf5607a26f8818dab0f766400e85c52bdff' 191 | shell: bash 192 | - run: ./setup.sh -t -p -n 0 any | grep 'flutter-linux-beta-0.11.13-x64-58c8489fcdb4e4ef6c010117584c9b23d15221aa' 193 | shell: bash 194 | - run: ./setup.sh -t -p | grep '/opt/hostedtoolcache/flutter/stable-3.7.7-x64' 195 | shell: bash 196 | - run: ./setup.sh -t -p stable | grep '/opt/hostedtoolcache/flutter/stable-3.7.7-x64' 197 | shell: bash 198 | - run: ./setup.sh -t -p beta | grep '/opt/hostedtoolcache/flutter/beta-3.9.0-0.1.pre-x64' 199 | shell: bash 200 | - run: ./setup.sh -t -p dev | grep '/opt/hostedtoolcache/flutter/dev-2.13.0-0.1.pre-x64' 201 | shell: bash 202 | - run: ./setup.sh -t -p master | grep '/opt/hostedtoolcache/flutter/master-any-x64' 203 | shell: bash 204 | - run: ./setup.sh -t -p -k 'custom-:channel:-:version:-:hash:' | grep 'custom-stable-3.7.7-2ad6cd72c040113b47ee9055e722606a490ef0da' 205 | shell: bash 206 | - run: ./setup.sh -t -p -k 'custom-:channel:-:version:-:sha256:' | grep 'custom-stable-3.7.7-cdd49597e88c35e5de5184e9acff433dfbb3c075b74ef7b27790af7f57ce2420' 207 | shell: bash 208 | - run: ./setup.sh -t -p -c '/tmp/flutter/:channel:-:version:-:hash:' | grep '/tmp/flutter/stable-3.7.7-2ad6cd72c040113b47ee9055e722606a490ef0da' 209 | shell: bash 210 | - run: ./setup.sh -t -p -d '/tmp/flutter/:channel:-:version:-:hash:-pub-cache-path' | grep '/tmp/flutter/stable-3.7.7-2ad6cd72c040113b47ee9055e722606a490ef0da-pub-cache-path' 211 | shell: bash 212 | - run: ./setup.sh -t -p -l '/tmp/flutter/:channel:-:version:-:hash:-pub-cache-key' | grep '/tmp/flutter/stable-3.7.7-2ad6cd72c040113b47ee9055e722606a490ef0da-pub-cache-key' 213 | shell: bash 214 | 215 | 216 | test_print_output_arm64: 217 | runs-on: macos-latest 218 | 219 | # These calls to setup.sh sepcify the -t flag, which enables test mode. 220 | # Test mode uses hardcoded Flutter release manifests from test/ directory. 221 | 222 | steps: 223 | - name: Clone repository 224 | uses: actions/checkout@v4 225 | - run: ./setup.sh -t -p -f test/pubspec.yaml | grep '3.3.10' 226 | shell: bash 227 | - run: ./setup.sh -t -p | grep 'stable' 228 | shell: bash 229 | - run: ./setup.sh -t -p | grep '3.7.7' 230 | shell: bash 231 | - run: ./setup.sh -t -p | grep 'arm64' 232 | shell: bash 233 | - run: ./setup.sh -t -p stable | grep 'stable' 234 | shell: bash 235 | - run: ./setup.sh -t -p beta | grep 'beta' 236 | shell: bash 237 | - run: ./setup.sh -t -p beta | grep '3.9.0-0.1.pre' 238 | shell: bash 239 | - run: ./setup.sh -t -p -n 3.3.10 stable | grep '3.3.10' 240 | shell: bash 241 | - run: ./setup.sh -t -p -n 3.3.1 stable | grep '3.3.1' 242 | shell: bash 243 | - run: ./setup.sh -t -p -n 3 any | grep 'beta' 244 | shell: bash 245 | - run: ./setup.sh -t -p -n 3 any | grep '3.9.0-0.1.pre' 246 | shell: bash 247 | - run: ./setup.sh -t -p -n 3 -a arm64 any | grep 'arm64' 248 | shell: bash 249 | - run: ./setup.sh -t -p -n any -a arm64 stable | grep 'stable' 250 | shell: bash 251 | - run: ./setup.sh -t -p -n any -a arm64 stable | grep '3.7.7' 252 | shell: bash 253 | - run: ./setup.sh -t -p -n any -a arm64 stable | grep 'arm64' 254 | shell: bash 255 | - run: ./setup.sh -t -p | grep 'flutter-macos-stable-3.7.7-arm64-2ad6cd72c040113b47ee9055e722606a490ef0da' 256 | shell: bash 257 | - run: ./setup.sh -t -p stable | grep 'flutter-macos-stable-3.7.7-arm64-2ad6cd72c040113b47ee9055e722606a490ef0da' 258 | shell: bash 259 | - run: ./setup.sh -t -p beta | grep 'flutter-macos-beta-3.9.0-0.1.pre-arm64-8b9b90e75107181aadc303d8d7422205863a35dd' 260 | shell: bash 261 | - run: ./setup.sh -t -p master | grep 'flutter-macos-master-any-arm64-master' 262 | shell: bash 263 | - run: ./setup.sh -t -p -n 5b12b74 master | grep 'flutter-macos-master-5b12b74-arm64-master' 264 | shell: bash 265 | - run: ./setup.sh -t -p -n 3.12.0-12.0.pre master | grep 'flutter-macos-master-3.12.0-12.0.pre-arm64-master' 266 | shell: bash 267 | - run: ./setup.sh -t -p -n stable master | grep 'flutter-macos-master-stable-arm64-master' 268 | shell: bash 269 | - run: ./setup.sh -t -p | grep '/Users/runner/hostedtoolcache/flutter/stable-3.7.7-arm64' 270 | shell: bash 271 | - run: ./setup.sh -t -p stable | grep '/Users/runner/hostedtoolcache/flutter/stable-3.7.7-arm64' 272 | shell: bash 273 | - run: ./setup.sh -t -p beta | grep '/Users/runner/hostedtoolcache/flutter/beta-3.9.0-0.1.pre-arm64' 274 | shell: bash 275 | - run: ./setup.sh -t -p master | grep '/Users/runner/hostedtoolcache/flutter/master-any-arm64' 276 | shell: bash 277 | - run: ./setup.sh -t -p -k 'custom-:channel:-:version:-:hash:' | grep 'custom-stable-3.7.7-2ad6cd72c040113b47ee9055e722606a490ef0da' 278 | shell: bash 279 | - run: ./setup.sh -t -p -k 'custom-:channel:-:version:-:sha256:' | grep 'custom-stable-3.7.7-0511b9f164a62f467b063e6c83d9c683bb3fb056ee556b2f45e987a2c2f4a260' 280 | shell: bash 281 | - run: ./setup.sh -t -p -c '/tmp/flutter/:channel:-:version:-:hash:' | grep '/tmp/flutter/stable-3.7.7-2ad6cd72c040113b47ee9055e722606a490ef0da' 282 | shell: bash 283 | - run: ./setup.sh -t -p -d '/tmp/flutter/:channel:-:version:-:hash:-pub-cache-path' | grep '/tmp/flutter/stable-3.7.7-2ad6cd72c040113b47ee9055e722606a490ef0da-pub-cache-path' 284 | shell: bash 285 | - run: ./setup.sh -t -p -l '/tmp/flutter/:channel:-:version:-:hash:-pub-cache-key' | grep '/tmp/flutter/stable-3.7.7-2ad6cd72c040113b47ee9055e722606a490ef0da-pub-cache-key' 286 | shell: bash 287 | --------------------------------------------------------------------------------