mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-09 08:04:45 +00:00
Merge pull request #3245 from vitorpamplona/release/1.12.1
Release 1.12.1
This commit is contained in:
@@ -738,125 +738,29 @@ fun SignerIntegration(accountViewModel: AccountViewModel) {
|
||||
|
||||
## 6. Build Configuration
|
||||
|
||||
### Android Block
|
||||
Build files — the `android {}` block, the version catalog, dependencies,
|
||||
Proguard/R8, and Desktop packaging — are **gradle-expert's** domain. Use
|
||||
`/gradle-expert` instead of duplicating that guidance here. In particular, the
|
||||
app version and the Android `versionCode` both live in
|
||||
`gradle/libs.versions.toml` (`app` / `appCode`); `amethyst/build.gradle.kts`
|
||||
reads both from the catalog, so a release bump is a single-file edit.
|
||||
|
||||
The one build detail that is genuinely Android-specific — not generic Gradle —
|
||||
is the **product-flavor split** that ships two channels from one codebase:
|
||||
|
||||
**build.gradle (Amethyst pattern):**
|
||||
```gradle
|
||||
android {
|
||||
namespace = 'com.vitorpamplona.amethyst'
|
||||
compileSdk = 37 // from libs.versions.toml android-compileSdk — check there, it drifts
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "com.vitorpamplona.amethyst"
|
||||
minSdk = 26 // Android 8.0 (Oreo)
|
||||
targetSdk = 37 // android-targetSdk in libs.versions.toml
|
||||
versionCode = 448
|
||||
versionName = generateVersionName(libs.versions.app.get(), rootDir)
|
||||
|
||||
vectorDrawables {
|
||||
useSupportLibrary = true
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
compose = true
|
||||
buildConfig = true // Enable BuildConfig access
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
|
||||
}
|
||||
|
||||
packaging {
|
||||
resources {
|
||||
excludes += '/META-INF/{AL2.0,LGPL2.1}'
|
||||
}
|
||||
}
|
||||
|
||||
// Product flavors for Play Store vs F-Droid
|
||||
flavorDimensions = ["channel"]
|
||||
productFlavors {
|
||||
create("play") {
|
||||
dimension = "channel"
|
||||
// Firebase, Google services
|
||||
}
|
||||
create("fdroid") {
|
||||
dimension = "channel"
|
||||
// UnifiedPush, open-source alternatives
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
jvmTarget = JvmTarget.JVM_21
|
||||
}
|
||||
flavorDimensions = ["channel"]
|
||||
productFlavors {
|
||||
create("play") { dimension = "channel" } // Firebase, Google services
|
||||
create("fdroid") { dimension = "channel" } // UnifiedPush, open-source only
|
||||
}
|
||||
```
|
||||
|
||||
### Dependencies
|
||||
`play` carries Firebase/Google services; `fdroid` swaps them for UnifiedPush and
|
||||
open-source alternatives so the F-Droid build stays proprietary-free.
|
||||
|
||||
**Key Android Dependencies:**
|
||||
```gradle
|
||||
dependencies {
|
||||
// Compose BOM
|
||||
implementation(platform(libs.androidx.compose.bom))
|
||||
implementation(libs.androidx.compose.ui)
|
||||
implementation(libs.androidx.compose.material3)
|
||||
implementation(libs.androidx.compose.ui.tooling.preview)
|
||||
|
||||
// Navigation
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
|
||||
// Lifecycle
|
||||
implementation(libs.androidx.lifecycle.runtime.compose)
|
||||
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
||||
|
||||
// Activity
|
||||
implementation(libs.androidx.activity.compose)
|
||||
|
||||
// Accompanist
|
||||
implementation(libs.accompanist.permissions)
|
||||
|
||||
// Shared module
|
||||
implementation(project(":commons"))
|
||||
implementation(project(":quartz"))
|
||||
}
|
||||
```
|
||||
|
||||
### Proguard Rules
|
||||
|
||||
**Common Rules for Amethyst:**
|
||||
```proguard
|
||||
# Keep Kotlin metadata
|
||||
-keep class kotlin.Metadata { *; }
|
||||
|
||||
# Keep Nostr event classes
|
||||
-keep class com.vitorpamplona.quartz.events.** { *; }
|
||||
|
||||
# Keep serialization
|
||||
-keepattributes *Annotation*, InnerClasses
|
||||
-dontnote kotlinx.serialization.AnnotationsKt
|
||||
|
||||
# OkHttp
|
||||
-dontwarn okhttp3.**
|
||||
-keep class okhttp3.** { *; }
|
||||
|
||||
# Compose
|
||||
-keep class androidx.compose.** { *; }
|
||||
-dontwarn androidx.compose.**
|
||||
```
|
||||
|
||||
**Reference:** See `references/proguard-rules.md` for complete Proguard configuration.
|
||||
|
||||
### APK Optimization
|
||||
|
||||
**Reference:** See `scripts/analyze-apk-size.sh` for APK size analysis.
|
||||
Proguard/R8 rules: see `references/proguard-rules.md`. APK size analysis:
|
||||
`scripts/analyze-apk-size.sh`.
|
||||
|
||||
## 7. KMP Android Source Sets
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ implementation(libs.jna)
|
||||
|
||||
**Current project config** (always re-check `gradle/libs.versions.toml` — these drift):
|
||||
```toml
|
||||
composeMultiplatform = "1.12.0" # Plugin + runtime
|
||||
composeMultiplatform = "1.11.1" # Plugin + runtime
|
||||
composeBom = "2026.05.01" # AndroidX Compose BOM
|
||||
kotlin = "2.3.21"
|
||||
```
|
||||
|
||||
@@ -212,7 +212,7 @@ implementation(compose.ui) // Compose Multiplatform BOM
|
||||
implementation(compose.material3)
|
||||
|
||||
// Version catalog alignment (re-check libs.versions.toml — these drift)
|
||||
composeMultiplatform = "1.12.0"
|
||||
composeMultiplatform = "1.11.1"
|
||||
composeBom = "2026.05.01" // AndroidX Compose
|
||||
```
|
||||
**Why:** Two Compose ecosystems (Multiplatform + AndroidX) must align
|
||||
|
||||
@@ -7,7 +7,7 @@ description: Integration guide for using the Quartz Nostr KMP library in externa
|
||||
|
||||
Reference for integrating `com.vitorpamplona.quartz:quartz` into external Nostr KMP projects.
|
||||
|
||||
**Published artifact**: `com.vitorpamplona.quartz:quartz:1.12.0` (Maven Central)
|
||||
**Published artifact**: `com.vitorpamplona.quartz:quartz:1.12.1` (Maven Central)
|
||||
**Targets**: JVM 21+, Android (minSdk 21+), iOS (XCFramework `quartz-kmpKit`)
|
||||
**License**: MIT
|
||||
|
||||
@@ -19,7 +19,7 @@ Reference for integrating `com.vitorpamplona.quartz:quartz` into external Nostr
|
||||
|
||||
```toml
|
||||
[versions]
|
||||
quartz = "1.12.0"
|
||||
quartz = "1.12.1"
|
||||
|
||||
[libraries]
|
||||
quartz = { module = "com.vitorpamplona.quartz:quartz", version.ref = "quartz" }
|
||||
@@ -41,7 +41,7 @@ kotlin {
|
||||
|
||||
```kotlin
|
||||
dependencies {
|
||||
implementation("com.vitorpamplona.quartz:quartz:1.12.0")
|
||||
implementation("com.vitorpamplona.quartz:quartz:1.12.1")
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Current version
|
||||
|
||||
```
|
||||
com.vitorpamplona.quartz:quartz:1.12.0
|
||||
com.vitorpamplona.quartz:quartz:1.12.1
|
||||
```
|
||||
|
||||
Check latest: https://central.sonatype.com/artifact/com.vitorpamplona.quartz/quartz
|
||||
@@ -16,7 +16,7 @@ Check latest: https://central.sonatype.com/artifact/com.vitorpamplona.quartz/qua
|
||||
|
||||
```toml
|
||||
[versions]
|
||||
quartz = "1.12.0"
|
||||
quartz = "1.12.1"
|
||||
|
||||
[libraries]
|
||||
quartz = { module = "com.vitorpamplona.quartz:quartz", version.ref = "quartz" }
|
||||
@@ -55,7 +55,7 @@ kotlin {
|
||||
```kotlin
|
||||
// build.gradle.kts (app module)
|
||||
dependencies {
|
||||
implementation("com.vitorpamplona.quartz:quartz:1.12.0")
|
||||
implementation("com.vitorpamplona.quartz:quartz:1.12.1")
|
||||
}
|
||||
```
|
||||
|
||||
@@ -70,7 +70,7 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.vitorpamplona.quartz:quartz:1.12.0")
|
||||
implementation("com.vitorpamplona.quartz:quartz:1.12.1")
|
||||
// JNA needed for libsodium (NIP-44) on JVM
|
||||
implementation("net.java.dev.jna:jna:5.18.1")
|
||||
}
|
||||
|
||||
+140
-32
@@ -1,13 +1,22 @@
|
||||
# Building Amethyst Desktop
|
||||
|
||||
This guide covers building Amethyst Desktop from source, the release pipeline,
|
||||
and one-time bootstrap steps for distribution channels.
|
||||
This guide has everything **any fork** needs to build Amethyst from source and
|
||||
cut its own release: prerequisites, build commands, the CI release pipeline, the
|
||||
secrets it needs, the distribution channels, and one-time bootstrap steps.
|
||||
|
||||
> **Amethyst maintainers:** the account-specific checklist for shipping the
|
||||
> official build (Play Console upload, Zapstore `zsp publish` with our nsec,
|
||||
> secret ownership) lives in [`RELEASE_OPS.md`](RELEASE_OPS.md). This
|
||||
> file stays fork-generic.
|
||||
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Clone + first build](#clone--first-build)
|
||||
- [Generated & vendored artifacts](#generated--vendored-artifacts)
|
||||
- [Per-format build commands](#per-format-build-commands)
|
||||
- [Asset naming contract](#asset-naming-contract)
|
||||
- [Release runbook](#release-runbook)
|
||||
- [Secrets the CI needs](#secrets-the-ci-needs)
|
||||
- [Distribution channels](#distribution-channels)
|
||||
- [Bootstrap runbook (one-time)](#bootstrap-runbook-one-time)
|
||||
- [Troubleshooting installs](#troubleshooting-installs)
|
||||
- [Uninstall + state paths](#uninstall--state-paths)
|
||||
@@ -68,6 +77,29 @@ cd amethyst
|
||||
|
||||
---
|
||||
|
||||
## Generated & vendored artifacts
|
||||
|
||||
Two build inputs are **generated by tools but committed to the repo**, so a
|
||||
normal build or release does **not** run either — Gradle just consumes the
|
||||
checked-in output. You only regenerate them under the specific conditions below,
|
||||
and each has its own guide:
|
||||
|
||||
| Artifact | Committed at | Regenerate when | Guide |
|
||||
|---|---|---|---|
|
||||
| **Material Symbols subset font** | `commons/src/commonMain/composeResources/font/material_symbols_outlined.ttf` | You add/remove a `MaterialSymbol("\uXXXX")` codepoint in `MaterialSymbols.kt`, or bump the upstream font | [`tools/material-symbols-subset/README.md`](tools/material-symbols-subset/README.md) — run `./tools/material-symbols-subset/subset.sh` |
|
||||
| **Arti (Tor) native libs** | `amethyst/src/main/jniLibs/*.so` | You update the pinned Arti version, change the JNI wrapper, or want to reproduce the binaries | [`tools/arti-build/README.md`](tools/arti-build/README.md) |
|
||||
|
||||
> **Material Symbols is mandatory after icon changes.** The bundled font is a
|
||||
> ~210-glyph subset; a new codepoint that isn't in it renders as tofu (□) at
|
||||
> runtime. Regenerate and commit the `.ttf` alongside the `MaterialSymbols.kt`
|
||||
> change. Reusing an existing codepoint needs no regeneration.
|
||||
|
||||
Both tools have their own prerequisites (`fonttools`/`brotli` for the font; a
|
||||
Rust toolchain + Android NDK 25+ for Arti) documented in their READMEs — they
|
||||
are **not** required to build Amethyst from the committed sources.
|
||||
|
||||
---
|
||||
|
||||
## Per-format build commands
|
||||
|
||||
| Artifact | Command | Output |
|
||||
@@ -111,11 +143,11 @@ amethyst-desktop-<version>-<family>-<arch>.<ext>
|
||||
|
||||
Where:
|
||||
|
||||
| Field | Values |
|
||||
|---|---------------------------------------------------------|
|
||||
| `<version>` | Tag stripped of leading `v` (e.g. `1.12.0`) |
|
||||
| `<family>` | `macos`, `windows`, `linux` |
|
||||
| `<arch>` | `x64`, `arm64` |
|
||||
| Field | Values |
|
||||
|---|-------------------------------------------------------|
|
||||
| `<version>` | Tag stripped of leading `vX.YY.ZZ` |
|
||||
| `<family>` | `macos`, `windows`, `linux` |
|
||||
| `<arch>` | `x64`, `arm64` |
|
||||
| `<ext>` | `dmg`, `msi`, `zip`, `deb`, `rpm`, `AppImage`, `tar.gz` |
|
||||
|
||||
Single source of truth: [`scripts/asset-name.sh`](scripts/asset-name.sh).
|
||||
@@ -124,10 +156,10 @@ any change is a breaking contract.
|
||||
|
||||
Examples:
|
||||
|
||||
- `amethyst-desktop-1.12.0-macos-x64.dmg`
|
||||
- `amethyst-desktop-1.12.0-macos-arm64.dmg`
|
||||
- `amethyst-desktop-1.12.0-windows-x64.msi`
|
||||
- `amethyst-desktop-1.12.0-linux-x64.AppImage`
|
||||
- `amethyst-desktop-1.12.1-macos-x64.dmg`
|
||||
- `amethyst-desktop-1.12.1-macos-arm64.dmg`
|
||||
- `amethyst-desktop-1.12.1-windows-x64.msi`
|
||||
- `amethyst-desktop-1.12.1-linux-x64.AppImage`
|
||||
|
||||
---
|
||||
|
||||
@@ -136,38 +168,37 @@ Examples:
|
||||
The release flow is driven by a tag push. Every cut ships Android + Desktop +
|
||||
Quartz library in one pipeline.
|
||||
|
||||
1. **Bump the app version** in `gradle/libs.versions.toml`:
|
||||
1. **Bump the app version and Android `versionCode`** in
|
||||
`gradle/libs.versions.toml` (`appCode` is a monotonic integer — it must
|
||||
increment even when `app` is unchanged):
|
||||
|
||||
```toml
|
||||
[versions]
|
||||
app = "1.08.1" # new semver
|
||||
appCode = "449" # Android versionCode
|
||||
```
|
||||
|
||||
2. **Bump Android `versionCode`** in `amethyst/build.gradle` (monotonic integer,
|
||||
must increment even for same `versionName`):
|
||||
`amethyst/build.gradle.kts` reads both from the catalog
|
||||
(`versionCode = libs.versions.appCode.get().toInt()`), so there is nothing
|
||||
else to edit.
|
||||
|
||||
```groovy
|
||||
versionCode = 448
|
||||
versionName = generateVersionName(libs.versions.app.get())
|
||||
```
|
||||
|
||||
3. **Commit + tag + push**:
|
||||
2. **Commit + tag + push**:
|
||||
|
||||
```bash
|
||||
git commit -am "chore(release): 1.12.0"
|
||||
git tag -s v1.12.0 -m "Release 1.12.0"
|
||||
git commit -am "chore(release): 1.12.1"
|
||||
git tag -s v1.12.1 -m "Release 1.12.1"
|
||||
git push && git push --tags
|
||||
```
|
||||
|
||||
4. **Wait** for the `Create Release Assets` workflow to finish (~25–30 min).
|
||||
3. **Wait** for the `Create Release Assets` workflow to finish (~25–30 min).
|
||||
|
||||
5. **Verify**:
|
||||
4. **Verify**:
|
||||
- GH Release contains 8 desktop assets + 12 Android assets
|
||||
- Asset sizes look sane (see §Enforce asset size budget — CI auto-fails at 1 GB/asset)
|
||||
- Intel + ARM DMGs both present
|
||||
- Android flow unchanged
|
||||
|
||||
6. **Stable vs prerelease** — a tag containing `-rc`, `-beta`, `-alpha`, `-dev`,
|
||||
5. **Stable vs prerelease** — a tag containing `-rc`, `-beta`, `-alpha`, `-dev`,
|
||||
or `-snapshot` is auto-classified as prerelease. Stable tags trigger the
|
||||
Homebrew + Winget bump workflows.
|
||||
|
||||
@@ -203,19 +234,96 @@ uninstall before a new release. Leave it alone forever.
|
||||
|
||||
---
|
||||
|
||||
## Secrets the CI needs
|
||||
|
||||
The `Create Release Assets` workflow reads these from GitHub repo secrets. A
|
||||
fork must provide its **own** values — none are inherited. (`GITHUB_TOKEN` is
|
||||
provided automatically; everything else you set yourself.)
|
||||
|
||||
| Secret | What it is | Used for |
|
||||
|---|---|---|
|
||||
| `SIGNING_KEY` | Base64 of your **Android keystore** (`.jks`/`.keystore`) | Signs the Play + F-Droid **AAB and APK** |
|
||||
| `KEY_ALIAS` | Keystore key alias | Same Android signing step |
|
||||
| `KEY_STORE_PASSWORD` | Keystore password | Same |
|
||||
| `KEY_PASSWORD` | Key password | Same |
|
||||
| `SONATYPE_USERNAME` | Maven Central (Sonatype) user token name | Publishing the `quartz` library |
|
||||
| `SONATYPE_PASSWORD` | Maven Central user token password | Same |
|
||||
| `SIGNING_PRIVATE_KEY` | **GPG/PGP** private key, ASCII-armored | Signs the Maven artifacts (Central requires it) |
|
||||
| `SIGNING_PASSWORD` | Passphrase for that GPG key | Same |
|
||||
| `HOMEBREW_TOKEN` | PAT for `Homebrew/homebrew-cask` | Desktop cask bump (stable tags) |
|
||||
| `WINGET_TOKEN` | PAT for `microsoft/winget-pkgs` | Desktop winget bump (stable tags) |
|
||||
| `CROWDIN_PERSONAL_TOKEN`, `CROWDIN_PROJECT_ID` | Crowdin API creds | Translation sync (separate workflow, not the release) |
|
||||
|
||||
Note the **two distinct signing identities** people often conflate:
|
||||
`SIGNING_KEY` + `KEY_*` is the **Android keystore**; `SIGNING_PRIVATE_KEY` +
|
||||
`SIGNING_PASSWORD` is the **GPG key** for Maven Central. They are unrelated.
|
||||
|
||||
Generating the values:
|
||||
|
||||
```bash
|
||||
# Android keystore → base64 for SIGNING_KEY (one line, no wrapping)
|
||||
keytool -genkey -v -keystore upload.jks -keyalg RSA -keysize 2048 \
|
||||
-validity 10000 -alias upload # creates the keystore (once)
|
||||
base64 -i upload.jks | tr -d '\n' # paste output into SIGNING_KEY
|
||||
|
||||
# GPG key → armored private key for SIGNING_PRIVATE_KEY
|
||||
gpg --full-generate-key # create the key (once)
|
||||
gpg --armor --export-secret-keys <KEY_ID> # paste output into SIGNING_PRIVATE_KEY
|
||||
```
|
||||
|
||||
`SONATYPE_USERNAME`/`SONATYPE_PASSWORD` are a **user token** from
|
||||
<https://central.sonatype.com> (Account → Generate User Token), not your login.
|
||||
A fork that doesn't publish a library can drop the `Publish Quartz Lib` step and
|
||||
the four Sonatype/GPG secrets.
|
||||
|
||||
---
|
||||
|
||||
## Distribution channels
|
||||
|
||||
One `v*` tag fans out to several channels. Which apply depends on where a fork
|
||||
distributes; the official Amethyst rollout for each is in
|
||||
[`RELEASE_OPS.md`](RELEASE_OPS.md).
|
||||
|
||||
| Channel | How it ships | Push or pull |
|
||||
|---|---|---|
|
||||
| **GitHub Releases** | The release workflow builds + signs all assets and attaches them to the tag's Release | Automatic (CI) |
|
||||
| **Maven Central** | Same workflow runs `publishAllPublicationsToMavenCentral` for `quartz` | Automatic (CI) |
|
||||
| **Google Play** | Download the signed `amethyst-googleplay-<version>.aab` from the GH Release and upload it in Play Console | **Manual push** |
|
||||
| **F-Droid** | F-Droid's build server detects the new tag and **builds the `fdroid` flavor from source** per its recipe in the external [`fdroiddata`](https://gitlab.com/fdroid/fdroiddata) repo, then signs + publishes itself | **Pull (build-from-source)** |
|
||||
| **Zapstore** | The [`zsp`](https://zapstore.dev/) CLI reads [`zapstore.yaml`](zapstore.yaml) and publishes a Nostr software-release event signed with the app's nsec | **Manual push (Nostr)** |
|
||||
| **Homebrew + Winget** | `bump-homebrew.yml` / `bump-winget.yml` open version-bump PRs on stable tags | Automatic (CI) |
|
||||
|
||||
Two channels need the build to stay split into product flavors (see
|
||||
`amethyst/build.gradle.kts` → `productFlavors`):
|
||||
|
||||
- **`play`** carries Firebase / Google Play Services (push notifications, ML
|
||||
Kit, etc.) → the Google Play AAB.
|
||||
- **`fdroid`** swaps those for UnifiedPush and no-op/open-source
|
||||
implementations (`amethyst/src/fdroid/…`) so the build is free of proprietary
|
||||
dependencies → what F-Droid builds and what Zapstore distributes.
|
||||
|
||||
**F-Droid is pull, not push.** We never upload to F-Droid; its server builds our
|
||||
tagged source. Keeping the `fdroid` flavor proprietary-free and the
|
||||
`fastlane/metadata/android/` descriptions current is all that's required. F-Droid
|
||||
reads an optional per-release changelog from
|
||||
`fastlane/metadata/android/en-US/changelogs/<versionCode>.txt`.
|
||||
|
||||
---
|
||||
|
||||
## Bootstrap runbook (one-time)
|
||||
|
||||
### Secrets to provision in GitHub repo settings
|
||||
|
||||
The full secret inventory is in [§ Secrets the CI needs](#secrets-the-ci-needs).
|
||||
The two that need the most setup care are the package-manager PATs, because of
|
||||
their token type and scope:
|
||||
|
||||
| Secret | Purpose | Scope |
|
||||
|---|---|---|
|
||||
| `HOMEBREW_TOKEN` | Bump Homebrew cask | Fine-grained PAT — `Homebrew/homebrew-cask` only — `Contents: write` + `Pull requests: write` — 90d expiry |
|
||||
| `WINGET_TOKEN` | Submit Winget manifests | Classic PAT — `public_repo` — 90d expiry (dedicated bot account preferred; `vedantmgoyal9/winget-releaser` does not support fine-grained) |
|
||||
|
||||
All existing secrets (`SIGNING_KEY`, `SONATYPE_USERNAME`, etc.) remain
|
||||
unchanged.
|
||||
|
||||
Rotate both on a 90-day cadence. Owner: assigned via `docs/RELEASE_OPS.md`
|
||||
Rotate both on a 90-day cadence. Owner: assigned via `RELEASE_OPS.md`
|
||||
or equivalent issue tracker. On rotation, paste new token and run
|
||||
`gh workflow run bump-homebrew.yml` on the most recent stable tag to verify.
|
||||
|
||||
@@ -223,8 +331,8 @@ or equivalent issue tracker. On rotation, paste new token and run
|
||||
|
||||
```bash
|
||||
brew bump-cask-pr amethyst-nostr \
|
||||
--version 1.12.0 \
|
||||
--url "https://github.com/vitorpamplona/amethyst/releases/download/v1.12.0/amethyst-desktop-1.12.0-macos-arm64.dmg"
|
||||
--version 1.12.1 \
|
||||
--url "https://github.com/vitorpamplona/amethyst/releases/download/v1.12.1/amethyst-desktop-1.12.1-macos-arm64.dmg"
|
||||
```
|
||||
|
||||
The cask filename is `amethyst-nostr` (not `amethyst` — that's taken by a
|
||||
@@ -235,7 +343,7 @@ auto-submits new version bumps on each stable release.
|
||||
|
||||
```bash
|
||||
wingetcreate new \
|
||||
https://github.com/vitorpamplona/amethyst/releases/download/v1.12.0/amethyst-desktop-1.12.0-windows-x64.msi
|
||||
https://github.com/vitorpamplona/amethyst/releases/download/v1.12.1/amethyst-desktop-1.12.1-windows-x64.msi
|
||||
```
|
||||
|
||||
Set `PackageIdentifier = VitorPamplona.Amethyst`. After the first manifest is
|
||||
|
||||
@@ -14,7 +14,8 @@ Join the social network you control.
|
||||
[](https://play.google.com/store/apps/details?id=com.vitorpamplona.amethyst)
|
||||
|
||||
[](https://github.com/vitorpamplona/amethyst)
|
||||
[](https://jitpack.io/#vitorpamplona/amethyst)
|
||||
[](https://central.sonatype.com/artifact/com.vitorpamplona.quartz/quartz)
|
||||
[](https://jitpack.io/#vitorpamplona/amethyst)
|
||||
[](https://github.com/vitorpamplona/amethyst/actions/workflows/build.yml)
|
||||
[](/LICENSE)
|
||||
[](https://deepwiki.com/vitorpamplona/amethyst)
|
||||
@@ -269,18 +270,16 @@ For the Play build:
|
||||
|
||||
## Deploying
|
||||
|
||||
Full release + bootstrap runbooks (Android AAB upload, desktop packaging,
|
||||
Homebrew cask, Winget manifest, Apple Developer signing budget time-box) live
|
||||
in [BUILDING.md § Release runbook](BUILDING.md#release-runbook) and
|
||||
[BUILDING.md § Bootstrap runbook (one-time)](BUILDING.md#bootstrap-runbook-one-time).
|
||||
A release is one tag push. Bump `app` and `appCode` in
|
||||
`gradle/libs.versions.toml`, then `git tag -s vX.Y.Z && git push --tags` — the
|
||||
`Create Release Assets` workflow builds and signs every Android, desktop, CLI,
|
||||
and Maven artifact, and Homebrew + Winget auto-bump on stable tags.
|
||||
|
||||
TL;DR for cutting a release:
|
||||
|
||||
1. Bump `app` in `gradle/libs.versions.toml` (e.g. `"1.08.1"`)
|
||||
2. Bump `versionCode` in `amethyst/build.gradle`
|
||||
3. `git commit -am "chore(release): 1.08.1" && git tag -s v1.08.1 && git push --tags`
|
||||
4. Wait for `Create Release Assets` workflow — 20 Android assets + 8 desktop assets go live on GH Release; Homebrew + Winget auto-bump on stable tags
|
||||
5. Upload AAB to Play Store manually (existing step)
|
||||
- **[BUILDING.md](BUILDING.md)** — everything any fork needs: build commands,
|
||||
the CI pipeline, the secrets it requires, and the distribution channels.
|
||||
- **[RELEASE_OPS.md](RELEASE_OPS.md)** — the Amethyst maintainers'
|
||||
ship checklist: the manual Play Store upload, Zapstore `zsp publish`, F-Droid
|
||||
pull, and release-notes publishing.
|
||||
|
||||
## Using the Quartz library
|
||||
|
||||
@@ -298,20 +297,43 @@ repositories {
|
||||
Add the following line to your `commonMain` dependencies:
|
||||
|
||||
```gradle
|
||||
implementation('com.vitorpamplona.quartz:quartz:1:05.0')
|
||||
implementation('com.vitorpamplona.quartz:quartz:1.12.1')
|
||||
```
|
||||
|
||||
Variations to each platform are also available:
|
||||
|
||||
```gradle
|
||||
implementation('com.vitorpamplona.quartz:quartz-android:1:05.0')
|
||||
implementation('com.vitorpamplona.quartz:quartz-jvm:1:05.0')
|
||||
implementation('com.vitorpamplona.quartz:quartz-iosarm64:1:05.0')
|
||||
implementation('com.vitorpamplona.quartz:quartz-iossimulatorarm64:1:05.0')
|
||||
implementation('com.vitorpamplona.quartz:quartz-android:1.12.1')
|
||||
implementation('com.vitorpamplona.quartz:quartz-jvm:1.12.1')
|
||||
implementation('com.vitorpamplona.quartz:quartz-iosarm64:1.12.1')
|
||||
implementation('com.vitorpamplona.quartz:quartz-iossimulatorarm64:1.12.1')
|
||||
```
|
||||
|
||||
Check versions on [MavenCentral](https://central.sonatype.com/search?q=com.vitorpamplona.quartz)
|
||||
|
||||
#### Snapshots (JitPack)
|
||||
|
||||
Tagged releases go to Maven Central. For **pre-release / snapshot** builds —
|
||||
e.g. to test an unreleased fix straight from `main` or a feature branch — use
|
||||
[JitPack](https://jitpack.io/#vitorpamplona/amethyst), which builds the module
|
||||
on demand from any git ref:
|
||||
|
||||
```gradle
|
||||
repositories {
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// version can be a tag, a commit hash, or "<branch>-SNAPSHOT"
|
||||
implementation("com.github.vitorpamplona.amethyst:quartz:main-SNAPSHOT")
|
||||
}
|
||||
```
|
||||
|
||||
The resolvable refs and the exact module coordinates are listed on the
|
||||
[JitPack page](https://jitpack.io/#vitorpamplona/amethyst). Prefer a Maven
|
||||
Central release for anything shipping to production — JitPack snapshots are not
|
||||
guaranteed stable.
|
||||
|
||||
### How to use
|
||||
|
||||
Manage logged in users with the `KeyPair` class
|
||||
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
# Release Ops (Amethyst maintainers)
|
||||
|
||||
This is the **operational checklist the Amethyst team follows to ship a
|
||||
release** — the account-specific, push-the-buttons side of cutting a version.
|
||||
The *generic* build/release mechanics (how the CI pipeline works, the asset
|
||||
naming contract, the secret names a fork must set, desktop packaging) live in
|
||||
[`BUILDING.md`](BUILDING.md). Read that first; this doc only covers what is
|
||||
specific to shipping the official Amethyst artifacts.
|
||||
|
||||
> Forks: you do **not** need this file. `BUILDING.md` has everything you need to
|
||||
> build and release your own fork. This describes our accounts and channels.
|
||||
|
||||
---
|
||||
|
||||
## At a glance
|
||||
|
||||
A release is one tag push that fans out to five distribution channels:
|
||||
|
||||
| Channel | Mechanism | Who pushes |
|
||||
|---|---|---|
|
||||
| **GitHub Releases** | Automatic — the `Create Release Assets` workflow builds + signs everything on the `v*` tag | CI |
|
||||
| **Google Play** | **Manual** — download the signed AAB from the GH Release, upload in Play Console | Maintainer |
|
||||
| **F-Droid** | **Pull** — F-Droid's build server builds the `fdroid` flavor from source when it sees the new tag | F-Droid (we just maintain the recipe + metadata) |
|
||||
| **Zapstore** | `zsp publish` reads `zapstore.yaml`, signs a Nostr release event with Amethyst's nsec | Maintainer |
|
||||
| **Homebrew + Winget** | Automatic — `bump-homebrew.yml` / `bump-winget.yml` fire on stable tags | CI |
|
||||
|
||||
Maven Central (the `quartz` library) also publishes automatically from the same
|
||||
workflow.
|
||||
|
||||
---
|
||||
|
||||
## 1. Pre-tag checklist
|
||||
|
||||
1. **Bump the version** in `gradle/libs.versions.toml` — both keys:
|
||||
```toml
|
||||
app = "1.12.1" # semver, drives every module + the tag
|
||||
appCode = "449" # Android versionCode, monotonic — must increment
|
||||
```
|
||||
That single edit propagates to Android (`versionName`/`versionCode`),
|
||||
Desktop & CLI (`packageVersion`), `quartz` (Maven version) and `geode`
|
||||
(`RelayInfo.VERSION`). Nothing else hardcodes the version.
|
||||
|
||||
2. **Write the changelog** as `docs/changelog/vMAJOR.MINOR.PP.md` (zero-padded,
|
||||
e.g. `v1.12.01.md`) and add it to `docs/changelog/README.md`. Follow the
|
||||
house style: plain text, short verb-first sentences.
|
||||
|
||||
3. **Publish the release-notes note on Nostr** with Amethyst's account and paste
|
||||
its event id into `amethyst/build.gradle.kts`:
|
||||
```kotlin
|
||||
buildConfigField("String", "RELEASE_NOTES_ID", "\"<new-event-id-hex>\"")
|
||||
```
|
||||
This id is what the in-app drawer's "Release Notes" link and the donation
|
||||
card open (`DrawerContent.kt`, `ShowDonationCard.kt`). It must point at the
|
||||
note for *this* version, so publish the note **before** tagging and commit
|
||||
the new id together with the version bump.
|
||||
|
||||
<!-- TODO(maintainer): document the exact command/account used to publish the
|
||||
release-notes note (which signer, which relays). -->
|
||||
|
||||
4. **Sanity-build locally** (optional but cheap): `./gradlew assembleRelease`
|
||||
and a desktop `packageDistributionForCurrentOS`, or run the workflow's
|
||||
dry-run (see BUILDING.md § Dry-run).
|
||||
|
||||
---
|
||||
|
||||
## 2. Cut the release
|
||||
|
||||
Commit, tag, push — see [`BUILDING.md` § Release runbook](BUILDING.md#release-runbook)
|
||||
for the exact commands. The tag must equal `app` from the catalog (the workflow
|
||||
asserts this and fails fast otherwise). A clean `vMAJOR.MINOR.PATCH` tag is
|
||||
classified **stable** and triggers the Homebrew/Winget bumps; anything with a
|
||||
`-rc`/`-beta`/`-alpha`/`-dev` suffix is a prerelease and skips them.
|
||||
|
||||
When the `Create Release Assets` workflow finishes (~25–30 min) the GH Release
|
||||
holds, per the asset-name contract:
|
||||
|
||||
- **Android:** 5 Google Play APKs + 5 F-Droid APKs + 2 AABs
|
||||
(`amethyst-googleplay-*-v…apk` / `.aab`, `amethyst-fdroid-*-v…apk` / `.aab`)
|
||||
- **Desktop:** 8 assets (DMG/MSI/DEB/RPM/AppImage/zip/tar.gz)
|
||||
- **CLI:** the `amy` artifacts
|
||||
- **Maven Central:** `com.vitorpamplona.quartz:quartz:<version>` published
|
||||
|
||||
---
|
||||
|
||||
## 3. Per-channel shipping
|
||||
|
||||
### GitHub Releases — automatic
|
||||
Nothing to do beyond pushing the tag. Verify the asset count and that Intel +
|
||||
ARM DMGs are both present (BUILDING.md § Verify).
|
||||
|
||||
### Google Play — manual upload
|
||||
1. Download `amethyst-googleplay-<version>.aab` from the GH Release.
|
||||
2. Play Console → app `com.vitorpamplona.amethyst` → **Production** (or the
|
||||
staged-rollout track we're using) → create release → upload the AAB.
|
||||
3. The release notes field can reuse the `docs/changelog` text.
|
||||
4. Roll out.
|
||||
|
||||
### F-Droid — pull / build-from-source
|
||||
F-Droid does **not** accept an upload from us. Its build server polls the repo,
|
||||
and when it sees the new `v*` tag it builds the **`fdroid` product flavor** from
|
||||
source (reproducibly) per the recipe in the separate
|
||||
[`fdroiddata`](https://gitlab.com/fdroid/fdroiddata) repo
|
||||
(`metadata/com.vitorpamplona.amethyst.yml`), then signs and publishes to the
|
||||
F-Droid repo on its own cadence.
|
||||
|
||||
What we own to keep that working:
|
||||
- The **`fdroid` flavor** (`amethyst/src/fdroid/…`) must stay free of
|
||||
proprietary deps — it swaps Firebase/Google services for UnifiedPush and
|
||||
no-op/open implementations (ML Kit, writing assistant, push). Google-only
|
||||
libraries live behind the `play` flavor.
|
||||
- The fastlane metadata under `fastlane/metadata/android/` (descriptions,
|
||||
images). F-Droid reads per-version changelogs from
|
||||
`fastlane/metadata/android/en-US/changelogs/<versionCode>.txt` if present —
|
||||
add one (e.g. `449.txt`) when we want a changelog shown on F-Droid; otherwise
|
||||
none is displayed.
|
||||
- The `AutoUpdateMode`/`UpdateCheckMode` in the fdroiddata recipe tracks tags,
|
||||
so a correct `vX.Y.Z` tag + bumped `versionCode` is usually all F-Droid needs.
|
||||
|
||||
After a release, just confirm F-Droid picked up the new version (it can lag a
|
||||
few days): <https://f-droid.org/packages/com.vitorpamplona.amethyst/>.
|
||||
|
||||
### Zapstore — `zsp publish` with Amethyst's nsec
|
||||
[Zapstore](https://zapstore.dev/) is a Nostr-native app store. The `zsp` CLI
|
||||
reads [`zapstore.yaml`](zapstore.yaml) at the repo root (name, summary,
|
||||
description, tags, license, screenshots, and the `variants` regexes that match
|
||||
our `*-fdroid-*.apk` / `*-googleplay-*.apk` GH-release assets), then publishes a
|
||||
signed software-release event to Nostr relays.
|
||||
|
||||
```bash
|
||||
# from the repo root, after the GH Release assets exist
|
||||
zsp publish
|
||||
```
|
||||
|
||||
It signs with **Amethyst's nsec** — provide the key the way `zsp` expects
|
||||
(env var / prompt / its own config), never commit it.
|
||||
|
||||
### Homebrew + Winget — automatic
|
||||
`bump-homebrew.yml` and `bump-winget.yml` fire on stable tags and open PRs
|
||||
against `Homebrew/homebrew-cask` (cask `amethyst-nostr`) and
|
||||
`microsoft/winget-pkgs` (`VitorPamplona.Amethyst`). No action unless one fails —
|
||||
then see BUILDING.md § Bootstrap and § Incident response.
|
||||
|
||||
---
|
||||
|
||||
## 4. Operated infrastructure
|
||||
|
||||
### Push notification server
|
||||
|
||||
The Google Play (FCM) flavor delivers push through a server we operate at
|
||||
`push.amethyst.social`, built from
|
||||
[`vitorpamplona/amethyst-push-notif-server`](https://github.com/vitorpamplona/amethyst-push-notif-server).
|
||||
It registers devices, watches their NIP-65 inbox / NIP-17 DM relays, and sends
|
||||
wake-up pushes.
|
||||
|
||||
- **`play` flavor** → push via this server (Firebase/FCM).
|
||||
- **`fdroid` flavor** → UnifiedPush through a distributor app the user installs
|
||||
(e.g. ntfy); it does **not** use our server.
|
||||
- Both are complemented by the on-device always-on `NotificationRelayService`
|
||||
(see [`PULL_NOTIFICATION.md`](PULL_NOTIFICATION.md)), which keeps the user's
|
||||
relay connections alive without any push server at all.
|
||||
|
||||
The push server has its **own repo, deploy, and release cadence** — a normal app
|
||||
release does **not** redeploy it. Coordinate a server deploy only when the app
|
||||
changes the registration/push contract (token format, payload, or endpoint), so
|
||||
the running server stays compatible with the shipped app.
|
||||
|
||||
<!-- TODO(maintainer): document the push-server deploy steps + hosting, and
|
||||
which app-side changes require a coordinated push-server deploy. -->
|
||||
|
||||
---
|
||||
|
||||
## 5. Secrets ownership & rotation
|
||||
|
||||
The workflow's required secrets and what they sign are inventoried generically
|
||||
in [`BUILDING.md` § Secrets](BUILDING.md#secrets-the-ci-needs). Amethyst-specific
|
||||
ownership:
|
||||
|
||||
| Secret(s) | Protects | Rotation |
|
||||
|---|---|---|
|
||||
| `SIGNING_KEY`, `KEY_ALIAS`, `KEY_STORE_PASSWORD`, `KEY_PASSWORD` | The **Android upload keystore** — losing/leaking it is the worst case; Play app signing identity | Keep the keystore backed up offline; never rotate casually (Play upload key reset is a support process) |
|
||||
| `SONATYPE_USERNAME`, `SONATYPE_PASSWORD` | Maven Central namespace `com.vitorpamplona` | On compromise |
|
||||
| `SIGNING_PRIVATE_KEY`, `SIGNING_PASSWORD` | The **GPG key** signing Maven artifacts | Per GPG key expiry |
|
||||
| `HOMEBREW_TOKEN`, `WINGET_TOKEN` | Cask + winget bump PRs | **90-day cadence** (see BUILDING.md § Bootstrap) |
|
||||
| `CROWDIN_PERSONAL_TOKEN`, `CROWDIN_PROJECT_ID` | Translation sync | On compromise |
|
||||
|
||||
Owner assignments and rotation reminders live with the team (issue tracker).
|
||||
|
||||
<!-- TODO(maintainer): name the owner per secret and where backups live. -->
|
||||
|
||||
---
|
||||
|
||||
## 6. Post-release verification
|
||||
|
||||
- [ ] GH Release: expected asset count, Intel + ARM DMGs, sizes sane.
|
||||
- [ ] Maven Central: `quartz:<version>` resolves (allow propagation time).
|
||||
- [ ] Play Console: rollout started, no policy rejection.
|
||||
- [ ] Zapstore: release event visible.
|
||||
- [ ] F-Droid: new version detected (may lag days).
|
||||
- [ ] Homebrew + Winget bump PRs opened (stable only).
|
||||
- [ ] In-app "Release Notes" link opens the note matching `RELEASE_NOTES_ID`.
|
||||
- [ ] Push still works on a `play` build (only if the push contract changed —
|
||||
see § 4); UnifiedPush still works on an `fdroid` build.
|
||||
|
||||
If anything ships broken, see [`BUILDING.md` § Incident response](BUILDING.md#incident-response).
|
||||
@@ -76,7 +76,10 @@ android {
|
||||
libs.versions.android.targetSdk
|
||||
.get()
|
||||
.toInt()
|
||||
versionCode = 448
|
||||
versionCode =
|
||||
libs.versions.appCode
|
||||
.get()
|
||||
.toInt()
|
||||
versionName = generateVersionName(libs.versions.app.get(), rootDir)
|
||||
buildConfigField("String", "RELEASE_NOTES_ID", "\"40e817712e397c07ba31784a92fa474aa095896a828c0e2dea0d09c60d49ee1e\"")
|
||||
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ plugins {
|
||||
}
|
||||
|
||||
// Shared app version for all subprojects — read from gradle/libs.versions.toml.
|
||||
// Android versionCode stays local in amethyst/build.gradle.kts (must be monotonic int).
|
||||
// Android versionCode is the `appCode` entry in the same catalog (must be monotonic int).
|
||||
// Desktop packageVersion inherits via project.version in desktopApp/build.gradle.kts.
|
||||
val appVersion = libs.versions.app.get()
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
---
|
||||
review_agents:
|
||||
- kieran-typescript-reviewer
|
||||
- performance-oracle
|
||||
- architecture-strategist
|
||||
- code-simplicity-reviewer
|
||||
- security-sentinel
|
||||
---
|
||||
|
||||
## Review Context
|
||||
|
||||
Kotlin Multiplatform desktop app (Compose Desktop). Nostr client with WebSocket relay connections.
|
||||
Key patterns: FeedViewModel + FeedFilter + FeedContentState (cache-centric), Coordinator for relay subscription management.
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
Release notes for Amethyst, one file per version. Files are named with zero-padded version numbers so they sort correctly in any file browser. Use [`TEMPLATE.md`](TEMPLATE.md) as the starting point for the next release.
|
||||
|
||||
- [v1.12.1 — Health Connect Workouts, Share as Image](v1.12.01.md)
|
||||
- [v1.12.0 — Payments, Private Posts & Workouts](v1.12.00.md)
|
||||
- [v1.11.0 — NIP-52 Calendars, On-Chain Zap Polish](v1.11.00.md)
|
||||
- [v1.10.0 — On-Chain zaps](v1.10.00.md)
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# v1.12.1: Health Connect Workouts, Share as Image
|
||||
|
||||
Highlights:
|
||||
|
||||
- Adds Health Connect: detect recorded workouts and suggest a NIP-101e post.
|
||||
- Adds Share as Image: turn any note into an uploaded image and share it.
|
||||
- Adds Immersive scrolling: hide the OS system bars while reading and in full-screen media.
|
||||
|
||||
## New Features
|
||||
|
||||
### Workouts
|
||||
|
||||
- Detects workouts from Health Connect and suggests a kind 1301 post.
|
||||
- Re-scans Health Connect when the app resumes.
|
||||
- Adds a recent-workouts carousel to the New Workout composer.
|
||||
- Moves Health Connect entirely into the New Workout composer.
|
||||
- Defaults the workout distance unit to the phone's measurement system.
|
||||
- Renders workout notes through the kind-1 text pipeline.
|
||||
- Shows workout metrics in the viewer's own units.
|
||||
- Records the source app or device name from Health Connect.
|
||||
- Aligns Health Connect import with RUNSTR (active calories and title).
|
||||
- Adds a Compose setting to disable workout suggestions.
|
||||
- Limits the feed workout banner to today's workouts.
|
||||
|
||||
### Sharing
|
||||
|
||||
- Shares any note as an uploaded image.
|
||||
- Adds a share-as-image screen with an image preview.
|
||||
|
||||
### Reading
|
||||
|
||||
- Hides the OS status bar during scroll immersive mode.
|
||||
- Hides the OS system bars during full-screen media.
|
||||
|
||||
## Improvements and Bug fixes
|
||||
|
||||
- Modernizes the New Workout composer.
|
||||
- Tightens the New Workout composer vertical spacing.
|
||||
- Centers the activity type chips in the New Workout composer.
|
||||
- Uses the Add icon on the New Workout FAB for consistency.
|
||||
- Stops the connect card from flashing on every screen open.
|
||||
- Keeps Health Connect prefs off the main thread (StrictMode).
|
||||
- Adds the Android 14+ Health Connect permission rationale activity-alias.
|
||||
- Polishes the share-as-image screen.
|
||||
- Fixes a Tor race: sets Active deterministically so the bootstrap callback can't race it.
|
||||
|
||||
## Desktop
|
||||
|
||||
- Ships a consistent macOS .icns and multi-size Windows .ico.
|
||||
- Excludes leaked kotlinx-coroutines-test from the release dmg.
|
||||
|
||||
## Translations
|
||||
|
||||
- Promotes Kenyan Swahili to the base resource qualifier.
|
||||
- New Crowdin translations.
|
||||
@@ -19,9 +19,34 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a BuildConfig.kt carrying the app version from the catalog so
|
||||
// RelayInfo.VERSION (reported over NIP-11) tracks releases automatically
|
||||
// instead of being a hand-bumped literal.
|
||||
val generateVersionFile by tasks.registering {
|
||||
val versionValue = libs.versions.app.get()
|
||||
val outDir = layout.buildDirectory.dir("generated/version/kotlin")
|
||||
inputs.property("version", versionValue)
|
||||
outputs.dir(outDir)
|
||||
doLast {
|
||||
val file = outDir.get().file("com/vitorpamplona/geode/BuildConfig.kt").asFile
|
||||
file.parentFile.mkdirs()
|
||||
file.writeText(
|
||||
buildString {
|
||||
appendLine("// Generated by the :geode build — do not edit.")
|
||||
appendLine("package com.vitorpamplona.geode")
|
||||
appendLine()
|
||||
appendLine("internal object BuildConfig {")
|
||||
appendLine(" const val VERSION = \"$versionValue\"")
|
||||
appendLine("}")
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
kotlin.srcDir("src/main/kotlin")
|
||||
kotlin.srcDir(generateVersionFile)
|
||||
}
|
||||
test {
|
||||
kotlin.srcDir("src/test/kotlin")
|
||||
|
||||
@@ -38,10 +38,10 @@ data class RelayInfo(
|
||||
val json: String by lazy { JsonMapper.toJson(document) }
|
||||
|
||||
companion object {
|
||||
const val NAME = "geode"
|
||||
const val DESCRIPTION = "Embedded Nostr relay from the Amethyst quartz library."
|
||||
const val NAME = "Geode"
|
||||
const val DESCRIPTION = "Nostr relay from Amethyst"
|
||||
const val SOFTWARE = "https://github.com/vitorpamplona/amethyst/tree/main/geode"
|
||||
const val VERSION = "1.12.0"
|
||||
const val VERSION = BuildConfig.VERSION
|
||||
|
||||
/**
|
||||
* NIPs this relay implements out of the box. Single source of
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
[versions]
|
||||
# Amethyst app version — single source of truth consumed by both Android (amethyst/)
|
||||
# and Desktop (desktopApp/). Android versionCode is bumped independently in
|
||||
# amethyst/build.gradle because it must be a monotonic integer.
|
||||
app = "1.12.0"
|
||||
# and Desktop (desktopApp/). `appCode` is the Android versionCode: a monotonic
|
||||
# integer that must increment on every release, even when `app` is unchanged.
|
||||
app = "1.12.1"
|
||||
appCode = "449"
|
||||
accompanistAdaptive = "0.37.3"
|
||||
cachemapVersion = "0.2.4"
|
||||
composeMultiplatform = "1.11.1"
|
||||
|
||||
@@ -449,7 +449,9 @@ mavenPublishing {
|
||||
coordinates(
|
||||
groupId = "com.vitorpamplona.quartz",
|
||||
artifactId = "quartz",
|
||||
version = "1.12.0",
|
||||
// Library version tracks the app version in gradle/libs.versions.toml,
|
||||
// bumped in lockstep with each release.
|
||||
version = libs.versions.app.get(),
|
||||
)
|
||||
|
||||
// Configure publishing to Maven Central
|
||||
|
||||
Reference in New Issue
Block a user