Library / SDK
subosito/flutter-action avatar
subosito/flutter-action

subosito/flutter-action: pinning a Flutter SDK inside GitHub Actions

Flutter environment for use in GitHub Actions. It works on Linux, Windows, and macOS.

2,609 stars271 forksShellMIT

At a glance

What is it?
A GitHub Action that installs a chosen Flutter SDK on Linux, Windows or macOS runners, with version resolution from pubspec.yaml or FVM config. The trade-off is that version selection, caching and workspace layout all become your problem.
Who is it for?
Adopt subosito/flutter-action if your Flutter builds already live in GitHub Actions and you want the SDK version pinned in the workflow file rather than on the runner image. Skip it if you build outside GitHub, or if you need a version range in pubspec.yaml, because flutter-version-file requires an exact value.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 154 days ago.
What is it written in?
Mainly Shell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The gap between a runner image and a reproducible Flutter build

GitHub-hosted runners give you an operating system, not a Flutter SDK. The SDK has to come from somewhere, and the two obvious answers both have costs. You can install it by hand in a run step, which means writing shell that differs per platform and re-downloading the archive on every job. Or you can rely on whatever Flutter happens to be preinstalled, which drifts as runner images are updated and turns a green build red without a commit from you.

subosito/flutter-action exists to remove that choice. It is a composite action, not a service: the repository holds action.yaml, setup.sh, a test directory and a LICENSE file. The README describes it as "Flutter environment for use in GitHub Actions" and states that it works on Linux, Windows and macOS. The audience is narrow and specific. If your Flutter app is tested or built in a GitHub workflow, this is the piece that decides which SDK the job runs against. If your CI lives in GitLab, Jenkins or a local script, nothing here applies, because the action only has meaning inside a GitHub Actions job.

How the action resolves a Flutter version before the job starts

The mechanism is a resolution step followed by an install. You declare a channel and a version selector in the with block, the action works out which concrete SDK build that maps to, installs it, and exports environment variables so later steps find the flutter binary. The README's patch example uses one of those variables directly: it changes into ${{ env.FLUTTER_ROOT }} to apply a git patch against the SDK checkout. That tells you the SDK is materialised as a git working tree on the runner, not as an opaque binary, which is what makes patching possible at all.

The selectors are more varied than a single version string. channel: stable with flutter-version: 3.19.0 pins an exact release. channel: stable with flutter-version: 1.22.x accepts a wildcard. channel: any with flutter-version: 3.x drops the channel constraint. channel: master with flutter-version: 5b12b74 treats the value as a tag, commit or branch. There is also git-source, which points the action at a fork instead of flutter/flutter; the README names Flock and a HarmonyOS-capable fork as examples. Version resolution can also be delegated to a file, which is the part most teams actually want.

Installing the action and running a first Flutter build

There is no package to install locally. You add the action to a workflow file in your repository. The README's minimal example checks out the code, sets up Flutter with an exact version, and prints the version to confirm the toolchain is on PATH.

yaml
steps:
  - name: Clone repository
    uses: actions/checkout@v6
  - name: Set up Flutter
    uses: subosito/flutter-action@v2
    with:
      channel: stable
      flutter-version: 3.19.0
  - run: flutter --version

After the job runs, the flutter --version step should print the release matching 3.19.0 on the stable channel. The same shape works for a build: the README's Android example adds flutter pub get, flutter test, flutter build apk and flutter build appbundle as separate run steps underneath the setup step.

yaml
steps:
  - name: Clone repository
    uses: actions/checkout@v6
  - name: Set up Flutter
    uses: subosito/flutter-action@v2
    with:
      flutter-version: 3.24.0
  - run: flutter pub get
  - run: flutter test
  - run: flutter build apk

Reading the SDK version from pubspec.yaml instead of the workflow

Hard-coding a version in the workflow means two places to update: the workflow and the pubspec. The flutter-version-file input removes that duplication. The README shows it accepting a path to pubspec.yaml, .fvmrc, or .fvm/fvm_config.json, and notes the design was inspired by actions/setup-go.

yaml
steps:
  - name: Clone repository
    uses: actions/checkout@v6
  - name: Set up Flutter
    uses: subosito/flutter-action@v2
    with:
      channel: stable
      flutter-version-file: pubspec.yaml
  - run: flutter --version

The constraint is strict and easy to miss. The README marks it important that the Flutter version in pubspec.yaml must be exact. An entry like flutter: 3.19.0 works. A range like flutter: ">= 3.19.0 <4.0.0" does not. That is a real limitation for teams who deliberately keep a range in the manifest, and it means the input is only usable if you are willing to pin. There is a second cost: the README states that flutter-version-file requires yq, that yq is not preinstalled on windows runners, and that the action installs it automatically when the input is specified. So the dependency is handled for you, but it is an added download on those jobs.

Caching, and the self-hosted runner constraint

The README documents integration with actions/cache and states that the action now uses actions/cache@v5 internally. That internal use is the source of the sharpest constraint in the whole document. For self-hosted runners, the README says the runner must be updated to Actions Runner 2.327.1 or newer before cache support is enabled. GitHub-hosted runners are not your concern here, but anyone running the action on their own hardware has a version floor to check before turning caching on. Get it wrong and the failure lands in the cache layer, not in your Dart code, which is a confusing place to debug.

Caching is also where the action's scope ends. It caches; it does not decide what is worth caching. The README's build examples run flutter pub get, flutter test, and then a build command, and none of them configure a pub cache key. Whether you wrap the action's own caching with a pub cache of your own is left to you. A reader expecting opinionated cache keys for the pub cache will not find them documented here.

Platform builds that the action cannot make portable

The action installs Flutter on all three runner families, but the build targets are not equally portable, and the README is explicit about two of them. Building for iOS requires a macOS runner; building for macOS desktop requires a macOS runner. That is a Flutter and Xcode constraint, not something the action can work around, and it means a matrix that wants iOS artifacts has to include macos-latest.

Linux desktop is the other case worth reading closely. The README's example installs ninja-build and libgtk-3-dev with apt-get before running flutter build linux. Those packages are not part of the Flutter SDK, so the action does not provide them. If you copy the setup step and skip the apt-get line, the failure will look like a missing toolchain rather than a missing action input. Android, web and Windows builds in the README do not carry extra system dependencies of this kind, which makes the Linux desktop path the one to read twice.

Alternatives: what changes if you use something else

The nearest alternative is FVM, the Flutter Version Management tool. The difference is where the pin lives. FVM keeps the version in a project-local config, and the README here explicitly supports reading that config through flutter-version-file, naming .fvmrc and .fvm/fvm_config.json as accepted paths. So the two are not mutually exclusive: if your team already pins Flutter with FVM for local development, this action can consume that same pin in CI, which keeps local and CI on one version. The trade-off is that FVM's config becomes a build input, and a change to it changes CI.

The second alternative is installing Flutter yourself in a run step. That gives you full control over the download source and the install layout, and it is the only option if you need a mirror or a fork that the action's git-source input does not cover. The cost is that you reimplement platform detection, archive extraction and PATH setup for three operating systems. The action's own README shows the mirror case is covered anyway through the FLUTTER_STORAGE_BASE_URL environment variable, set to https://storage.flutter-io.cn in the example, with a pointer to Flutter's official China documentation. A third option, relying on the runner's preinstalled Flutter, is the one to avoid if reproducibility matters: the version is outside your control.

Maintenance, licence and upgrade cost

The repository is not archived, and the last push was on 2026-04-30. Releases are tagged at a steady cadence: v2.23.0 on 2026-03-25, v2.22.0 on 2026-03-17, and v2.21.0 on 2025-06-24. The gap between v2.21.0 and v2.22.0 is roughly nine months, so the release rhythm is not uniform, and a team that pins to a tag should expect occasional quiet periods followed by clustered releases.

The licence is MIT, which permits commercial and private use; this is a statement of what the licence file says, not legal advice, and anyone with specific obligations should read the LICENSE file themselves. The practical upgrade cost is low because the action is referenced by tag in the workflow, and the README's examples all use @v2. Moving between v2 releases is a one-line edit. The larger cost is not the action version but the Flutter version it installs: bumping flutter-version changes the compiler, the Dart SDK and the plugin resolution at once, so the action update and the SDK update should be treated as separate changes rather than one commit.

Editorial conclusion

Adopt subosito/flutter-action if your Flutter builds already live in GitHub Actions and you want the SDK version pinned in the workflow file rather than on the runner image. Skip it if you build outside GitHub, or if you need a version range in pubspec.yaml, because flutter-version-file requires an exact value. Before merging, check the runner's Actions Runner version against the 2.327.1 floor the README sets for cache support, and confirm whether your project needs the extra apt packages for a Linux desktop build.

Frequently asked questions

What does subosito/flutter-action do?

It installs a Flutter SDK on a GitHub Actions runner so later steps can run flutter commands. The README describes it as a Flutter environment for use in GitHub Actions that works on Linux, Windows and macOS.

Can subosito/flutter-action read the Flutter version from pubspec.yaml?

Yes, through the flutter-version-file input, which the README shows accepting a path to pubspec.yaml, .fvmrc or .fvm/fvm_config.json. The README states the version in pubspec.yaml must be exact, so a range is not accepted.

Does subosito/flutter-action support caching?

The README documents integration with actions/cache and states the action now uses actions/cache@v5 internally. For self-hosted runners it says the runner must be updated to Actions Runner 2.327.1 or newer before enabling cache support.

Can subosito/flutter-action build a Flutter app for iOS?

The action installs Flutter, but the README notes that building for iOS requires a macOS runner, so the job must use a macOS runner such as macos-latest. The same note applies to building for macOS desktop.

Can subosito/flutter-action use a Flutter fork instead of flutter/flutter?

Yes. The README documents a git-source input for alternative Flutters and names Flock and a HarmonyOS-capable fork as examples, used alongside channel and flutter-version.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Releases
  5. subosito/flutter-action on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/subosito-flutter-action.svg)](https://hysenlabs.com/projects/subosito-flutter-action)