As part of my goal to decrease my smartphone addiction, I recently bought a Unihertz Jelly phone, which could be a good compromise between a smartphone and a dumbphone. The phone has a multi-purpose function button. You can assign it to specific pre-defined actions or launch any application. As I regularly use the phone screen in grayscale mode, I decided to assign the button to an application that would toggle this mode. I searched and couldn't find a simple app to toggle it when launching. So I decided to write my own. However, this previous background could be a post on its own.
As I've been trying to leverage GitHub actions for manual tasks, I searched GitHub and found many actions that could do this for me. I tried with a couple of them, and they didn't work. One of the issues is that the actions are using obsolete dependencies, and I spent way more time trying to make them run than I wanted.
I decided to make it work without a pre-built action and write all of the required steps in a GitHub workflow, which, in the end, was very simple. Here's the action. I will do a walk-through so you can use it in your projects.
name: Release APK
on:
push:
tags:
- '*'
This workflow will run when pushing a tag to a repository.
jobs:
Gradle:
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v3
This is the standard step to checkout the code. It can run with the latest checkout
action (v3).
- name: setup jdk
uses: actions/setup-java@v3
with:
java-version: 17
distribution: 'temurin'
Then, we need to set up the JDK. Again, using the latest setup-java
action (v3). I set the Java version to 17, which is the one that my Android Project uses. You can adjust the distribution, too. Refer to setup-java
s documentation.
Now, to sign the released APK, we'll need to load the Keystore (you can read how to generate it on Android's official documentation).
- name: Load keystore
run: |
echo "${{ secrets.KEYSTORE_FILE_CONTENTS }}" | base64 -d > keystore.jks && \
The secret KEYSTORE_FILE_CONTENTS
, contains the base64 encoded content of the keystore.jks file you generated. You can get the text for the secret by running cat keystore.jks | base64 -w0
.
cat <<EOL > local.properties
storeFilePath=$PWD/keystore.jks
storePassword=${{ secrets.RELEASE_STORE_PASSWORD }}
keyAlias=${{ secrets.RELEASE_KEY_ALIAS }}
keyPassword=${{ secrets.RELEASE_KEY_PASSWORD }}
EOL
The rest of the secrets are the ones you entered when configuring your keystore.
Next, we'll build the APK:
- name: Build Release APK
run: ./gradlew assembleRelease
env:
GRADLE_USER_HOME: ./gradle-config
And set the current directory as a safe repository, as this is a known issue with actions/checkout@v3
. And because we'll later use github-cli
to do the release, I didn't want it to complain that it couldn't read the repository.
- name: Set current directory as a safe repository
run: git config --global --add safe.directory /github/workspace
- uses: ButterCam/setup-github-cli@master
Finally, release the APK and upload it to the repository's releases page.
- name: Release using github cli
run: gh release create ${GITHUB_REF##*/} ./app/build/outputs/apk/release/**.apk
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
You'll need to generate a token with repo
access for this to work. For some reason, using the default repository's GITHUB_TOKEN
won't work.
And here's the full YAML in case you want to copy-paste it. You can also check it in my repository.
name: Release APK
on:
push:
tags:
- '*'
jobs:
Release:
runs-on: ubuntu-latest
steps:
- name: checkout code
uses: actions/checkout@v3
- name: setup jdk
uses: actions/setup-java@v3
with:
java-version: 17
distribution: 'temurin'
- name: Load keystore
run: |
echo "${{ secrets.KEYSTORE_FILE_CONTENTS }}" | base64 -d > keystore.jks && \
cat <<EOL > local.properties
storeFilePath=$PWD/keystore.jks
storePassword=${{ secrets.RELEASE_STORE_PASSWORD }}
keyAlias=${{ secrets.RELEASE_KEY_ALIAS }}
keyPassword=${{ secrets.RELEASE_KEY_PASSWORD }}
EOL
- name: Build Release APK
run: ./gradlew assembleRelease
env:
GRADLE_USER_HOME: ./gradle-config
- name: Set current directory as a safe repository
run: git config --global --add safe.directory /github/workspace
- uses: ButterCam/setup-github-cli@master
- name: Release using github cli
run: gh release create ${GITHUB_REF##*/} ./app/build/outputs/apk/release/**.apk
env:
GITHUB_TOKEN: ${{ secrets.TOKEN }}
There's still one thing that needs configuration to sign the APK properly. You'll need to edit your app/build.gradle.kts
file so we can feed the properties from GitHub secrets to the assmbleRelease
task. Kudos to Willi Metzel's Stack Overflow answer. Inside android
in app/build.gradle.kts
add:
signingConfigs {
create("release") {
val properties = Properties().apply {
load(File("local.properties").reader())
}
storeFile = File(properties.getProperty("storeFilePath"))
storePassword = properties.getProperty("storePassword")
keyPassword = properties.getProperty("keyPassword")
keyAlias = properties.getProperty("keyAlias")
}
}
Then, add signingConfig = signingConfigs.getByName("release")
to release
inside buildTypes
. It should look something like:
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
signingConfig = signingConfigs.getByName("release")
}
}
See here for a complete reference to my app/build.gradle.kts
.
Credits to r0adkll for his previous work; without it, building this would have been more difficult.
You can follow me at GitHub (@ivanvc). And check the repository (and source code for my grayscale switching app) if you're interested.
Top comments (2)
Auto build means , automatically sent to internal testing to Google play console?
No, currently, it only uploads the generated APK to GitHub releases. I plan on doing that later.