feat: Implement Windows runner for Flutter application

- Added FlutterWindow class to manage the Flutter view within a Win32 window.
- Created main entry point in main.cpp to initialize and run the Flutter application.
- Implemented utility functions for console attachment and command line argument parsing.
- Added resource management for application icon and manifest.
- Enhanced Win32Window class for DPI awareness and theme management.
- Included necessary headers and resource files for building the Windows runner.
This commit is contained in:
Janez T
2025-11-14 09:52:00 +01:00
commit 4577dec95a
314 changed files with 103048 additions and 0 deletions

411
.github/FASTLANE_TESTFLIGHT_SETUP.md vendored Normal file
View File

@@ -0,0 +1,411 @@
# Fastlane TestFlight Setup for CI/CD
This document describes how to configure Fastlane for automatic iOS beta deployments to TestFlight from GitHub Actions.
## Overview
The CI/CD pipeline automatically builds and uploads iOS beta builds to TestFlight for every push to `main`, `develop`, or release tags. This provides:
- **Automatic TestFlight distribution** for beta testers
- **Version management** with build number increments
- **Code signing** handled automatically in CI
- **Release notes** from git commits
## Prerequisites
Before setting up the CI/CD pipeline, ensure you have:
1. **Apple Developer Account** with:
- Paid Apple Developer Program membership ($99/year)
- App registered in App Store Connect
- TestFlight enabled for your app
2. **App Store Connect Access**:
- Admin or App Manager role
- App-specific password generated
3. **Code Signing Certificates**:
- Distribution certificate (`.p12` file)
- Ad Hoc or App Store provisioning profile
## Required GitHub Secrets
Configure these secrets in your GitHub repository settings (`Settings``Secrets and variables``Actions`):
### Certificate & Provisioning
| Secret Name | Description | How to Obtain |
|-------------|-------------|---------------|
| `IOS_P12_BASE64` | Base64-encoded distribution certificate | See [Exporting Certificate](#exporting-certificate) |
| `IOS_P12_PASSWORD` | Password for the .p12 certificate | Password you set when exporting |
| `IOS_PROVISION_PROFILE_BASE64` | Base64-encoded provisioning profile | See [Exporting Provisioning Profile](#exporting-provisioning-profile) |
### Apple Account Authentication
| Secret Name | Description | How to Obtain |
|-------------|-------------|---------------|
| `FASTLANE_USER` | Apple ID email address | Your Apple Developer account email (e.g., `hey@dz0ny.dev`) |
| `FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD` | App-specific password | See [Generating App-Specific Password](#generating-app-specific-password) |
| `FASTLANE_SESSION` | *(Optional)* Fastlane session for 2FA | See [Handling 2FA](#handling-2fa-optional) |
## Step-by-Step Setup
### 1. Exporting Certificate
#### Export Distribution Certificate from Keychain
1. Open **Keychain Access** on macOS
2. Select **login** keychain in the left sidebar
3. Select **Certificates** category
4. Find your **Apple Distribution** certificate
- Look for "Apple Distribution: Your Name (Team ID)"
- Ensure it has a valid private key (arrow to expand)
5. **Right-click****Export "Apple Distribution: ..."**
6. Save as: `distribution.p12`
7. **Set a strong password** (you'll need this for `IOS_P12_PASSWORD`)
8. Click **Save**
#### Convert to Base64
```bash
# Encode the .p12 file to base64
base64 -i distribution.p12 | pbcopy
```
The base64 string is now in your clipboard. Add it as `IOS_P12_BASE64` secret.
**Security Note**: Delete `distribution.p12` after encoding!
### 2. Exporting Provisioning Profile
#### Download from Apple Developer Portal
1. Log in to [Apple Developer Portal](https://developer.apple.com/account)
2. Navigate to **Certificates, Identifiers & Profiles**
3. Click **Profiles** in the left sidebar
4. Find your **App Store** or **Ad Hoc** provisioning profile
- Must match your app's bundle identifier: `com.meshcore.sar.meshcoreSarApp`
5. Click the profile → **Download**
6. Save as: `profile.mobileprovision`
#### Convert to Base64
```bash
# Encode the provisioning profile to base64
base64 -i profile.mobileprovision | pbcopy
```
The base64 string is now in your clipboard. Add it as `IOS_PROVISION_PROFILE_BASE64` secret.
**Security Note**: Delete `profile.mobileprovision` after encoding!
### 3. Generating App-Specific Password
App-specific passwords are required for App Store Connect API access when 2FA is enabled.
1. Log in to [Apple ID Account](https://appleid.apple.com/)
2. Navigate to **Sign-In and Security****App-Specific Passwords**
3. Click **Generate an app-specific password**
4. Enter a label: `GitHub Actions Fastlane`
5. Click **Create**
6. **Copy the generated password** (format: `xxxx-xxxx-xxxx-xxxx`)
- This will only be shown once!
7. Add it as `FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD` secret
### 4. Configure GitHub Secrets
1. Go to your GitHub repository
2. Navigate to **Settings****Secrets and variables****Actions**
3. Click **New repository secret** for each of the following:
**IOS_P12_BASE64**:
```
Paste the base64-encoded certificate from step 1
```
**IOS_P12_PASSWORD**:
```
The password you set when exporting the .p12 certificate
```
**IOS_PROVISION_PROFILE_BASE64**:
```
Paste the base64-encoded provisioning profile from step 2
```
**FASTLANE_USER**:
```
hey@dz0ny.dev
```
**FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD**:
```
xxxx-xxxx-xxxx-xxxx
```
### 5. Handling 2FA (Optional)
If your Apple account has two-factor authentication enabled, Fastlane may require a session token for long-running CI jobs.
#### Generate Fastlane Session
On your local machine:
```bash
# Install Fastlane if not already installed
gem install fastlane
# Generate session token
fastlane spaceauth -u hey@dz0ny.dev
```
You'll be prompted for:
1. Apple ID password
2. 2FA code (sent to your device)
Fastlane will output a session cookie. Copy the entire cookie string and add it as `FASTLANE_SESSION` secret.
**Note**: Session tokens expire after ~30 days. You'll need to regenerate periodically.
**Alternative**: If you don't set `FASTLANE_SESSION`, Fastlane will use the app-specific password, which works for most cases.
## Workflow Configuration
The workflow is already configured in `.github/workflows/build-multiplatform.yml`:
- **Triggers**: Pushes to `main`, `develop`, or version tags (`v*`)
- **Runs on**: macOS runner (required for iOS builds)
- **Fastlane Lane**: `beta` (builds IPA and uploads to TestFlight)
### What the Workflow Does
1. **Checks out code** and downloads versioned `pubspec.yaml` (for tags)
2. **Sets up Flutter** and installs dependencies
3. **Generates localizations** (`flutter gen-l10n`)
4. **Installs CocoaPods** dependencies
5. **Sets up Ruby** and installs Fastlane
6. **Imports code signing certificate** into temporary keychain
7. **Imports provisioning profile**
8. **Runs Fastlane beta lane**:
- Increments build number
- Builds signed IPA
- Uploads to TestFlight
9. **Cleans up keychain** (security)
10. **Uploads logs** if build fails (for debugging)
## Fastlane Configuration
The Fastlane configuration is in `ios/fastlane/`:
### Fastfile
```ruby
platform :ios do
desc "Push a new beta build to TestFlight"
lane :beta do
increment_build_number(xcodeproj: "Runner.xcodeproj")
build_app(workspace: "Runner.xcworkspace", scheme: "Runner")
upload_to_testflight
end
end
```
### Appfile
Contains your app configuration:
- Bundle identifier: `com.meshcore.sar.meshcoreSarApp`
- Apple ID: `hey@dz0ny.dev`
- Team IDs for App Store Connect and Developer Portal
## Testing the Setup
1. **Push a commit** to `main` or `develop` branch:
```bash
git checkout main
git commit --allow-empty -m "Test TestFlight deployment"
git push origin main
```
2. **Monitor the workflow**:
- Go to **Actions** tab in GitHub
- Click on the running workflow
- Watch the **Deploy iOS Beta to TestFlight** job
3. **Check TestFlight**:
- Log in to [App Store Connect](https://appstoreconnect.apple.com/)
- Navigate to **My Apps** → **MeshCore SAR** → **TestFlight**
- You should see a new build processing (takes 5-15 minutes)
4. **Verify build**:
- Once processing completes, the build is available for testing
- Add internal testers in TestFlight
- Testers will receive notification to download via TestFlight app
## Troubleshooting
### "Invalid certificate" error
**Cause**: Certificate doesn't match the provisioning profile or is expired.
**Solutions**:
- Verify certificate is **Distribution** type (not Development)
- Check certificate expiration date in Keychain Access
- Ensure provisioning profile includes the certificate
- Re-export and re-encode both certificate and profile
### "Invalid provisioning profile" error
**Cause**: Provisioning profile doesn't match app bundle ID or is expired.
**Solutions**:
- Verify bundle ID: `com.meshcore.sar.meshcoreSarApp`
- Check profile type: App Store or Ad Hoc (not Development)
- Regenerate profile in Apple Developer Portal
- Ensure profile includes all required devices (for Ad Hoc)
### "Authentication failed" error
**Cause**: Apple ID credentials are incorrect or expired.
**Solutions**:
- Verify `FASTLANE_USER` matches your Apple ID email
- Regenerate `FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD`
- If using 2FA, regenerate `FASTLANE_SESSION` token
- Check Apple Developer account is active (membership paid)
### "Build number conflict" error
**Cause**: Build number already exists in TestFlight.
**Solutions**:
- Fastlane auto-increments build number, but may fail if out of sync
- Manually increment version in `pubspec.yaml`
- Or modify Fastfile to use timestamp-based build numbers:
```ruby
increment_build_number(
build_number: Time.now.to_i.to_s,
xcodeproj: "Runner.xcodeproj"
)
```
### "Session expired" error
**Cause**: `FASTLANE_SESSION` token expired (lasts ~30 days).
**Solutions**:
- Regenerate session token: `fastlane spaceauth -u hey@dz0ny.dev`
- Update `FASTLANE_SESSION` secret in GitHub
- Or remove the secret and rely on app-specific password only
### Workflow doesn't run
**Cause**: Conditional check failed (wrong branch or secrets missing).
**Solutions**:
- Verify you pushed to `main` or `develop` branch
- Check all required secrets are configured in GitHub
- Review workflow logs for conditional evaluation
## Advanced Configuration
### Custom Release Notes
Add release notes from git commits:
Edit `ios/fastlane/Fastfile`:
```ruby
lane :beta do
increment_build_number(xcodeproj: "Runner.xcodeproj")
build_app(workspace: "Runner.xcworkspace", scheme: "Runner")
# Generate changelog from git
changelog = changelog_from_git_commits(
pretty: "- %s",
merge_commit_filtering: "exclude_merges"
)
upload_to_testflight(
changelog: changelog,
skip_waiting_for_build_processing: true
)
end
```
### Selective TestFlight Groups
Upload to specific tester groups:
```ruby
upload_to_testflight(
groups: ["Internal Testers", "Beta Team"],
distribute_external: false,
skip_waiting_for_build_processing: true
)
```
### Automatic Screenshot Upload
Generate and upload screenshots for App Store:
```ruby
lane :screenshots do
snapshot
end
lane :beta do
increment_build_number(xcodeproj: "Runner.xcodeproj")
build_app(workspace: "Runner.xcworkspace", scheme: "Runner")
upload_to_testflight
upload_to_app_store(
screenshots_path: "./fastlane/screenshots",
skip_binary_upload: true,
skip_metadata: true
)
end
```
## Security Best Practices
1. **Never commit secrets** to your repository
2. **Rotate certificates** before expiration (annually)
3. **Regenerate app-specific passwords** periodically
4. **Use temporary keychains** in CI (already implemented)
5. **Delete certificates** after encoding to base64
6. **Limit GitHub Actions secrets** to repository scope
7. **Review workflow logs** for sensitive data leaks
8. **Enable branch protection** for `main` and `develop`
## Cost Considerations
### Apple Developer Program
- **$99/year** for individual account
- **$299/year** for enterprise account
- Required for TestFlight distribution
### GitHub Actions
- **Free tier**: 2,000 minutes/month for private repos
- **macOS runners**: 10x multiplier (1 min = 10 mins)
- **Typical iOS build**: ~15-20 minutes (~150-200 minutes counted)
- **Monthly estimate**: ~10 builds = ~2,000 minutes (free tier limit)
**Tip**: Use caching and selective triggers to minimize build minutes.
## Additional Resources
- [Fastlane Documentation](https://docs.fastlane.tools/)
- [Fastlane TestFlight Guide](https://docs.fastlane.tools/actions/upload_to_testflight/)
- [Apple Developer Portal](https://developer.apple.com/account)
- [App Store Connect](https://appstoreconnect.apple.com/)
- [GitHub Actions for iOS](https://docs.github.com/en/actions/deployment/deploying-xcode-applications)
- [Fastlane Best Practices](https://docs.fastlane.tools/best-practices/)
## Support
For issues with:
- **Fastlane**: Check [Fastlane Docs](https://docs.fastlane.tools/) or [GitHub Issues](https://github.com/fastlane/fastlane/issues)
- **GitHub Actions**: Check [workflow logs](https://github.com/meshcore-dev/meshcore_sar_app/actions)
- **Code signing**: Check [Apple's Code Signing Guide](https://developer.apple.com/support/code-signing/)
- **TestFlight**: Check [App Store Connect Help](https://developer.apple.com/support/app-store-connect/)

285
.github/R2_SETUP.md vendored Normal file
View File

@@ -0,0 +1,285 @@
# Cloudflare R2 Setup for CI/CD
This document describes how to configure Cloudflare R2 for automatic artifact uploads from GitHub Actions.
## Overview
The CI/CD pipeline uploads build artifacts (APK, AAB, DMG, Windows ZIP) to a Cloudflare R2 bucket in the `unstable/` directory for every successful build. This provides:
- **Automatic artifact hosting** for all branches and commits
- **Latest builds** from main branch always available at `unstable/latest/`
- **Version tracking** with timestamps and commit hashes
- **Public download URLs** (optional) for testers and developers
- **Build manifests** with metadata for each build
- **Commit history** showing last 10 commits for each build
## Required GitHub Secrets
Configure these secrets in your GitHub repository settings (`Settings``Secrets and variables``Actions`):
### Required Secrets
| Secret Name | Description | How to Obtain |
|-------------|-------------|---------------|
| `R2_ACCOUNT_ID` | Your Cloudflare account ID | Cloudflare Dashboard → R2 → Overview (right sidebar) |
| `R2_ACCESS_KEY_ID` | R2 API token access key ID | Cloudflare Dashboard → R2 → Manage R2 API Tokens → Create API Token |
| `R2_SECRET_ACCESS_KEY` | R2 API token secret key | Generated when creating the API token (save immediately!) |
| `R2_BUCKET_NAME` | Name of your R2 bucket | Example: `meshcore-sar-builds` |
### Optional Secrets
| Secret Name | Description | Example |
|-------------|-------------|---------|
| `R2_PUBLIC_URL` | Public URL for R2 bucket (if public access configured) | `https://meshcore-sar.dz0ny.dev` |
## Step-by-Step Setup
### 1. Create Cloudflare R2 Bucket
1. Log in to [Cloudflare Dashboard](https://dash.cloudflare.com/)
2. Navigate to **R2** in the left sidebar
3. Click **Create Bucket**
4. Enter bucket name (e.g., `meshcore-sar-builds`)
5. Choose a location (e.g., `Automatic` or `ENAM` for Europe/North America)
6. Click **Create Bucket**
### 2. Create R2 API Token
1. In Cloudflare Dashboard, go to **R2****Manage R2 API Tokens**
2. Click **Create API Token**
3. Configure the token:
- **Token name**: `github-actions-upload`
- **Permissions**: Select **Object Read & Write**
- **Bucket scope**:
- Choose **Apply to specific buckets only**
- Select your bucket (e.g., `meshcore-sar-builds`)
4. Click **Create API Token**
5. **IMPORTANT**: Copy both the **Access Key ID** and **Secret Access Key** immediately
- The secret key will only be shown once!
- Save them securely (e.g., password manager)
### 3. Get Your Account ID
1. In Cloudflare Dashboard, go to **R2****Overview**
2. Your Account ID is displayed in the right sidebar
3. Copy the Account ID
### 4. Configure GitHub Secrets
1. Go to your GitHub repository
2. Navigate to **Settings****Secrets and variables****Actions**
3. Click **New repository secret** for each of the following:
**R2_ACCOUNT_ID**:
```
Paste your Cloudflare Account ID
```
**R2_ACCESS_KEY_ID**:
```
Paste the Access Key ID from step 2
```
**R2_SECRET_ACCESS_KEY**:
```
Paste the Secret Access Key from step 2
```
**R2_BUCKET_NAME**:
```
meshcore-sar-builds
```
### 5. (Optional) Configure Public Access
To enable public downloads from your R2 bucket:
#### Option A: Custom Domain (Recommended)
1. In Cloudflare Dashboard, go to **R2** → **Settings** for your bucket
2. Under **Public Access**, click **Connect Domain**
3. Enter your custom domain (e.g., `builds.meshcore.example.com`)
4. Follow Cloudflare's instructions to configure DNS
5. Add GitHub secret:
```
R2_PUBLIC_URL = https://builds.meshcore.example.com
```
#### Option B: R2.dev Subdomain (Quick Setup)
1. In Cloudflare Dashboard, go to **R2** → **Settings** for your bucket
2. Under **Public Access**, click **Allow Access**
3. Enable **R2.dev subdomain**
4. Copy the generated URL (e.g., `https://pub-xxxxx.r2.dev`)
5. Add GitHub secret:
```
R2_PUBLIC_URL = https://pub-xxxxx.r2.dev
```
**Note**: Without `R2_PUBLIC_URL` configured, artifacts will still upload successfully but download URLs won't be generated.
## Artifact Structure
Artifacts are uploaded with the following structure:
```
unstable/
├── latest/ # ⭐ Always has the latest main branch build
│ ├── index.html # 🌐 Download page with last 10 commits
│ ├── meshcore-sar-latest.apk
│ ├── meshcore-sar-latest.aab
│ ├── meshcore-sar-latest.dmg
│ ├── meshcore-sar-latest-windows.zip
│ ├── manifest.json
│ └── commits.json # Last 10 commit messages
├── main-abc1234/ # Branch + commit hash
│ ├── index.html # 🌐 Download page with last 10 commits
│ ├── meshcore-sar-main-abc1234-20241022-143022.apk
│ ├── meshcore-sar-main-abc1234-20241022-143022.aab
│ ├── meshcore-sar-main-abc1234-20241022-143022.dmg
│ ├── meshcore-sar-main-abc1234-20241022-143022-windows.zip
│ ├── manifest.json
│ └── commits.json # Last 10 commit messages
├── v1.2.3/ # Release tag
│ ├── index.html # 🌐 Download page with last 10 commits
│ ├── meshcore-sar-v1.2.3-20241022-150045.apk
│ ├── meshcore-sar-v1.2.3-20241022-150045.aab
│ ├── meshcore-sar-v1.2.3-20241022-150045.dmg
│ ├── meshcore-sar-v1.2.3-20241022-150045-windows.zip
│ ├── manifest.json
│ └── commits.json # Last 10 commit messages
└── develop-def5678/
└── ...
```
### Download Page (index.html)
Each build includes a beautiful, responsive HTML download page with:
- **Build Information**: Build ID, timestamp, commit hash, workflow run number
- **Download Buttons**: One-click downloads for all available platforms
- **File Sizes**: Displayed for each artifact
- **Commit History**: Last 10 commit messages with hash, date, author, and message
- **Direct Links**: Links to manifest.json, commits.json, and GitHub repository
- **Mobile Responsive**: Works perfectly on phones, tablets, and desktops
Access the download pages:
- **Latest main branch build**: `https://meshcore-sar.dz0ny.dev/unstable/latest/`
- **Specific build**: `https://meshcore-sar.dz0ny.dev/unstable/<build-prefix>/`
### Manifest Example
Each build includes a `manifest.json` file:
```json
{
"build_id": "main-abc1234-20241022-143022",
"commit": "abc1234567890abcdef1234567890abcdef12345",
"commit_short": "abc1234",
"branch": "main",
"tag": "",
"timestamp": "20241022-143022",
"workflow_run": "123",
"artifacts": [
"meshcore-sar-main-abc1234-20241022-143022.apk",
"meshcore-sar-main-abc1234-20241022-143022.aab",
"meshcore-sar-main-abc1234-20241022-143022.dmg",
"meshcore-sar-main-abc1234-20241022-143022-windows.zip"
]
}
```
### Commits Data (commits.json)
Each build includes a `commits.json` file with the last 10 commits:
```json
[
{
"hash": "abc1234",
"date": "2024-10-22 14:30:22 +0000",
"message": "feat: Add Fastlane TestFlight setup documentation",
"author": "John Doe"
},
{
"hash": "def5678",
"date": "2024-10-22 12:15:10 +0000",
"message": "fix: Correctly set BASE_URL for unstable build artifacts",
"author": "Jane Smith"
}
]
```
## Testing the Setup
1. Push a commit to your repository (or re-run an existing workflow)
2. Navigate to **Actions** tab in GitHub
3. Click on the running workflow
4. Wait for all build jobs to complete
5. Check the **Upload to Cloudflare R2** job:
- Should show "✅ Artifacts uploaded to R2 bucket"
- If `R2_PUBLIC_URL` is configured, download links will appear in the job summary
6. Verify in Cloudflare Dashboard:
- Go to **R2** → Your bucket
- Navigate to `unstable/` directory
- You should see your build artifacts
## Troubleshooting
### "Invalid credentials" error
- **Solution**: Verify `R2_ACCESS_KEY_ID` and `R2_SECRET_ACCESS_KEY` are correct
- Regenerate API token if needed (remember to update secrets)
### "Bucket not found" error
- **Solution**: Check `R2_BUCKET_NAME` matches exactly (case-sensitive)
- Verify the bucket exists in your Cloudflare R2 dashboard
### "Permission denied" error
- **Solution**: Ensure API token has **Object Read & Write** permissions
- Verify token scope includes the specific bucket
### Artifacts not visible in R2
- **Solution**: Check workflow logs for upload errors
- Verify at least one build job completed successfully
- Check bucket permissions and CORS settings if accessing via browser
### Download URLs not showing
- **Solution**: This is normal if `R2_PUBLIC_URL` secret is not configured
- Artifacts are uploaded successfully even without public URLs
- Configure public access (see step 5) to enable download links
## Security Best Practices
1. **Never commit secrets** to your repository
2. Use **specific bucket scopes** for API tokens (not account-wide)
3. **Rotate API tokens** periodically (e.g., every 90 days)
4. **Limit public access** if artifacts contain sensitive data
5. Set up **bucket lifecycle rules** to auto-delete old unstable builds
6. Use **custom domains** instead of R2.dev subdomains for production
## Cost Considerations
Cloudflare R2 pricing (as of 2024):
- **Storage**: $0.015/GB per month
- **Operations**:
- Class A (write): $4.50 per million requests
- Class B (read): $0.36 per million requests
- **Egress**: **Free** (no bandwidth charges)
For typical usage:
- ~100 builds/month × 4 platforms × ~100MB = ~40GB storage
- Monthly cost: ~$0.60 + minimal operation costs
**Tip**: Set up lifecycle rules to automatically delete builds older than 30 days to minimize storage costs.
## Additional Resources
- [Cloudflare R2 Documentation](https://developers.cloudflare.com/r2/)
- [R2 API Documentation](https://developers.cloudflare.com/r2/api/s3/)
- [GitHub Actions Secrets](https://docs.github.com/en/actions/security-guides/encrypted-secrets)
- [ryand56/r2-upload-action](https://github.com/ryand56/r2-upload-action)

100
.github/workflows/README.md vendored Normal file
View File

@@ -0,0 +1,100 @@
# CI/CD Workflows
## Build Multi-Platform Workflow
Automatically builds the MeshCore SAR app for Android, iOS, macOS, and Windows.
### Triggers
- **Push to main/develop**: Builds with version `1.0.0+1` (from pubspec.yaml)
- **Pull requests to main**: Test builds only
- **Version tags** (e.g., `v1.2.3`): Release builds with versioned artifacts
- **Manual**: Via GitHub Actions UI
### Creating a Release
1. **Ensure your local version is 1.0.0**:
```bash
# pubspec.yaml should show:
version: 1.0.0+1
```
2. **Commit all changes**:
```bash
git add .
git commit -m "Prepare for release"
git push origin main
```
3. **Create and push a version tag**:
```bash
git tag v1.2.3
git push origin v1.2.3
```
4. **GitHub Actions will**:
- Temporarily patch version to `1.2.3+<timestamp>` in builds only
- Build Android APK & App Bundle
- Build iOS app (unsigned - configure secrets for signed IPA)
- Build macOS DMG
- Build Windows executable (ZIP)
- Create a draft GitHub release with all artifacts
5. **Publish the release**:
- Go to GitHub Releases
- Edit the draft release
- Add release notes
- Publish
### Build Artifacts
| Platform | Artifact | Location |
|----------|----------|----------|
| Android APK | `app-release.apk` | `artifacts/android-apk/` |
| Android Bundle | `app-release.aab` | `artifacts/android-appbundle/` |
| macOS | `MeshCore-SAR.dmg` | `artifacts/macos-dmg/` |
| iOS | `Runner.app` | `artifacts/ios-build/` (unsigned) |
| Windows | `MeshCore-SAR-Windows.zip` | `artifacts/windows-executable/` |
### iOS Code Signing (Optional)
To build signed IPA files, add these repository secrets:
1. **IOS_P12_BASE64**: Base64-encoded .p12 certificate
```bash
base64 -i Certificate.p12 | pbcopy
```
2. **IOS_P12_PASSWORD**: Password for the .p12 certificate
3. **IOS_PROVISION_PROFILE_BASE64**: Base64-encoded provisioning profile
```bash
base64 -i Profile.mobileprovision | pbcopy
```
Then uncomment the signing steps in the workflow.
### Version Numbering
- **Local**: Always keep `pubspec.yaml` at `version: 1.0.0+1`
- **CI builds**: Uses `1.0.0+1` for regular commits
- **Release builds**: Uses `<tag>+<timestamp>` (e.g., `1.2.3+1729512345`)
- **No commits**: Version changes are temporary and never committed back
### Troubleshooting
**Build fails on macOS DMG creation**:
- The workflow tries `create-dmg` first, then falls back to `hdiutil`
- Check if app icon path exists at `macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png`
**Windows build fails**:
- Ensure Windows desktop is properly configured in project
- Run locally: `flutter config --enable-windows-desktop && flutter build windows`
**iOS build fails**:
- Check CocoaPods version and dependencies
- Review code signing configuration (currently set to `--no-codesign`)
**Android build fails**:
- Verify Java 17 is compatible with your Gradle version
- Check `android/build.gradle` for minimum SDK requirements

1330
.github/workflows/build-multiplatform.yml vendored Normal file

File diff suppressed because it is too large Load Diff