Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 17 additions & 8 deletions .eas/workflows/build-android-production.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,20 @@ jobs:
params:
platform: android
profile: production
# To auto-upload to Google Play after the build, add a submit job once the
# Play service-account JSON is configured in eas.json (submit.production):
# submit_android:
# needs: [build_android]
# type: submit
# params:
# platform: android
# profile: production

submit_android:
name: Submit to Google Play
needs: [build_android]
type: submit
environment: production
params:
build_id: ${{ needs.build_android.outputs.build_id }}
profile: production
hooks:
after_submit:
- name: Publish Play Store release notes
run: |
set -euo pipefail
printf '%s' "$GOOGLE_SERVICE_ACCOUNT_JSON" > "$GOOGLE_SERVICE_ACCOUNT_KEY_PATH"
chmod 600 "$GOOGLE_SERVICE_ACCOUNT_KEY_PATH"
node scripts/play-release-notes.mjs
5 changes: 3 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@
- Web: `bun run web`
- Preview cloud build: `bun run build:android:preview`
- Production cloud build: `bun run build:android:production`
- Production submit: `bun run submit:android:production` (Google Play submission is currently performed manually)
- Build from GitHub: EAS Workflow `.eas/workflows/build-android-production.yml` (Android production), triggered on a version tag push (`v*`) or manual dispatch only
- Production submit: `bun run submit:android:production` (manual fallback; the tag workflow submits a draft automatically)
- Build from GitHub: EAS Workflow `.eas/workflows/build-android-production.yml` (Android production build, Google Play draft submission and release-notes promotion), triggered on a version tag push (`v*`) or manual dispatch only
- Play Store release notes: `store/play/release-notes/<version>/it-IT.txt` and `en-US.txt`, short and user-facing, at most 500 characters each. These are separate from the technical `CHANGELOG.md`; a release without valid notes stays a Play Console draft.
- Android bundle export check: `bunx expo export --platform android --output-dir C:\tmp\keysoft-android-export`
- Lint: `bun run lint`
- Typecheck: `bun run typecheck`
Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,17 @@ All notable project changes are documented here.

## [Unreleased]

### Release

- Rebuilt Keysoft 3.3.2 from `main` HEAD `8c893ea` as versionCode 132 with `targetSdkVersion`
36 and submitted it to the Google Play production track; Play review is pending while
3.3.2/131 remains live.
- Automates Google Play release submission from the version-tag EAS workflow: the build is
uploaded as a draft, then `scripts/play-release-notes.mjs` adds the Play Store release notes
and promotes it to a completed production release. Play Store notes live under
`store/play/release-notes/<version>/` and are short, user-facing and separate from this
technical changelog.

## [3.3.2] - 2026-10-23

### Release
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ bun run deps:audit
```

`bun run verify` runs formatting, type checking, linting, tests with coverage and
`expo-doctor`. Release artifacts are produced through EAS; build, submission, tag and release
`expo-doctor`. Release artifacts are produced through EAS; a version tag builds, submits to
Google Play and publishes the release notes automatically. Build, submission, tag and release
operations are documented in the [development guide](docs/development.md) and the
[release guide](docs/release.md). Architecture notes live in [docs/architecture.md](docs/architecture.md).

Expand Down
11 changes: 6 additions & 5 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,14 @@ bun run build:android:preview
bun run build:android:production
```

The repository is also linked to EAS Build, and the EAS Workflow `.eas/workflows/build-android-production.yml` can build the Android production app-bundle from GitHub. It is triggered only by a version tag push (`v*`) or manual dispatch to limit build-credit usage; it does not run on every push. iOS remains available only through the explicitly approved cloud-simulator workflow; App Store publication is outside the project workflow.
The repository is also linked to EAS Build, and the EAS Workflow `.eas/workflows/build-android-production.yml` builds the Android production app bundle from GitHub. It is triggered only by a version tag push (`v*`) or manual dispatch to limit build-credit usage; it does not run on every push. The same workflow submits the build to Google Play as a draft and then runs `scripts/play-release-notes.mjs` to add the Play Store release notes and promote it. iOS remains available only through the explicitly approved cloud-simulator workflow; App Store publication is outside the project workflow.

When publishing an approved release, push and verify `main` first, wait for the GitHub
`Validate` and CodeQL checks, then create the version tag on that exact commit. The tag push
already starts the EAS production workflow; do not also run `bun run
build:android:production` unless the tag-triggered workflow failed to start and a deliberate
replacement build is approved.
`Validate` and CodeQL checks, add the short Play Store notes under
`store/play/release-notes/<version>/`, then create the version tag on that exact commit. The tag
push starts the EAS production workflow, build, draft submission and notes promotion; do not
also run `bun run build:android:production` unless the tag-triggered workflow failed to start
and a deliberate replacement build is approved.

Expo Go cannot load custom native modules. Keysoft therefore uses the PBKDF2 KDF fallback in Expo Go and keeps Argon2 for EAS/native builds where `react-native-argon2` is available.

Expand Down
48 changes: 37 additions & 11 deletions docs/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

## Release Readiness Checklist

Current source release and Android build target: Keysoft 3.3.2, versionCode 131. Google Play
currently distributes Keysoft 3.3.1, versionCode 130, until the new app bundle completes
review and is submitted manually. EAS remote versioning remains authoritative for Android
builds. iOS remains a cloud-simulator compatibility target and is not an App Store release
target.
Current source release: Keysoft 3.3.2. The local manifest mirrors versionCode 131; the Android
16 compliance rebuild produced EAS remote versionCode 132 from `main` HEAD and is in Play
review. Google Play serves 3.3.2/131 until 3.3.2/132 is approved. EAS remote versioning remains
authoritative for Android builds, and the same workflow now submits the next release to Google
Play automatically. iOS remains a cloud-simulator compatibility target and is not an App Store
release target.

Before preparing a release:

Expand Down Expand Up @@ -42,11 +43,12 @@ Application version data is maintained in:
- Android native configuration where applicable

For the 3.3.2 source release, `app.config.js` uses `version: "3.3.2"`,
`android.versionCode: 131`, and an iOS simulator baseline of `ios.buildNumber: "1"`. Before
the build, the EAS remote Android value is 130; the production profile auto-increments it to
131. The local value mirrors the target for manifest visibility but does not control the EAS
counter. Because EAS Update uses the `appVersion` runtime policy, this release uses native
runtime 3.3.2. Google Play remains on 3.3.1/130 until manual submission and publication.
`android.versionCode: 131`, and an iOS simulator baseline of `ios.buildNumber: "1"`. The local
value mirrors the target for manifest visibility but does not control the EAS counter. Because
EAS Update uses the `appVersion` runtime policy, this release uses native runtime 3.3.2. The
Android 16 compliance rebuild produced remote versionCode 132 from `main` HEAD; Google Play
serves 3.3.2/131 until 3.3.2/132 is approved. The production workflow increments the remote
Android value on every build and submits the matching app bundle to Google Play.

Read the current remote value with
`bunx eas-cli build:version:get --platform android --profile production --non-interactive`
Expand Down Expand Up @@ -102,12 +104,36 @@ The artifact can then be tested in Appetize. App Store signing, submission metad

### Google Play Submission

Google Play submission is currently performed manually (upload the app-bundle in the Play Console). To automate it later, configure a Google service-account key in `eas.json` (`submit.production`) and run:
The production EAS workflow is the normal release path. A matching version tag builds the
Android app bundle and submits it to Google Play as a **draft** with EAS Submit. The
`after_submit` hook then runs `scripts/play-release-notes.mjs`, which adds the Play Store
release notes and promotes the draft to a completed production release. A release without
valid notes stays in draft and the workflow fails.

The workflow needs these EAS project environment variables in `production`:

- `GOOGLE_SERVICE_ACCOUNT_JSON`: the Google service account key, stored as a secret.
- `GOOGLE_SERVICE_ACCOUNT_KEY_PATH`: a temporary path where the workflow writes the key.

EAS Submit also needs the same service account assigned under the Android application
identifier in the project credentials.

Play Store release notes are written for a non-technical audience and live in
`store/play/release-notes/<version>/` as `it-IT.txt` and `en-US.txt`, one short paragraph per
language, at most 500 characters each. Keep `CHANGELOG.md` technical for GitHub readers; the
Play Store text is separate. See
[`store/play/release-notes/README.md`](../store/play/release-notes/README.md) for the format
and examples.

The manual fallback is:

```bash
bun run submit:android:production
```

It uses the same draft submit profile and still requires the matching release notes before the
release can be promoted. Do not run it while the tag-triggered workflow is in progress.

The production EAS workflow normally runs for every matching version tag. When
backfilling a GitHub tag for an artifact that is already built and published,
put `[eas skip]` in the tagged commit message to prevent a duplicate cloud
Expand Down
8 changes: 8 additions & 0 deletions docs/releases/3.3.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,11 @@ The `v3.3.2` tag identifies the exact source used to start the EAS Android produ
The EAS production profile produces an Android App Bundle and auto-increments the remote
version from 130 to 131. It does not submit to Google Play; store review and publication
remain manual.

## Rebuild 132

On 2026-11-01 the release was rebuilt from `main` HEAD `8c893ea` as versionCode 132 with
`targetSdkVersion` 36, to satisfy Google Play's Android 16 target-API requirement. The build
was submitted to the production track with EAS Submit and the Play Store release notes were
applied; review is pending. Google Play continues to serve versionCode 131 until 132 is
approved.
8 changes: 7 additions & 1 deletion eas.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@
}
},
"submit": {
"production": {}
"production": {
"android": {
"track": "production",
"releaseStatus": "draft",
"changesNotSentForReview": false
}
}
}
}
Loading
Loading