A collection of reusable GitHub workflows and actions for Flutter projects, providing automated CI/CD pipelines for Android builds, testing, and release management.
Install the workflows in your Flutter repository with a single command:
curl -fsSL https://raw.githubusercontent.com/lumicrafte/ci-kit/main/install.sh | bashOr download and run the installer:
curl -fsSL https://raw.githubusercontent.com/lumicrafte/ci-kit/main/install.sh -o install.sh
chmod +x install.sh
./install.shDownload the installer and install a specific version by providing a tag or branch name:
# Download the installer
curl -fsSL https://raw.githubusercontent.com/lumicrafte/ci-kit/main/install.sh -o install.sh
chmod +x install.sh
# Install specific version tag
./install.sh v1.0.0
# Or install from a specific branch
./install.sh developOr in one command:
# Install specific version
curl -fsSL https://raw.githubusercontent.com/lumicrafte/ci-kit/main/install.sh | bash -s v1.0.0To update to the latest version, download and run the installer again:
curl -fsSL https://raw.githubusercontent.com/lumicrafte/ci-kit/main/install.sh | bashOr to update to a specific version:
curl -fsSL https://raw.githubusercontent.com/lumicrafte/ci-kit/main/install.sh | bash -s v1.0.0If you already have install.sh downloaded, you can simply run:
./install.sh # Latest version
./install.sh v1.0.0 # Specific version- ci.yml - Continuous Integration workflow for automated testing and builds
- manual-build.yml - Manual trigger for building Android releases
- publish-playstore.yml - Publish app bundles to Google Play Store tracks
- promote-playstore.yml - Promote releases between Play Store tracks
- update-playstore-listing.yml - Update Play Store listing metadata (title, descriptions, screenshots, graphics)
- tag-validation.yml - Validates version tags and ensures proper versioning
- setup-android-signing - Configures Android app signing with keystore
- setup-flutter - Sets up Flutter SDK with caching
- build-android - Builds Android APK/AAB with configurable options
- process-release-notes - Processes multilingual release notes for Play Store
- validate-playstore-secrets - Validates Play Store configuration (secrets and variables)
- validate-playstore-structure - Validates .playstore directory structure and files
- process-listing-metadata - Processes .playstore files into API-ready format
- update-playstore-listing - Updates Play Store listing via Google Play API
After installation, configure these variables in your GitHub repository or organization:
Go to Settings → Secrets and variables → Actions → Variables and add:
Note: Variables can be set at the organization level and inherited by all repositories. Individual repositories can override organization-level variables by setting their own values.
| Variable | Description | Example |
|---|---|---|
ANDROID_KEYSTORE_BASE64 |
Base64 encoded keystore file | (see below) |
ANDROID_KEY_PROPERTIES |
Key properties file content | (see below) |
PLAY_STORE_PACKAGE_NAME |
Your app's package name (for Play Store publishing) | com.example.myapp |
| Secret | Description | Example |
|---|---|---|
PLAY_STORE_SERVICE_ACCOUNT |
Service account JSON from Google Play Console | (see below) |
| Variable | Description | Default |
|---|---|---|
FLUTTER_VERSION |
Flutter SDK version | 3.35.x |
JAVA_VERSION |
Java JDK version | 17 |
base64 -w 0 android/app/upload-keystore.jks > keystore.base64Copy the contents of keystore.base64 and paste it as the value for ANDROID_KEYSTORE_BASE64 variable.
Create a variable named ANDROID_KEY_PROPERTIES with this format:
storePassword=YOUR_STORE_PASSWORD
keyPassword=YOUR_KEY_PASSWORD
keyAlias=YOUR_KEY_ALIAS
storeFile=upload-keystore.jksReplace the placeholders with your actual keystore credentials.
⚠️ IMPORTANT PREREQUISITE: Before using these workflows to publish to Play Store, you must manually create your app in the Play Console first. The Google Play API cannot create new apps - it can only manage existing ones.To create your app:
- Go to Google Play Console
- Click "Create app"
- Fill in app details (name, default language, app type, category)
- Use the exact package name that matches your Flutter app (found in
android/app/build.gradle)- Complete required setup sections:
- App access
- Content rating questionnaire
- Target audience and content
- Store presence (at minimum)
- Once created, you can use the workflows below to automate publishing
Without creating the app first, the workflow will fail with a clear error message.
- Go to Google Cloud Console
- Select your project (or create a new one)
- Navigate to IAM & Admin → Service Accounts
- Click Create Service Account
- Name it (e.g., "GitHub Actions Publisher")
- Click Create and Continue
- Skip granting roles (permissions handled in Play Console)
- Click Done
- Click on the created service account → Keys tab
- Add Key → Create new key → JSON
- Download the JSON file (keep it secure!)
- Note the service account email (looks like
name@project-id.iam.gserviceaccount.com)
-
Go to Google Play Console
-
Navigate to Users and permissions (left sidebar)
-
Click Invite new users
-
Enter the service account email from step 1
-
Option A - Create Permission Group (Recommended):
- Click Create and manage permission groups
- Click Create permission group
- Name it (e.g., "API Publishers")
- In Account permissions tab, select:
- ✅ Release to production, exclude devices, and use Play App Signing
- ✅ Release apps to testing tracks
- ✅ Manage store presence
- In App permissions tab, select your app and grant the same permissions
- Click Create
- Go back to invite user, assign the permission group
Option B - Direct Permissions:
- Select permissions manually in both Account and App tabs
- Grant the same permissions listed above
-
Click Invite user / Send invite
GitHub Repository → Settings → Secrets and variables → Actions:
Secrets tab:
PLAY_STORE_SERVICE_ACCOUNT: Paste the entire content of the downloaded JSON file from step 1
Variables tab:
PLAY_STORE_PACKAGE_NAME: Your app's package name (e.g.,com.example.app)
Publish new build:
-
Build: Go to Actions → Manual Build
- Click Run workflow
- Select "Build Android App Bundle Release"
- Click Run workflow
- Wait for build to complete
- Copy the workflow run URL from your browser (e.g.,
https://github.com/owner/repo/actions/runs/123456)
-
Publish: Go to Actions → Publish to Play Store
- Click Run workflow
- Paste the build run URL (from step 1)
- Select track (internal, alpha, beta, or production)
- Select release status:
draft- Save release for manual review (use for unpublished/draft apps)completed- Publish immediately (default)inProgress- Start staged rollouthalted- Pause an existing rollout
- Optional: Add release notes and configure rollout percentage
- Click Run workflow
Important for first-time releases:
- If your app is not yet published, use
release_status: draft - After the first manual publish through Play Console, use
release_status: completed
Promote between tracks:
- Actions → Promote Play Store Release → Select from/to tracks
- Keeps existing release notes unless you provide new ones
Available tracks: internal → alpha → beta → production
Update your app's Play Store listing (title, descriptions, screenshots, graphics) without publishing a new version.
Create the following structure in your repository:
.playstore/
├── metadata.yaml # App details (category, contact, privacy policy)
├── app-info.yaml # Multi-locale app info (title, descriptions)
├── graphics/
│ ├── icon.png # 512x512 app icon
│ ├── feature-graphic.png # 1024x500 feature graphic
│ └── promo-graphic.png # 180x120 promo graphic (optional)
└── screenshots/
├── en-US/
│ ├── phone/ # 2-8 phone screenshots (PNG/JPG)
│ ├── tablet/ # Tablet screenshots (optional)
│ └── wear/ # Wear screenshots (optional)
└── es-ES/ # Additional locales...
└── phone/
category: GAME_PUZZLE # See Google Play categories
contact:
website: https://example.com
email: support@example.com
phone: "+1234567890"
privacy_policy_url: https://example.com/privacy
default_language: en-USlocales:
en-US:
title: "My Awesome App" # Max 30 characters
short_description: "Quick puzzle game" # Max 80 characters
full_description: | # Max 4000 characters
A detailed description of the app.
Multiple lines supported.
Features:
- Feature 1
- Feature 2
video: "https://www.youtube.com/watch?v=..." # Optional
es-ES:
title: "Mi Aplicación Increíble"
short_description: "Juego de rompecabezas rápido"
full_description: |
Una descripción detallada de la aplicación...- Icon: 512x512 PNG at
.playstore/graphics/icon.png - Feature Graphic: 1024x500 PNG/JPG at
.playstore/graphics/feature-graphic.png - Screenshots: 320-3840px PNG/JPG (2-8 per device type)
Go to Actions → Update Play Store Listing:
-
Select what to update:
- ☑️ Update app details (metadata.yaml)
- ☑️ Update app info (app-info.yaml)
- ☑️ Update icon
- ☑️ Update feature graphic
- ☑️ Update screenshots
-
Optional: Specify locales (e.g.,
en-US,es-ES) or leave empty for all -
Optional: Enable dry run to validate without publishing
-
Click Run workflow
Tips:
- Use dry run first to validate your files
- You can update individual components without touching others
- Changes go live immediately (no draft mode for listing updates)
- All text fields have character limits - validation will catch issues
MIT