Integrate with Fastline, Create a release script

This commit is contained in:
Mo Tarbin
2026-07-14 12:16:36 -04:00
parent 7f68f7dd9d
commit eacfca715c
13 changed files with 726 additions and 197 deletions

2
.bundle/config Normal file
View File

@@ -0,0 +1,2 @@
---
BUNDLE_PATH: "vendor/bundle"

18
.gitignore vendored
View File

@@ -25,3 +25,21 @@ dist-ssr
resources/android/**/*
resources/ios/**/*
# Secrets (pulled via scripts/pull-secrets.sh)
.env.production
android/app/google-services.json
android/app/release/*.jks
android/keystore.properties
android/local.properties
ios/App/App/GoogleService-Info.plist
ios/*.p8
# Release build outputs
build/android
build/ios
fastlane/report.xml
fastlane/Preview.html
fastlane/.env
fastlane/*.log
vendor/bundle

3
Gemfile Normal file
View File

@@ -0,0 +1,3 @@
source "https://rubygems.org"
gem "fastlane"

233
Gemfile.lock Normal file
View File

@@ -0,0 +1,233 @@
GEM
remote: https://rubygems.org/
specs:
CFPropertyList (3.0.9)
abbrev (0.1.2)
addressable (2.9.0)
public_suffix (>= 2.0.2, < 8.0)
artifactory (3.0.17)
atomos (0.1.3)
aws-eventstream (1.3.2)
aws-partitions (1.1109.0)
aws-sdk-core (3.224.1)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
aws-sigv4 (~> 1.9)
base64
jmespath (~> 1, >= 1.6.1)
logger
aws-sdk-kms (1.101.0)
aws-sdk-core (~> 3, >= 3.216.0)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.188.0)
aws-sdk-core (~> 3, >= 3.224.1)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.11.0)
aws-eventstream (~> 1, >= 1.0.2)
babosa (1.0.4)
base64 (0.2.0)
claide (1.1.0)
colored (1.2)
colored2 (3.1.2)
commander (4.6.0)
highline (~> 2.0.0)
csv (3.3.5)
declarative (0.0.20)
digest-crc (0.7.0)
rake (>= 12.0.0, < 14.0.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.8.1)
emoji_regex (3.2.3)
excon (0.109.0)
faraday (1.10.6)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0)
faraday-multipart (~> 1.0)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.0)
faraday-patron (~> 1.0)
faraday-rack (~> 1.0)
faraday-retry (~> 1.0)
ruby2_keywords (>= 0.0.4)
faraday-cookie_jar (0.0.8)
faraday (>= 0.8.0)
http-cookie (>= 1.0.0)
faraday-em_http (1.0.0)
faraday-em_synchrony (1.0.1)
faraday-excon (1.1.0)
faraday-httpclient (1.0.1)
faraday-multipart (1.2.0)
multipart-post (~> 2.0)
faraday-net_http (1.0.2)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
faraday-rack (1.0.0)
faraday-retry (1.0.4)
faraday_middleware (1.2.1)
faraday (~> 1.0)
fastimage (2.4.1)
fastlane (2.230.0)
CFPropertyList (>= 2.3, < 4.0.0)
abbrev (~> 0.1.2)
addressable (>= 2.8, < 3.0.0)
artifactory (~> 3.0)
aws-sdk-s3 (~> 1.0)
babosa (>= 1.0.3, < 2.0.0)
base64 (~> 0.2.0)
bundler (>= 1.12.0, < 3.0.0)
colored (~> 1.2)
commander (~> 4.6)
csv (~> 3.3)
dotenv (>= 2.1.1, < 3.0.0)
emoji_regex (>= 0.1, < 4.0)
excon (>= 0.71.0, < 1.0.0)
faraday (~> 1.0)
faraday-cookie_jar (~> 0.0.6)
faraday_middleware (~> 1.0)
fastimage (>= 2.1.0, < 3.0.0)
fastlane-sirp (>= 1.0.0)
gh_inspector (>= 1.1.2, < 2.0.0)
google-apis-androidpublisher_v3 (~> 0.3)
google-apis-playcustomapp_v1 (~> 0.1)
google-cloud-env (>= 1.6.0, < 2.0.0)
google-cloud-storage (~> 1.31)
highline (~> 2.0)
http-cookie (~> 1.0.5)
json (< 3.0.0)
jwt (>= 2.1.0, < 3)
logger (>= 1.6, < 2.0)
mini_magick (>= 4.9.4, < 5.0.0)
multipart-post (>= 2.0.0, < 3.0.0)
mutex_m (~> 0.3.0)
naturally (~> 2.2)
nkf (~> 0.2.0)
optparse (>= 0.1.1, < 1.0.0)
plist (>= 3.1.0, < 4.0.0)
rubyzip (>= 2.0.0, < 3.0.0)
security (= 0.1.5)
simctl (~> 1.6.3)
terminal-notifier (>= 2.0.0, < 3.0.0)
terminal-table (~> 3)
tty-screen (>= 0.6.3, < 1.0.0)
tty-spinner (>= 0.8.0, < 1.0.0)
word_wrap (~> 1.0.0)
xcodeproj (>= 1.13.0, < 2.0.0)
xcpretty (~> 0.4.1)
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
fastlane-sirp (1.1.0)
gh_inspector (1.1.3)
google-apis-androidpublisher_v3 (0.54.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-core (0.11.3)
addressable (~> 2.5, >= 2.5.1)
googleauth (>= 0.16.2, < 2.a)
httpclient (>= 2.8.1, < 3.a)
mini_mime (~> 1.0)
representable (~> 3.0)
retriable (>= 2.0, < 4.a)
rexml
google-apis-iamcredentials_v1 (0.17.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-playcustomapp_v1 (0.13.0)
google-apis-core (>= 0.11.0, < 2.a)
google-apis-storage_v1 (0.29.0)
google-apis-core (>= 0.11.0, < 2.a)
google-cloud-core (1.6.1)
google-cloud-env (>= 1.0, < 3.a)
google-cloud-errors (~> 1.0)
google-cloud-env (1.6.0)
faraday (>= 0.17.3, < 3.0)
google-cloud-errors (1.3.1)
google-cloud-storage (1.45.0)
addressable (~> 2.8)
digest-crc (~> 0.4)
google-apis-iamcredentials_v1 (~> 0.1)
google-apis-storage_v1 (~> 0.29.0)
google-cloud-core (~> 1.6)
googleauth (>= 0.16.2, < 2.a)
mini_mime (~> 1.0)
googleauth (1.8.1)
faraday (>= 0.17.3, < 3.a)
jwt (>= 1.4, < 3.0)
multi_json (~> 1.11)
os (>= 0.9, < 2.0)
signet (>= 0.16, < 2.a)
highline (2.0.3)
http-cookie (1.0.8)
domain_name (~> 0.5)
httpclient (2.9.0)
mutex_m
jmespath (1.6.2)
json (2.7.6)
jwt (2.10.3)
base64
logger (1.7.0)
mini_magick (4.13.2)
mini_mime (1.1.5)
multi_json (1.15.0)
multipart-post (2.4.1)
mutex_m (0.3.0)
nanaimo (0.4.0)
naturally (2.3.0)
nkf (0.2.0)
optparse (0.8.1)
os (1.1.4)
plist (3.7.2)
public_suffix (5.1.1)
rake (13.4.2)
representable (3.2.0)
declarative (< 0.1.0)
trailblazer-option (>= 0.1.1, < 0.2.0)
uber (< 0.2.0)
retriable (3.8.0)
rexml (3.4.4)
rouge (3.28.0)
ruby2_keywords (0.0.5)
rubyzip (2.4.1)
security (0.1.5)
signet (0.18.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a)
jwt (>= 1.5, < 3.0)
multi_json (~> 1.10)
simctl (1.6.10)
CFPropertyList
naturally
terminal-notifier (2.0.0)
terminal-table (3.0.2)
unicode-display_width (>= 1.1.1, < 3)
trailblazer-option (0.1.2)
tty-cursor (0.7.1)
tty-screen (0.8.2)
tty-spinner (0.9.3)
tty-cursor (~> 0.7)
uber (0.1.0)
unf (0.2.0)
unicode-display_width (2.6.0)
word_wrap (1.0.0)
xcodeproj (1.28.1)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
base64
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
nanaimo (~> 0.4.0)
nkf
rexml (>= 3.3.6, < 4.0)
xcpretty (0.4.1)
rouge (~> 3.28.0)
xcpretty-travis-formatter (1.0.1)
xcpretty (~> 0.2, >= 0.0.7)
PLATFORMS
ruby
DEPENDENCIES
fastlane
BUNDLED WITH
1.17.2

View File

@@ -13,8 +13,8 @@ android {
applicationId "com.donetick.app"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 28
versionName "1.2.7"
versionCode 31
versionName "1.2.10"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.

4
fastlane/Appfile Normal file
View File

@@ -0,0 +1,4 @@
app_identifier("com.donetick.app")
team_id("6UJJ78R3BS")
apple_id(ENV["APPLE_ID"]) if ENV["APPLE_ID"]

66
fastlane/Fastfile Normal file
View File

@@ -0,0 +1,66 @@
require "shellwords"
default_platform(:ios)
IOS_KEY_PATH = File.expand_path("../ios/AuthKey_84F695CDQ3.p8")
IOS_OUTPUT_DIR = File.expand_path("../build/ios")
ANDROID_PROJECT_DIR = File.expand_path("../android")
platform :ios do
desc "Build a signed, App Store-ready .ipa"
lane :release do
Dir.chdir(File.expand_path("../ios/App")) do
Bundler.with_clean_env do
sh("pod install --repo-update")
end
end
build_app(
workspace: "ios/App/App.xcworkspace",
scheme: "App",
export_method: "app-store",
output_directory: IOS_OUTPUT_DIR,
output_name: "Donetick.ipa",
export_options: {
signingStyle: "manual",
provisioningProfiles: {
"com.donetick.app" => "Donetick App Store(fastline)",
},
},
)
UI.success("Signed .ipa at #{IOS_OUTPUT_DIR}/Donetick.ipa")
end
end
platform :android do
desc "Build a signed release .aab"
lane :release do
keystore_properties = File.join(ANDROID_PROJECT_DIR, "keystore.properties")
UI.user_error!("Missing #{keystore_properties} — run scripts/pull-secrets.sh first") unless File.exist?(keystore_properties)
gradle(
task: "bundle",
build_type: "Release",
project_dir: "#{ANDROID_PROJECT_DIR}/",
)
aab_path = lane_context[SharedValues::GRADLE_AAB_OUTPUT_PATH]
UI.success("Signed .aab at #{aab_path}")
end
desc "Build a signed release .apk (for sideloading/testing)"
lane :apk do
keystore_properties = File.join(ANDROID_PROJECT_DIR, "keystore.properties")
UI.user_error!("Missing #{keystore_properties} — run scripts/pull-secrets.sh first") unless File.exist?(keystore_properties)
gradle(
task: "assemble",
build_type: "Release",
project_dir: "#{ANDROID_PROJECT_DIR}/",
)
apk_path = lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]
UI.success("Signed .apk at #{apk_path}")
end
end

53
fastlane/README.md Normal file
View File

@@ -0,0 +1,53 @@
fastlane documentation
----
# Installation
Make sure you have the latest version of the Xcode command line tools installed:
```sh
xcode-select --install
```
For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane)
# Available Actions
## iOS
### ios release
```sh
[bundle exec] fastlane ios release
```
Build a signed, App Store-ready .ipa
----
## Android
### android release
```sh
[bundle exec] fastlane android release
```
Build a signed release .aab
### android apk
```sh
[bundle exec] fastlane android apk
```
Build a signed release .apk (for sideloading/testing)
----
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools).
The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools).

View File

@@ -274,7 +274,6 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -331,7 +330,6 @@
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
@@ -360,13 +358,13 @@
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 28;
CURRENT_PROJECT_VERSION = 31;
DEVELOPMENT_TEAM = 6UJJ78R3BS;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.2.10;
PRODUCT_BUNDLE_IDENTIFIER = com.donetick.app;
MARKETING_VERSION = 1.2.7;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -380,13 +378,15 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION = YES;
CODE_SIGN_ENTITLEMENTS = App/App.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 28;
CODE_SIGN_IDENTITY = "Apple Distribution";
CODE_SIGN_STYLE = Manual;
PROVISIONING_PROFILE_SPECIFIER = "Donetick App Store(fastline)";
CURRENT_PROJECT_VERSION = 31;
DEVELOPMENT_TEAM = 6UJJ78R3BS;
INFOPLIST_FILE = App/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
MARKETING_VERSION = 1.2.7;
MARKETING_VERSION = 1.2.10;
PRODUCT_BUNDLE_IDENTIFIER = com.donetick.app;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "";

View File

@@ -31,7 +31,7 @@ PODS:
- Capacitor
- CapacitorNetwork (8.0.1):
- Capacitor
- CapacitorPluginSafeArea (5.0.0):
- CapacitorPluginSafeArea (5.0.1):
- Capacitor
- CapacitorPreferences (8.0.1):
- Capacitor
@@ -41,9 +41,9 @@ PODS:
- Capacitor
- CapgoCapacitorDocumentScanner (8.4.0):
- Capacitor
- CapgoCapacitorNfc (8.1.7):
- CapgoCapacitorNfc (8.2.2):
- Capacitor
- CapgoCapacitorSocialLogin (8.3.34):
- CapgoCapacitorSocialLogin (8.3.36):
- Alamofire (~> 5.10.2)
- Capacitor
- FBSDKCoreKit (~> 18.0)
@@ -249,13 +249,13 @@ SPEC CHECKSUMS:
CapacitorLocalLlm: a05516151a02923a9e7dae9949d3817e85e321f0
CapacitorLocalNotifications: 2615aa008f608b95d3921a778ee1988abf1e6148
CapacitorNetwork: 8812ce60d11fb63d8f2e4ba51a49b2e59892ebe2
CapacitorPluginSafeArea: 9d0682951c011bf0b36e513a89103c5fbff7ac49
CapacitorPluginSafeArea: 874619c00586248f1694210e72038123d422c2d9
CapacitorPreferences: cca2021f386efb75947c850334447d9ff22b14f1
CapacitorPushNotifications: ec08d589c226a2c0db7c032ec1bf5b044ec85f8e
CapacitorStatusBar: 01d5763b4ed720de5ce2edbc938de6a98f4c8f32
CapgoCapacitorDocumentScanner: 7ad9e8ed9c054d551bfc948660d995b9545723d8
CapgoCapacitorNfc: 5bf5a951ca231d7c40f1ac20549d2abcd1b8f939
CapgoCapacitorSocialLogin: b0e67630b9d9b5f14fff774c825c1b8fa85eff7b
CapgoCapacitorNfc: 8ea158143c441e1cf6d231a971e375511558d027
CapgoCapacitorSocialLogin: adffda2bec52a765bdaebf3fa9a6083bd9341d60
FBAEMKit: 64088ff0380f50e4a56e2ee07d984f7f1aef7595
FBSDKCoreKit: 8390ea3a8fac186f444275f31d7512e760b47cba
FBSDKCoreKit_Basics: 3a0005c78b355388bf2df5c6dbe6381b77ea4be3

428
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
{
"name": "donetick",
"private": true,
"version": "1.2.7",
"version": "1.2.10",
"type": "module",
"engines": {
"node": ">=20.0.0",

82
scripts/release.sh Executable file
View File

@@ -0,0 +1,82 @@
#!/usr/bin/env bash
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$REPO_ROOT"
PLATFORM="both"
BUMP="patch"
SKIP_BUMP=false
usage() {
cat <<EOF
Usage: $(basename "$0") [--android|--ios] [--bump patch|minor|major] [--skip-bump]
Builds signed release artifacts for Android (.aab) and/or iOS (.ipa).
--android Build Android only
--ios Build iOS only
--bump TYPE Version bump type before building (default: patch)
--skip-bump Don't bump the version, build with the current one
-h, --help Show this help
Requires:
- scripts/pull-secrets.sh to have been run (keystore, google-services, App Store Connect key)
- ASC_ISSUER_ID env var set (App Store Connect API key issuer id) for iOS builds
- bundle install (fastlane) run at least once
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
--android) PLATFORM="android"; shift ;;
--ios) PLATFORM="ios"; shift ;;
--bump) BUMP="$2"; shift 2 ;;
--skip-bump) SKIP_BUMP=true; shift ;;
-h|--help) usage; exit 0 ;;
*) echo "Unknown option: $1" >&2; usage; exit 1 ;;
esac
done
if [ -f "$REPO_ROOT/.env.production" ]; then
set -a
# shellcheck disable=SC1091
source "$REPO_ROOT/.env.production"
set +a
fi
if [ "$SKIP_BUMP" = false ]; then
echo "→ Bumping version ($BUMP)"
node bump-version.js "$BUMP"
fi
echo "→ Building web assets"
npm run build
echo "→ Syncing Capacitor"
npx cap sync
if [ -f Gemfile ] && command -v bundle >/dev/null 2>&1; then
RUN="bundle exec fastlane"
else
RUN="fastlane"
fi
if [ "$PLATFORM" = "android" ] || [ "$PLATFORM" = "both" ]; then
echo "→ Building signed Android release (.aab)"
$RUN android release
fi
if [ "$PLATFORM" = "ios" ] || [ "$PLATFORM" = "both" ]; then
echo "→ Building signed iOS release (.ipa)"
$RUN ios release
fi
echo "✓ Release build complete"
[ -f android/app/build/outputs/bundle/release/app-release.aab ] && echo " Android: android/app/build/outputs/bundle/release/app-release.aab"
[ -f build/ios/Donetick.ipa ] && echo " iOS: build/ios/Donetick.ipa"
echo ""
echo "Next steps:"
echo " git add . && git commit -m \"Release \$(node -p \"require('./package.json').version\")\""
echo " git tag v\$(node -p \"require('./package.json').version\") && git push origin develop --tags"