# Google Play publishing only. # # Building and signing are deliberately NOT fastlane's job: release.yaml drives # Gradle directly so the release build stays F-Droid-reproducible (`vcsInfo`, # `dependenciesInfo` and the AGP metadata block are disabled in # app/build.gradle.kts and guarded by scripts/check_reproducible_release.sh). # Interposing fastlane there would add a layer that can inject Gradle flags into # the one build whose byte-for-byte output is verified by a third party. # # What fastlane IS here for is `supply` — the Play Developer API client — because # the store listing already lives in fastlane/metadata/android, which the # official F-Droid repo harvests from the tagged source tree. One metadata tree, # two stores. default_platform(:android) # fastlane runs a lane body with the working directory set to `fastlane/`, not # the project root, so a relative artifact path from the caller has to be # resolved explicitly. Absolute paths pass through untouched. def project_path(path) File.expand_path(path, File.expand_path("..", FastlaneCore::FastlaneFolder.path || ".")) end platform :android do desc "Upload an already-built, already-signed AAB to Play" lane :deploy do |options| aab = project_path(options[:aab] || "app/build/outputs/bundle/release/app-release.aab") UI.user_error!("AAB not found at #{aab}") unless File.exist?(aab) supply( aab: aab, track: options[:track] || "internal", release_status: options[:release_status] || "completed", # The APK belongs to F-Droid and the Codeberg download; Play only ever # gets the bundle. Never let the uploader reach for the other artifact. skip_upload_apk: true, # Listing text is synced deliberately via the `listing` lane, not on every # release. Overwriting a live listing by accident triggers a Play policy # review, which is not a quick revert. skip_upload_metadata: true, # "What's New" DOES track every release. # scripts/sync_changelog_to_fastlane.sh writes # fastlane/metadata/android/en-US/changelogs/.txt from # CHANGELOG.md, so Play shows exactly the text F-Droid does. skip_upload_changelogs: false, # See the `listing` lane for why the committed images can't go to Play yet. skip_upload_images: true, skip_upload_screenshots: true, # Dry run: validate the edit against the API and roll it back instead of # committing it. Used for the first end-to-end rehearsal. validate_only: options[:dry_run].to_s == "true", ) end desc "Sync the store listing text (and, once the assets qualify, the images)" lane :listing do |options| # Deliberate and manual: `bundle exec fastlane listing`. Not wired into the # release pipeline. # # Images stay off by default because the committed assets do not satisfy # Play today, even though F-Droid accepts all of them: # # * phoneScreenshots are 1280x2856. Play caps the long edge at twice the # short edge (2560 here), so every screenshot is rejected. # * those PNGs are 32-bit RGBA. Play wants 24-bit PNG, no alpha. # * icon.png is 512x512 but 24-bit RGB. Play's icon wants 32-bit PNG. # * there is no featureGraphic.png. Play requires one, exactly 1024x500. # # Until that is fixed, the Play listing's graphics are managed by hand in the # console. Pass images:true once the assets qualify. upload_images = options[:images].to_s == "true" supply( skip_upload_aab: true, skip_upload_apk: true, skip_upload_metadata: false, skip_upload_changelogs: true, skip_upload_images: !upload_images, skip_upload_screenshots: !upload_images, ) end end