# 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 release
- `0.0.1-m4` - Milestone 4 release
- `1.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`
```yaml
version: 0.0.1-m4+1
```

**Client Mobile:** `apps/mobile/apps/client/pubspec.yaml`
```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

```markdown
# [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:

1. **Product Release** (`.github/workflows/product-release.yml`) - Standard releases
2. **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

1. **Ensure milestone is complete**
   - All features implemented
   - All tests passing
   - Code reviews completed

2. **Update CHANGELOG**
   ```bash
   # Edit the appropriate CHANGELOG file
   vi apps/mobile/apps/staff/CHANGELOG.md
   # OR
   vi apps/mobile/apps/client/CHANGELOG.md
   ```

3. **Update version in pubspec.yaml**
   ```yaml
   # apps/mobile/apps/staff/pubspec.yaml
   version: 0.0.1-m4+1
   ```

4. **Commit changes**
   ```bash
   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

1. **Navigate to GitHub Actions**
   - Go to: https://github.com/Oloodi/krow-workforce/actions
   - Select **"📦 Product Release"** workflow

2. **Click "Run workflow"**

3. **Select parameters:**
   - **Branch**: `dev` (or release branch)
   - **Product**: `worker-mobile-app` or `client-mobile-app`
   - **Environment**: `dev`, `stage`, or `prod`
   - **Pre-release**: Check if this is not a production release

4. **Click "Run workflow"**

### Step 3: Monitor Workflow

The workflow performs these steps automatically:

1. ✅ **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

2. 🔨 **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

1. **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)

2. **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

1. **Navigate to GitHub Actions**
   - Go to: https://github.com/Oloodi/krow-workforce/actions
   - Select **"🚨 Product Hotfix - Create Branch"** workflow

2. **Click "Run workflow"**

3. **Fill in parameters:**
   - **Product**: `worker-mobile-app` or `client-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)

4. **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.yaml` with new version
   - Updates CHANGELOG.md with hotfix entry
   - Creates Pull Request with hotfix instructions

5. **Fix the bug:**
   ```bash
   # 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
   ```

6. **Merge and Release:**
   - Review and merge the Pull Request to `main` (or production branch)
   - Trigger **Product Release** workflow with `prod` environment
   - Workflow will create tag `krow-withus-worker-mobile/prod-v1.0.1`
   - Deploy hotfix to production

7. **Backport to dev:**
   ```bash
   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 repo
- `krow_staff_staging.jks` - ⚠️ Store in GitHub Secrets only
- `krow_staff_prod.jks` - ⚠️ Store in GitHub Secrets only

**Client Mobile:**
- `krow_with_us_client_dev.jks` - ✅ Committed to repo
- `krow_client_staging.jks` - ⚠️ Store in GitHub Secrets only
- `krow_client_prod.jks` - ⚠️ Store in GitHub Secrets only

### Required GitHub Secrets

#### Worker Mobile - 12 Secrets

**Dev Environment:**
- `WORKER_KEYSTORE_DEV_BASE64`
- `WORKER_KEYSTORE_PASSWORD_DEV`
- `WORKER_KEY_ALIAS_DEV`
- `WORKER_KEY_PASSWORD_DEV`

**Staging Environment:**
- `WORKER_KEYSTORE_STAGING_BASE64`
- `WORKER_KEYSTORE_PASSWORD_STAGING`
- `WORKER_KEY_ALIAS_STAGING`
- `WORKER_KEY_PASSWORD_STAGING`

**Production Environment:**
- `WORKER_KEYSTORE_PROD_BASE64`
- `WORKER_KEYSTORE_PASSWORD_PROD`
- `WORKER_KEY_ALIAS_PROD`
- `WORKER_KEY_PASSWORD_PROD`

#### Client Mobile - 12 Secrets

**Dev Environment:**
- `CLIENT_KEYSTORE_DEV_BASE64`
- `CLIENT_KEYSTORE_PASSWORD_DEV`
- `CLIENT_KEY_ALIAS_DEV`
- `CLIENT_KEY_PASSWORD_DEV`

**Staging Environment:**
- `CLIENT_KEYSTORE_STAGING_BASE64`
- `CLIENT_KEYSTORE_PASSWORD_STAGING`
- `CLIENT_KEY_ALIAS_STAGING`
- `CLIENT_KEY_PASSWORD_STAGING`

**Production Environment:**
- `CLIENT_KEYSTORE_PROD_BASE64`
- `CLIENT_KEYSTORE_PASSWORD_PROD`
- `CLIENT_KEY_ALIAS_PROD`
- `CLIENT_KEY_PASSWORD_PROD`

### Setup Using Helper Script

We provide an interactive script to configure all secrets:

```bash
.github/scripts/setup-mobile-github-secrets.sh
```

This script will:
1. Prompt for keystore file paths
2. Convert keystores to base64
3. Prompt for passwords and aliases
4. Display GitHub CLI commands to set secrets
5. Optionally execute the commands

### Manual Setup

If you prefer manual setup:

```bash
# 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:

```bash
# 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:

```bash
.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**: 
```bash
.github/scripts/extract-version.sh <path-to-pubspec.yaml>
```
**Example**:
```bash
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**:
```bash
.github/scripts/generate-tag-name.sh <app> <env> <version>
```
**Example**:
```bash
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**:
```bash
.github/scripts/extract-release-notes.sh <app> <env> <version> <tag>
```
**Example**:
```bash
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**:
```bash
.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):
```bash
.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**:
```bash
.github/scripts/verify-apk-signature.sh <apk-path> <expected-alias>
```
**Example**:
```bash
.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**:
```bash
.github/scripts/attach-apk-to-release.sh <tag> <apk-path> <app>
```
**Example**:
```bash
.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**:
```bash
.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**:
```yaml
# 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**:
1. Check secret name matches exactly (case-sensitive)
2. Run `.github/scripts/setup-mobile-github-secrets.sh`
3. Verify secrets at: Repository → Settings → Secrets and variables → Actions

### APK Signing Fails

**Cause**: Invalid keystore or wrong password  
**Solution**:
1. Verify keystore base64 encoding: `base64 -i keystore.jks | base64 -d > test.jks`
2. Test password locally: `keytool -list -keystore test.jks`
3. Verify alias: `keytool -list -v -keystore test.jks | grep "Alias name"`

### CHANGELOG Not Extracted

**Cause**: Version format doesn't match in CHANGELOG  
**Solution**:
```markdown
# 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**:
```bash
# 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

- [Agent Development Rules](../MOBILE/00-agent-development-rules.md)
- [Architecture Principles](../MOBILE/01-architecture-principles.md)
- [Mobile CI Workflow](../../.github/workflows/mobile-ci.yml)

### 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

```bash
# 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.
