18 KiB
Mobile App Release Process
For Staff Mobile & Client Mobile Apps
Document Version: 2.0
Last Updated: 2026-03-06
Status: ✅ Production Ready
📱 Overview
This document covers the complete release process for both mobile applications:
- Staff Mobile App (Worker Mobile) -
krow-withus-worker-mobile - Client Mobile App -
krow-withus-client-mobile
Both apps:
- Built with Flutter
- Distributed via iOS App Store & Google Play Store
- Maintain independent versions
- Have independent CHANGELOGs
- Released via GitHub Actions workflows
📐 Versioning Strategy
Semantic Versioning with Milestones
We use Semantic Versioning 2.0.0 with milestone suffixes:
MAJOR.MINOR.PATCH-milestone
Examples:
0.0.1-m3- Milestone 3 release0.0.1-m4- Milestone 4 release1.0.0- First production release (no suffix)1.0.1- Production patch release
Version Rules:
- MAJOR: Breaking changes, major architectural updates
- MINOR: New features, backward-compatible changes
- PATCH: Bug fixes, minor improvements
- SUFFIX:
-m3,-m4, etc. for milestone tracking
Version Location
Versions are defined in pubspec.yaml:
Staff Mobile: apps/mobile/apps/staff/pubspec.yaml
version: 0.0.1-m4+1
Client Mobile: apps/mobile/apps/client/pubspec.yaml
version: 0.0.1-m4+1
Format: X.Y.Z-suffix+buildNumber
0.0.1-m4= version with milestone+1= build number (for app stores)
Version Auto-Extraction
GitHub Actions workflows automatically extract the version from pubspec.yaml using .github/scripts/extract-version.sh. No manual version input required.
📝 CHANGELOG Management
File Locations
- Staff Mobile:
apps/mobile/apps/staff/CHANGELOG.md - Client Mobile:
apps/mobile/apps/client/CHANGELOG.md
Format Standard
# [App Name] - Change Log
## [v0.0.1-m4] - Milestone 4 - 2026-03-05
### Added - [Category Name]
- Feature description
- Another feature
### Fixed
- Bug fix description
### Changed
- Changed behavior
---
## [v0.0.1-m3] - Milestone 3 - 2026-02-15
### Added - [Category Name]
...
Section Guidelines
Use these standard categories:
- Added: New features
- Fixed: Bug fixes
- Changed: Changes to existing functionality
- Deprecated: Soon-to-be removed features
- Removed: Removed features
- Security: Security fixes
When to Update CHANGELOG
✅ Update BEFORE release:
- When milestone is complete
- Document all user-facing changes
- Include technical features if relevant
❌ Don't document:
- Internal refactoring (unless architecturally significant)
- Development-only changes
- Code formatting/linting
🏷️ Git Tag Format
Tag Structure
krow-withus-<app>-mobile/<env>-v<version>
Examples
Staff Mobile (Worker):
krow-withus-worker-mobile/dev-v0.0.1-m3
krow-withus-worker-mobile/stage-v0.0.1-m4
krow-withus-worker-mobile/prod-v1.0.0
Client Mobile:
krow-withus-client-mobile/dev-v0.0.1-m3
krow-withus-client-mobile/stage-v0.0.1-m4
krow-withus-client-mobile/prod-v1.0.0
Tag Components
| Component | Values | Example |
|---|---|---|
| Product | worker, client |
worker |
| Type | mobile |
mobile |
| Environment | dev, stage, prod |
dev |
| Version | From pubspec.yaml | v0.0.1-m3 |
Note: Tags include the full version with milestone suffix (e.g., v0.0.1-m4, not just v0.0.1)
🚀 Release Workflows
Release Types
We have 2 GitHub Actions workflows for releases:
- Product Release (
.github/workflows/product-release.yml) - Standard releases - Hotfix Branch Creation (
.github/workflows/hotfix-branch-creation.yml) - Emergency fixes
Both workflows use manual triggers only (workflow_dispatch) - no automatic releases.
📦 Standard Release Process
Step 1: Prepare Release
-
Ensure milestone is complete
- All features implemented
- All tests passing
- Code reviews completed
-
Update CHANGELOG
# Edit the appropriate CHANGELOG file vi apps/mobile/apps/staff/CHANGELOG.md # OR vi apps/mobile/apps/client/CHANGELOG.md -
Update version in pubspec.yaml
# apps/mobile/apps/staff/pubspec.yaml version: 0.0.1-m4+1 -
Commit changes
git add apps/mobile/apps/staff/CHANGELOG.md apps/mobile/apps/staff/pubspec.yaml git commit -m "docs(mobile): prepare staff app v0.0.1-m4 release" git push origin dev
Step 2: Trigger Release Workflow
-
Navigate to GitHub Actions
- Go to: https://github.com/Oloodi/krow-workforce/actions
- Select "📦 Product Release" workflow
-
Click "Run workflow"
-
Select parameters:
- Branch:
dev(or release branch) - Product:
worker-mobile-apporclient-mobile-app - Environment:
dev,stage, orprod - Pre-release: Check if this is not a production release
- Branch:
-
Click "Run workflow"
Step 3: Monitor Workflow
The workflow performs these steps automatically:
-
✅ Validate & Create Release (Job 1)
- Extract version from pubspec.yaml
- Validate version format
- Generate tag name
- Create Git tag
- Extract release notes from CHANGELOG
- Create GitHub Release with formatted notes
-
🔨 Build Mobile Artifacts (Job 2)
- Setup Node.js 20
- Install Firebase CLI
- Generate Data Connect SDK
- Setup Java 17
- Setup Flutter 3.38.x
- Bootstrap with Melos
- Decode keystore from secrets
- Build signed APK
- Verify APK signature
- Upload APK to GitHub Release
Step 4: Verify Release
-
Check GitHub Releases page
- URL: https://github.com/Oloodi/krow-workforce/releases
- Verify release was created with correct tag
- Verify release notes display correctly
- Verify APK is attached (if applicable)
-
Test the release
- Download APK (dev releases)
- Install on test device
- Verify app launches and core features work
🔥 Hotfix Process
When to Use Hotfix
✅ Use hotfix for:
- Critical bug in production affecting users
- Data loss or security vulnerability
- Service unavailable or major feature broken
- Customer-blocking issue
❌ Don't use hotfix for:
- Minor bugs (can wait for next release)
- Feature requests
- UI/UX improvements
- Styling issues
Hotfix Workflow
-
Navigate to GitHub Actions
- Go to: https://github.com/Oloodi/krow-workforce/actions
- Select "🚨 Product Hotfix - Create Branch" workflow
-
Click "Run workflow"
-
Fill in parameters:
- Product:
worker-mobile-apporclient-mobile-app - Current Production Version: e.g.,
1.0.0(without 'v' prefix) - Issue Description: Brief description of the bug (used in CHANGELOG and branch name)
- Product:
-
The workflow automatically:
- Creates hotfix branch:
hotfix/krow-withus-worker-mobile/prod-v1.0.1 - Increments PATCH version:
1.0.0→1.0.1 - Updates
pubspec.yamlwith new version - Updates CHANGELOG.md with hotfix entry
- Creates Pull Request with hotfix instructions
- Creates hotfix branch:
-
Fix the bug:
# Checkout the hotfix branch git fetch origin git checkout hotfix/krow-withus-worker-mobile/prod-v1.0.1 # Make your fix # ... edit files ... # Test thoroughly flutter test # Commit your fix git add . git commit -m "fix(mobile): resolve critical production bug" git push origin hotfix/krow-withus-worker-mobile/prod-v1.0.1 -
Merge and Release:
- Review and merge the Pull Request to
main(or production branch) - Trigger Product Release workflow with
prodenvironment - Workflow will create tag
krow-withus-worker-mobile/prod-v1.0.1 - Deploy hotfix to production
- Review and merge the Pull Request to
-
Backport to dev:
git checkout dev git merge hotfix/krow-withus-worker-mobile/prod-v1.0.1 git push origin dev
🔐 APK Signing Setup
Overview
All Android builds require signing with keystores. We use 24 GitHub Secrets (12 per app × 2 apps):
- 6 keystores (2 apps × 3 environments)
- 4 secrets per keystore (base64, password, alias, key password)
Keystore Files
Worker Mobile (Staff App):
krow_with_us_staff_dev.jks- ✅ Committed to repokrow_staff_staging.jks- ⚠️ Store in GitHub Secrets onlykrow_staff_prod.jks- ⚠️ Store in GitHub Secrets only
Client Mobile:
krow_with_us_client_dev.jks- ✅ Committed to repokrow_client_staging.jks- ⚠️ Store in GitHub Secrets onlykrow_client_prod.jks- ⚠️ Store in GitHub Secrets only
Required GitHub Secrets
Worker Mobile - 12 Secrets
Dev Environment:
WORKER_KEYSTORE_DEV_BASE64WORKER_KEYSTORE_PASSWORD_DEVWORKER_KEY_ALIAS_DEVWORKER_KEY_PASSWORD_DEV
Staging Environment:
WORKER_KEYSTORE_STAGING_BASE64WORKER_KEYSTORE_PASSWORD_STAGINGWORKER_KEY_ALIAS_STAGINGWORKER_KEY_PASSWORD_STAGING
Production Environment:
WORKER_KEYSTORE_PROD_BASE64WORKER_KEYSTORE_PASSWORD_PRODWORKER_KEY_ALIAS_PRODWORKER_KEY_PASSWORD_PROD
Client Mobile - 12 Secrets
Dev Environment:
CLIENT_KEYSTORE_DEV_BASE64CLIENT_KEYSTORE_PASSWORD_DEVCLIENT_KEY_ALIAS_DEVCLIENT_KEY_PASSWORD_DEV
Staging Environment:
CLIENT_KEYSTORE_STAGING_BASE64CLIENT_KEYSTORE_PASSWORD_STAGINGCLIENT_KEY_ALIAS_STAGINGCLIENT_KEY_PASSWORD_STAGING
Production Environment:
CLIENT_KEYSTORE_PROD_BASE64CLIENT_KEYSTORE_PASSWORD_PRODCLIENT_KEY_ALIAS_PRODCLIENT_KEY_PASSWORD_PROD
Setup Using Helper Script
We provide an interactive script to configure all secrets:
.github/scripts/setup-mobile-github-secrets.sh
This script will:
- Prompt for keystore file paths
- Convert keystores to base64
- Prompt for passwords and aliases
- Display GitHub CLI commands to set secrets
- Optionally execute the commands
Manual Setup
If you prefer manual setup:
# 1. Convert keystore to base64
base64 -i /path/to/keystore.jks | pbcopy
# 2. Add to GitHub Secrets via web UI
# Go to: Repository → Settings → Secrets and variables → Actions
# Click "New repository secret"
# Name: WORKER_KEYSTORE_PROD_BASE64
# Value: Paste the base64 string
# 3. Repeat for all 24 secrets
Or use GitHub CLI:
# Set a secret using gh CLI
gh secret set WORKER_KEYSTORE_PROD_BASE64 < /path/to/keystore_base64.txt
# Set multiple secrets
gh secret set WORKER_KEYSTORE_PASSWORD_PROD -b "your_password"
gh secret set WORKER_KEY_ALIAS_PROD -b "your_alias"
gh secret set WORKER_KEY_PASSWORD_PROD -b "your_key_password"
Verifying APK Signature
After build, the workflow automatically verifies the APK signature using:
.github/scripts/verify-apk-signature.sh <path-to-apk> <expected-alias>
📅 Release Cadence
Development Releases (dev)
- Frequency: As needed (daily/weekly)
- Purpose: Test features, integration testing
- Stability: Unstable, may have bugs
- Distribution: Internal testing only
- APK: Signed with dev keystore
- Tag example:
krow-withus-worker-mobile/dev-v0.0.1-m3
Staging Releases (stage)
- Frequency: Bi-weekly (end of sprints)
- Purpose: QA testing, client demos
- Stability: Stable, feature-complete
- Distribution: QA team, stakeholders
- APK: Signed with staging keystore
- Tag example:
krow-withus-worker-mobile/stage-v0.0.1-m4
Production Releases (prod)
- Frequency: Monthly or milestone-based
- Purpose: Public release to app stores
- Stability: Production-grade, thoroughly tested
- Distribution: Public (App Store, Play Store)
- APK: Signed with production keystore
- Tag example:
krow-withus-worker-mobile/prod-v1.0.0
🛠️ Helper Scripts Reference
All scripts are located in .github/scripts/ and are used by workflows:
1. extract-version.sh
Purpose: Extract version from pubspec.yaml
Usage:
.github/scripts/extract-version.sh <path-to-pubspec.yaml>
Example:
VERSION=$(.github/scripts/extract-version.sh apps/mobile/apps/staff/pubspec.yaml)
echo $VERSION # Output: 0.0.1-m4
2. generate-tag-name.sh
Purpose: Generate consistent Git tag names
Usage:
.github/scripts/generate-tag-name.sh <app> <env> <version>
Example:
TAG=$(.github/scripts/generate-tag-name.sh worker dev 0.0.1-m4)
echo $TAG # Output: krow-withus-worker-mobile/dev-v0.0.1-m4
3. extract-release-notes.sh
Purpose: Extract CHANGELOG section for a specific version
Usage:
.github/scripts/extract-release-notes.sh <app> <env> <version> <tag>
Example:
NOTES=$(.github/scripts/extract-release-notes.sh worker dev 0.0.1-m4 krow-withus-worker-mobile/dev-v0.0.1-m4)
Output format:
**Environment:** DEV
**Tag:** krow-withus-worker-mobile/dev-v0.0.1-m4
## What is new in this release
[CHANGELOG content for v0.0.1-m4]
4. create-release-summary.sh
Purpose: Generate GitHub Step Summary with emojis
Usage:
.github/scripts/create-release-summary.sh <app> <env> <version> <tag>
Creates: Formatted summary in GitHub Actions UI
5. setup-apk-signing.sh
Purpose: Setup APK signing environment variables
Usage (in workflow):
.github/scripts/setup-apk-signing.sh <app> <env>
What it does:
- Decodes base64 keystore to file
- Sets
CM_KEYSTORE_PATH_<APP>environment variable - Sets keystore password, alias, and key password
6. verify-apk-signature.sh
Purpose: Verify APK is properly signed
Usage:
.github/scripts/verify-apk-signature.sh <apk-path> <expected-alias>
Example:
.github/scripts/verify-apk-signature.sh build/app/outputs/apk/release/app-release.apk androidreleasekey
7. attach-apk-to-release.sh
Purpose: Upload APK to existing GitHub Release
Usage:
.github/scripts/attach-apk-to-release.sh <tag> <apk-path> <app>
Example:
.github/scripts/attach-apk-to-release.sh krow-withus-worker-mobile/dev-v0.0.1-m4 build/app/outputs/apk/release/app-release.apk worker
8. setup-mobile-github-secrets.sh
Purpose: Interactive helper to configure all GitHub Secrets
Usage:
.github/scripts/setup-mobile-github-secrets.sh
Interactive prompts for:
- Keystore file paths
- Passwords and aliases
- Generates GitHub CLI commands
- Optionally executes commands
📋 Pre-Release Checklist
Before triggering a release, ensure:
Code Quality
- All automated tests pass
- No critical linting errors
- Code review completed (for stage/prod)
- Security audit passed (for prod)
Documentation
- CHANGELOG.md updated with all changes
- Version in pubspec.yaml matches CHANGELOG
- Breaking changes documented
- Migration guide created (if needed)
Testing
- Feature testing completed
- Regression testing passed
- Performance testing acceptable
- Device compatibility verified
Configuration
- Environment variables configured
- API endpoints correct for environment
- Feature flags set appropriately
- Analytics tracking verified
GitHub Secrets (First-time setup)
- All 24 secrets configured
- Keystore passwords verified
- Test build succeeded with signing
🐛 Troubleshooting
Workflow Fails: "Version not found in pubspec.yaml"
Cause: Invalid version format or missing version
Solution:
# Ensure version line in pubspec.yaml looks like:
version: 0.0.1-m4+1
# Not:
version: 0.0.1 # Missing build number
version: "0.0.1-m4+1" # Don't quote the version
Workflow Fails: "Secret not found"
Cause: Missing GitHub Secret
Solution:
- Check secret name matches exactly (case-sensitive)
- Run
.github/scripts/setup-mobile-github-secrets.sh - Verify secrets at: Repository → Settings → Secrets and variables → Actions
APK Signing Fails
Cause: Invalid keystore or wrong password
Solution:
- Verify keystore base64 encoding:
base64 -i keystore.jks | base64 -d > test.jks - Test password locally:
keytool -list -keystore test.jks - Verify alias:
keytool -list -v -keystore test.jks | grep "Alias name"
CHANGELOG Not Extracted
Cause: Version format doesn't match in CHANGELOG
Solution:
# CHANGELOG.md must have this EXACT format:
## [v0.0.1-m4] - Milestone 4 - 2026-03-05
# OR
## [0.0.1-m4] - Milestone 4 - 2026-03-05
# The script tries both [vX.Y.Z] and [X.Y.Z] formats
Tag Already Exists
Cause: Trying to create a duplicate tag
Solution:
# Delete the existing tag (CAREFUL!)
git tag -d krow-withus-worker-mobile/dev-v0.0.1-m4
git push origin :refs/tags/krow-withus-worker-mobile/dev-v0.0.1-m4
# Then re-run the workflow
📚 Additional Resources
Related Documentation
GitHub Actions Workflows
- Product Release:
.github/workflows/product-release.yml - Hotfix Branch Creation:
.github/workflows/hotfix-branch-creation.yml - Mobile CI:
.github/workflows/mobile-ci.yml
Useful Commands
# View current version
grep "^version:" apps/mobile/apps/staff/pubspec.yaml
# List all mobile tags
git tag -l "krow-withus-*-mobile/*"
# View latest releases
gh release list --limit 10
# Download APK from release
gh release download krow-withus-worker-mobile/dev-v0.0.1-m4 --pattern "*.apk"
🔄 Version History
| Version | Date | Changes |
|---|---|---|
| 2.0 | 2026-03-06 | Consolidated all release docs into single file |
| 1.0 | 2026-03-05 | Initial separate documentation files |
Questions or Issues?
Contact the DevOps team or create an issue in the repository.