A real pain point for mobile apps is waiting days or weeks for App Store and Play Store reviews whenever you need to ship a fix or a small update to users. That exact problem is what we are solving in this article. I’ll show you exactly how to automate your Flutter releases and patches using Shorebird and GitHub Actions, so you can push updates to users in minutes instead of waiting for store review. We are going to create a clean, production-ready CI pipeline for both full releases and instant code-push updates. Prerequisites Before we start, here’s what you need: A Shorebird account and an app already set up with Shorebird Shorebird CLI installed and logged in on your machine A Flutter project that already has Shorebird initialized A GitHub repository Basic understanding of GitHub Actions If you haven’t set up Shorebird in your Flutter app yet, check out my video on YouTube on how to set up Shorebird . This article assumes that’s already done. Authentication Setup The first thing we need is authentication so GitHub Actions can talk to Shorebird. Go to the Shorebird Console → Account → API Keys → Create API Key. Give it a clear name, e.g “GitHub Actions”, choose an expiration, and set the required permissions. Copy the key immediately because you won’t see it again. Now go to your GitHub repository → Settings → Secrets and variables → Actions → New repository secret. Name it exactly: SHOREBIRD_TOKEN Paste the key and save. This token will be available in all your workflows as {{ secrets.SHOREBIRD_TOKEN }} . That’s the only authentication step you need. Official Shorebird GitHub Actions Shorebird provides three official GitHub Actions that make life much easier: shorebirdtech/setup-shorebird@v1 — installs Shorebird on the runner shorebirdtech/shorebird-release@v1 — creates a release shorebirdtech/shorebird-patch@v1 — creates a patch I strongly recommend using these instead of calling the CLI manually. They’re cleaner and maintained by the Shorebird team. Release Workflow Let’s build the release workflow first. Create a new file in your project: .github/workflows/shorebird-release.yml Here’s the structure: Trigger on version tags: v1.0.0, v1.2.3, etc. or manually trigger the workflow Set the SHOREBIRD_TOKEN as an environment variable Pin your Flutter version (very important) Checkout the code Set up Java for Android (or Xcode signing for iOS) Set up Shorebird with caching Decode your keystore/certificates from secrets Run the official shorebird-release action Upload the APK, AAB, or IPA as artifacts I’ll show both Android and iOS versions. For Android, the key steps are decoding the keystore and creating the key.properties file from secrets. GitHub Secrets You Need to Add for Android Go to GitHub → repo → Settings → Secrets and variables → Actions → New repository secret Secret name - Value ANDROID_KEY_ALIAS - your_key_alias ANDROID_KEY_PASSWORD - your_key_password ANDROID_STORE_PASSWORD - your_store_password ANDROID_KEYSTORE_BASE64 - run ` base64 -i ~/path/to/upload.jks | tr -d '\n' | pbcopy ` The keystore base64 will be copied to your clipboard ; paste it into GitHub Secrets GitHub Secrets You Need to Add for iOS Go to GitHub → repo → Settings → Secrets and variables → Actions → New repository secret Secret name - Value IOS_CERTIFICATE_BASE64 - base64 of your .p12 IOS_CERTIFICATE_PASSWORD - Password you set when exporting the .p12 IOS_PROVISIONING_PROFILE_BASE64 - base64 of com.example.app profile For iOS, you need to import the certificate and provisioning profile into a temporary keychain. # IOS_CERTIFICATE_BASE64 - export your .p12 from Keychain Access first, then: base64 -i ~/path/to/distribution.p12 | tr -d '\n' | pbcopy # IOS_PROVISIONING_PROFILE_BASE64 - download from Apple Developer Portal base64 -i ~/path/to/YourApp_AppStore.mobileprovision | tr -d '\n' | pbcopy You can check out this document on how to create an Apple Distribution Certificate . Once this workflow finishes, you get signed artifacts ready to upload to the stores. This is your normal full release path. name : Shorebird Release on : workflow_dispatch : inputs : platform : description : ' Target platform' required : true default : ' both' type : choice options : - android - ios - both jobs : release_android : name : Release Android if : {{ github.event.inputs.platform == 'android' || github.event.inputs.platform == 'both' }} runs-on : ubuntu-latest steps : - name : Checkout Repository uses : actions/checkout@v4 - name : Setup Java uses : actions/setup-java@v4 with : distribution : ' temurin' java-version : ' 17' - name : Setup Android Keystore run : | echo "{{ secrets.ANDROID_STORE_PASSWORD }} keyPassword={{ secrets.ANDROID_KEY_ALIAS }} storeFile=keystore.jks EOF shell : bash - name : Setup Shorebird uses : shorebirdtech/setup-shorebird@v1 - name : Shorebird Release (Android) uses : shorebirdtech/shorebird-release@v1 id : shorebird-release with : flutter-version : latest platform : android env : SHOREBIRD_TOKEN : {{ steps.shorebird-release.outputs.release-version }}" shell : bash Full release on GitHub Gist . Patch Workflow — The Real Power Now, the part that actually lets you skip App Store review. Create another file: .github/workflows/shorebird-patch.yml name : Shorebird Patch on : push : branches : - main workflow_dispatch : inputs : platform : description : ' Target platform' required : true default : ' both' type : choice options : - android - ios - both release-version : description : ' Release version to patch (e.g. 1.0.0+1). Defaults to latest.' required : false default : ' latest' jobs : patch_android : name : Patch Android if : {{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 --decode > android/app/keystore.jks cat > android/key.properties <<EOF storePassword={{ secrets.ANDROID_KEY_PASSWORD }} keyAlias={{ github.event.inputs.release-version || 'latest' }} args : --allow-asset-diffs --allow-native-diffs env : SHOREBIRD_TOKEN : {{ steps.shorebird-patch.outputs.patch-number }}" shell : bash Full release on GitHub Gist . Trigger this one on hotfix tags, for example: v1.0.0-hotfix.1 The structure is almost identical to the release workflow, but we use the shorebird-patch action instead. Important points: A patch can only be applied to an existing release Use the — staging flag first so you can preview the update After testing with shorebird preview — track=staging, promote it to production from the Shorebird Console. This is the real magic. Users get the fix over-the-air (OTA) in minutes. No waiting for review. No forcing them to download a new version from the store. Recommended Development Workflow Here’s the clean workflow I recommend (and the one Shorebird documents): Work on features and fixes on feature branches Open a pull request into main CI runs formatting, analysis, and tests Squash and merge into main (main stays always releasable) When you’re ready for a full release → create a tag like v1.2.0 → the release workflow runs automatically If a critical bug appears → fix it on main → cherry-pick into the release branch → create a hotfix tag like v1.2.0-hotfix.1 → the patch workflow runs Preview on staging → promote to production This keeps everything automated, clean, and low-risk. Best Practices A few important tips: Always pin the Flutter version on releases using — flutter-version Use — dry-run on pull requests so you catch build issues early without creating real releases or patches Keep your SHOREBIRD_TOKEN secure — never hardcode it For iOS environments without certificates, you can use — no-codesign (then sign later) Shorebird automatically runs in non-interactive mode in CI when the token is present Follow these, and your pipeline will be solid. Resources All of this is based on the official Shorebird documentation: GitHub Integration guide Generic CI guide Development Workflow guide I’m also a Shorebird Ambassador , so if you have questions, drop them in the comments. That’s it. You now have a complete automated system: Full releases go through the stores as usual Critical updates and bug fixes go live to users in minutes via Shorebird No more waiting for review every single time. If this was useful, hit the like button, subscribe, and turn on notifications so you don’t miss the next post. If you want personalized help setting this up for your project, you can send a DM. I’ll see you in the next one. Peace.

Automate Flutter Releases with Shorebird + GitHub Actions (Skip App Store Review)
Samuel Adekunle

