mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-09 16:14:40 +00:00
Follow-up to the linux-arm64 CI leg (feat/release-linux-arm64). Extends the
release matrix to Windows in three places, all on free public-repo hosted
GitHub runners:
* build-desktop: adds windows-11-arm (arm64) alongside the existing
windows-latest (x64). jpackage/jlink on Windows arm64 produce arm64 MSIs
natively; the same packageReleaseMsi + createReleaseDistributable task
list is used unchanged and the portable-archive step already parameterises
on ${{ matrix.arch }}.
* build-cli: adds windows-latest (x64) and windows-11-arm (arm64) legs
running :cli:amyImage. Windows has no jpackageDeb/Rpm and MSI-for-CLI is
deferred (portable zip is the documented Windows install path); the
headless-lib assertion runs unchanged under git-bash. amyImage now emits
both a POSIX `bin/amy` shell launcher AND a Windows `bin/amy.bat`
launcher into the flat image so the tree layout is uniform regardless of
build host. The .bat pins UTF-8 (chcp 65001) for sun.jnu.encoding, same
reason the installDist .bat was already patched.
* build-geode: adds windows-latest + windows-11-arm legs running
:geode:geodeImage. The existing --port smoke test is generalised to pick
bin/geode.bat on Windows; NIP-11 fetch via curl works unchanged under
git-bash on GH windows runners. Same dual-launcher pattern as amy.
scripts/asset-name.sh: collect_cli_assets and collect_geode_assets now
package the flat image as .zip on Windows (7z when available, falling
back to `zip`, then a portable python3 zipfile.ZipFile invocation). Every
other OS continues to use tar.gz. Adds the expected Windows examples to
the header block.
BUILDING.md: mentions the windows-11-arm runner and updates the asset
count in the Release runbook. No asset-naming contract changes — the
existing amethyst-desktop-<v>-windows-<arch>.<ext>, amy-<v>-windows-<arch>.zip,
and geode-<v>-windows-<arch>.zip shapes were already in scope, they just
weren't produced by any CI leg before.
Local validation on macOS arm64 (build host: JDK 21, gradle 9.5.0):
./gradlew :cli:amyImage -> bin/amy + bin/amy.bat both present
./gradlew :geode:geodeImage -> bin/geode + bin/geode.bat both present
./bin/amy --help -> parses (unix launcher unbroken)
./bin/geode --port 17447 -> NIP-11 served, "supported_nips" present
collect_cli_assets windows arm64 ... -> valid .zip with bin/amy.bat
collect_geode_assets windows x64 ... -> valid .zip with bin/geode.bat
actionlint .github/workflows/create-release.yml -> no new findings
Cross-compile is impossible for jlink/jpackage, so end-to-end
Windows-runtime validation still happens on GH CI on the first PR
build; nothing in this change can be verified any harder locally.
269 lines
11 KiB
Bash
Executable File
269 lines
11 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Single source of truth for Amethyst release asset naming.
|
|
#
|
|
# Three product lines share this contract:
|
|
# amethyst-desktop-<version>-<family>-<arch>.<ext> (Compose Desktop app)
|
|
# amy-<version>-<family>-<arch>.<ext> (Amy CLI — cli/ module)
|
|
# geode-<version>-<family>-<arch>.<ext> (geode relay — geode/ module)
|
|
#
|
|
# <version> = tag stripped of leading 'v' (e.g. "1.08.0")
|
|
# <family> = macos | windows | linux
|
|
# <arch> = x64 | arm64
|
|
# <ext> = dmg | msi | zip | deb | rpm | AppImage | flatpak | tar.gz
|
|
#
|
|
# Consumed by: .github/workflows/create-release.yml, .github/workflows/bump-*.yml,
|
|
# BUILDING.md, local release runbooks.
|
|
#
|
|
# Usage:
|
|
# source scripts/asset-name.sh
|
|
# collect_assets <family> <arch> <version> <dest_dir> # desktop
|
|
# collect_cli_assets <family> <arch> <version> <dest_dir> # amy CLI
|
|
#
|
|
# Expected examples:
|
|
# amethyst-desktop-1.08.0-macos-x64.dmg
|
|
# amethyst-desktop-1.08.0-macos-arm64.dmg
|
|
# amethyst-desktop-1.08.0-windows-x64.msi
|
|
# amethyst-desktop-1.08.0-windows-x64.zip
|
|
# amethyst-desktop-1.08.0-windows-arm64.msi
|
|
# amethyst-desktop-1.08.0-windows-arm64.zip
|
|
# amethyst-desktop-1.08.0-linux-x64.deb
|
|
# amethyst-desktop-1.08.0-linux-x64.rpm
|
|
# amethyst-desktop-1.08.0-linux-x64.AppImage
|
|
# amethyst-desktop-1.08.0-linux-x64.flatpak
|
|
# amethyst-desktop-1.08.0-linux-x64.tar.gz
|
|
# amethyst-desktop-1.08.0-linux-arm64.deb
|
|
# amethyst-desktop-1.08.0-linux-arm64.rpm
|
|
# amethyst-desktop-1.08.0-linux-arm64.AppImage
|
|
# amethyst-desktop-1.08.0-linux-arm64.flatpak
|
|
# amethyst-desktop-1.08.0-linux-arm64.tar.gz
|
|
# amy-1.08.0-macos-arm64.tar.gz
|
|
# amy-1.08.0-macos-x64.tar.gz
|
|
# amy-1.08.0-linux-x64.tar.gz
|
|
# amy-1.08.0-linux-x64.deb
|
|
# amy-1.08.0-linux-x64.rpm
|
|
# amy-1.08.0-linux-arm64.tar.gz
|
|
# amy-1.08.0-linux-arm64.deb
|
|
# amy-1.08.0-linux-arm64.rpm
|
|
# amy-1.08.0-windows-x64.zip
|
|
# amy-1.08.0-windows-arm64.zip
|
|
# geode-1.08.0-macos-arm64.tar.gz
|
|
# geode-1.08.0-linux-x64.tar.gz
|
|
# geode-1.08.0-linux-x64.deb
|
|
# geode-1.08.0-linux-x64.rpm
|
|
# geode-1.08.0-linux-arm64.tar.gz
|
|
# geode-1.08.0-linux-arm64.deb
|
|
# geode-1.08.0-linux-arm64.rpm
|
|
# geode-1.08.0-windows-x64.zip
|
|
# geode-1.08.0-windows-arm64.zip
|
|
#
|
|
# Two assets break the family/arch shape on purpose: the no-JRE jar bundles for
|
|
# Homebrew-core are pure JVM bytecode (no bundled runtime), so a single
|
|
# platform-independent artifact serves every OS:
|
|
# amy-1.08.0-jvm.tar.gz
|
|
# geode-1.08.0-jvm.tar.gz
|
|
# They are packaged inline in create-release.yml (linux leg), not via the helpers
|
|
# below, since they have no <family>/<arch> dimension.
|
|
|
|
set -euo pipefail
|
|
|
|
# Print the canonical asset filename for a given family/arch/version/extension.
|
|
# Usage: asset_name <family> <arch> <version> <ext>
|
|
asset_name() {
|
|
local family="$1" arch="$2" version="$3" ext="$4"
|
|
printf 'amethyst-desktop-%s-%s-%s.%s' "$version" "$family" "$arch" "$ext"
|
|
}
|
|
|
|
# CLI variant of asset_name — same shape, different product prefix.
|
|
# Usage: cli_asset_name <family> <arch> <version> <ext>
|
|
cli_asset_name() {
|
|
local family="$1" arch="$2" version="$3" ext="$4"
|
|
printf 'amy-%s-%s-%s.%s' "$version" "$family" "$arch" "$ext"
|
|
}
|
|
|
|
# geode relay variant of asset_name — same shape, different product prefix.
|
|
# Usage: geode_asset_name <family> <arch> <version> <ext>
|
|
geode_asset_name() {
|
|
local family="$1" arch="$2" version="$3" ext="$4"
|
|
printf 'geode-%s-%s-%s.%s' "$version" "$family" "$arch" "$ext"
|
|
}
|
|
|
|
# Copy + rename build outputs into <dest_dir> using the canonical naming scheme.
|
|
# Usage: collect_assets <family> <arch> <version> <dest_dir>
|
|
# Expects build outputs under desktopApp/build/... (Compose binaries + custom tasks + portable archives).
|
|
collect_assets() {
|
|
local family="$1" arch="$2" version="$3" dest="$4"
|
|
# Normalize internal matrix family aliases to canonical asset-name families.
|
|
[[ "$family" == "linux-portable" ]] && family="linux"
|
|
mkdir -p "$dest"
|
|
shopt -s nullglob
|
|
|
|
# Compose Desktop jpackage outputs (main-release/<format>/*.ext)
|
|
local src ext base dst
|
|
for src in \
|
|
desktopApp/build/compose/binaries/main-release/dmg/*.dmg \
|
|
desktopApp/build/compose/binaries/main-release/msi/*.msi \
|
|
desktopApp/build/compose/binaries/main-release/deb/*.deb \
|
|
desktopApp/build/compose/binaries/main-release/rpm/*.rpm \
|
|
desktopApp/build/appimage/*.AppImage \
|
|
desktopApp/build/flatpak/*.flatpak \
|
|
desktopApp/build/portable/*.tar.gz \
|
|
desktopApp/build/portable/*.zip \
|
|
; do
|
|
[ -f "$src" ] || continue
|
|
base="$(basename "$src")"
|
|
case "$base" in
|
|
*.tar.gz) ext="tar.gz" ;;
|
|
*) ext="${base##*.}" ;;
|
|
esac
|
|
dst="$dest/$(asset_name "$family" "$arch" "$version" "$ext")"
|
|
cp "$src" "$dst"
|
|
echo "Collected: $dst"
|
|
done
|
|
shopt -u nullglob
|
|
}
|
|
|
|
# Copy + rename amy CLI build outputs into <dest_dir> using the canonical
|
|
# amy-<version>-<family>-<arch>.<ext> scheme.
|
|
#
|
|
# Expected inputs:
|
|
# cli/build/amy-image/amy/ flat app-image built by :cli:amyImage
|
|
# (bin/amy + bin/amy.bat + lib/*.jar + runtime/)
|
|
# cli/build/jpackage/*.deb from :cli:jpackageDeb (Linux only)
|
|
# cli/build/jpackage/*.rpm from :cli:jpackageRpm (Linux only)
|
|
#
|
|
# On Windows the flat image is packaged as .zip (native archive format,
|
|
# preserves file layout without requiring a tar tool at install time). Every
|
|
# other OS uses tar.gz.
|
|
#
|
|
# Usage: collect_cli_assets <family> <arch> <version> <dest_dir>
|
|
collect_cli_assets() {
|
|
local family="$1" arch="$2" version="$3" dest="$4"
|
|
mkdir -p "$dest"
|
|
local abs_dest
|
|
abs_dest="$(cd "$dest" && pwd)"
|
|
shopt -s nullglob
|
|
|
|
# 1. Archive the flat app-image into amy-<version>-<family>-<arch>.<ext>.
|
|
# macOS runners produce only this one. Windows uses .zip; every other
|
|
# OS uses tar.gz.
|
|
local app_image="cli/build/amy-image/amy"
|
|
if [ -d "$app_image" ]; then
|
|
if [ "$family" = "windows" ]; then
|
|
local zipfile="$abs_dest/$(cli_asset_name "$family" "$arch" "$version" zip)"
|
|
# Prefer 7z when available (bash+7zip is standard on GH windows runners),
|
|
# else fall back to a portable python3 zipfile. `zip` itself is not always
|
|
# present on GH windows runners.
|
|
if command -v 7z >/dev/null 2>&1; then
|
|
( cd "$(dirname "$app_image")" && 7z a -tzip "$zipfile" "$(basename "$app_image")/" >/dev/null )
|
|
elif command -v zip >/dev/null 2>&1; then
|
|
( cd "$(dirname "$app_image")" && zip -qr "$zipfile" "$(basename "$app_image")" )
|
|
else
|
|
python3 - "$app_image" "$zipfile" <<'PY'
|
|
import os, sys, zipfile
|
|
src, dst = sys.argv[1], sys.argv[2]
|
|
root = os.path.dirname(src)
|
|
base = os.path.basename(src)
|
|
with zipfile.ZipFile(dst, "w", zipfile.ZIP_DEFLATED) as zf:
|
|
for dirpath, _dirs, files in os.walk(src):
|
|
for f in files:
|
|
p = os.path.join(dirpath, f)
|
|
zf.write(p, os.path.relpath(p, root))
|
|
PY
|
|
fi
|
|
echo "Collected: $zipfile"
|
|
else
|
|
local tarball="$abs_dest/$(cli_asset_name "$family" "$arch" "$version" tar.gz)"
|
|
( cd "$(dirname "$app_image")" && tar czf "$tarball" "$(basename "$app_image")" )
|
|
echo "Collected: $tarball"
|
|
fi
|
|
fi
|
|
|
|
# 2. Linux native installers (.deb, .rpm). jpackage writes them directly
|
|
# to cli/build/jpackage/ with its own naming, so we re-copy under the
|
|
# canonical scheme.
|
|
local src base ext dst
|
|
for src in \
|
|
cli/build/jpackage/*.deb \
|
|
cli/build/jpackage/*.rpm \
|
|
; do
|
|
[ -f "$src" ] || continue
|
|
base="$(basename "$src")"
|
|
ext="${base##*.}"
|
|
dst="$abs_dest/$(cli_asset_name "$family" "$arch" "$version" "$ext")"
|
|
cp "$src" "$dst"
|
|
echo "Collected: $dst"
|
|
done
|
|
shopt -u nullglob
|
|
}
|
|
|
|
# Copy + rename geode relay build outputs into <dest_dir> using the canonical
|
|
# geode-<version>-<family>-<arch>.<ext> scheme.
|
|
#
|
|
# Expected inputs:
|
|
# geode/build/geode-image/geode/ flat app-image built by :geode:geodeImage
|
|
# (bin/geode + bin/geode.bat + lib/*.jar
|
|
# + runtime/ + share/)
|
|
# geode/build/jpackage/*.deb from :geode:jpackageDeb (Linux only)
|
|
# geode/build/jpackage/*.rpm from :geode:jpackageRpm (Linux only)
|
|
#
|
|
# On Windows the flat image is packaged as .zip; every other OS uses tar.gz.
|
|
# See the matching comment in collect_cli_assets for the tool-selection order.
|
|
#
|
|
# Usage: collect_geode_assets <family> <arch> <version> <dest_dir>
|
|
collect_geode_assets() {
|
|
local family="$1" arch="$2" version="$3" dest="$4"
|
|
mkdir -p "$dest"
|
|
local abs_dest
|
|
abs_dest="$(cd "$dest" && pwd)"
|
|
shopt -s nullglob
|
|
|
|
# 1. Archive the flat app-image into geode-<version>-<family>-<arch>.<ext>.
|
|
# macOS runners produce only this one. Windows uses .zip; every other
|
|
# OS uses tar.gz.
|
|
local app_image="geode/build/geode-image/geode"
|
|
if [ -d "$app_image" ]; then
|
|
if [ "$family" = "windows" ]; then
|
|
local zipfile="$abs_dest/$(geode_asset_name "$family" "$arch" "$version" zip)"
|
|
if command -v 7z >/dev/null 2>&1; then
|
|
( cd "$(dirname "$app_image")" && 7z a -tzip "$zipfile" "$(basename "$app_image")/" >/dev/null )
|
|
elif command -v zip >/dev/null 2>&1; then
|
|
( cd "$(dirname "$app_image")" && zip -qr "$zipfile" "$(basename "$app_image")" )
|
|
else
|
|
python3 - "$app_image" "$zipfile" <<'PY'
|
|
import os, sys, zipfile
|
|
src, dst = sys.argv[1], sys.argv[2]
|
|
root = os.path.dirname(src)
|
|
base = os.path.basename(src)
|
|
with zipfile.ZipFile(dst, "w", zipfile.ZIP_DEFLATED) as zf:
|
|
for dirpath, _dirs, files in os.walk(src):
|
|
for f in files:
|
|
p = os.path.join(dirpath, f)
|
|
zf.write(p, os.path.relpath(p, root))
|
|
PY
|
|
fi
|
|
echo "Collected: $zipfile"
|
|
else
|
|
local tarball="$abs_dest/$(geode_asset_name "$family" "$arch" "$version" tar.gz)"
|
|
( cd "$(dirname "$app_image")" && tar czf "$tarball" "$(basename "$app_image")" )
|
|
echo "Collected: $tarball"
|
|
fi
|
|
fi
|
|
|
|
# 2. Linux native installers (.deb, .rpm). jpackage writes them directly
|
|
# to geode/build/jpackage/ with its own naming, so we re-copy under the
|
|
# canonical scheme.
|
|
local src base ext dst
|
|
for src in \
|
|
geode/build/jpackage/*.deb \
|
|
geode/build/jpackage/*.rpm \
|
|
; do
|
|
[ -f "$src" ] || continue
|
|
base="$(basename "$src")"
|
|
ext="${base##*.}"
|
|
dst="$abs_dest/$(geode_asset_name "$family" "$arch" "$version" "$ext")"
|
|
cp "$src" "$dst"
|
|
echo "Collected: $dst"
|
|
done
|
|
shopt -u nullglob
|
|
}
|