mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-13 15:51:00 +00:00
f35b189ca2
A WidgetKit extension (TREKWidgets) with two parts: the next trip on the home screen, with a countdown before it starts and today's day and next stops while it runs, and a Live Activity for the travel day on the lock screen and in the Dynamic Island showing the next timed stop and the day's progress. The web app builds both from the trips stored offline on the device (native/widgets.ts) and hands them over through TrekShell (setWidgetSnapshot, syncTripDay, endTripDay). The texts are already translated, so the widget needs no localisation of its own. The snapshot lives in the keychain group the app shares with its extensions, so no App Group is needed. Taps open com.liketrek.trek://navigate/<path>. NativeWidgetsSync refreshes on start, on returning to the foreground and every quarter hour. Both parts are gated behind the widgets / liveActivity capabilities, so older binaries and the PWA are unaffected.
113 lines
4.4 KiB
Ruby
113 lines
4.4 KiB
Ruby
# iOS release signing and TestFlight upload, driven by .github/workflows/native-release.yml.
|
|
#
|
|
# Automatic signing cannot work on a CI runner with no registered devices: it signs
|
|
# the archive for development and then needs a development provisioning profile, which
|
|
# requires a device. So this signs manually for distribution instead. The distribution
|
|
# certificate and the App Store provisioning profile are created (or reused) through the
|
|
# App Store Connect API key, which means no certificate or profile has to be stored as a
|
|
# secret: the key the workflow already holds is enough.
|
|
#
|
|
# The lane expects these in the environment (the workflow sets them):
|
|
# ASC_KEY_ID, ASC_ISSUER_ID, ASC_KEY_PATH — the App Store Connect API key
|
|
# APPLE_TEAM_ID — the developer team
|
|
# MARKETING_VERSION, CURRENT_PROJECT_VERSION — the version and build number
|
|
# RUNNER_TEMP — a writable scratch directory
|
|
|
|
default_platform(:ios)
|
|
|
|
APP_IDENTIFIER = "com.liketrek.trek"
|
|
PROJECT = "ios/App/App.xcodeproj"
|
|
|
|
# Every signed target with its bundle identifier: the app and its extensions
|
|
# (ios/scripts/add-extension.rb put them in the project). Each gets its own App
|
|
# Store profile, created or reused through the API key like the app's.
|
|
SIGNED_TARGETS = {
|
|
"App" => APP_IDENTIFIER,
|
|
"NotificationService" => "com.liketrek.trek.notifications",
|
|
"TREKWidgets" => "com.liketrek.trek.widgets",
|
|
}
|
|
|
|
platform :ios do
|
|
desc "Build the signed Release app and upload it to TestFlight (internal testing)."
|
|
lane :beta do
|
|
key = app_store_connect_api_key(
|
|
key_id: ENV.fetch("ASC_KEY_ID"),
|
|
issuer_id: ENV.fetch("ASC_ISSUER_ID"),
|
|
key_filepath: ENV.fetch("ASC_KEY_PATH"),
|
|
in_house: false,
|
|
)
|
|
|
|
# A throwaway keychain with a known password, so fastlane can unlock the imported
|
|
# private key for code signing (without the password it cannot set the key's access
|
|
# list and the certificate is never usable).
|
|
keychain_name = "trek_ci.keychain"
|
|
keychain_password = "trek-ci-#{ENV.fetch('GITHUB_RUN_ID', 'local')}"
|
|
create_keychain(
|
|
name: keychain_name,
|
|
password: keychain_password,
|
|
default_keychain: true,
|
|
unlock: true,
|
|
timeout: 3600,
|
|
lock_when_sleeps: false,
|
|
)
|
|
keychain_path = File.expand_path("~/Library/Keychains/#{keychain_name}-db")
|
|
|
|
# Import the one distribution certificate from its stored .p12, rather than
|
|
# minting a new one each run — Apple caps distribution certificates at two, so
|
|
# a fresh one per build would quickly hit the limit. The matching App Store
|
|
# profile is created (or reused) through the API key.
|
|
import_certificate(
|
|
certificate_path: ENV.fetch("CERT_P12_PATH"),
|
|
certificate_password: ENV.fetch("CERT_P12_PASSWORD"),
|
|
keychain_name: keychain_name,
|
|
keychain_path: keychain_path,
|
|
keychain_password: keychain_password,
|
|
)
|
|
profiles = {}
|
|
SIGNED_TARGETS.each do |target, identifier|
|
|
get_provisioning_profile(
|
|
api_key: key,
|
|
app_identifier: identifier,
|
|
development: false,
|
|
)
|
|
profiles[identifier] = lane_context[SharedValues::SIGH_NAME]
|
|
|
|
# Pin each target to its profile for this build; automatic signing stays the
|
|
# default a developer sees when they open the project in Xcode.
|
|
update_code_signing_settings(
|
|
path: PROJECT,
|
|
use_automatic_signing: false,
|
|
team_id: ENV.fetch("APPLE_TEAM_ID"),
|
|
code_sign_identity: "Apple Distribution",
|
|
bundle_identifier: identifier,
|
|
profile_name: profiles[identifier],
|
|
targets: [target],
|
|
)
|
|
end
|
|
|
|
build_app(
|
|
project: PROJECT,
|
|
scheme: "App",
|
|
configuration: "Release",
|
|
export_method: "app-store",
|
|
output_directory: File.join(ENV.fetch("RUNNER_TEMP"), "export"),
|
|
xcargs: [
|
|
"MARKETING_VERSION=#{ENV.fetch('MARKETING_VERSION')}",
|
|
"CURRENT_PROJECT_VERSION=#{ENV.fetch('CURRENT_PROJECT_VERSION')}",
|
|
].join(" "),
|
|
export_options: {
|
|
signingStyle: "manual",
|
|
provisioningProfiles: profiles,
|
|
},
|
|
)
|
|
|
|
# Upload to App Store Connect; it shows up in TestFlight after Apple finishes processing.
|
|
# Internal testing needs no App Review, so nothing here submits the app for review.
|
|
upload_to_testflight(
|
|
api_key: key,
|
|
skip_waiting_for_build_processing: true,
|
|
skip_submission: true,
|
|
)
|
|
end
|
|
end
|