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

Merged
merged 4 commits into from
Feb 16, 2025

Conversation

Sahil06012002
Copy link
Contributor

@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
Contributor 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
Contributor 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
Contributor 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
Contributor 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
Contributor 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?

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.

This looks like it should work in the two cases I consider important:

  • "I want to test a release build" -> now can be done easily without configuring keystore
  • "We are generating a release build" -> All the environment variables we set appear to be taken into account and should be used correctly

Excellent

Will keep fingers crossed for the next release build to make sure it goes smoothly

@mikehardy mikehardy merged commit ee580d5 into ankidroid:main Feb 16, 2025
9 checks passed
@github-actions github-actions bot added this to the 2.21 release milestone Feb 16, 2025
@mikehardy mikehardy removed the Needs Author Reply Waiting for a reply from the original author label Feb 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

docs: Document how to test on release builds
2 participants