Skip to content

Commit 98fd89c

Browse files
authored
Merge pull request #795 from synonymdev/release/176
chore: release 2.0.2
2 parents b769ed3 + 048f13e commit 98fd89c

7 files changed

Lines changed: 209 additions & 4 deletions

File tree

.claude/commands/release.md

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
---
2+
description: "Create a new release: bump version, create PR, build mainnet, publish draft release"
3+
argument_hint: "[--critical]"
4+
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
5+
---
6+
7+
Automate the full release process for bitkit-android.
8+
9+
**Examples:**
10+
- `/release` - Interactive, prompts for version (defaults to patch bump)
11+
- `/release --critical` - Same, but marks the release as critical in release.json
12+
13+
## Steps
14+
15+
### 1. Read Current Version
16+
17+
Read `app/build.gradle.kts` and extract:
18+
- `versionCode` (integer, e.g. `176`)
19+
- `versionName` (string, e.g. `"2.0.2"`)
20+
21+
Parse versionName into `{major}.{minor}.{patch}` components.
22+
23+
Compute defaults:
24+
- Next patch: `{major}.{minor}.{patch+1}`
25+
- Next minor: `{major}.{minor+1}.0`
26+
- Next major: `{major+1}.0.0`
27+
- Next versionCode: `versionCode + 1`
28+
29+
### 2. Parse Arguments
30+
31+
From `$ARGUMENTS`:
32+
- `--critical`: Set `critical: true` in `.github/release.json` (default: `false`)
33+
34+
### 3. Ask for Version
35+
36+
Use `AskUserQuestion` with header "Version":
37+
38+
**Question:** `"New version? (current: {versionName}, build {versionCode})"`
39+
40+
**Options:**
41+
1. `{major}.{minor}.{patch+1}` (Recommended) — description: "Patch release"
42+
2. `{major}.{minor+1}.0` — description: "Minor release"
43+
3. `{major+1}.0.0` — description: "Major release"
44+
45+
The user can always pick "Other" to enter a custom version string.
46+
47+
Store the chosen version as `newVersionName` and compute `newVersionCode = versionCode + 1`.
48+
49+
### 4. Create Release Branch & Bump Version
50+
51+
```bash
52+
git checkout master
53+
git pull origin master
54+
git checkout -b release/{newVersionCode}
55+
```
56+
57+
Edit `app/build.gradle.kts`:
58+
- Change `versionCode = {old}` to `versionCode = {newVersionCode}`
59+
- Change `versionName = "{old}"` to `versionName = "{newVersionName}"`
60+
61+
```bash
62+
git add app/build.gradle.kts
63+
git commit -m "chore: version {newVersionName}"
64+
git push -u origin release/{newVersionCode}
65+
```
66+
67+
### 5. Create Version Bump PR
68+
69+
Read `.github/pull_request_template.md` for structure. Create PR:
70+
71+
- **Title:** `chore: bump version {newVersionName}`
72+
- **Base:** master
73+
- **Body:**
74+
```
75+
Bump version to {newVersionName} (build {newVersionCode}) for release.
76+
77+
### Description
78+
79+
- `versionCode`: {oldVersionCode} → {newVersionCode}
80+
- `versionName`: {oldVersionName} → {newVersionName}
81+
82+
### Preview
83+
84+
N/A
85+
86+
### QA Notes
87+
88+
N/A
89+
```
90+
91+
Store the PR URL for the summary.
92+
93+
### 6. Build Mainnet Release
94+
95+
```bash
96+
./gradlew assembleMainnetRelease
97+
```
98+
99+
Expected APK path: `app/build/outputs/apk/mainnet/release/bitkit-mainnet-release-{newVersionCode}-universal.apk`
100+
101+
Verify the file exists. If the build fails, stop and report the error to the user.
102+
103+
### 7. Update `.github/release.json`
104+
105+
Get current UTC timestamp: `date -u +"%Y-%m-%dT%H:%M:%SZ"`
106+
107+
Write `.github/release.json`:
108+
```json
109+
{
110+
"platforms": {
111+
"android": {
112+
"version": "v{newVersionName}",
113+
"buildNumber": {newVersionCode},
114+
"notes": "https://github.com/synonymdev/bitkit/releases/tag/v{newVersionName}",
115+
"pub_date": "{UTC timestamp}",
116+
"url": "https://play.google.com/store/apps/details?id=to.bitkit",
117+
"critical": {true if --critical flag, false otherwise}
118+
}
119+
}
120+
}
121+
```
122+
123+
Commit and push:
124+
```bash
125+
git add .github/release.json
126+
git commit -m "chore: update release.json"
127+
git push
128+
```
129+
130+
### 8. Tag & Push
131+
132+
Determine the previous version tag for changelog generation: `v{oldVersionName}`.
133+
134+
```bash
135+
git tag -a v{newVersionName} -m "v{newVersionName}"
136+
git push origin v{newVersionName}
137+
```
138+
139+
### 9. Create Draft GitHub Release
140+
141+
```bash
142+
gh release create v{newVersionName} \
143+
--title "v{newVersionName}" \
144+
--draft \
145+
--generate-notes \
146+
--notes-start-tag v{oldVersionName}
147+
```
148+
149+
### 10. Upload APK to Draft Release
150+
151+
```bash
152+
gh release upload v{newVersionName} \
153+
app/build/outputs/apk/mainnet/release/bitkit-mainnet-release-{newVersionCode}-universal.apk
154+
```
155+
156+
### 11. Return to Master
157+
158+
```bash
159+
git checkout master
160+
```
161+
162+
### 12. Output Summary
163+
164+
```
165+
Release v{newVersionName} (build {newVersionCode})
166+
167+
Version bump PR: {PR URL}
168+
Release branch: release/{newVersionCode}
169+
Tag: v{newVersionName}
170+
Draft release: {release URL}
171+
APK uploaded: bitkit-mainnet-release-{newVersionCode}-universal.apk
172+
173+
Next: publish the draft release on GitHub when ready.
174+
```

.github/release.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"platforms": {
3+
"ios": null,
4+
"android": {
5+
"version": "v2.0.2",
6+
"buildNumber": 176,
7+
"notes": "https://github.com/synonymdev/bitkit/releases/tag/v2.0.2",
8+
"pub_date": "2026-02-16T23:20:07Z",
9+
"url": "https://play.google.com/store/apps/details?id=to.bitkit",
10+
"critical": false
11+
}
12+
}
13+
}

app/src/main/java/to/bitkit/data/dto/AppUpdaterDTO.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ data class ReleaseInfoDTO(
1414
@Serializable
1515
data class Platforms(
1616
val android: PlatformDetails,
17-
val ios: PlatformDetails?,
17+
val ios: PlatformDetails? = null,
1818
)
1919

2020
/**

app/src/main/java/to/bitkit/env/Env.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import org.lightningdevkit.ldknode.LogLevel
55
import org.lightningdevkit.ldknode.Network
66
import org.lightningdevkit.ldknode.PeerDetails
77
import to.bitkit.BuildConfig
8+
import to.bitkit.BuildConfig.VERSION_NAME
89
import to.bitkit.ext.ensureDir
910
import to.bitkit.ext.of
1011
import to.bitkit.models.BlocktankNotificationType
@@ -22,7 +23,7 @@ internal object Env {
2223
val locales = BuildConfig.LOCALES.split(",")
2324
const val walletSyncIntervalSecs = 10_uL
2425
val platform = "Android ${Build.VERSION.RELEASE} (API ${Build.VERSION.SDK_INT})"
25-
const val version = "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
26+
const val version = "$VERSION_NAME (${BuildConfig.VERSION_CODE})"
2627

2728
val ldkLogLevel = LogLevel.TRACE
2829

@@ -127,7 +128,8 @@ internal object Env {
127128
const val APP_STORE_URL = "https://apps.apple.com/app/bitkit-wallet/id6502440655"
128129
const val PLAY_STORE_URL = "https://play.google.com/store/apps/details?id=to.bitkit"
129130

130-
const val RELEASE_URL = "https://github.com/synonymdev/bitkit-android/releases/download/updater/release.json"
131+
const val REPO_URL = "https://github.com/synonymdev/bitkit-android"
132+
const val RELEASE_URL = "$REPO_URL/releases/download/updater/release.json"
131133
const val EXCHANGES_URL = "https://bitcoin.org/en/exchanges#international"
132134
const val BTC_MAP_URL = "https://btcmap.org/map"
133135
const val BITKIT_WEBSITE = "https://bitkit.to/"

app/src/main/java/to/bitkit/services/AppUpdaterService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class AppUpdaterService @Inject constructor(
3030
}
3131

3232
else -> throw AppUpdaterError.InvalidResponse(
33-
"Failed to fetch release info: ${response.status.description}"
33+
"Failed to fetch release info: ${response.status}"
3434
)
3535
}
3636
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#This file is generated by updateDaemonJvm
2+
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/29ee363f71d060405f729a8f1b7f7aef/redirect
3+
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/ecd23fd7707c683afbcd6052998cb6a9/redirect
4+
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/29ee363f71d060405f729a8f1b7f7aef/redirect
5+
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/ecd23fd7707c683afbcd6052998cb6a9/redirect
6+
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/10fc3bf1ee0001078a473afe6e43cfdb/redirect
7+
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/9c55677aff3966382f3d853c0959bfb2/redirect
8+
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/29ee363f71d060405f729a8f1b7f7aef/redirect
9+
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/ecd23fd7707c683afbcd6052998cb6a9/redirect
10+
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/248ffb1098f61659502d0c09aa348294/redirect
11+
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/ac151d55def6b6a9a159dc4cb4642851/redirect
12+
toolchainVendor=JETBRAINS
13+
toolchainVersion=21

settings.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ pluginManagement {
2727
gradlePluginPortal()
2828
}
2929
}
30+
plugins {
31+
id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
32+
}
3033
@Suppress("UnstableApiUsage")
3134
dependencyResolutionManagement {
3235
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)

0 commit comments

Comments
 (0)