Files
eranos/ios/fastlane/Fastfile
T
Chad Curtis 1b4399df68 Rebrand app identifier and IPA name from Ditto to Agora
Renames the Capacitor app identifier from pub.agora.app to
spot.agora.app and cleans up Ditto-branded artifacts that don't refer
to upstream Ditto-the-project or Ditto-stack services.

App identifier (pub.agora.app -> spot.agora.app):
- capacitor.config.ts appId
- android applicationId, namespace, package_name string, custom_url_scheme
- iOS PRODUCT_BUNDLE_IDENTIFIER (Debug + Release)
- public/.well-known/assetlinks.json package_name
- public/.well-known/apple-app-site-association app id
- Info.plist BGTaskSchedulerPermittedIdentifiers and the matching
  Swift bgTaskIdentifier (previously mismatched: plist said
  pub.agora.app.notification-refresh, Swift said
  pub.ditto.app.notification-refresh, so background refresh would
  silently fail to register)
- src/lib/helpContent.ts Zapstore URLs
- .gitlab-ci.yml --package_name for fastlane supply

Android Java package (pub.ditto.app -> spot.agora.app):
- Move android/app/src/main/java/pub/ditto/app/ ->
  android/app/src/main/java/spot/agora/app/ (4 files: MainActivity,
  DittoNotificationPlugin, NostrPoller, NotificationRelayService)
- Update package declarations to match the new Android namespace
  (was a hard build failure with namespace = spot.agora.app)
- Update proguard -keep rule
- Update NotificationRelayService ACTION_FETCH intent string
  pub.ditto.app.ACTION_FETCH -> spot.agora.app.ACTION_FETCH

Fastlane (pub.ditto.app -> spot.agora.app):
- Appfile, Matchfile, Fastfile provisioning profile specifiers.
  Matchfile still points at Soapbox's certificates git repo; a new
  match repo with certs for spot.agora.app is required before iOS CI
  signing works.

IPA artifact name (Ditto.ipa -> Agora.ipa):
- Fastfile output_name and matching CI artifact paths
- .gitlab-ci.yml: artifacts/Ditto.ipa references and the GitLab
  Generic Packages path from /packages/generic/ditto/ ->
  /packages/generic/agora/ (matches how APK/AAB are already
  published). Existing release artifacts at the old path remain
  reachable; new releases land at the new path.

Release-notes script fallback (Ditto vX.Y.Z -> Agora vX.Y.Z):
- scripts/extract-release-notes.mjs fallback used as the App Store /
  Play Store 'What's New' blurb when a changelog section has no
  summary.

manifest.webmanifest:
- Update related_applications Play Store entry to spot.agora.app.
- Remove the iTunes related_applications entry that pointed at
  the existing Ditto App Store listing; not applicable to Agora
  until Agora has its own listing.

Capacitor sync incidentals:
- npm run cap:sync picked up @capacitor/barcode-scanner registration
  that had been missed in a prior plugin install
  (android/app/capacitor.build.gradle, capacitor.settings.gradle,
  ios/App/CapApp-SPM/Package.swift).

Intentionally NOT touched:
- ditto.json filename, DittoConfigSchema, DittoConfig, and JSDoc
  references to ditto.json. The config-system shape is shared with
  upstream Ditto by design.
- relay.ditto.pub, blossom.ditto.pub, ditto.pub/api/* and other
  Ditto-stack services Agora actively consumes.
- The DittoNotificationPlugin Android/iOS class name, the
  DittoNotification JS bridge name, ditto_notification_config
  SharedPreferences keys, ic_stat_ditto drawables, and the
  DittoBridgeViewController. Renaming requires a coordinated
  JS-side rename plus a SharedPreferences migration or existing
  users on the Ditto fork lose their notification config on upgrade.
- Ditto references in skill docs, NIP.md kind comments, README, and
  zapstore.yaml attribution \u2014 those correctly describe the upstream
  Ditto project that Agora forked from.

Follow-ups required before CI succeeds end-to-end (out of scope here):
- Stand up a new fastlane match git repo containing certs +
  provisioning profiles for spot.agora.app, or update Matchfile
  git_url to point at it.
- Register spot.agora.app in App Store Connect for team GZLTTH5DLM
  and create a new App Store listing.
- Create a new Google Play Console listing for spot.agora.app
  (package name is immutable per app on Play; the existing
  pub.agora.app listing cannot be reused).
- Re-publish to Zapstore under spot.agora.app so the URLs in
  helpContent.ts resolve.
2026-05-17 18:42:46 -05:00

147 lines
5.4 KiB
Ruby

default_platform(:ios)
platform :ios do
# ─── Lanes ────────────────────────────────────────────────────────────
desc "Build and sign the App Store IPA. Output at ../artifacts/Agora.ipa."
lane :build_ipa do
setup_lane_signing!
build_release_ipa!
end
desc "Submit an already-built IPA to App Store Connect for review. " \
"Set IPA_PATH to the IPA's location."
lane :submit_release do
ipa_path = ENV.fetch("IPA_PATH") do
UI.user_error!("submit_release requires the IPA_PATH env var")
end
UI.user_error!("IPA not found at #{ipa_path}") unless File.exist?(ipa_path)
submit_release_for_review!(ipa_path)
end
desc "Build, sign, and submit Agora to the App Store for review (single-step convenience)."
lane :release do
setup_lane_signing!
build_release_ipa!
# Use the IPA path set by build_app rather than recomputing it from
# __dir__, which gets fragile across fastlane-relative paths.
ipa_path = lane_context[SharedValues::IPA_OUTPUT_PATH]
UI.user_error!("build_app did not set IPA_OUTPUT_PATH") unless ipa_path
submit_release_for_review!(ipa_path)
end
desc "Submit an already-uploaded build for review (skip build/upload). " \
"Use BUILD_NUMBER and VERSION env vars."
lane :submit_only do
submit_release_for_review!(nil)
end
# ─── Helpers ──────────────────────────────────────────────────────────
def setup_lane_signing!
# Create an ephemeral keychain so we never touch the login keychain.
setup_ci
api_key = build_api_key!
# Fetch encrypted distribution cert + provisioning profile from the
# shared certificates repo. --readonly: never mutate from CI.
# Passing api_key makes match contact Apple's portal to verify the
# cert is still valid for the team — fails fast on revoked/expired
# certs instead of letting xcodebuild stumble later.
match(type: "appstore", readonly: true, api_key: api_key)
api_key
end
def build_api_key!
# Build the API key hash inline. We avoid the app_store_connect_api_key
# action because it sets APP_STORE_CONNECT_API_KEY_PATH (path to the .p8)
# which collides with match's APP_STORE_CONNECT_API_KEY_PATH (path to a
# JSON descriptor). Same env name, different formats.
@api_key ||= {
key_id: ENV.fetch("APP_STORE_CONNECT_API_KEY_ID"),
issuer_id: ENV.fetch("APP_STORE_CONNECT_API_KEY_ISSUER_ID"),
key: File.binread(ENV.fetch("ASC_KEY_PATH")),
duration: 1200,
in_house: false,
}
end
def build_release_ipa!
# Stamp build number from CI pipeline ID so every release is monotonically increasing.
increment_build_number(
xcodeproj: "App/App.xcodeproj",
build_number: ENV.fetch("CI_PIPELINE_IID"),
)
# Marketing version is set externally (sed in CI) before this lane runs.
build_app(
project: "App/App.xcodeproj",
scheme: "App",
configuration: "Release",
export_method: "app-store",
output_directory: "../artifacts",
output_name: "Agora.ipa",
clean: true,
# Override the Xcode project's Automatic signing for this build only.
# Match has already installed the AppStore cert + profile into the
# ephemeral keychain; tell xcodebuild to use them explicitly so it
# doesn't also try to find an iOS Development cert (which we never
# provision in CI).
xcargs: [
"CODE_SIGN_STYLE=Manual",
"CODE_SIGN_IDENTITY='Apple Distribution'",
"PROVISIONING_PROFILE_SPECIFIER='match AppStore spot.agora.app'",
"DEVELOPMENT_TEAM=GZLTTH5DLM",
].join(" "),
export_options: {
method: "app-store",
signingStyle: "manual",
teamID: "GZLTTH5DLM",
provisioningProfiles: {
"spot.agora.app" => "match AppStore spot.agora.app",
},
},
)
end
# If ipa_path is nil, deliver picks up the latest processed build for the
# configured app version (used by the submit_only lane).
def submit_release_for_review!(ipa_path)
api_key = build_api_key!
options = {
api_key: api_key,
submit_for_review: true,
automatic_release: false,
force: true,
precheck_include_in_app_purchases: false,
# Don't try to PATCH content rights on every submit — Apple's API
# rejects updates to contentRightsDeclaration once the listing has
# an established state. The values stay as set in the App Store
# Connect UI / from a prior submission.
submission_information: {
export_compliance_uses_encryption: false,
},
skip_screenshots: true,
# Keep skip_app_version_update=false: deliver needs to PATCH the
# version's whatsNew (release notes) and platform-version metadata
# before submit_for_review will accept the version.
skip_app_version_update: false,
skip_metadata: false,
metadata_path: "./fastlane/metadata",
run_precheck_before_submit: false,
}
options[:ipa] = ipa_path if ipa_path
if ENV["BUILD_NUMBER"]
options[:build_number] = ENV["BUILD_NUMBER"]
options[:skip_binary_upload] = true
end
options[:app_version] = ENV["VERSION"] if ENV["VERSION"]
deliver(**options)
end
end