mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 19:28:25 +00:00
Merge pull request #4086 from vitorpamplona/chore/release-1.15.1
chore(release): bump to 1.15.1, unblocking the AAB on AGP 9.4.0
This commit is contained in:
@@ -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.
|
Reference for integrating `com.vitorpamplona.quartz:quartz` into external Nostr KMP projects.
|
||||||
|
|
||||||
**Published artifact**: `com.vitorpamplona.quartz:quartz:1.15.0` (Maven Central)
|
**Published artifact**: `com.vitorpamplona.quartz:quartz:1.15.1` (Maven Central)
|
||||||
**Targets**: JVM 21+, Android (minSdk 21+), iOS (XCFramework `quartz-kmpKit`)
|
**Targets**: JVM 21+, Android (minSdk 21+), iOS (XCFramework `quartz-kmpKit`)
|
||||||
**License**: MIT
|
**License**: MIT
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ Reference for integrating `com.vitorpamplona.quartz:quartz` into external Nostr
|
|||||||
|
|
||||||
```toml
|
```toml
|
||||||
[versions]
|
[versions]
|
||||||
quartz = "1.15.0"
|
quartz = "1.15.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
quartz = { module = "com.vitorpamplona.quartz:quartz", version.ref = "quartz" }
|
quartz = { module = "com.vitorpamplona.quartz:quartz", version.ref = "quartz" }
|
||||||
@@ -41,7 +41,7 @@ kotlin {
|
|||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.vitorpamplona.quartz:quartz:1.15.0")
|
implementation("com.vitorpamplona.quartz:quartz:1.15.1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
## Current version
|
## Current version
|
||||||
|
|
||||||
```
|
```
|
||||||
com.vitorpamplona.quartz:quartz:1.15.0
|
com.vitorpamplona.quartz:quartz:1.15.1
|
||||||
```
|
```
|
||||||
|
|
||||||
Check latest: https://central.sonatype.com/artifact/com.vitorpamplona.quartz/quartz
|
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
|
```toml
|
||||||
[versions]
|
[versions]
|
||||||
quartz = "1.15.0"
|
quartz = "1.15.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
quartz = { module = "com.vitorpamplona.quartz:quartz", version.ref = "quartz" }
|
quartz = { module = "com.vitorpamplona.quartz:quartz", version.ref = "quartz" }
|
||||||
@@ -55,7 +55,7 @@ kotlin {
|
|||||||
```kotlin
|
```kotlin
|
||||||
// build.gradle.kts (app module)
|
// build.gradle.kts (app module)
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.vitorpamplona.quartz:quartz:1.15.0")
|
implementation("com.vitorpamplona.quartz:quartz:1.15.1")
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.vitorpamplona.quartz:quartz:1.15.0")
|
implementation("com.vitorpamplona.quartz:quartz:1.15.1")
|
||||||
// JNA needed for libsodium (NIP-44) on JVM
|
// JNA needed for libsodium (NIP-44) on JVM
|
||||||
implementation("net.java.dev.jna:jna:5.18.1")
|
implementation("net.java.dev.jna:jna:5.18.1")
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -533,7 +533,7 @@ reads an optional per-release changelog from
|
|||||||
|
|
||||||
## Bootstrap runbook (one-time)
|
## Bootstrap runbook (one-time)
|
||||||
|
|
||||||
> **Status as of v1.15.0:** both Homebrew packages are now live upstream — the
|
> **Status as of v1.15.1:** both Homebrew packages are now live upstream — the
|
||||||
> `amethyst-nostr` cask (`Homebrew/homebrew-cask`, at 1.14.0) and the `amy`
|
> `amethyst-nostr` cask (`Homebrew/homebrew-cask`, at 1.14.0) and the `amy`
|
||||||
> formula (`Homebrew/homebrew-core`) both answer 200 on `formulae.brew.sh`, so
|
> formula (`Homebrew/homebrew-core`) both answer 200 on `formulae.brew.sh`, so
|
||||||
> `bump-homebrew.yml` finally has something to bump. **Winget is still not
|
> `bump-homebrew.yml` finally has something to bump. **Winget is still not
|
||||||
@@ -587,7 +587,7 @@ The token then lives only in that maintainer's shell:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
export HOMEBREW_GITHUB_API_TOKEN=ghp_... # classic PAT, `repo` scope
|
export HOMEBREW_GITHUB_API_TOKEN=ghp_... # classic PAT, `repo` scope
|
||||||
scripts/bump-homebrew-cask.sh v1.15.0
|
scripts/bump-homebrew-cask.sh v1.15.1
|
||||||
```
|
```
|
||||||
|
|
||||||
Create one at
|
Create one at
|
||||||
@@ -603,7 +603,7 @@ Same split, and it needs **no token at all**. `scripts/bump-winget.sh` drives
|
|||||||
runs fine from macOS or Linux:
|
runs fine from macOS or Linux:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
scripts/bump-winget.sh v1.15.0
|
scripts/bump-winget.sh v1.15.1
|
||||||
```
|
```
|
||||||
|
|
||||||
CI (`bump-winget.yml`, `GITHUB_TOKEN` only) does the bookkeeping: downloads the
|
CI (`bump-winget.yml`, `GITHUB_TOKEN` only) does the bookkeeping: downloads the
|
||||||
|
|||||||
@@ -328,16 +328,16 @@ repositories {
|
|||||||
Add the following line to your `commonMain` dependencies:
|
Add the following line to your `commonMain` dependencies:
|
||||||
|
|
||||||
```gradle
|
```gradle
|
||||||
implementation('com.vitorpamplona.quartz:quartz:1.15.0')
|
implementation('com.vitorpamplona.quartz:quartz:1.15.1')
|
||||||
```
|
```
|
||||||
|
|
||||||
Variations to each platform are also available:
|
Variations to each platform are also available:
|
||||||
|
|
||||||
```gradle
|
```gradle
|
||||||
implementation('com.vitorpamplona.quartz:quartz-android:1.15.0')
|
implementation('com.vitorpamplona.quartz:quartz-android:1.15.1')
|
||||||
implementation('com.vitorpamplona.quartz:quartz-jvm:1.15.0')
|
implementation('com.vitorpamplona.quartz:quartz-jvm:1.15.1')
|
||||||
implementation('com.vitorpamplona.quartz:quartz-iosarm64:1.15.0')
|
implementation('com.vitorpamplona.quartz:quartz-iosarm64:1.15.1')
|
||||||
implementation('com.vitorpamplona.quartz:quartz-iossimulatorarm64:1.15.0')
|
implementation('com.vitorpamplona.quartz:quartz-iossimulatorarm64:1.15.1')
|
||||||
```
|
```
|
||||||
|
|
||||||
Check versions on [MavenCentral](https://central.sonatype.com/search?q=com.vitorpamplona.quartz)
|
Check versions on [MavenCentral](https://central.sonatype.com/search?q=com.vitorpamplona.quartz)
|
||||||
|
|||||||
+2
-2
@@ -240,9 +240,9 @@ readable by anyone with push access here), so a maintainer runs the last step:
|
|||||||
```bash
|
```bash
|
||||||
# after merging the sync PRs
|
# after merging the sync PRs
|
||||||
export HOMEBREW_GITHUB_API_TOKEN=ghp_... # classic PAT, `repo` scope
|
export HOMEBREW_GITHUB_API_TOKEN=ghp_... # classic PAT, `repo` scope
|
||||||
scripts/bump-homebrew-cask.sh v1.15.0
|
scripts/bump-homebrew-cask.sh v1.15.1
|
||||||
|
|
||||||
scripts/bump-winget.sh v1.15.0 # no token — uses your `gh` auth
|
scripts/bump-winget.sh v1.15.1 # no token — uses your `gh` auth
|
||||||
```
|
```
|
||||||
|
|
||||||
Both scripts re-verify the published artifact's sha256 before submitting, and
|
Both scripts re-verify the published artifact's sha256 before submitting, and
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
import java.io.File
|
||||||
|
import java.util.zip.ZipEntry
|
||||||
|
import java.util.zip.ZipFile
|
||||||
|
import java.util.zip.ZipOutputStream
|
||||||
import org.gradle.api.services.BuildService
|
import org.gradle.api.services.BuildService
|
||||||
import org.gradle.api.services.BuildServiceParameters
|
import org.gradle.api.services.BuildServiceParameters
|
||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||||
@@ -611,3 +615,75 @@ dependencies {
|
|||||||
implementation(libs.androidx.camera.view)
|
implementation(libs.androidx.camera.view)
|
||||||
implementation(libs.androidx.camera.extensions)
|
implementation(libs.androidx.camera.extensions)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AGP 9.4.0's PerModuleBundleTask refuses to write an AAB entry whose name contains a colon:
|
||||||
|
//
|
||||||
|
// Entry name contains invalid characters: root/META-INF/zoomable-root:zoomable.kotlin_module
|
||||||
|
//
|
||||||
|
// A .kotlin_module is named after the Gradle project path that produced it, colons included, and
|
||||||
|
// 14 of the 98 merged into this app carry one -- zoomable, Negentropy, vico, seven coil3 artifacts
|
||||||
|
// and four of ours. The entries are identical under 9.3.1, which writes them without complaint, so
|
||||||
|
// 9.4.0 added the rejection rather than the names.
|
||||||
|
//
|
||||||
|
// packaging.resources.excludes cannot remove them: with minification on, R8 emits the java
|
||||||
|
// resources and PerModuleBundleTask.addHybridFolder hands JarFlinger its own predicate, so those
|
||||||
|
// filters are never consulted. Nothing in the AAB reads a .kotlin_module either -- it exists for
|
||||||
|
// the Kotlin compiler to resolve top-level declarations across modules at COMPILE time.
|
||||||
|
//
|
||||||
|
// So drop them from R8's java-res jar in the moment before the bundle task opens it, then put the
|
||||||
|
// jar back exactly as R8 left it. The strip is doFirst on the CONSUMER rather than doLast on R8, so
|
||||||
|
// a build-cache hit on R8 cannot skip it; the restore is what keeps R8 up to date next build --
|
||||||
|
// without it Gradle sees a modified output and re-runs R8 every time, which measured ~2 min a build
|
||||||
|
// here for no work.
|
||||||
|
fun stripColonNamedEntries(jar: File): Int {
|
||||||
|
val offenders = ZipFile(jar).use { zip -> zip.entries().toList().count { ':' in it.name } }
|
||||||
|
if (offenders == 0) return 0
|
||||||
|
|
||||||
|
val rewritten = File(jar.parentFile, "${jar.name}.stripped")
|
||||||
|
ZipFile(jar).use { zip ->
|
||||||
|
ZipOutputStream(rewritten.outputStream().buffered()).use { out ->
|
||||||
|
zip.entries().asSequence().filterNot { ':' in it.name }.forEach { entry ->
|
||||||
|
out.putNextEntry(ZipEntry(entry.name))
|
||||||
|
zip.getInputStream(entry).use { it.copyTo(out) }
|
||||||
|
out.closeEntry()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rewritten.copyTo(jar, overwrite = true)
|
||||||
|
rewritten.delete()
|
||||||
|
return offenders
|
||||||
|
}
|
||||||
|
|
||||||
|
androidComponents.onVariants { variant ->
|
||||||
|
val variantName = variant.name
|
||||||
|
val capitalized = variantName.replaceFirstChar { it.uppercase() }
|
||||||
|
tasks.matching { it.name == "build${capitalized}PreBundle" }.configureEach {
|
||||||
|
val javaResDir = layout.buildDirectory.dir("intermediates/merged_java_res/$variantName")
|
||||||
|
val backups = mutableMapOf<File, File>()
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
javaResDir.get().asFile
|
||||||
|
.walkTopDown()
|
||||||
|
.filter { it.isFile && it.extension == "jar" }
|
||||||
|
.forEach { jar ->
|
||||||
|
val backup = File(jar.parentFile, "${jar.name}.orig")
|
||||||
|
jar.copyTo(backup, overwrite = true)
|
||||||
|
val dropped = stripColonNamedEntries(jar)
|
||||||
|
if (dropped > 0) {
|
||||||
|
backups[jar] = backup
|
||||||
|
logger.lifecycle("Stripped $dropped colon-named entries from ${jar.name}")
|
||||||
|
} else {
|
||||||
|
backup.delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
backups.forEach { (jar, backup) ->
|
||||||
|
backup.copyTo(jar, overwrite = true)
|
||||||
|
backup.delete()
|
||||||
|
}
|
||||||
|
backups.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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.
|
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.15.1 — Release Build Fix](v1.15.01.md)
|
||||||
- [v1.15.0 — Marmot Updates, a Advanced Search Box, and Books, DVM Updates](v1.15.00.md)
|
- [v1.15.0 — Marmot Updates, a Advanced Search Box, and Books, DVM Updates](v1.15.00.md)
|
||||||
- [v1.14.0 — Highlights, Relay Login, and a Much Faster Start](v1.14.00.md)
|
- [v1.14.0 — Highlights, Relay Login, and a Much Faster Start](v1.14.00.md)
|
||||||
- [v1.13.1 — Follow-up Fixes for Buzz, Concord and the Keyboard](v1.13.01.md)
|
- [v1.13.1 — Follow-up Fixes for Buzz, Concord and the Keyboard](v1.13.01.md)
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# v1.15.1: Release Build Fix
|
||||||
|
|
||||||
|
v1.15.0 was tagged but never shipped: its `Create Release Assets` run failed in
|
||||||
|
`deploy-android` before producing a single artifact. This release carries the
|
||||||
|
whole of [v1.15.0](v1.15.00.md) plus the fix for that failure — read those notes
|
||||||
|
for what actually changed in the app.
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
- Strips colon-named `.kotlin_module` entries out of R8's java-resource jar
|
||||||
|
before the app bundle is written. AGP 9.4.0 refuses them:
|
||||||
|
|
||||||
|
```
|
||||||
|
Execution failed for task ':amethyst:buildFdroidReleasePreBundle'
|
||||||
|
> Entry name contains invalid characters: root/META-INF/zoomable-root:zoomable.kotlin_module
|
||||||
|
```
|
||||||
|
|
||||||
|
A `.kotlin_module` is named after the Gradle project path that produced it,
|
||||||
|
colons included, and 14 of the 98 modules merged into the app carry one —
|
||||||
|
zoomable, Negentropy, vico, seven coil3 artifacts, and four of ours
|
||||||
|
(`Amethyst:quartz`, `:commons`, `:quic`, `:nestsClient`). The entries are
|
||||||
|
byte-identical under AGP 9.3.1, which writes the bundle without complaint, so
|
||||||
|
9.4.0 added the rejection rather than the names.
|
||||||
|
|
||||||
|
`packaging.resources.excludes` cannot remove them — with minification on, R8
|
||||||
|
emits the java resources and `PerModuleBundleTask` hands `JarFlinger` its own
|
||||||
|
predicate, so those filters are never consulted. Nothing reads a
|
||||||
|
`.kotlin_module` out of an installed app either; the file exists for the
|
||||||
|
Kotlin compiler to resolve top-level declarations across modules at compile
|
||||||
|
time.
|
||||||
+3
-3
@@ -32,7 +32,7 @@ docker run -d --name geode -p 7447:7447 \
|
|||||||
```
|
```
|
||||||
|
|
||||||
with `in_memory = false` and `file = "/var/lib/geode/events.db"` in your
|
with `in_memory = false` and `file = "/var/lib/geode/events.db"` in your
|
||||||
`geode.toml`. Pin a version (`:1.15.0`) instead of `:latest` for reproducible
|
`geode.toml`. Pin a version (`:1.15.1`) instead of `:latest` for reproducible
|
||||||
deploys. To build the image yourself, from the repo root:
|
deploys. To build the image yourself, from the repo root:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -47,7 +47,7 @@ it — a minimal JRE is bundled, so no system Java is required. It installs to
|
|||||||
`/opt/geode/` with the launcher at `/opt/geode/bin/geode`.
|
`/opt/geode/` with the launcher at `/opt/geode/bin/geode`.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo dpkg -i geode-1.15.0-linux-x64.deb # or: sudo rpm -i geode-1.15.0-linux-x64.rpm
|
sudo dpkg -i geode-1.15.1-linux-x64.deb # or: sudo rpm -i geode-1.15.1-linux-x64.rpm
|
||||||
```
|
```
|
||||||
|
|
||||||
To run it as a managed service, wire up the shipped systemd unit
|
To run it as a managed service, wire up the shipped systemd unit
|
||||||
@@ -69,7 +69,7 @@ formula: [`packaging/homebrew/geode-relay.rb`](packaging/homebrew/geode-relay.rb
|
|||||||
Download `geode-<version>-<os>-<arch>.tar.gz`, unpack, and run:
|
Download `geode-<version>-<os>-<arch>.tar.gz`, unpack, and run:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
tar xzf geode-1.15.0-linux-x64.tar.gz
|
tar xzf geode-1.15.1-linux-x64.tar.gz
|
||||||
./geode/bin/geode --config geode/share/geode/config.example.toml
|
./geode/bin/geode --config geode/share/geode/config.example.toml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
# Amethyst app version — single source of truth consumed by both Android (amethyst/)
|
# Amethyst app version — single source of truth consumed by both Android (amethyst/)
|
||||||
# and Desktop (desktopApp/). `appCode` is the Android versionCode: a monotonic
|
# and Desktop (desktopApp/). `appCode` is the Android versionCode: a monotonic
|
||||||
# integer that must increment on every release, even when `app` is unchanged.
|
# integer that must increment on every release, even when `app` is unchanged.
|
||||||
app = "1.15.0"
|
app = "1.15.1"
|
||||||
appCode = "458"
|
appCode = "459"
|
||||||
accompanistAdaptive = "0.37.3"
|
accompanistAdaptive = "0.37.3"
|
||||||
# Pinned: 0.3.0 turns CacheMap.entries/keys/values into DeprecationLevel.ERROR (and
|
# Pinned: 0.3.0 turns CacheMap.entries/keys/values into DeprecationLevel.ERROR (and
|
||||||
# throws UnsupportedOperationException at runtime), which breaks quartz's appleMain
|
# throws UnsupportedOperationException at runtime), which breaks quartz's appleMain
|
||||||
@@ -13,6 +13,9 @@ accompanistAdaptive = "0.37.3"
|
|||||||
cachemapVersion = "0.2.4"
|
cachemapVersion = "0.2.4"
|
||||||
composeMultiplatform = "1.12.0"
|
composeMultiplatform = "1.12.0"
|
||||||
activityCompose = "1.13.0"
|
activityCompose = "1.13.0"
|
||||||
|
# 9.4.0's PerModuleBundleTask rejects an AAB entry whose name contains a colon, which every
|
||||||
|
# .kotlin_module named after a Gradle project path has. Worked around in amethyst/build.gradle.kts
|
||||||
|
# (stripColonNamedEntries) rather than by pinning to 9.3.1; drop that block if AGP fixes it.
|
||||||
agp = "9.4.0"
|
agp = "9.4.0"
|
||||||
android-compileSdk = "37"
|
android-compileSdk = "37"
|
||||||
android-minSdk = "26"
|
android-minSdk = "26"
|
||||||
|
|||||||
Reference in New Issue
Block a user