Skip to content

Move the upload keystore out of the checkout - #23261

Open
mokagio wants to merge 3 commits into
trunkfrom
ainfra-2968-adopt-the-out-of-repo-keystore-convention-in-wordpress
Open

Move the upload keystore out of the checkout#23261
mokagio wants to merge 3 commits into
trunkfrom
ainfra-2968-adopt-the-out-of-repo-keystore-convention-in-wordpress

Conversation

@mokagio

@mokagio mokagio commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Description

Closes AINFRA-2968.

The upload keystore now decrypts next to secrets.properties, outside of the checkout, as described internally in paaHJt-akR-p2.

.gitignore still ignores WordPress/*.jks because pre-change checkouts still have WordPress/upload.jks on disk.

uploadStoreFile and debugStoreFile are unused after this. Dropping them from mobile-secrets is a separate follow-up, so this PR stays revertible on its own.

After merging, run bundle exec fastlane run configure_apply and delete the stale WordPress/upload.jks.

Testing instructions

Signing is not in the unit suite.
Compare ./gradlew :WordPress:signingReport.

Without secrets:

  • wordpressRelease / jetpackReleaseConfig: none
  • wordpressDebug~/.android/debug.keystore

After bundle exec fastlane run configure_apply:

  • release configs → Config: release, Store: in the out-of-repo configure directory, not the repo
  • Alias: matches uploadKeyAlias
  • wordpressDebug → shared debug.keystore from that directory

For the record: I run all the check on my end.

PR CI does not exercise release signing.
Prototype builds on this PR did pick up the renamed debug keystore.

Also verified on a CI agent

Because no PR job exercises release signing, the same checks were run on a Buildkite agent from a throwaway stacked PR (#23267, now closed): build #28383, job "🔐 Validate signing config".

After configure_apply on the agent:

Variant: wordpressRelease
Config: release
Store: /var/lib/buildkite-agent/.configure/wordpress-android/secrets/upload.jks
SHA-256: 14:F0:…:9F:A6   (same certificate as the local report)

Two negative cases ran against a throwaway user.home symlinked to the real credentials, so the agent's secrets directory was never touched:

  • Credentials readable, no upload keystore → both release variants drop to Config: none. The keystore file, not secrets.properties, is what gates signing.
  • No shared debug.keystore → debug variants fall back to ~/.android/debug.keystore with Error: Missing keystore. This is why a green prototype build was never on its own evidence that the shared key was read.

Still unproven until the scheduled trunk-internal build: that bundleRelease signs and uploads with this keystore. signingReport shows the config resolves, not that the artifact ships.

Section added by Claude (Opus 5) on behalf of @mokagio with approval. Re-run after the branch kept the .jks extension; the earlier run was #23266 / build #28371.

@mokagio mokagio self-assigned this Aug 25, 2026
@wpmobilebot

wpmobilebot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

App Icon📲 You can test the changes from this Pull Request in Jetpack Android by scanning the QR code below to install the corresponding build.

App NameJetpack Android
Build TypeDebug
Versionpr23261-0f8554a
Build Number1498
Application IDcom.jetpack.android.prealpha
Commit0f8554a
Installation URL1ou00flce8qr0
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@wpmobilebot

wpmobilebot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

App Icon📲 You can test the changes from this Pull Request in WordPress Android by scanning the QR code below to install the corresponding build.

App NameWordPress Android
Build TypeDebug
Versionpr23261-0f8554a
Build Number1498
Application IDorg.wordpress.android.prealpha
Commit0f8554a
Installation URL19nqaspsipsh8
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

Applies the convention from the out-of-repo Android keystores RFC:
https://appsinfrap2.wordpress.com/2026/08/21/rfc-convention-for-out-of-repo-android-keystores/

The upload keystore was the last genuine secret still decrypted into the
working tree. It now lands in the same out-of-repo secrets directory that
already holds `secrets.properties`, so nothing sensitive sits inside the
checkout for an editor, a backup, or an agent to pick up.

Naming the directory `decryptedSecretsDir` is deliberate: it is the name
the RFC's snippet uses for the `a8c-secrets` equivalent, so adopting
`a8c-secrets` later only changes what the variable points at, not the
signing config that reads it.

Gating on the keystore file rather than on `uploadStoreFile` lets the
path stop being a secret value — a filename the build script owns is not
something `secrets.properties` needs to carry. `uploadStoreFile` and
`debugStoreFile` are now unused and can be dropped from `mobile-secrets`
separately.

`.gitignore` keeps its `WordPress/*.jks` entries on purpose. Checkouts
that ran `configure_apply` before this change still have a stale
`WordPress/upload.jks` on disk, and un-ignoring it would make a real
signing key committable.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Code Opus 5 <noreply@anthropic.com>
@mokagio
mokagio force-pushed the ainfra-2968-adopt-the-out-of-repo-keystore-convention-in-wordpress branch from b210b1c to 97122d3 Compare August 26, 2026 04:02
Comment thread settings.gradle
isCi = System.getenv('CI')?.toBoolean() ?: false

secretPath = "${System.getProperty("user.home")}/.configure/wordpress-android/secrets/secrets.properties"
decryptedSecretsDir = file("${System.getProperty("user.home")}/.configure/wordpress-android/secrets")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This will become a8c-secrets ad hoc project's folder once we adopt the tool.

@mokagio
mokagio requested review from a team and wzieba August 26, 2026 10:33
@mokagio mokagio added this to the 27.2 milestone Aug 26, 2026
@mokagio
mokagio marked this pull request as ready for review August 26, 2026 10:33
Copilot AI lite review requested due to automatic review settings August 26, 2026 10:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Updates the Android signing setup so decrypted keystores live alongside secrets.properties in the out-of-repo ~/.configure/wordpress-android/secrets directory, avoiding sensitive keystore files being written into the git checkout.

Changes:

  • Switch release signing to use ~/.configure/wordpress-android/secrets/upload.keystore (when present + credentials exist).
  • Switch shared debug signing to use ~/.configure/wordpress-android/secrets/debug.keystore (when present).
  • Introduce a shared decryptedSecretsDir setting and update .configure copy destinations to match the new keystore locations/names.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
WordPress/build.gradle Reads release/debug keystores from the decrypted secrets directory and gates signing on their presence.
settings.gradle Adds decryptedSecretsDir and builds secretPath from it for consistent out-of-repo secrets resolution.
.configure Renames and relocates keystore destinations to the out-of-repo secrets directory.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread WordPress/build.gradle Outdated
Comment on lines 283 to 287
def uploadKeystore = new File(gradle.ext.decryptedSecretsDir, "upload.keystore")
def uploadCredentials = ["uploadStorePassword", "uploadKeyAlias", "uploadKeyPassword"]
if (uploadKeystore.exists() && uploadCredentials.every { gradle.ext.secretProperties.containsKey(it) }) {
logger.info("Upload keystore found, configuring signing for release builds.")
release {
Renaming it to `.keystore` alongside the move out of the checkout was
gratuitous: the file this PR relocates is already `automattic_upload.jks`
in `mobile-secrets`, so keeping the extension makes the move the only
change under review.

---

Generated with the help of Claude Code, https://claude.ai/code

Co-Authored-By: Claude Code Opus 5 <noreply@anthropic.com>
mokagio added a commit that referenced this pull request Aug 27, 2026
[DO NOT MERGE] Throwaway validation for #23261, closed once it has answered.

Nothing in the PR pipeline exercises release signing: prototype builds
assemble the `Debug` build type, lint and the manifest diffs never sign,
and `release-builds.yml` and `beta-builds.yml` are API-triggered from
release automation and check out a release branch rather than the PR.
The first run that would notice a broken release signing config is the
scheduled trunk-internal build, after merge.

The debug side is worse than uncovered: when the shared keystore is
absent AGP falls back to `~/.android/debug.keystore` and the build still
goes green, so every prototype build so far has passed without proving
the renamed `debug.keystore` was ever read.

Both negative cases run against a throwaway `user.home` holding symlinks
to the real credentials, so the agent's secrets directory is never
mutated and no decrypted secret is copied anywhere.

---

Generated with the help of Claude Code, https://claude.com/claude-code

Co-Authored-By: Claude Code Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants