Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added fallback-release-keystore.jks file as a fallback for release builds #17961

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

Sahil06012002
Copy link

@Sahil06012002 Sahil06012002 commented Feb 10, 2025

Purpose / Description

  • Previously, testing the project in release mode required manually creating a keystore and configuring environment variables, which was a tedious and inconvenient process.
  • To streamline the testing process, this PR introduces a fallback-release-keystore.jks file. The release signing configuration will automatically fall back to this keystore if no environment variables are set.
  • By implementing this approach:
  • Developers can easily test release builds without manual setup.

Fixes

Approach

  • Introduced a fallback keystore (fallback-release-keystore.jks), removing the need for manual keystore setup.
  • Updated the release signing configuration to automatically use the fallback keystore when necessary.
  • Streamlined the tests_emulator.yml workflow for a more efficient process.

How Has This Been Tested?

  • Verified that release builds successfully use the fallback keystore when no environment variables are provided.
  • Ran the emulator tests to confirm that the workflow functions correctly with the updated signing configuration.

Checklist

  • You have a descriptive commit message with a short title (first line, max 50 chars).
  • You have commented your code, particularly in hard-to-understand areas
  • You have performed a self-review of your own code
  • UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
  • UI Changes: You have tested your change using the Google Accessibility Scanner

@Sahil06012002
Copy link
Author

@mikehardy can you please review this once.

Copy link
Member

@mikehardy mikehardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not ready for review - fails the testing that depends on it in CI


* What went wrong:
Execution failed for task ':AnkiDroid:packagePlayReleaseAndroidTest'.
> A failure occurred while executing com.android.build.gradle.tasks.PackageAndroidArtifact$IncrementalSplitterRunnable
   > com.android.ide.common.signing.KeytoolException: Failed to read key nrkeystorealias from store "/home/runner/work/Anki-Android/Anki-Android/tools/fallback-release-keystore.jks": keystore password was incorrect

You may reproduce this test result locally by doing what CI does and setting this variable:

TEST_RELEASE_BUILD: true

Note that the CI workflow should probably be changed as well - if we are bundling a test keystore in the repository now, we no longer need the step "Test Credential Prep"

- name: Test Credential Prep
run: |
echo "KSTOREPWD=$STOREPASS" >> $GITHUB_ENV
echo "KEYPWD=$KEYPASS" >> $GITHUB_ENV
mkdir $STOREFILEDIR
cd $STOREFILEDIR
echo y | keytool -genkeypair -dname "cn=AnkiDroid, ou=ankidroid, o=AnkiDroid, c=US" -alias $KEYALIAS -keypass $KEYPASS -keystore "$STOREFILE" -storepass $STOREPASS -keyalg RSA -validity 20000
shell: bash

...nor does the workflow need to set all the variables related to the test keystore (location, passwords, key alias etc) that are all over the file - will be nice to simplify it

@mikehardy mikehardy added the Needs Author Reply Waiting for a reply from the original author label Feb 10, 2025
@mikehardy
Copy link
Member

Also note that you have left the description of the PR blank it still just says:

Describe the problem or feature and motivation

That's your opportunity to make a first impression with the PR. Please put something in there that explains why the PR exists, and what the PR does to address that reason

Similarly, the commit currently says:

update:add fallback-release-keystore.jks file as a fallback

We don't strictly follow the "conventional commits" standard, but I do in other repos, and the 'update' appears to be a keyword for conventional commits but isn't a recognized keyword. I'd expect "feat:" for feature - this is a cool doc explaining conventional commits tags used by lots of open source repositories: https://www.conventionalcommits.org/en/v1.0.0/#specification

historically, feat, fix, docs, chore, build, release are the ones I use most of the time

"add fallback-release-keystore.jks file as a fallback" with no other comment won't help people going through commits if they're looking to fix an issue later

Maybe something like:


feat: add fallback release signing keystore if no env vars present

this should help people trying to test release builds that haven't set up
a release signing keystore - we'll provide one along with all the config
key alias / password info to use it if release build is requested but no
environment variables are present

@Sahil06012002
Copy link
Author

@mikehardy Thanks for the review, working on the changes.

this should help people trying to test release builds that haven't set up a release signing keystore - we'll provide one along with all the config key alias / password info to use it if release build is requested but no environment variables are present
Copy link
Member

@mikehardy mikehardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

almost there - looks like the fallback will work, but now it works every time with no option of env vars, and we still use env vars for the final + real + official publish

Comment on lines -100 to +103
storeFile file(System.getenv("KEYSTOREPATH") ?: "${homePath}/src/android-keystore")
storePassword System.getenv("KEYSTOREPWD") ?: System.getenv("KSTOREPWD")
keyAlias System.getenv("KEYALIAS") ?: "nrkeystorealias"
keyPassword System.getenv("KEYPWD")
storeFile file("${rootDir}/tools/fallback-release-keystore.jks")
storePassword "Test@123"
keyAlias "my-key"
keyPassword "Test@123"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Close but not quite - we still need the ability to specify things by environment variable.
Why?
./tools/release.sh drives the real release process using environment variables and a keystore / keystore secrets that are stored in github secrets and used in the workflow

So we need the environment variables specified here to continue working:

- name: Credential Prep
run: |
echo "KEYSTOREPATH=$HOME/src/android-keystore" >> $GITHUB_ENV
echo "KEYALIAS=nrkeystorealias" >> $GITHUB_ENV
echo "KEYSTOREPWD=${{ secrets.KEYSTORE_PASSWORD }}" >> $GITHUB_ENV
echo "KEYPWD=${{ secrets.KEYSTORE_KEY_PASSWORD }}" >> $GITHUB_ENV
mkdir ~/src
cd ~/src
echo "${{ secrets.AMAZON_PUBLISH_CREDENTIALS }}" | base64 -d > ./AnkiDroid-Amazon-Publish-Security-Profile.json.gz
echo "${{ secrets.GOOGLE_PUBLISH_CREDENTIALS }}" | base64 -d > ./AnkiDroid-GCP-Publish-Credentials.json.gz
echo "${{ secrets.RELEASES_PUBLISH_TOKEN }}" | base64 -d > ./my-github-personal-access-token.gz
echo "${{ secrets.KEYSTORE }}" | base64 -d > ./android-keystore.gz
gunzip *.gz
shell: bash

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we still need the ability to specify things by environment variable.
I anticipated this while updating build.gradle 😅.

@Sahil06012002
Copy link
Author

@mikehardy Got it,
Quick question:
If KEYSTOREPATH is invalid, we’ll fall back to the local keystore file. However, KEYSTOREPWD, KEYALIAS, and KEYPWD might still have valid dummy values, which could cause issues when used with the local keystore.

Would it make sense to check only KEYSTOREPATH? If it's missing or doesn't point to a valid keystore, we switch entirely to the local keystore, including its associated credentials. Something like this:

def keystorePath = System.getenv("KEYSTOREPATH")

if (keystorePath != null && !keystorePath.trim().isEmpty()) {
    storeFile file(keystorePath)
    storePassword System.getenv("KEYSTOREPWD")
    keyAlias System.getenv("KEYALIAS")
    keyPassword System.getenv("KEYPWD")
} else {
    storeFile file("${rootDir}/tools/fallback-release-keystore.jks")
    storePassword "passwordforthefallbackkeystore"
    keyAlias "my-key"
    keyPassword "passwordforthefallbackkeystore"
}

Would this approach work for our use case?

Also, should I add the part where we set the environment variables in tests_emulator.yml, or should I leave it as is?

@mikehardy
Copy link
Member

I think if someone explicitly set an incorrect keystorepath, the build should fail and that's a good thing, let it fail

I do not think we need to set env vars in the emulator test, the only place that will use them now is publish.yml, that's okay

@Sahil06012002
Copy link
Author

Sahil06012002 commented Feb 14, 2025

I think if someone explicitly set an incorrect keystorepath, the build should fail and that's a good thing, let it fail

One approach would be to use

storeFile file(System.getenv("KEYSTOREPATH") ?: "${rootDir}/tools/fallback-release-keystore.jks")
storePassword System.getenv("KEYSTOREPWD") ?: System.getenv("KSTOREPWD" ?:  "passwordforthefallbackkeystore")
keyAlias System.getenv("KEYALIAS") ?: "my-key" 
keyPassword System.getenv("KEYPWD") ?: "passwordforthefallbackkeystore"

However, my concern with this approach is that KEYSTOREPATH might not be provided, while any one or more of the other environment variables (KEYSTOREPWD, KSTOREPWD, KEYALIAS, KEYPWD) could still be set, leading to an inconsistent configuration.
Given this, I’ll proceed with the following implementation.

def keystorePath = System.getenv("KEYSTOREPATH")

if (keystorePath != null && !keystorePath.trim().isEmpty()) {
    storeFile file(keystorePath)
    storePassword System.getenv("KEYSTOREPWD")
    keyAlias System.getenv("KEYALIAS")
    keyPassword System.getenv("KEYPWD")
} else {
    storeFile file("${rootDir}/tools/fallback-release-keystore.jks")
    storePassword "passwordforthefallbackkeystore"
    keyAlias "my-key"
    keyPassword "passwordforthefallbackkeystore"
}

This approach ensures that if KEYSTOREPATH is explicitly set but incorrect, the build will fail as expected. If it's missing, we fall back to the local keystore..
@mikehardy,do you have any additional suggestions or considerations that I should keep in mind?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Author Reply Waiting for a reply from the original author
Projects
None yet
Development

Successfully merging this pull request may close these issues.

docs: Document how to test on release builds
2 participants