Commit Graph
27 Commits
Author SHA1 Message Date
mstrofnone a110ce0a30 ci: publish linux-arm64 desktop, amy, and geode release assets
Amethyst v1.13.1 (and every prior release) shipped only linux-x64 desktop
binaries — .deb, .rpm, .AppImage, .flatpak, .tar.gz. Same for the amy
CLI and geode relay. Users on aarch64 hardware (Pinebook, Ampere
Altra, Raspberry Pi 4/5, AWS Graviton, arm64 servers, arm64 Chromebooks
running crostini, etc.) can't install any of them.

This teaches the release matrix about arm64:

- Add `ubuntu-24.04-arm` legs to build-desktop, build-cli, and
  build-geode. This is a standard, free public-repo GitHub-hosted
  runner (4 CPU / 16 GB / 14 GB SSD / arm64) since early 2025. No
  cross-compilation: jpackage / jlink / Compose Multiplatform 1.11
  all produce host-native artifacts.

- Fetch the matching `appimagetool-<arch>.AppImage` from the same
  1.9.0 release with an arch-specific SHA256 pin. `APPIMAGETOOL_URL`
  becomes `APPIMAGETOOL_VERSION` + per-arch SHA256 env vars.

- Parametrize the portable tarball/zip filename by `matrix.arch`
  (`amethyst-desktop-<ver>-linux-arm64.tar.gz` is now produced).

- Parametrize the Flatpak bundle filename and rewrite the manifest's
  `GST_PLUGIN_SYSTEM_PATH` from `x86_64-linux-gnu` to
  `aarch64-linux-gnu` on the arm64 leg. The Flathub-submission manifest
  (`desktopApp/packaging/flatpak/flathub/`) still gates on
  `only-arches: x86_64` — flipping that to include aarch64 is a
  follow-up once a Flathub aarch64 build has been validated end-to-end.

- Make the `createReleaseAppImage` gradle task pick its host arch from
  `System.getProperty("os.arch")` (amd64/x86_64 → `x86_64`, aarch64/
  arm64 → `aarch64`). Same task, same command, drives both legs.

- Fix `desktopApp/packaging/appimage/AppRun` to compute the multiarch
  library path from `uname -m` at launch time instead of hard-coding
  `x86_64-linux-gnu`. One script works in both AppImages on the target
  machine.

- Extend the desktop smoke test to run the release .deb build + launch
  probe on `ubuntu-24.04-arm` too, so arch-specific ProGuard/jlink
  breakage (missing native lib, arch-specific reflection root) is
  caught at PR time.

- Update BUILDING.md and scripts/asset-name.sh docs with the new
  arm64 asset names.

Follow-up assets published for the next tag push (v1.13.2+):

- amethyst-desktop-<ver>-linux-arm64.{deb,rpm,AppImage,flatpak,tar.gz}
- amy-<ver>-linux-arm64.{deb,rpm,tar.gz}
- geode-<ver>-linux-arm64.{deb,rpm,tar.gz}

Verification (local, before submitting):

- `python3 -c 'import yaml; yaml.safe_load(open(".github/workflows/create-release.yml"))'` — parses clean
- `bash -n scripts/asset-name.sh desktopApp/packaging/appimage/AppRun` — parses clean
- `actionlint` — reports only pre-existing shellcheck style hints; no new errors
- Confirmed `linuxdeploy-aarch64.AppImage` and
  `appimagetool-aarch64.AppImage` exist under the same pinned release
  tags used for x86_64; SHA256 recorded from a fresh download.

Not addressed (out of scope for this PR):

- Homebrew / winget bump workflows (`bump-homebrew*.yml`,
  `bump-winget.yml`) — those consume the assets by name; the new arm64
  filenames don't change any x86_64 name they already reference.
- Android arm64 continues to ship as before (already had it).
2026-08-04 10:51:16 +10:00
Vitor Pamplona 8a183d1cbd refactor(ci): move the Winget bump out of CI onto a maintainer machine
Mirrors the Homebrew cask change. The old design stored a classic `public_repo`
PAT as WINGET_TOKEN and handed it to the third-party
vedantmgoyal9/winget-releaser action: a token with write access to every public
repo the owning account can reach, given to code we do not control, in a place
any push-access collaborator could read it from (a pushed branch containing a
workflow runs with repo secrets).

- CI (bump-winget.yml, now "Sync Winget Manifest Reference") uses GITHUB_TOKEN
  only: downloads the MSI, computes the sha256, reads the ProductCode from the
  MSI Property table via msitools, and opens an in-repo PR syncing
  desktopApp/packaging/winget/. Runs on ubuntu (1x billing) rather than Windows
  since msitools reads the Property table fine.
- scripts/bump-winget.sh does the upstream PR. It needs NO new token: it drives
  `gh`, which a maintainer already has authenticated, and it does not need
  wingetcreate (Windows-only) because the manifests are plain YAML — so it runs
  from macOS or Linux.

Add the three reference manifests under desktopApp/packaging/winget/, matching
the schema 1.12.0 shape used upstream. All three validate against Microsoft's
published JSON schemas.

Validation caught one real bug worth noting: an all-digit 64-char InstallerSha256
parses as a YAML *integer* and fails the schema's `string` type, so it is written
quoted. ProductCode is re-read every release because jpackage regenerates it per
build; it is the ARP key `winget upgrade` matches on.

Drops the last package-manager PAT from the secret inventory.
2026-07-29 10:30:21 -04:00
Vitor Pamplona db529444c4 refactor(ci): move the Homebrew cask bump out of CI onto a maintainer machine
`brew bump-cask-pr` forks homebrew-cask into the token owner's account, which
requires a CLASSIC PAT with the `repo` scope. That scope cannot be narrowed: it
grants write to every repository the owning account can reach, including this
one. As an Actions secret it would be usable by anyone with push access here,
because a pushed branch containing a workflow runs with repo secrets — a strict
escalation for a channel that ships one DMG a month.

Split the work so the token never becomes a CI secret:

- CI (bump-homebrew.yml, now "Sync Homebrew Cask Reference") does the
  error-prone bookkeeping with GITHUB_TOKEN only: downloads the DMG, asserts it
  is notarized + stapled, computes the sha256, and opens an in-repo PR syncing
  desktopApp/packaging/homebrew/amethyst-nostr.rb. This makes it a third sibling
  of the amy/geode formula-sync workflows rather than a special case.
- scripts/bump-homebrew-cask.sh does the upstream PR from a maintainer's shell,
  re-verifying sha256 and the notarization ticket against the live asset first,
  and refusing to submit if either fails. Verified against v1.13.1: the sha256
  matches and it correctly refuses on the missing notarization ticket.

Drop HOMEBREW_TOKEN from the secret inventory, and rewrite the two formula
TODO(bootstrap) notes that proposed reintroducing it so a future homebrew-core
submission follows the same local pattern.
2026-07-29 10:19:57 -04:00
Vitor Pamplona 2e47e9cd56 docs: correct the HOMEBREW_TOKEN type and scope
BUILDING.md called for a fine-grained PAT scoped to Homebrew/homebrew-cask.
That token cannot exist: a fine-grained PAT's repository selector only lists
repos owned by the resource owner, so a repo you do not own can never be
selected, and Homebrew's API layer authorises against classic OAuth scopes
(x-oauth-scopes) which fine-grained tokens do not emit.

brew bump-cask-pr forks homebrew-cask into the TOKEN OWNER's account, pushes a
branch there, and opens the PR upstream. Homebrew declares the requirement as
CREATE_ISSUE_FORK_OR_PR_SCOPES = ["repo"] in utils/github.rb, so it is a classic
PAT with the `repo` scope.

Add the create-token link and call out that `repo` grants write to every repo
the account can reach -- including this one -- so the CI secret should belong to
a dedicated bot account whose only asset is the fork.
2026-07-29 10:04:25 -04:00
Vitor Pamplona 8a8f58e7ad fix(release): actually notarize the macOS DMG, and verify it
The macOS leg ran only `packageReleaseDmg`, which SIGNS the DMG but does not
notarize it — notarization is a separate Compose task. The `notarization {}`
block in desktopApp/build.gradle.kts only supplies credentials; nothing invoked
it. So every release up to v1.13.1 shipped a signed but unnotarized DMG:
`xcrun stapler validate` reports no ticket on either the .app or the .dmg, and
Gatekeeper blocks it on first launch.

Append `:desktopApp:notarizeReleaseDmg` on the macOS leg. Compose 1.11.1's
AbstractNotarizationTask runs `notarytool submit --wait` and then `stapler
staple` in place, so the asset-collection step still finds the same file. Raise
that leg's inner timeout to 45m since the submit blocks on Apple.

Gate it on the cert AND all three notary secrets, so forks and credential-less
runs keep producing a plain unsigned DMG instead of failing.

Add a verify step that asserts the stapled ticket. The bug survived many
releases precisely because nothing ever checked the outcome.

Also update the reference cask to 1.13.1 and make it pass `brew audit --new
--cask` + `brew style` cleanly: add the missing conflicts_with (the tiling
window manager's cask installs the same Amethyst.app), add depends_on :macos,
fix stanza order, drop the unnecessary `verified:` (url and homepage share a
domain), and widen the zap to the state dirs the source actually uses.

Correct BUILDING.md's macOS state table, which listed a
com.vitorpamplona.amethyst.desktop.plist that does not exist and omitted
~/.amethyst. Note that Java's Preferences API writes to a SHARED
com.apple.java.util.prefs.plist, which is why the cask must not zap it.
2026-07-29 09:59:41 -04:00
Vitor Pamplona 054dffd55d fix(ci): make the Homebrew/Winget bump workflows actually fire
All four bump workflows triggered on `release: types: [released]`, which never
fires here: create-release.yml publishes the release with GITHUB_TOKEN, and
GitHub suppresses workflow-triggering events for GITHUB_TOKEN actions. They had
zero runs across every release up to v1.13.1.

Switch them to `workflow_run` on "Create Release Assets" completion, filtered to
a successful tag push. That also removes a latent race: `released` fired while
the matrix legs were still uploading assets, whereas workflow_run fires after
all of them finish.

The workflow_run payload carries no draft/prerelease flags, so add a
resolve-release composite action that reads them back from the API and feeds
assert-stable-release, keeping the defense-in-depth guard intact instead of
inferring stability from the tag string alone.

Also gate the cask/winget bumps on the package existing upstream. Neither
`amethyst-nostr` nor `VitorPamplona.Amethyst` has been bootstrapped, and
bump-cask-pr/winget-releaser can only update an existing package — without the
gate, fixing the trigger would file a spurious [release-ops] issue on every
release.

Docs: correct the claims this uncovered — Homebrew/Winget are not shipping,
macOS is arm64-only (no Intel DMG), the release carries 31 assets (13 Android,
not 12), Maven Central publishes from a step inside deploy-android and lags
repo1 by tens of minutes, RELEASE_NOTES_ID is minor-releases-only, and note the
git-credential-manager hang that blocks the release push.
2026-07-29 09:37:24 -04:00
Claude 7e78204336 feat: ship a Flatpak bundle of the desktop app on release CI
The linux-portable release leg now wraps the createReleaseDistributable
tree it already builds into a single-file Flatpak bundle and attaches it
to the GH Release as amethyst-desktop-<version>-linux-x64.flatpak.

Packaging fixes to the existing (previously unwired) Flathub manifest:
- add the missing 512x512 icon (copy of desktopApp icon.png) and install
  it under hicolor/512x512 instead of the never-present 256px path
- drop the openjdk module + sdk-extension: the jpackage tree bundles its
  own trimmed JRE, so /app/jre was pure bloat
- grant --socket=x11 instead of wayland/fallback-x11: Compose Desktop
  renders via AWT/skiko (X11-only on Linux, XWayland on Wayland), so
  fallback-x11 left the app socketless on Wayland sessions

CI wiring:
- install flatpak tooling + the freedesktop runtime/sdk (version greped
  from the manifest so the pin can't drift), retried like other fetches
- inject the AppStream <release> entry for the tagged version at build
  time (the checked-in metainfo deliberately carries none)
- flatpak-builder with --disable-rofiles-fuse (GH runners) and a
  --state-dir under desktopApp/build so the repo tree stays clean
- collect via the existing asset-name.sh contract (new flatpak ext)

Verified end-to-end locally: built the bundle from the manifest with a
stubbed jpackage tree, installed it, and ran the exported command inside
the sandbox (freedesktop 24.08, args forwarded through the wrapper).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GYfNxhPZC3WRrn82Dm2Cb4
2026-07-14 14:06:37 +00:00
davotoulaandClaude Opus 4.8 d7e163111a build: remove Kover coverage plugin
Reverts the Kover coverage aggregation (introduced in dca345212b) from every
module, the root aggregation block, the Sonar coverage import, the version
catalog, and BUILDING.md. With the plugin present the 16 GB CI runner OOM-killed
during the Android test+build job even with Kover opt-in disabled; removing it
entirely clears the OOM. No other CI changes — the diff versus main is exactly
the inverse of dca345212b.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 16:52:29 +01:00
davotoula dca345212b build: aggregate Kover coverage for SonarQube import
- Apply Kover (Apache-2.0, build-time only) to the KMP/JVM modules and aggregate at the root
- include amethyst playDebug in the aggregated Kover coverage
2026-07-11 15:37:40 +01:00
davotoulaandClaude Fable 5 9731185d49 docs: document importing Android Lint reports into local Sonar analysis
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HLfwhTdf72qFPnmPRYnzqu
2026-07-09 13:21:28 +01:00
davotoula cf43e6e435 build: opt-in local SonarQube analysis via local.properties
Adds a `sonar` Gradle target that activates only when `sonar.host.url`
is present in local.properties (gitignored). Developers who don't opt
in are unaffected: the scanner plugin is neither resolved nor applied,
so no dependency downloads, no extra tasks, no config-time cost
2026-07-08 22:33:06 +01:00
Claude 6bb2f8045d build: pre-merge audit fixes for reproducibility work
Bugs / inconsistencies found while reviewing the branch for merge:

- dependenciesInfo comment falsely claimed Play "still derives this data
  server-side, nothing is lost." Not true: includeInBundle=false means the
  .aab carries no dependency metadata, so Play Console's dependency-insights /
  SDK-vulnerability alerts go unpopulated (uploads still succeed). Corrected
  the comment and the BUILDING.md framing (it called the blob "the one
  remaining blocker" when the Arti .so was the bigger one).

- Version-bump workflow was broken: the README told you to run
  `build-arti.sh --clean` to refresh Cargo.lock, but the build is now --locked
  (fails on a stale lock) and the clone moved to the canonical /tmp path. Added
  a dedicated `--regen-lock` mode (clone + cargo generate-lockfile, no NDK
  needed) and pointed the docs at it. Verified it reproduces the committed lock
  byte-for-byte.

- verify-reproducible.sh: new helper that builds twice and diffs to prove
  byte-for-byte reproducibility; uses portable sha256 (sha256sum/shasum) and
  plain `sort` so it runs on macOS too.

- README verify recipe referenced paths that only resolved from the repo root
  while telling you to cd into tools/arti-build — replaced with the helper.

- rust-toolchain.toml listed four Android targets but only two ABIs ship a
  .so; trimmed to match (check_prerequisites adds any other on the fly).

- BUILDING.md: documented that the bundled Arti .so is reproducible-from-source
  and that secp256k1/webrtc are version-pinned Maven prebuilts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JtjUcSjjpu4auFndw1QKeU
2026-06-27 00:19:26 +00:00
Claude 69457ec10d build: make release APKs reproducible
AGP embeds a dependency-metadata blob (the resolved dependency tree, a
protobuf encrypted with a Google public key) into the APK/AAB signing
block by default. That ciphertext is non-deterministic, so it was the one
remaining thing preventing our release artifacts from being rebuilt
bit-for-bit by a third party.

Disable it via dependenciesInfo { includeInApk = false; includeInBundle =
false }. Combined with the already-pinned toolchain (AGP/Kotlin/R8/JDK 21),
the absence of any build-time clock in BuildConfig, and a deterministic
version name, release APKs now reproduce exactly — letting F-Droid /
Zapstore independently verify our developer-signed builds. Play derives
this dependency data server-side, so nothing is lost there.

Document the guarantee and a diffoscope-based verification recipe in
BUILDING.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JtjUcSjjpu4auFndw1QKeU
2026-06-26 20:28:38 +00:00
Claude 87c16afe1d refactor: move amy.rb into cli/packaging/homebrew (was root packaging/)
The Homebrew formula is the cli module's product (amy), and the CLI already
owns its packaging artifacts under cli/packaging/ (cli/packaging/macos/
amy.entitlements). The root packaging/ dir was new in this branch and held
nothing else, so co-locate the formula with the module that owns it and drop
the stray root dir. Updates the two BUILDING.md references.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sso31DfSF9B6EFCVkEqWD
2026-06-18 13:13:43 +00:00
Claude 3c422b1824 ci(cli): surface notary log on non-Accepted; record signing validation
macOS validation (Developer ID D77MCV9NZ7) confirmed the hardened-runtime
entitlements are correct and load-bearing: amy init derives a secp256k1 key
cleanly, and dropping disable-library-validation reproduces the runtime
dlopen Team-ID failure. The one unverified gap is whether Apple's notary
service accepts the unsigned Mach-O dylibs embedded inside lib/*.jar
(secp256k1/jna/sqlite/skiko), which it inspects recursively.

- create-release.yml: the notarize step now submits with --output-format json,
  and on any non-Accepted status dumps `notarytool log` (per-file issues) and
  fails — so the first real run names the offending files instead of failing
  opaquely. No speculative in-jar signing yet; gather the log first.
- BUILDING.md: record the validation result, the embedded-jar-native risk, the
  one-run way to decide it (workflow_dispatch dry_run with MAC_* secrets), and
  the staged fixes (sign-in-jar and/or strip the skiko/Compose leak). Note the
  desktop app shares the same jars and needs its own dry-run.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sso31DfSF9B6EFCVkEqWD
2026-06-18 00:49:26 +00:00
Claude d10e6c4d81 feat(cli): codesign + notarize the macOS amy tarball
Sign the macOS jlink image (amy-<version>-macos-arm64.tar.gz) so users who
download it directly clear Gatekeeper. Reuses the same Developer ID cert and
the six MAC_* secrets as the desktop DMG; no-op when they're absent.

- .github/actions/import-macos-cert: factor the throwaway-keychain cert import
  into a composite action; the desktop leg now uses it too (was inline).
- create-release.yml (build-cli macOS leg): import the cert, then codesign
  every Mach-O binary in the bundled JRE (executables get hardened-runtime
  entitlements, dylibs don't) and notarize via notarytool --wait. Runs before
  the collect step so the tarred image is signed. Job timeout 30->45 min for
  notarization headroom.
- cli/packaging/macos/amy.entitlements: hardened-runtime entitlements; the
  disable-library-validation key lets the JVM load the secp256k1 native dylib
  it extracts from a jar at runtime (would otherwise crash under notarization).
- BUILDING.md: document the tarball signing, the no-stapling/online-check
  caveat, and that the Homebrew-core jvm bundle is intentionally left unsigned.

Untested end-to-end (no macOS runner / Apple creds here) — validate with a
workflow_dispatch dry-run once the secrets are provisioned.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sso31DfSF9B6EFCVkEqWD
2026-06-18 00:21:58 +00:00
Claude f24fc10212 feat(cli): publish no-JRE jar bundle + Homebrew-core formula for amy
Enable distributing the `amy` CLI via Homebrew-core (mainline formulae).
Homebrew-core builds in a network-sandboxed env, so a from-source Gradle
build can't resolve Maven deps there; the accepted pattern for JVM tools is a
pre-built no-JRE jar bundle + `depends_on "openjdk"`. installDist already
produces exactly that (bin/amy + lib/*.jar, no bundled runtime).

- create-release.yml: publish `amy-<version>-jvm.tar.gz` (the installDist tree)
  as a release asset on the linux leg. Pure JVM bytecode, so one
  platform-independent artifact serves every OS.
- packaging/homebrew/amy.rb: reference formula (depends_on openjdk, livecheck
  for BrewTestBot auto-bumps, `amy --help` smoke test). Not consumed by any
  build here — it's the artifact to submit to Homebrew/homebrew-core.
- BUILDING.md: homebrew-core submission runbook; note that the desktop app is
  already on mainline Homebrew (homebrew/cask); document name-collision and
  pre-built-jar review caveats.
- asset-name.sh: document the jvm bundle naming exception.

Verified locally: :cli:installDist builds with only a JDK (no Android SDK),
and the extracted bundle runs via JAVA_HOME (`amy --help` exits 0).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sso31DfSF9B6EFCVkEqWD
2026-06-18 00:14:09 +00:00
Claude c81dbb0127 feat(desktop): wire macOS Developer ID signing + notarization
Add gated code-signing + notarization for the macOS desktop DMG so it can
clear Gatekeeper and stay in Homebrew's main cask (unsigned casks are
rejected after 2026-09-01).

- desktopApp/build.gradle.kts: macOS signing{}/notarization{} blocks, gated
  on the AMETHYST_MAC_SIGN_IDENTITY env var. Absent => unsigned DMG, exactly
  as before, so local dev and PR CI are unaffected.
- create-release.yml: import a Developer ID cert into a throwaway keychain on
  the macOS leg and export the signing/notary env. Soft-gated on the
  MAC_CERTIFICATE_P12 secret — no secret => unsigned build.
- BUILDING.md: document the six MAC_* secrets, how to generate them, and flip
  the unsigned-cask fallback note to reflect the wiring is now in place
  (pending Apple credentials).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015sso31DfSF9B6EFCVkEqWD
2026-06-17 23:06:07 +00:00
Vitor PamplonaandClaude Opus 4.8 0c59bb89ee docs: complete the build/release guide and add RELEASE_OPS
Make BUILDING.md everything a fork needs to build and release, and add a
maintainer-facing ship checklist.

- BUILDING.md: full CI secrets inventory (Android keystore vs GPG/Maven, with
  generation commands), a distribution-channels table (GitHub, Maven, Play,
  F-Droid pull, Zapstore, Homebrew/Winget), and a "generated & vendored
  artifacts" section (Material Symbols subset, Arti native libs).
- RELEASE_OPS.md (new, repo root): Amethyst-specific shipping — pre-tag
  checklist, per-channel rollout (manual Play AAB, Zapstore `zsp publish` with
  our nsec, F-Droid build-from-source), the push-notification server
  (amethyst-push-notif-server), secret ownership, and verification.
- README.md: slim the Deploying section to point at both docs, fix the stale
  quartz dependency version, and add a Maven Central badge plus JitPack
  snapshot docs.
- android-expert skill: drop the duplicated build-config block, delegate to
  gradle-expert, keep only the Android-specific flavor note.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 11:20:36 -04:00
Vitor Pamplona 0572b0091c v1.12.0 2026-06-16 14:38:13 -04:00
Vitor Pamplona e0abc4a224 v1.11.0 2026-05-20 18:59:05 -04:00
Vitor Pamplona 280f21159f v1.10.0 2026-05-16 16:53:00 -04:00
Claude 7ed93bcbc2 fix(desktop): package AppImage with appimagetool, not linuxdeploy
linuxdeploy auto-walks every binary in the staged AppDir with ldd to
bundle their shared-library deps. That fights jpackage's self-contained
output on two axes and aborts the createReleaseAppImage task before any
AppImage is produced:

  - The bundled JRE puts libjvm.so at usr/lib/runtime/lib/server/, while
    its sibling libs (libmanagement.so, libawt_xawt.so, libfontmanager.so
    and others in usr/lib/runtime/lib/) have RPATH=$ORIGIN. ldd cannot
    resolve libjvm.so from those libs without help, so linuxdeploy errors:
        ERROR: Could not find dependency: libjvm.so
        ERROR: Failed to deploy dependencies for existing files

  - The bundled libvlc plugins under usr/lib/app/resources/vlc/ are
    UPX-compressed by the vlc-setup plugin. patchelf cannot read their
    section headers, so linuxdeploy aborts:
        ERROR: Call to patchelf failed:
        patchelf: no section headers. The input file is probably a
        statically linked, self-decompressing binary

  - Even after working around libjvm.so via LD_LIBRARY_PATH, several VLC
    libs have RUNPATH pointing at the wrong directory, so ldd fails on
    libva.so.2 / libvlccore.so.9 next.

This is why v1.09.2 shipped .deb + .rpm from the linux leg but no
.AppImage and no linux .tar.gz from the linux-portable leg — the gradle
step failed on linuxdeploy, so the subsequent "Build portable archives"
step never ran.

Swap to appimagetool, which only embeds the AppDir as-is into a
SquashFS-backed, runtime-prepended AppImage and never touches the
contents. jpackage already bundles a complete, self-contained app —
we don't need linuxdeploy's dep-discovery. AppRun continues to handle
LD_LIBRARY_PATH at launch.

Verified locally on ubuntu-24.04: a fresh
:desktopApp:createReleaseAppImage now produces a valid 254 MB
Amethyst-1.09.2-x86_64.AppImage in ~30 s on top of an up-to-date
createReleaseDistributable.

Side changes:
- Workflow installs desktop-file-utils (appimagetool 1.9.0 calls
  desktop-file-validate on the .desktop entry).
- BUILDING.md updated with the new local-dev fetch command.
- .gitignore replaces the linuxdeploy paths with appimagetool's.
2026-05-16 19:04:07 +00:00
Vitor Pamplona 8a498695a9 v1.09.2 2026-05-16 12:06:32 -04:00
Vitor Pamplona 5a30b10a77 v1.09.1 2026-05-15 18:25:17 -04:00
Claude 3ff721b31a refactor: move packaging/appimage into desktopApp module
The AppImage build inputs (AppRun, .desktop entry, icon, and the
CI-fetched linuxdeploy binary) are consumed only by desktopApp's
createReleaseAppImage task. Co-locating them under
desktopApp/packaging/appimage/ removes the `../` path escape from the
build script and keeps all desktop packaging assets inside the module.

https://claude.ai/code/session_0137ULcfJkASmfmffFBdW8ac
2026-05-14 18:21:28 +00:00
nrobi144 c428661601 feat(release): expand desktop distribution to 8 assets + 2 package managers
Phases 3, 4, 5, 6 of the multi-platform distribution plan.

## create-release.yml rewrite
- Replace deprecated actions/create-release@v1 + upload-release-asset@v1 with
  softprops/action-gh-release@v2 (SHA-pinned)
- Expand build-desktop matrix: macos-13 (Intel), macos-14 (ARM),
  windows-latest, ubuntu-latest × 2 legs (deb+rpm, AppImage+tar.gz)
- Each matrix job uploads directly to release (no artifact round-trip — saves
  ~10 min + 1.5GB transfer per run)
- Inline portable archives: Windows .zip via 7z, Linux .tar.gz via tar
- linuxdeploy SHA-verified fetch for AppImage builds (not `continuous` tag)
- Per-asset size budget: hard fail at 1 GB per asset
- prerelease inferred from tag regex (-rc|-beta|-alpha|-dev|-snapshot)
- workflow_dispatch dry_run input: builds all assets without publishing,
  skips Android + bump workflows
- Tag-vs-libs.versions.toml assertion as first step in each matrix job
- Android + Quartz jobs preserved; migrated to softprops/action-gh-release@v2

## Package manager bump workflows (Homebrew + Winget)
- .github/workflows/bump-homebrew.yml — macauley/action-homebrew-bump-cask
  on ubuntu-latest (saves macOS runner quota). Cask name: `amethyst-nostr`.
- .github/workflows/bump-winget.yml — vedantmgoyal9/winget-releaser on
  windows-latest. PackageIdentifier: `VitorPamplona.Amethyst`.
- Shared composite action .github/actions/assert-stable-release rejects
  draft/prerelease/malformed-tag releases at action boundary (defense in
  depth vs workflow-level `if:` alone).
- Both workflows auto-open `release-ops`-labeled GH Issues on failure.
- Concurrency groups per tag prevent re-fire races.
- AUR + Scoop deferred to follow-up PR (unresolved ownership questions).

## Documentation
- BUILDING.md: per-platform build commands, asset naming contract, release
  runbook, bootstrap runbook, troubleshooting, uninstall paths, incident
  response, fallback plans (macos-13 retirement, Homebrew Sept 2026 deadline)
- README: expanded Download section with per-OS install matrix for 7 formats
  + 2 package managers. Deploying section points at BUILDING.md.

## Supply chain
- .github/dependabot.yml: monthly bumps for github-actions ecosystem
- All new third-party actions SHA-pinned:
  - softprops/action-gh-release v2.6.2
  - macauley/action-homebrew-bump-cask v4.0.0
  - vedantmgoyal9/winget-releaser v2
  - nick-fields/retry v3.0.2
- linuxdeploy binary SHA256-verified against pinned release tag
2026-04-16 14:54:51 +03:00