Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/100
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
name: Release — F-Droid repo + Gitea/Codeberg release
|
name: Release — F-Droid repo + Gitea/Codeberg release + Play
|
||||||
|
|
||||||
# A release is cut by merging a release branch into main with a bumped
|
# A release is cut by merging a release branch into main with a bumped
|
||||||
# versionName (see docs/RELEASING.md). This workflow reads that versionName and,
|
# versionName (see docs/RELEASING.md). This workflow reads that versionName and,
|
||||||
@@ -9,6 +9,12 @@ name: Release — F-Droid repo + Gitea/Codeberg release
|
|||||||
# trigger. Ordinary merges (no version bump) fall through `detect` and do
|
# trigger. Ordinary merges (no version bump) fall through `detect` and do
|
||||||
# nothing.
|
# nothing.
|
||||||
#
|
#
|
||||||
|
# A trailing `play` job then uploads the App Bundle to Google Play. It is last
|
||||||
|
# and separate because Play is the only channel that can reject a good build for
|
||||||
|
# reasons the pipeline can't see, and that must not endanger a release which has
|
||||||
|
# already shipped to F-Droid and Codeberg. It skips cleanly until the
|
||||||
|
# PLAY_SERVICE_ACCOUNT_JSON secret exists.
|
||||||
|
#
|
||||||
# A manual workflow_dispatch (from a branch) runs the re-sign-only recovery
|
# A manual workflow_dispatch (from a branch) runs the re-sign-only recovery
|
||||||
# path: it re-signs the existing F-Droid index with the repo key and re-uploads,
|
# path: it re-signs the existing F-Droid index with the repo key and re-uploads,
|
||||||
# without building an APK or creating a release. Used for key rotation / repo
|
# without building an APK or creating a release. Used for key rotation / repo
|
||||||
@@ -203,6 +209,33 @@ jobs:
|
|||||||
if: env.IS_RELEASE == 'true'
|
if: env.IS_RELEASE == 'true'
|
||||||
run: ./gradlew assembleRelease
|
run: ./gradlew assembleRelease
|
||||||
|
|
||||||
|
# Play takes an App Bundle, not the APK, so it is a second artifact from
|
||||||
|
# the same source and the same signing config — not a repackage of the
|
||||||
|
# APK. The release key signs it, but Play only ever treats that key as the
|
||||||
|
# *upload* key: Play App Signing re-signs with Google's own key before
|
||||||
|
# delivery. A Play install and an F-Droid install therefore carry
|
||||||
|
# different signatures and cannot update each other. That divergence is a
|
||||||
|
# deliberate, documented choice (docs/RELEASING.md), not an accident.
|
||||||
|
#
|
||||||
|
# Nothing here touches the F-Droid path: the AAB is never copied into the
|
||||||
|
# repo, never attached to a release, and its build cannot change the APK
|
||||||
|
# that was already produced above.
|
||||||
|
#
|
||||||
|
# AGP embeds the R8 mapping in the bundle's BUNDLE-METADATA, so Play gets
|
||||||
|
# deobfuscated stacktraces without a separate mapping upload.
|
||||||
|
- name: Build release AAB
|
||||||
|
if: env.IS_RELEASE == 'true'
|
||||||
|
run: ./gradlew bundleRelease
|
||||||
|
|
||||||
|
- name: Hand the AAB to the Play job
|
||||||
|
if: env.IS_RELEASE == 'true'
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-aab-${{ needs.detect.outputs.version }}
|
||||||
|
path: app/build/outputs/bundle/release/app-release.aab
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 14
|
||||||
|
|
||||||
- name: Setup F-Droid Server Tools
|
- name: Setup F-Droid Server Tools
|
||||||
run: |
|
run: |
|
||||||
SUDO=""
|
SUDO=""
|
||||||
@@ -477,3 +510,123 @@ jobs:
|
|||||||
"$API/releases/$ID/assets?name=$A" -o /dev/null -w "asset $A HTTP %{http_code}\n"
|
"$API/releases/$ID/assets?name=$A" -o /dev/null -w "asset $A HTTP %{http_code}\n"
|
||||||
done
|
done
|
||||||
echo "Published $TAG to Codeberg."
|
echo "Published $TAG to Codeberg."
|
||||||
|
|
||||||
|
# Google Play channel.
|
||||||
|
#
|
||||||
|
# A separate job, on purpose, running only AFTER the F-Droid publish and both
|
||||||
|
# forge releases have completed. Play is the one channel that can reject a
|
||||||
|
# perfectly good build for reasons outside the pipeline (listing rules, policy
|
||||||
|
# review, API outage, a track that needs manual promotion). Isolating it means
|
||||||
|
# such a rejection surfaces as one red job next to a release that already
|
||||||
|
# shipped everywhere else, instead of failing the workflow that publishes it.
|
||||||
|
#
|
||||||
|
# Not a `container:` job even though a fastlane image exists: act_runner does
|
||||||
|
# not provide node inside custom job containers, so JavaScript actions
|
||||||
|
# (checkout, download-artifact) can't run there. The Renovate job gets away
|
||||||
|
# with a container because its only step is a shell command. Ruby is installed
|
||||||
|
# the same way sshpass, jq and fdroidserver are in the job above.
|
||||||
|
play:
|
||||||
|
needs: [detect, release]
|
||||||
|
# workflow_dispatch is the F-Droid re-sign recovery path — it must never
|
||||||
|
# touch Play, so gate on a real release only.
|
||||||
|
if: needs.detect.outputs.is_release == 'true'
|
||||||
|
runs-on: docker
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.detect.outputs.version }}
|
||||||
|
VERSION_CODE: ${{ needs.detect.outputs.version_code }}
|
||||||
|
# Where the bundle lands. `internal` by default so a release reaches
|
||||||
|
# testers rather than the public, and promotion to production stays a
|
||||||
|
# deliberate human action in the Play Console — the same posture as
|
||||||
|
# holding UI releases for on-device review. Override with the PLAY_TRACK
|
||||||
|
# repo variable once the flow is trusted.
|
||||||
|
PLAY_TRACK: ${{ vars.PLAY_TRACK || 'internal' }}
|
||||||
|
PLAY_RELEASE_STATUS: ${{ vars.PLAY_RELEASE_STATUS || 'completed' }}
|
||||||
|
# Set PLAY_DRY_RUN=true to validate the edit against the API and discard
|
||||||
|
# it instead of committing — used to rehearse the first upload.
|
||||||
|
PLAY_DRY_RUN: ${{ vars.PLAY_DRY_RUN || 'false' }}
|
||||||
|
BUNDLE_PATH: vendor/bundle
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# Skip cleanly (not fatally) when Play isn't configured yet, so the rest
|
||||||
|
# of the release pipeline keeps working during setup — same contract as
|
||||||
|
# the Codeberg mirror step.
|
||||||
|
- name: Write the Play service-account key
|
||||||
|
id: key
|
||||||
|
env:
|
||||||
|
PLAY_SERVICE_ACCOUNT_JSON: ${{ secrets.PLAY_SERVICE_ACCOUNT_JSON }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if [ -z "${PLAY_SERVICE_ACCOUNT_JSON:-}" ]; then
|
||||||
|
echo "PLAY_SERVICE_ACCOUNT_JSON not set — skipping the Play upload."
|
||||||
|
echo "configured=false" >> "$GITHUB_OUTPUT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
printf '%s' "$PLAY_SERVICE_ACCOUNT_JSON" > play-service-account.json
|
||||||
|
# Fail here, with a clear message, rather than inside fastlane: a
|
||||||
|
# mangled multi-line secret is the likeliest setup mistake.
|
||||||
|
python3 -c "import json,sys; d=json.load(open('play-service-account.json')); sys.exit(0 if d.get('type')=='service_account' else 1)" \
|
||||||
|
|| { echo "PLAY_SERVICE_ACCOUNT_JSON is not a valid service-account JSON." >&2; exit 1; }
|
||||||
|
echo "configured=true" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Download the AAB
|
||||||
|
if: steps.key.outputs.configured == 'true'
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: release-aab-${{ needs.detect.outputs.version }}
|
||||||
|
path: dist
|
||||||
|
|
||||||
|
- name: Install Ruby
|
||||||
|
if: steps.key.outputs.configured == 'true'
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
SUDO=""
|
||||||
|
if command -v sudo >/dev/null 2>&1; then SUDO="sudo"; fi
|
||||||
|
$SUDO apt-get update
|
||||||
|
# ruby-dev + build-essential: several of fastlane's dependencies build
|
||||||
|
# native extensions.
|
||||||
|
$SUDO apt-get install -y ruby-full ruby-dev build-essential
|
||||||
|
ruby -v
|
||||||
|
|
||||||
|
# Only the first release pays the full gem build; afterwards this restores.
|
||||||
|
- name: Cache bundled gems
|
||||||
|
if: steps.key.outputs.configured == 'true'
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: vendor/bundle
|
||||||
|
key: ${{ runner.os }}-gems-${{ hashFiles('Gemfile') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-gems-
|
||||||
|
|
||||||
|
- name: Install fastlane
|
||||||
|
if: steps.key.outputs.configured == 'true'
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
gem install bundler --no-document
|
||||||
|
bundle config set --local path vendor/bundle
|
||||||
|
bundle install --jobs 4
|
||||||
|
bundle exec fastlane --version
|
||||||
|
|
||||||
|
- name: Upload to Play
|
||||||
|
if: steps.key.outputs.configured == 'true'
|
||||||
|
env:
|
||||||
|
SUPPLY_JSON_KEY: play-service-account.json
|
||||||
|
# supply is chatty on a TTY-less runner otherwise.
|
||||||
|
FASTLANE_SKIP_UPDATE_CHECK: '1'
|
||||||
|
FASTLANE_HIDE_CHANGELOG: '1'
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
test -f "dist/app-release.aab"
|
||||||
|
bundle exec fastlane deploy \
|
||||||
|
aab:"dist/app-release.aab" \
|
||||||
|
track:"$PLAY_TRACK" \
|
||||||
|
release_status:"$PLAY_RELEASE_STATUS" \
|
||||||
|
dry_run:"$PLAY_DRY_RUN"
|
||||||
|
echo "Uploaded $VERSION (code $VERSION_CODE) to the '$PLAY_TRACK' track."
|
||||||
|
|
||||||
|
# The workspace is reused between runs on a self-hosted runner, so the
|
||||||
|
# credential must not outlive the job.
|
||||||
|
- name: Shred the service-account key
|
||||||
|
if: always()
|
||||||
|
run: shred -u play-service-account.json 2>/dev/null || rm -f play-service-account.json
|
||||||
|
|||||||
11
.gitignore
vendored
11
.gitignore
vendored
@@ -61,5 +61,16 @@ Thumbs.db
|
|||||||
# KSP
|
# KSP
|
||||||
.ksp/
|
.ksp/
|
||||||
|
|
||||||
|
# Google Play Developer API service-account key. Reconstructed in CI from the
|
||||||
|
# PLAY_SERVICE_ACCOUNT_JSON secret and shredded afterwards — never committed.
|
||||||
|
/play-service-account.json
|
||||||
|
|
||||||
|
# fastlane (Play uploader only — see fastlane/Fastfile)
|
||||||
|
/fastlane/report.xml
|
||||||
|
/fastlane/README.md
|
||||||
|
/vendor/bundle/
|
||||||
|
/.bundle/
|
||||||
|
Gemfile.lock
|
||||||
|
|
||||||
# Claude Code
|
# Claude Code
|
||||||
/CLAUDE.md
|
/CLAUDE.md
|
||||||
|
|||||||
10
Gemfile
Normal file
10
Gemfile
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
# fastlane is used ONLY to upload the release bundle to Google Play
|
||||||
|
# (see fastlane/Fastfile). It is not part of the build or the signing path, so
|
||||||
|
# it never runs on a PR — only in release.yaml's `play` job.
|
||||||
|
#
|
||||||
|
# Pinned exactly; Renovate's bundler manager keeps it bumped. No Gemfile.lock is
|
||||||
|
# committed on purpose: this resolves an uploader's transitive deps, not the
|
||||||
|
# app's, and none of it affects the reproducible release build.
|
||||||
|
gem "fastlane", "2.237.0"
|
||||||
@@ -87,6 +87,9 @@ release work when a merge actually cuts a release:
|
|||||||
mirror the release to **Codeberg** with the signed APK + a SHA-256 checksum
|
mirror the release to **Codeberg** with the signed APK + a SHA-256 checksum
|
||||||
(both best-effort). Ordinary merges with no version bump fall through `detect`
|
(both best-effort). Ordinary merges with no version bump fall through `detect`
|
||||||
and do nothing.
|
and do nothing.
|
||||||
|
- **`play` job** (same workflow, after `release`) — uploads the App Bundle to
|
||||||
|
Google Play. Runs last and separately so a Play rejection can't endanger a
|
||||||
|
release that already shipped; skips cleanly until Play is configured.
|
||||||
|
|
||||||
### Codeberg direct-download channel
|
### Codeberg direct-download channel
|
||||||
|
|
||||||
@@ -102,6 +105,58 @@ unset. One-time setup: the repo's **Releases** unit must be enabled and a
|
|||||||
`CODEBERG_RELEASE_TOKEN` secret (Codeberg access token, `write:repository` scope) added
|
`CODEBERG_RELEASE_TOKEN` secret (Codeberg access token, `write:repository` scope) added
|
||||||
to Gitea Actions.
|
to Gitea Actions.
|
||||||
|
|
||||||
|
### Google Play channel
|
||||||
|
|
||||||
|
Play is a third channel alongside F-Droid and the Codeberg download, and it is
|
||||||
|
the only one that gets a different artifact and a different signature.
|
||||||
|
|
||||||
|
**Artifact.** Play takes an **App Bundle** (`bundleRelease`), not the APK. It is
|
||||||
|
a second output of the same source and the same signing config — never a
|
||||||
|
repackage of the published APK, which stays untouched so the F-Droid
|
||||||
|
reproducibility guarantee is unaffected. `dependenciesInfo` stays disabled for
|
||||||
|
the bundle too; Play's "app dependencies" report is optional and re-enabling it
|
||||||
|
would break reproducibility.
|
||||||
|
|
||||||
|
**Signature — read this before assuming an update path exists.** Play App
|
||||||
|
Signing is mandatory for new apps, and Google generates and holds the app
|
||||||
|
signing key. The release keystore in CI is registered only as the **upload
|
||||||
|
key**: Play verifies uploads with it, then re-signs with Google's key before
|
||||||
|
delivery. Consequences, accepted deliberately:
|
||||||
|
|
||||||
|
- A Play install and an F-Droid install have **different signatures** and
|
||||||
|
**cannot update each other**. Switching channels requires uninstall +
|
||||||
|
reinstall, which loses nothing (all data lives in the system calendar
|
||||||
|
provider) but must be stated wherever both channels are advertised.
|
||||||
|
- Losing the upload key is **recoverable** — request an upload-key reset in the
|
||||||
|
Play Console. Losing the app key still is not, for F-Droid.
|
||||||
|
|
||||||
|
**Build and signing are not fastlane's job.** Gradle does both, exactly as
|
||||||
|
before. fastlane appears only as the Play Developer API client (`supply`),
|
||||||
|
because the store listing already lives in `fastlane/metadata/android/` — the
|
||||||
|
same tree the official F-Droid repo harvests. One metadata source, two stores.
|
||||||
|
|
||||||
|
**What gets uploaded per release:** the AAB, plus the per-version "What's New"
|
||||||
|
from `fastlane/metadata/android/en-US/changelogs/<versionCode>.txt` (generated
|
||||||
|
from `CHANGELOG.md` by `scripts/sync_changelog_to_fastlane.sh`). Listing text is
|
||||||
|
**not** touched — an accidental overwrite of a live listing triggers a Play
|
||||||
|
policy review. Sync it deliberately with `bundle exec fastlane listing`.
|
||||||
|
|
||||||
|
**Screenshots and graphics are skipped**, because the committed assets satisfy
|
||||||
|
F-Droid but not Play:
|
||||||
|
|
||||||
|
| Asset | Committed | Play requires |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `phoneScreenshots/*.png` | 1280×2856, 32-bit RGBA | long edge ≤ 2× short edge (so ≤ 2560), 24-bit PNG, no alpha |
|
||||||
|
| `icon.png` | 512×512, 24-bit RGB | 512×512, 32-bit PNG |
|
||||||
|
| `featureGraphic.png` | *missing* | required, exactly 1024×500 |
|
||||||
|
|
||||||
|
Until those are fixed, Play's graphics are managed by hand in the console. Then
|
||||||
|
pass `images:true` to the `listing` lane.
|
||||||
|
|
||||||
|
**Track.** Uploads go to `internal` by default; promotion to production stays a
|
||||||
|
manual action in the Play Console, matching the rule that UI releases wait for
|
||||||
|
on-device review. Override with the `PLAY_TRACK` repo variable.
|
||||||
|
|
||||||
### Manual re-sign / recovery
|
### Manual re-sign / recovery
|
||||||
|
|
||||||
A manual `workflow_dispatch` of the release workflow runs a **re-sign-only**
|
A manual `workflow_dispatch` of the release workflow runs a **re-sign-only**
|
||||||
@@ -153,6 +208,15 @@ Two consequences worth remembering:
|
|||||||
| `HETZNER_HOST`, `HETZNER_USER`, `HETZNER_PASS` | Upload target for the F-Droid repo. |
|
| `HETZNER_HOST`, `HETZNER_USER`, `HETZNER_PASS` | Upload target for the F-Droid repo. |
|
||||||
| `GITHUB_TOKEN` | Provided by Gitea Actions; used to create the release + attach assets. |
|
| `GITHUB_TOKEN` | Provided by Gitea Actions; used to create the release + attach assets. |
|
||||||
| `CODEBERG_RELEASE_TOKEN` | Codeberg access token (`write:repository` scope) — creates the mirrored Codeberg release + uploads the APK/checksum. Best-effort; if unset the Codeberg step skips. |
|
| `CODEBERG_RELEASE_TOKEN` | Codeberg access token (`write:repository` scope) — creates the mirrored Codeberg release + uploads the APK/checksum. Best-effort; if unset the Codeberg step skips. |
|
||||||
|
| `PLAY_SERVICE_ACCOUNT_JSON` | Google Cloud service-account key (full JSON) with Play Console access — uploads the AAB. If unset, the `play` job skips cleanly. |
|
||||||
|
|
||||||
|
### Variables (Gitea → repo Settings → Actions → Variables)
|
||||||
|
|
||||||
|
| Variable | Default | Purpose |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `PLAY_TRACK` | `internal` | Play track the bundle is uploaded to. |
|
||||||
|
| `PLAY_RELEASE_STATUS` | `completed` | `completed`, `draft`, `inProgress` or `halted`. |
|
||||||
|
| `PLAY_DRY_RUN` | `false` | `true` validates the Play edit against the API and discards it — use to rehearse. |
|
||||||
|
|
||||||
The two keys are independent: the **app key** signs APKs; the **repo key**
|
The two keys are independent: the **app key** signs APKs; the **repo key**
|
||||||
signs the index (its fingerprint is what users pin). Neither key nor the
|
signs the index (its fingerprint is what users pin). Neither key nor the
|
||||||
|
|||||||
7
fastlane/Appfile
Normal file
7
fastlane/Appfile
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# fastlane is used in this repo ONLY as a Google Play Developer API client
|
||||||
|
# (see fastlane/Fastfile). It never builds and never signs.
|
||||||
|
|
||||||
|
# Reconstructed in CI from the PLAY_SERVICE_ACCOUNT_JSON secret; gitignored.
|
||||||
|
json_key_file(ENV["SUPPLY_JSON_KEY"] || "play-service-account.json")
|
||||||
|
|
||||||
|
package_name("de.jeanlucmakiola.calendula")
|
||||||
80
fastlane/Fastfile
Normal file
80
fastlane/Fastfile
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# 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)
|
||||||
|
|
||||||
|
platform :android do
|
||||||
|
desc "Upload an already-built, already-signed AAB to Play"
|
||||||
|
lane :deploy do |options|
|
||||||
|
aab = 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/<versionCode>.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
|
||||||
Reference in New Issue
Block a user