OpenMiInk/third_party/ci-notary-service/doc/googleplaypublisher.md
Hellings b8c8ff98e2 Hi
2026-10-16 09:05:56 -04:00

6.2 KiB

googleplaypublisher.py - A Google Play Publishing Service

This services publishs AABs and APKs in Google Play.

Prerequisites

The service needs an SFTP server for exchanging data with the clients.

Installation

Install an Android SDK

googleplaypublisher.py need the apkanalyzer tool from an Android SDK. The following instructions are based on the installation of the Android SDK in KDE's Android Docker image.

export NDK_VERSION=22.1.7171670
export SDK_PLATFORM=android-33
export SDK_BUILD_TOOLS=30.0.3
export SDK_PACKAGES="tools platform-tools"

export ANDROID_HOME=~/android-sdk
export ANDROID_SDK_ROOT=${ANDROID_HOME}
export PATH=${ANDROID_HOME}/cmdline-tools/tools/bin:${ANDROID_HOME}/tools:${ANDROID_HOME}/platform-tools:${PATH}

curl -Lo /tmp/sdk-tools.zip 'https://dl.google.com/android/repository/commandlinetools-linux-6609375_latest.zip'
mkdir -p ${ANDROID_SDK_ROOT}/cmdline-tools
unzip -q /tmp/sdk-tools.zip -d ${ANDROID_SDK_ROOT}/cmdline-tools
rm -f /tmp/sdk-tools.zip

yes | sdkmanager --licenses
sdkmanager --verbose "platforms;${SDK_PLATFORM}" "build-tools;${SDK_BUILD_TOOLS}" "ndk;${NDK_VERSION}" ${SDK_PACKAGES}
sdkmanager --uninstall --verbose emulator

Install Fastlane Supply

This service uses Fastlane for interaction with Google Play.

# writeable base directory
FASTLANE_INSTALL_PREFIX=~
# install location for the fastlane tool
FASTLANE_DIR=$FASTLANE_INSTALL_PREFIX/fastlane
# executable name of Ruby Bundler
BUNDLE_EXECUTABLE=bundle3.0

# setup bundler to no try to install things in the global prefix
export BUNDLE_EXECUTABLE
export BUNDLE_PATH=$FASTLANE_INSTALL_PREFIX/vendor/bundle
export BUNDLE_APP_CONFIG=$FASTLANE_INSTALL_PREFIX/.bundle
$BUNDLE_EXECUTABLE config set --local path $BUNDLE_PATH

# install/update fastlane
mkdir -p $FASTLANE_DIR
pushd $FASTLANE_DIR

cat >Gemfile <<EOF
source "https://rubygems.org"
gem "fastlane"
EOF

$BUNDLE_EXECUTABLE install

popd

Install Bundletool

Bundletool is needed if you want to publish AABs. Download the jar file from the GitHub repository.

Install the Service

Clone this repository on a server that shall provide the service, create a virtual environment, and install the requirements.

git clone https://invent.kde.org/sysadmin/ci-notary-service.git googleplaypublisher
cd googleplaypublisher
python3 -m venv .venv
. .venv/bin/activate
pip3 install -r requirements.txt

Configure the Service

Copy googleplaypublisher.sample.ini to googleplaypublisher.ini and replace the example values with the appropriate values for your installation.

Then copy googleplaypublisher-projects.sample.yaml to googleplaypublisher-projects.yaml and specify the settings for the projects you want to publish AABs or APKs for.

Run the Service

Activate the virtual environment and start googleplaypublisher.py.

cd ~/googleplaypublisher
. .venv/bin/activate
python3 googleplaypublisher.py --id workerA --config googleplaypublisher.ini

where you replace workerA with a unique alpha-numeric ID for each instance of googleplaypublisher.py you start.

Use the Service to Publish an AAB or one or more APKs

Clone this repository on the client, create a virtual environment, and install the requirements.

git clone https://invent.kde.org/sysadmin/ci-notary-service.git googleplaypublisher
cd googleplaypublisher
python3 -m venv .venv
. .venv/bin/activate
pip3 install -r requirements.txt

Copy publishongoogleplay.sample.ini to publishongoogleplay.ini and replace the example values with the appropriate values for your installation. In particular, the value for BasePath must match the corresponding value in the settings of the service.

Then run publishongoogleplay.py to publish an (unsigned) AAB or one or more signed APKs

python3 publishongoogleplay.py --config publishongoogleplay.ini --fastlane <fastlane> <aab or apk>...

where <aab or apk>... is the AAB or the APKs you want to publish and <fastlane> is the fastlane zip file containing the meta data for the app.

Manage the Service with systemd

We set up the service under the user's control with a per-user systemd instance.

Copy googleplaypublisher-user.sample.service to ~/.config/systemd/user/googleplaypublisher-user.service and modify it as needed. The example uses the username as ID of the service worker. Make sure that the ID is unique if you run multiple service workers.

Start the service with

systemctl --user start googleplaypublisher-user.service

If you want the service to be started automatically, then enable autostart with

systemctl --user enable googleplaypublisher-user.service

Note: By default, the systemd user instance and thus the user-managed services are started after the first login of a user and killed after the last session of the user is closed. To start the user instance right after boot, and keep the systemd user instance running after the last session closes you have to enable lingering for the user:

loginctl enable-linger USERNAME

For more details on user-managed services see https://wiki.archlinux.org/title/Systemd/User.

Trouble Shooting

The following lists errors that occurred when trying to publish a new app on Google Play.

Downloading existing metadata fails with undefined method 'name' for nil:NilClass in block in latest_version

This happens if there is no release in the production track. As workaround one can create a production release but save it as draft. If you already created a release in another track then you can promote this release to the production track. It is automatically saved as draft when you promote it.

Uploading metadata fails with undefined method 'flat_map' for nil:NilClass in track_version_codes

This happens if there is no release in the beta (aka Open Testing) track. As workaround one can create a beta release but save it as draft. If you already created a release in another testing track then you can promote this release to the beta track. It is automatically saved as draft when you promote it.