From 9e01711e9cec0b37f7adad9dfd88d7499cfd3715 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 18 Feb 2026 02:23:53 +0100 Subject: [PATCH 1/7] chore: add github release.json --- .github/release.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/release.json diff --git a/.github/release.json b/.github/release.json new file mode 100644 index 000000000..640f4cdb4 --- /dev/null +++ b/.github/release.json @@ -0,0 +1,12 @@ +{ + "platforms": { + "android": { + "version": "v2.0.2", + "buildNumber": 176, + "notes": "https://github.com/synonymdev/bitkit/releases/tag/v2.0.2", + "pub_date": "2026-02-16T23:20:07Z", + "url": "https://play.google.com/store/apps/details?id=to.bitkit", + "critical": false + } + } +} From 3a0a45ade8d3b6bcd86b2ef963fba1e4996b354a Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Wed, 18 Feb 2026 08:46:23 +0100 Subject: [PATCH 2/7] chore: add ai release command --- .claude/commands/release.md | 174 +++++++++++++++++++++++++ app/src/main/java/to/bitkit/env/Env.kt | 6 +- 2 files changed, 178 insertions(+), 2 deletions(-) create mode 100644 .claude/commands/release.md diff --git a/.claude/commands/release.md b/.claude/commands/release.md new file mode 100644 index 000000000..9b61ae465 --- /dev/null +++ b/.claude/commands/release.md @@ -0,0 +1,174 @@ +--- +description: "Create a new release: bump version, create PR, build mainnet, publish draft release" +argument_hint: "[--critical]" +allowed_tools: Bash, Read, Edit, Write, Glob, Grep, AskUserQuestion, mcp__github__create_pull_request, mcp__github__list_pull_requests, mcp__github__pull_request_read, mcp__github__get_file_contents, mcp__github__update_pull_request +--- + +Automate the full release process for bitkit-android. + +**Examples:** +- `/release` - Interactive, prompts for version (defaults to patch bump) +- `/release --critical` - Same, but marks the release as critical in release.json + +## Steps + +### 1. Read Current Version + +Read `app/build.gradle.kts` and extract: +- `versionCode` (integer, e.g. `176`) +- `versionName` (string, e.g. `"2.0.2"`) + +Parse versionName into `{major}.{minor}.{patch}` components. + +Compute defaults: +- Next patch: `{major}.{minor}.{patch+1}` +- Next minor: `{major}.{minor+1}.0` +- Next major: `{major+1}.0.0` +- Next versionCode: `versionCode + 1` + +### 2. Parse Arguments + +From `$ARGUMENTS`: +- `--critical`: Set `critical: true` in `.github/release.json` (default: `false`) + +### 3. Ask for Version + +Use `AskUserQuestion` with header "Version": + +**Question:** `"New version? (current: {versionName}, build {versionCode})"` + +**Options:** +1. `{major}.{minor}.{patch+1}` (Recommended) — description: "Patch release" +2. `{major}.{minor+1}.0` — description: "Minor release" +3. `{major+1}.0.0` — description: "Major release" + +The user can always pick "Other" to enter a custom version string. + +Store the chosen version as `newVersionName` and compute `newVersionCode = versionCode + 1`. + +### 4. Create Release Branch & Bump Version + +```bash +git checkout master +git pull origin master +git checkout -b release/{newVersionCode} +``` + +Edit `app/build.gradle.kts`: +- Change `versionCode = {old}` to `versionCode = {newVersionCode}` +- Change `versionName = "{old}"` to `versionName = "{newVersionName}"` + +```bash +git add app/build.gradle.kts +git commit -m "chore: version {newVersionName}" +git push -u origin release/{newVersionCode} +``` + +### 5. Create Version Bump PR + +Read `.github/pull_request_template.md` for structure. Create PR: + +- **Title:** `chore: bump version {newVersionName}` +- **Base:** master +- **Body:** +``` +Bump version to {newVersionName} (build {newVersionCode}) for release. + +### Description + +- `versionCode`: {oldVersionCode} → {newVersionCode} +- `versionName`: {oldVersionName} → {newVersionName} + +### Preview + +N/A + +### QA Notes + +N/A +``` + +Store the PR URL for the summary. + +### 6. Build Mainnet Release + +```bash +./gradlew assembleMainnetRelease +``` + +Expected APK path: `app/build/outputs/apk/mainnet/release/bitkit-mainnet-release-{newVersionCode}-universal.apk` + +Verify the file exists. If the build fails, stop and report the error to the user. + +### 7. Update `.github/release.json` + +Get current UTC timestamp: `date -u +"%Y-%m-%dT%H:%M:%SZ"` + +Write `.github/release.json`: +```json +{ + "platforms": { + "android": { + "version": "v{newVersionName}", + "buildNumber": {newVersionCode}, + "notes": "https://github.com/synonymdev/bitkit/releases/tag/v{newVersionName}", + "pub_date": "{UTC timestamp}", + "url": "https://play.google.com/store/apps/details?id=to.bitkit", + "critical": {true if --critical flag, false otherwise} + } + } +} +``` + +Commit and push: +```bash +git add .github/release.json +git commit -m "chore: update release.json" +git push +``` + +### 8. Tag & Push + +Determine the previous version tag for changelog generation: `v{oldVersionName}`. + +```bash +git tag -a v{newVersionName} -m "v{newVersionName}" +git push origin v{newVersionName} +``` + +### 9. Create Draft GitHub Release + +```bash +gh release create v{newVersionName} \ + --title "v{newVersionName}" \ + --draft \ + --generate-notes \ + --notes-start-tag v{oldVersionName} +``` + +### 10. Upload APK to Draft Release + +```bash +gh release upload v{newVersionName} \ + app/build/outputs/apk/mainnet/release/bitkit-mainnet-release-{newVersionCode}-universal.apk +``` + +### 11. Return to Master + +```bash +git checkout master +``` + +### 12. Output Summary + +``` +Release v{newVersionName} (build {newVersionCode}) + +Version bump PR: {PR URL} +Release branch: release/{newVersionCode} +Tag: v{newVersionName} +Draft release: {release URL} +APK uploaded: bitkit-mainnet-release-{newVersionCode}-universal.apk + +Next: publish the draft release on GitHub when ready. +``` diff --git a/app/src/main/java/to/bitkit/env/Env.kt b/app/src/main/java/to/bitkit/env/Env.kt index c4436dfd1..70b11b614 100644 --- a/app/src/main/java/to/bitkit/env/Env.kt +++ b/app/src/main/java/to/bitkit/env/Env.kt @@ -5,6 +5,7 @@ import org.lightningdevkit.ldknode.LogLevel import org.lightningdevkit.ldknode.Network import org.lightningdevkit.ldknode.PeerDetails import to.bitkit.BuildConfig +import to.bitkit.BuildConfig.VERSION_NAME import to.bitkit.ext.ensureDir import to.bitkit.ext.of import to.bitkit.models.BlocktankNotificationType @@ -22,7 +23,7 @@ internal object Env { val locales = BuildConfig.LOCALES.split(",") const val walletSyncIntervalSecs = 10_uL val platform = "Android ${Build.VERSION.RELEASE} (API ${Build.VERSION.SDK_INT})" - const val version = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})" + const val version = "$VERSION_NAME (${BuildConfig.VERSION_CODE})" val ldkLogLevel = LogLevel.TRACE @@ -127,7 +128,8 @@ internal object Env { const val APP_STORE_URL = "https://apps.apple.com/app/bitkit-wallet/id6502440655" const val PLAY_STORE_URL = "https://play.google.com/store/apps/details?id=to.bitkit" - const val RELEASE_URL = "https://github.com/synonymdev/bitkit-android/releases/download/updater/release.json" + const val REPO_URL = "https://github.com/synonymdev/bitkit-android/" + const val RELEASE_URL = "$REPO_URL/releases/$VERSION_NAME/release.json" const val EXCHANGES_URL = "https://bitcoin.org/en/exchanges#international" const val BTC_MAP_URL = "https://btcmap.org/map" const val BITKIT_WEBSITE = "https://bitkit.to/" From a2bf6723aac7e5a8c17b174f1119e81c87b500f5 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Thu, 19 Feb 2026 18:41:17 +0100 Subject: [PATCH 3/7] fix: restore use of `updater` release --- app/src/main/java/to/bitkit/env/Env.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/to/bitkit/env/Env.kt b/app/src/main/java/to/bitkit/env/Env.kt index 70b11b614..6ca6f5a60 100644 --- a/app/src/main/java/to/bitkit/env/Env.kt +++ b/app/src/main/java/to/bitkit/env/Env.kt @@ -129,7 +129,7 @@ internal object Env { const val PLAY_STORE_URL = "https://play.google.com/store/apps/details?id=to.bitkit" const val REPO_URL = "https://github.com/synonymdev/bitkit-android/" - const val RELEASE_URL = "$REPO_URL/releases/$VERSION_NAME/release.json" + const val RELEASE_URL = "$REPO_URL/releases/updater/release.json" const val EXCHANGES_URL = "https://bitcoin.org/en/exchanges#international" const val BTC_MAP_URL = "https://btcmap.org/map" const val BITKIT_WEBSITE = "https://bitkit.to/" From 756c6ef99ef64c349ccf6ade14cf4de35f288c92 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Thu, 19 Feb 2026 18:55:03 +0100 Subject: [PATCH 4/7] fix: remove end slash from repo url --- app/src/main/java/to/bitkit/env/Env.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/to/bitkit/env/Env.kt b/app/src/main/java/to/bitkit/env/Env.kt index 6ca6f5a60..212229b65 100644 --- a/app/src/main/java/to/bitkit/env/Env.kt +++ b/app/src/main/java/to/bitkit/env/Env.kt @@ -128,7 +128,7 @@ internal object Env { const val APP_STORE_URL = "https://apps.apple.com/app/bitkit-wallet/id6502440655" const val PLAY_STORE_URL = "https://play.google.com/store/apps/details?id=to.bitkit" - const val REPO_URL = "https://github.com/synonymdev/bitkit-android/" + const val REPO_URL = "https://github.com/synonymdev/bitkit-android" const val RELEASE_URL = "$REPO_URL/releases/updater/release.json" const val EXCHANGES_URL = "https://bitcoin.org/en/exchanges#international" const val BTC_MAP_URL = "https://btcmap.org/map" From d82ed9f5019adb6c9668f4ff9255b9bf4d9b884a Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Thu, 19 Feb 2026 19:50:50 +0100 Subject: [PATCH 5/7] chore: migrate project to gradle daemon --- gradle/gradle-daemon-jvm.properties | 13 +++++++++++++ settings.gradle.kts | 3 +++ 2 files changed, 16 insertions(+) create mode 100644 gradle/gradle-daemon-jvm.properties diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties new file mode 100644 index 000000000..500e90918 --- /dev/null +++ b/gradle/gradle-daemon-jvm.properties @@ -0,0 +1,13 @@ +#This file is generated by updateDaemonJvm +toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/29ee363f71d060405f729a8f1b7f7aef/redirect +toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/ecd23fd7707c683afbcd6052998cb6a9/redirect +toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/29ee363f71d060405f729a8f1b7f7aef/redirect +toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/ecd23fd7707c683afbcd6052998cb6a9/redirect +toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/10fc3bf1ee0001078a473afe6e43cfdb/redirect +toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/9c55677aff3966382f3d853c0959bfb2/redirect +toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/29ee363f71d060405f729a8f1b7f7aef/redirect +toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/ecd23fd7707c683afbcd6052998cb6a9/redirect +toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/248ffb1098f61659502d0c09aa348294/redirect +toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/ac151d55def6b6a9a159dc4cb4642851/redirect +toolchainVendor=JETBRAINS +toolchainVersion=21 diff --git a/settings.gradle.kts b/settings.gradle.kts index 538bf73e8..0f208580d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -27,6 +27,9 @@ pluginManagement { gradlePluginPortal() } } +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" +} @Suppress("UnstableApiUsage") dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) From 6694067b796273bfa39158dea4827a72c0e230d8 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Thu, 19 Feb 2026 20:49:49 +0100 Subject: [PATCH 6/7] fix: handle missing ios field in release info --- .github/release.json | 1 + app/src/main/java/to/bitkit/data/dto/AppUpdaterDTO.kt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/release.json b/.github/release.json index 640f4cdb4..f1f8e0f74 100644 --- a/.github/release.json +++ b/.github/release.json @@ -1,5 +1,6 @@ { "platforms": { + "ios": null, "android": { "version": "v2.0.2", "buildNumber": 176, diff --git a/app/src/main/java/to/bitkit/data/dto/AppUpdaterDTO.kt b/app/src/main/java/to/bitkit/data/dto/AppUpdaterDTO.kt index 161413a9f..9c8707337 100644 --- a/app/src/main/java/to/bitkit/data/dto/AppUpdaterDTO.kt +++ b/app/src/main/java/to/bitkit/data/dto/AppUpdaterDTO.kt @@ -14,7 +14,7 @@ data class ReleaseInfoDTO( @Serializable data class Platforms( val android: PlatformDetails, - val ios: PlatformDetails?, + val ios: PlatformDetails? = null, ) /** From 048f13e3554aa59a0c9c16b273138c071f0e80d8 Mon Sep 17 00:00:00 2001 From: Ovi Trif Date: Thu, 19 Feb 2026 21:34:55 +0100 Subject: [PATCH 7/7] fix: updater.json release url --- app/src/main/java/to/bitkit/env/Env.kt | 2 +- app/src/main/java/to/bitkit/services/AppUpdaterService.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/to/bitkit/env/Env.kt b/app/src/main/java/to/bitkit/env/Env.kt index 212229b65..48aeedcf9 100644 --- a/app/src/main/java/to/bitkit/env/Env.kt +++ b/app/src/main/java/to/bitkit/env/Env.kt @@ -129,7 +129,7 @@ internal object Env { const val PLAY_STORE_URL = "https://play.google.com/store/apps/details?id=to.bitkit" const val REPO_URL = "https://github.com/synonymdev/bitkit-android" - const val RELEASE_URL = "$REPO_URL/releases/updater/release.json" + const val RELEASE_URL = "$REPO_URL/releases/download/updater/release.json" const val EXCHANGES_URL = "https://bitcoin.org/en/exchanges#international" const val BTC_MAP_URL = "https://btcmap.org/map" const val BITKIT_WEBSITE = "https://bitkit.to/" diff --git a/app/src/main/java/to/bitkit/services/AppUpdaterService.kt b/app/src/main/java/to/bitkit/services/AppUpdaterService.kt index eedf28331..6fd48c2f3 100644 --- a/app/src/main/java/to/bitkit/services/AppUpdaterService.kt +++ b/app/src/main/java/to/bitkit/services/AppUpdaterService.kt @@ -30,7 +30,7 @@ class AppUpdaterService @Inject constructor( } else -> throw AppUpdaterError.InvalidResponse( - "Failed to fetch release info: ${response.status.description}" + "Failed to fetch release info: ${response.status}" ) } }