mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-12 17:00:28 +00:00
feat: Add Makefile, Fastlane configuration, and update Android build settings for release management
This commit is contained in:
@@ -48,7 +48,8 @@
|
|||||||
"Bash(flutter run)",
|
"Bash(flutter run)",
|
||||||
"Bash(echo:*)",
|
"Bash(echo:*)",
|
||||||
"Bash(pkill:*)",
|
"Bash(pkill:*)",
|
||||||
"Bash(git restore:*)"
|
"Bash(git restore:*)",
|
||||||
|
"Bash(keytool:*)"
|
||||||
],
|
],
|
||||||
"deny": [],
|
"deny": [],
|
||||||
"ask": []
|
"ask": []
|
||||||
|
|||||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -43,6 +43,11 @@ app.*.map.json
|
|||||||
/android/app/debug
|
/android/app/debug
|
||||||
/android/app/profile
|
/android/app/profile
|
||||||
/android/app/release
|
/android/app/release
|
||||||
|
|
||||||
|
# Android signing
|
||||||
|
android/key.properties
|
||||||
|
*.jks
|
||||||
|
*.keystore
|
||||||
*.zip
|
*.zip
|
||||||
*.ipa
|
*.ipa
|
||||||
ios/Runner.app.dSYM.zip
|
ios/Runner.app.dSYM.zip
|
||||||
|
|||||||
5
.osgrep/server.json
Normal file
5
.osgrep/server.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"port": 4444,
|
||||||
|
"pid": 16846,
|
||||||
|
"authToken": "1c614f30-164f-4c79-9189-784b99f02ac4"
|
||||||
|
}
|
||||||
118
Makefile
Normal file
118
Makefile
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# MeshCore SAR Makefile
|
||||||
|
# Version format: YYYY.MMDD.N+build (Flutter-compatible semver with date)
|
||||||
|
# Example: 2025.1205.1+1
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
APP_NAME := meshcore-sar
|
||||||
|
PUBSPEC := pubspec.yaml
|
||||||
|
BUILD_DIR := build/app/outputs/flutter-apk
|
||||||
|
|
||||||
|
# Get current date parts
|
||||||
|
YEAR := $(shell date +%Y)
|
||||||
|
MMDD := $(shell date +%m%d)
|
||||||
|
|
||||||
|
# Get current version info from pubspec.yaml
|
||||||
|
CURRENT_VERSION := $(shell grep '^version:' $(PUBSPEC) | sed 's/version: //')
|
||||||
|
CURRENT_BUILD_NUMBER := $(shell echo $(CURRENT_VERSION) | cut -d'+' -f2)
|
||||||
|
|
||||||
|
# Extract current MMDD from version (middle part)
|
||||||
|
CURRENT_MMDD := $(shell echo $(CURRENT_VERSION) | cut -d'.' -f2)
|
||||||
|
|
||||||
|
# Calculate new build number
|
||||||
|
# IMPORTANT: Build number (version code) must ALWAYS increment for Android updates
|
||||||
|
# Never reset to 1, even on date changes
|
||||||
|
NEW_BUILD_NUMBER := $(shell echo $$(($(CURRENT_BUILD_NUMBER) + 1)))
|
||||||
|
|
||||||
|
# Calculate daily sequence number (resets each day for version name readability)
|
||||||
|
DAILY_BUILD := $(shell \
|
||||||
|
if [ "$(CURRENT_MMDD)" = "$(MMDD)" ]; then \
|
||||||
|
echo $(CURRENT_VERSION) | cut -d'.' -f3 | cut -d'+' -f1 | awk '{print $$1 + 1}'; \
|
||||||
|
else \
|
||||||
|
echo 1; \
|
||||||
|
fi)
|
||||||
|
|
||||||
|
# Version format: YYYY.MMDD.DAILY+BUILD
|
||||||
|
# DAILY resets each day (for readability), BUILD always increments (for Android)
|
||||||
|
NEW_VERSION := $(YEAR).$(MMDD).$(DAILY_BUILD)+$(NEW_BUILD_NUMBER)
|
||||||
|
|
||||||
|
.PHONY: help version bump build release release-android release-ios clean deps analyze test icon
|
||||||
|
|
||||||
|
help: ## Show this help
|
||||||
|
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'
|
||||||
|
|
||||||
|
version: ## Show current and next version
|
||||||
|
@echo "Current version: $(CURRENT_VERSION)"
|
||||||
|
@echo "Current build: $(CURRENT_BUILD_NUMBER)"
|
||||||
|
@echo "---"
|
||||||
|
@echo "Next version: $(NEW_VERSION)"
|
||||||
|
|
||||||
|
bump: ## Bump version in pubspec.yaml
|
||||||
|
@echo "Bumping version to $(NEW_VERSION)..."
|
||||||
|
@sed -i '' 's/^version: .*/version: $(NEW_VERSION)/' $(PUBSPEC)
|
||||||
|
@echo "Version bumped to $(NEW_VERSION)"
|
||||||
|
|
||||||
|
deps: ## Install dependencies
|
||||||
|
flutter pub get
|
||||||
|
|
||||||
|
analyze: ## Run Flutter analyze
|
||||||
|
flutter analyze
|
||||||
|
|
||||||
|
test: ## Run tests
|
||||||
|
flutter test
|
||||||
|
|
||||||
|
icon: ## Generate app icons from icon.png
|
||||||
|
dart run flutter_launcher_icons
|
||||||
|
|
||||||
|
build: bump ## Build release APK (auto-bumps version)
|
||||||
|
@echo "Building release APK..."
|
||||||
|
flutter build apk --release
|
||||||
|
@echo "APK built: $(BUILD_DIR)/app-release.apk"
|
||||||
|
@ls -lh $(BUILD_DIR)/app-release.apk
|
||||||
|
|
||||||
|
build-no-bump: ## Build release APK without bumping version
|
||||||
|
flutter build apk --release
|
||||||
|
@ls -lh $(BUILD_DIR)/app-release.apk
|
||||||
|
|
||||||
|
release: build release-ios ## Build APK, create GitHub release, and upload iOS to TestFlight
|
||||||
|
$(eval VERSION := $(shell grep '^version:' $(PUBSPEC) | sed 's/version: //' | cut -d'+' -f1))
|
||||||
|
@echo "Creating GitHub release v$(VERSION)..."
|
||||||
|
@if ! command -v gh &> /dev/null; then \
|
||||||
|
echo "Error: GitHub CLI (gh) not installed. Install with: brew install gh"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
@cp $(BUILD_DIR)/app-release.apk $(BUILD_DIR)/$(APP_NAME)-$(VERSION).apk
|
||||||
|
gh release create "v$(VERSION)" \
|
||||||
|
"$(BUILD_DIR)/$(APP_NAME)-$(VERSION).apk#MeshCore SAR $(VERSION) APK" \
|
||||||
|
--title "MeshCore SAR v$(VERSION)" \
|
||||||
|
--notes "Release $(VERSION)" \
|
||||||
|
--latest
|
||||||
|
@echo "Release v$(VERSION) created!"
|
||||||
|
|
||||||
|
release-android: build ## Build APK and create GitHub release (Android only)
|
||||||
|
$(eval VERSION := $(shell grep '^version:' $(PUBSPEC) | sed 's/version: //' | cut -d'+' -f1))
|
||||||
|
@echo "Creating GitHub release v$(VERSION)..."
|
||||||
|
@if ! command -v gh &> /dev/null; then \
|
||||||
|
echo "Error: GitHub CLI (gh) not installed. Install with: brew install gh"; \
|
||||||
|
exit 1; \
|
||||||
|
fi
|
||||||
|
@cp $(BUILD_DIR)/app-release.apk $(BUILD_DIR)/$(APP_NAME)-$(VERSION).apk
|
||||||
|
gh release create "v$(VERSION)" \
|
||||||
|
"$(BUILD_DIR)/$(APP_NAME)-$(VERSION).apk#MeshCore SAR $(VERSION) APK" \
|
||||||
|
--title "MeshCore SAR v$(VERSION)" \
|
||||||
|
--notes "Release $(VERSION)" \
|
||||||
|
--latest
|
||||||
|
@echo "Release v$(VERSION) created!"
|
||||||
|
|
||||||
|
release-ios: ## Build iOS and upload to TestFlight
|
||||||
|
@echo "Building iOS and uploading to TestFlight..."
|
||||||
|
cd ios && fastlane release
|
||||||
|
@echo "iOS release uploaded!"
|
||||||
|
|
||||||
|
clean: ## Clean build artifacts
|
||||||
|
flutter clean
|
||||||
|
rm -rf $(BUILD_DIR)
|
||||||
|
|
||||||
|
# Build for all platforms
|
||||||
|
build-all: bump ## Build for Android and iOS
|
||||||
|
flutter build apk --release
|
||||||
|
flutter build ios --release --no-codesign
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
import java.util.Properties
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
id("kotlin-android")
|
id("kotlin-android")
|
||||||
@@ -5,6 +8,13 @@ plugins {
|
|||||||
id("dev.flutter.flutter-gradle-plugin")
|
id("dev.flutter.flutter-gradle-plugin")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load keystore properties from key.properties file
|
||||||
|
val keystorePropertiesFile = rootProject.file("key.properties")
|
||||||
|
val keystoreProperties = Properties()
|
||||||
|
if (keystorePropertiesFile.exists()) {
|
||||||
|
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
|
||||||
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
namespace = "com.meshcore.sar.meshcore_sar_app"
|
namespace = "com.meshcore.sar.meshcore_sar_app"
|
||||||
compileSdk = flutter.compileSdkVersion
|
compileSdk = flutter.compileSdkVersion
|
||||||
@@ -16,22 +26,17 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_11
|
|
||||||
targetCompatibility = JavaVersion.VERSION_11
|
|
||||||
// Required by some dependencies (e.g., flutter_local_notifications)
|
|
||||||
// to support Java 8+ APIs on older Android devices.
|
|
||||||
isCoreLibraryDesugaringEnabled = true
|
isCoreLibraryDesugaringEnabled = true
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = JavaVersion.VERSION_11.toString()
|
jvmTarget = JavaVersion.VERSION_17.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
|
||||||
applicationId = "com.meshcore.sar.meshcore_sar_app"
|
applicationId = "com.meshcore.sar.meshcore_sar_app"
|
||||||
// You can update the following values to match your application needs.
|
|
||||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
|
||||||
minSdk = flutter.minSdkVersion
|
minSdk = flutter.minSdkVersion
|
||||||
targetSdk = flutter.targetSdkVersion
|
targetSdk = flutter.targetSdkVersion
|
||||||
versionCode = flutter.versionCode
|
versionCode = flutter.versionCode
|
||||||
@@ -43,11 +48,20 @@ android {
|
|||||||
buildConfigField("String", "COMMIT_HASH", "\"$commitHash\"")
|
buildConfigField("String", "COMMIT_HASH", "\"$commitHash\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signingConfigs {
|
||||||
|
create("release") {
|
||||||
|
if (keystorePropertiesFile.exists()) {
|
||||||
|
keyAlias = keystoreProperties["keyAlias"] as String
|
||||||
|
keyPassword = keystoreProperties["keyPassword"] as String
|
||||||
|
storeFile = file(keystoreProperties["storeFile"] as String)
|
||||||
|
storePassword = keystoreProperties["storePassword"] as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
// TODO: Add your own signing config for the release build.
|
signingConfig = signingConfigs.getByName("release")
|
||||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
|
||||||
signingConfig = signingConfigs.getByName("debug")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,6 +71,5 @@ flutter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// Core library desugaring support library
|
|
||||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
|
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
|
||||||
}
|
}
|
||||||
|
|||||||
2
android/fastlane/Appfile
Normal file
2
android/fastlane/Appfile
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
json_key_file("/Users/dz0ny/android-keystores/fastlane-480919-0cb30c62db50.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one
|
||||||
|
package_name("com.meshcore.sar.meshcore_sar_app") # e.g. com.krausefx.app
|
||||||
59
android/fastlane/Fastfile
Normal file
59
android/fastlane/Fastfile
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# This file contains the fastlane.tools configuration
|
||||||
|
# You can find the documentation at https://docs.fastlane.tools
|
||||||
|
#
|
||||||
|
# For a list of all available actions, check out
|
||||||
|
#
|
||||||
|
# https://docs.fastlane.tools/actions
|
||||||
|
#
|
||||||
|
# For a list of all available plugins, check out
|
||||||
|
#
|
||||||
|
# https://docs.fastlane.tools/plugins/available-plugins
|
||||||
|
#
|
||||||
|
|
||||||
|
# Uncomment the line if you want fastlane to automatically update itself
|
||||||
|
# update_fastlane
|
||||||
|
|
||||||
|
default_platform(:android)
|
||||||
|
|
||||||
|
platform :android do
|
||||||
|
desc "Runs all the tests"
|
||||||
|
lane :test do
|
||||||
|
gradle(task: "test")
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Build release APK"
|
||||||
|
lane :beta do
|
||||||
|
# Get the project root directory (two levels up from android/fastlane/)
|
||||||
|
project_root = File.expand_path("../..", __dir__)
|
||||||
|
|
||||||
|
# Build APK with Flutter
|
||||||
|
sh("cd #{project_root} && flutter build apk --release")
|
||||||
|
|
||||||
|
apk_path = File.join(project_root, "build/app/outputs/flutter-apk/app-release.apk")
|
||||||
|
|
||||||
|
# Uncomment to distribute via Firebase App Distribution:
|
||||||
|
# firebase_app_distribution(
|
||||||
|
# app: "YOUR_FIREBASE_APP_ID",
|
||||||
|
# apk_path: apk_path,
|
||||||
|
# groups: "testers"
|
||||||
|
# )
|
||||||
|
|
||||||
|
UI.success("APK built at: #{apk_path}")
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Deploy a new version to the Google Play"
|
||||||
|
lane :deploy do
|
||||||
|
# Get the project root directory (two levels up from android/fastlane/)
|
||||||
|
project_root = File.expand_path("../..", __dir__)
|
||||||
|
|
||||||
|
# Build AAB with Flutter (required for Play Store since 2021)
|
||||||
|
sh("cd #{project_root} && flutter build appbundle --release")
|
||||||
|
|
||||||
|
aab_path = File.join(project_root, "build/app/outputs/bundle/release/app-release.aab")
|
||||||
|
|
||||||
|
upload_to_play_store(
|
||||||
|
aab: aab_path,
|
||||||
|
track: "internal"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -16,10 +16,17 @@
|
|||||||
default_platform(:ios)
|
default_platform(:ios)
|
||||||
|
|
||||||
platform :ios do
|
platform :ios do
|
||||||
|
desc "Push a new release build to the App Store"
|
||||||
|
lane :release do
|
||||||
|
increment_build_number(xcodeproj: "Runner.xcodeproj")
|
||||||
|
build_app(workspace: "Runner.xcworkspace", scheme: "Runner")
|
||||||
|
upload_to_app_store(skip_metadata: true, skip_screenshots: true)
|
||||||
|
end
|
||||||
|
|
||||||
desc "Push a new beta build to TestFlight"
|
desc "Push a new beta build to TestFlight"
|
||||||
lane :beta do
|
lane :beta do
|
||||||
increment_build_number(xcodeproj: "Runner.xcodeproj")
|
increment_build_number(xcodeproj: "Runner.xcodeproj")
|
||||||
build_app(workspace: "Runner.xcworkspace", scheme: "Runner")
|
build_app(workspace: "Runner.xcworkspace", scheme: "Runner")
|
||||||
upload_to_testflight
|
upload_to_testflight(skip_waiting_for_build_processing: true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user