No reference to the maintainer's own server: .gitmodules and PKGBUILD are the public ones on every branch, the nobilis release is its own script and the mirroring is kept outside the repository, and the maintainer is [email protected] everywhere it is named

Closes #335

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
2026-10-11 00:28:47 -04:00
co-authored by Claude Sonnet 5.5
parent 64ade92ee1
commit 97611c8742
7 changed files with 80 additions and 159 deletions
+3 -4
View File
@@ -99,9 +99,8 @@ jobs:
build: ${{ steps.stamp.outputs.build }}
steps:
# nobilis is a submodule, and on master its URL is the public GitHub
# one - on development it points at Gitea. That is the other reason this
# workflow only ever runs on master.
# nobilis is a submodule at a commit its own master holds, which is why
# this workflow only ever runs on master.
#
# Depth 1 is enough: nobilis/build.rs only asks git for a short sha and
# a dirty flag, and falls back to "unknown" rather than failing.
@@ -340,7 +339,7 @@ jobs:
retention-days: 7
# The daemon on its own, for nobilis's release - attached to that by
# scripts/mirror-release.sh, since this job's token can only release
# scripts/release-nobilis.sh, since this job's token can only release
# here. Not an asset of moho's release: the AppImage already carries it.
- uses: actions/upload-artifact@v4
if: github.ref_type == 'tag'
+1 -1
View File
@@ -1,3 +1,3 @@
[submodule "nobilis"]
path = nobilis
url = https://git.salastil.com/Salastil/nobilis.git
url = https://github.com/Moho-Chat/nobilis.git
+2 -34
View File
@@ -1,43 +1,21 @@
# Maintainer: Salastil <[email protected]>
#
# Builds moho from source the way an AUR VCS package does: compile the Rust
# daemon, build the renderer, then assemble an unpacked Electron tree and
# install it under /opt.
#
# Deliberately NOT the AppImage: an AppImage is a self-contained blob that
# needs libfuse2 at runtime and integrates with nothing. `npm run pack` still
# produces one for portable use; this is the path for installing it properly.
pkgname=moho-git
pkgver=r1.268751e
pkgrel=1
pkgdesc="Unified desktop chat client for IRC, Discord, Sneedchat and Matrix"
arch=('x86_64')
url="https://git.salastil.com/Salastil/moho"
url="https://github.com/Moho-Chat/moho"
license=('GPL3')
# Electron ships its own copy of Chromium, but still links against the
# system's GTK/NSS/audio stack at runtime.
depends=('gtk3' 'nss' 'alsa-lib' 'libxss' 'libnotify')
makedepends=('git' 'cargo' 'nodejs' 'npm')
provides=('moho')
conflicts=('moho')
# The daemon lives in its own repository and is pulled in as a submodule;
# makepkg does not recurse into submodules on its own, so prepare() does it.
source=("git+https://git.salastil.com/Salastil/moho.git")
source=("git+https://github.com/Moho-Chat/moho.git")
sha256sums=('SKIP')
# The bundled Electron binaries are already stripped and have their own debug
# handling; letting makepkg reprocess ~150MB of them wastes minutes and can
# corrupt the ASAR integrity checks.
options=(!strip !debug !lto)
pkgver() {
cd "$srcdir/moho"
# The release's own number first (#239), then where in the history this
# build sits: 1.0.0.r1234.abc1234. A number sorts above the bare r1234.abc
# this used to be, so an existing install upgrades rather than going back.
# A pre-release is written the way pacman orders one, without the hyphen
# it does not allow: 1.0.0-rc.1 is 1.0.0rc1, which sorts before 1.0.0 and
# after 1.0.0rc0 - so the release upgrades its own candidates.
printf "%s.r%s.%s" \
"$(sed -n 's/^ "version": "\(.*\)",$/\1/p' package.json | sed -E 's/-([a-z]+)\.?([0-9]+)$/\1\2/')" \
"$(git rev-list --count HEAD)" "$(git rev-parse --short HEAD)"
@@ -46,16 +24,11 @@ pkgver() {
prepare() {
cd "$srcdir/moho"
git submodule update --init --recursive
# `npm ci` respects the allowScripts entries in package.json, so the
# electron and esbuild postinstalls that fetch their platform binaries are
# permitted without any interactive approval.
npm ci
}
build() {
cd "$srcdir/moho"
# The daemon is bundled from the submodule's build output, so it has to
# exist before electron-builder assembles the tree.
cargo build --release --locked --manifest-path nobilis/Cargo.toml
npm run build
npx --no-install electron-builder --linux dir
@@ -73,16 +46,11 @@ package() {
install -dm755 "$pkgdir/opt/moho"
cp -a dist/linux-unpacked/. "$pkgdir/opt/moho/"
# Electron's setuid sandbox helper: without the setuid bit, Chromium either
# refuses to start or falls back to running unsandboxed.
chmod 4755 "$pkgdir/opt/moho/chrome-sandbox"
install -dm755 "$pkgdir/usr/bin"
ln -s /opt/moho/moho "$pkgdir/usr/bin/moho"
# Written here rather than shipped as a source file: this PKGBUILD builds
# from a plain git clone, so keeping it inline means there is nothing extra
# to keep in sync between the repo and the package.
install -dm755 "$pkgdir/usr/share/applications"
cat > "$pkgdir/usr/share/applications/moho.desktop" <<'DESKTOP'
[Desktop Entry]
+1 -1
Submodule nobilis updated: 95ee3b1338...1c70d322eb
+2 -2
View File
@@ -2,7 +2,7 @@
"name": "moho",
"version": "1.0.0-rc.5",
"description": "Unified desktop chat client for IRC, Discord, Sneedchat and Matrix",
"author": "Salastil",
"author": "Salastil <[email protected]>",
"license": "GPL-3.0-or-later",
"homepage": "https://github.com/Moho-Chat/moho",
"repository": {
@@ -79,7 +79,7 @@
"AppImage",
"deb"
],
"maintainer": "Salastil <salastil@users.noreply.github.com>",
"maintainer": "Salastil <salastil@cock.li>",
"category": "Network",
"synopsis": "Unified desktop chat client",
"icon": "resources/icons/moho.png",
-117
View File
@@ -1,117 +0,0 @@
#!/usr/bin/env bash
# Mirrors a published GitHub release of moho to Gitea, and makes nobilis's
# release of the same version on both hosts. Run here, by hand, once the
# release workflow has published the tag on GitHub - Gitea releases are never
# made by Actions.
#
# scripts/mirror-release.sh v1.0.0
#
# moho on Gitea: the same title, notes, pre-release flag and files as GitHub.
# nobilis, on GitHub and Gitea: tagged at the commit moho's tag points to,
# named after the same version, its notes the version's major features and
# the nobilis lines of the changelog, with the two daemon binaries the
# release's run built.
#
# Safe to run again: a release that exists is updated rather than repeated.
set -euo pipefail
TAG="${1:?usage: scripts/mirror-release.sh vX.Y.Z}"
VERSION="${TAG#v}"
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
# Through Cloudflare by default, which refuses a request body over 100 MB. The
# files that are bigger go to Gitea directly across the network, which is what
# MIRROR_GITEA is for - the same instance, reached by its own address:
#
# MIRROR_GITEA=http://192.168.1.212:8991/api/v1 MIRROR_MAX_BYTES=1000000000 \
# scripts/mirror-release.sh v1.0.0
GITEA="${MIRROR_GITEA:-https://git.salastil.com/api/v1}"
TOKEN="$(cat "$HOME/.config/gitea/token")"
# What Cloudflare in front of Gitea will take in one request.
MAX_UPLOAD="${MIRROR_MAX_BYTES:-100000000}"
WORK="$(mktemp -d)"
trap 'rm -rf "$WORK"' EXIT
gitea() { # method path [curl args...]
local method="$1" path="$2"; shift 2
curl -fsS -X "$method" -H "Authorization: token $TOKEN" "$GITEA$path" "$@"
}
# Creates or updates a Gitea release and makes its files exactly those given.
gitea_release() { # repo title notes-file prerelease file...
local repo="$1" title="$2" notes="$3" pre="$4"; shift 4
local body id
body="$(python3 -c 'import json,sys; print(json.dumps({"tag_name": sys.argv[1], "name": sys.argv[2], "body": open(sys.argv[3]).read(), "prerelease": sys.argv[4] == "true"}))' "$TAG" "$title" "$notes" "$pre")"
if id="$(gitea GET "/repos/$repo/releases/tags/$TAG" 2>/dev/null | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])' 2>/dev/null)"; then
gitea PATCH "/repos/$repo/releases/$id" -H 'Content-Type: application/json' -d "$body" >/dev/null
for asset in $(gitea GET "/repos/$repo/releases/$id/assets" | python3 -c 'import json,sys; print(" ".join(str(a["id"]) for a in json.load(sys.stdin)))'); do
gitea DELETE "/repos/$repo/releases/$id/assets/$asset" >/dev/null
done
else
id="$(gitea POST "/repos/$repo/releases" -H 'Content-Type: application/json' -d "$body" | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')"
fi
for f in "$@"; do
# Gitea is behind Cloudflare, which refuses a request body over 100 MB (a
# 413, or a 502 when the connection is cut mid-upload). A file over that
# stays on GitHub only, said plainly rather than failing the whole mirror
# and leaving everything after it - nobilis's releases - undone.
if [ "$(stat -c %s "$f")" -gt "$MAX_UPLOAD" ]; then
echo " SKIPPED $(basename "$f") ($(( $(stat -c %s "$f") / 1000000 )) MB) - over Cloudflare's ${MAX_UPLOAD} byte limit; it is on GitHub only" >&2
continue
fi
gitea POST "/repos/$repo/releases/$id/assets?name=$(basename "$f")" -F "attachment=@$f" >/dev/null
echo " uploaded $(basename "$f") -> Gitea $repo"
done
}
# --- moho -------------------------------------------------------------------
echo "moho $TAG: GitHub -> Gitea"
read -r PRE TITLE < <(gh release view "$TAG" --repo Moho-Chat/moho --json isPrerelease,name -q '"\(.isPrerelease) \(.name)"')
gh release view "$TAG" --repo Moho-Chat/moho --json body -q .body > "$WORK/moho-notes.md"
mkdir -p "$WORK/moho"
gh release download "$TAG" --repo Moho-Chat/moho --dir "$WORK/moho"
git -C "$ROOT" push -q origin "refs/tags/$TAG" 2>/dev/null || true
gitea_release Salastil/moho "$TITLE" "$WORK/moho-notes.md" "$PRE" "$WORK"/moho/*
# --- nobilis ------------------------------------------------------------------
NOBILIS_SHA="$(git -C "$ROOT" rev-parse "$TAG:nobilis")"
echo "nobilis $TAG at ${NOBILIS_SHA:0:7}"
if ! git -C "$ROOT/nobilis" rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
git -C "$ROOT/nobilis" tag -a "$TAG" "$NOBILIS_SHA" -m "nobilis $VERSION"
fi
git -C "$ROOT/nobilis" push -q github "refs/tags/$TAG"
git -C "$ROOT/nobilis" push -q origin "refs/tags/$TAG"
# Its notes: the version's major features, and the nobilis lines only.
SECTION="$VERSION"
grep -q "^## \[$VERSION\]" "$ROOT/CHANGELOG.md" || SECTION="${VERSION%%-*}"
awk -v v="$SECTION" '
index($0, "## [" v "]") == 1 { on = 1; next }
on && /^## \[/ { exit }
!on { next }
/^### / { fixes = ($0 ~ /^### Fixes/); print; next }
/^- / { if (!fixes || /\[nobilis /) print; next }
{ print }
' "$ROOT/CHANGELOG.md" > "$WORK/nobilis-notes.md"
printf '\nnobilis is the daemon inside moho %s; these are its own builds, for running it on its own.\n' "$VERSION" >> "$WORK/nobilis-notes.md"
# The daemon binaries, from the run that built this release.
RUN="$(gh run list --repo Moho-Chat/moho --workflow release.yml --branch "$TAG" --status success --limit 1 --json databaseId -q '.[0].databaseId')"
[ -n "$RUN" ] || { echo "no successful release run for $TAG" >&2; exit 1; }
mkdir -p "$WORK/nobilis"
gh run download "$RUN" --repo Moho-Chat/moho -n daemon-linux -D "$WORK/d-linux"
gh run download "$RUN" --repo Moho-Chat/moho -n daemon-windows -D "$WORK/d-win"
install -m 755 "$WORK/d-linux/nobilis" "$WORK/nobilis/nobilis-$VERSION-linux-x86_64"
install -m 644 "$WORK/d-win/nobilis.exe" "$WORK/nobilis/nobilis-$VERSION-windows-x86_64.exe"
NOBILIS_FLAGS=(--latest)
[ "$PRE" = "true" ] && NOBILIS_FLAGS=(--prerelease --latest=false)
if gh release view "$TAG" --repo Moho-Chat/nobilis >/dev/null 2>&1; then
gh release edit "$TAG" --repo Moho-Chat/nobilis --notes-file "$WORK/nobilis-notes.md"
gh release upload "$TAG" --repo Moho-Chat/nobilis "$WORK"/nobilis/* --clobber
else
gh release create "$TAG" --repo Moho-Chat/nobilis --verify-tag --title "nobilis $VERSION" \
--notes-file "$WORK/nobilis-notes.md" "${NOBILIS_FLAGS[@]}" "$WORK"/nobilis/*
fi
echo " GitHub Moho-Chat/nobilis $TAG"
gitea_release Salastil/nobilis "nobilis $VERSION" "$WORK/nobilis-notes.md" "$PRE" "$WORK"/nobilis/*
echo "done: moho and nobilis $TAG on GitHub and Gitea"
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env bash
# Makes nobilis's release of the same version as one of moho's.
#
# Run by the maintainer once the release workflow has published moho's tag:
# the daemon is its own repository with its own releases, and the job that
# builds it holds a token that can only release moho.
#
# scripts/release-nobilis.sh v1.0.0
# scripts/release-nobilis.sh v1.0.0 --keep DIR leave the notes and the two
# daemon binaries in DIR
#
# nobilis is tagged at the commit moho's tag points to, named after the same
# version, its notes the version's major features and the nobilis lines of the
# changelog, with the two daemon binaries the release's run built. Safe to run
# again: a release that exists is updated rather than repeated.
set -euo pipefail
TAG="${1:?usage: scripts/release-nobilis.sh vX.Y.Z [--keep DIR]}"
KEEP=""
[ "${2:-}" = "--keep" ] && KEEP="${3:?--keep needs a directory}"
VERSION="${TAG#v}"
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
WORK="$(mktemp -d)"
trap 'rm -rf "$WORK"' EXIT
read -r PRE < <(gh release view "$TAG" --repo Moho-Chat/moho --json isPrerelease -q .isPrerelease)
NOBILIS_SHA="$(git -C "$ROOT" rev-parse "$TAG:nobilis")"
echo "nobilis $TAG at ${NOBILIS_SHA:0:7}"
if ! git -C "$ROOT/nobilis" rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
git -C "$ROOT/nobilis" tag -a "$TAG" "$NOBILIS_SHA" -m "nobilis $VERSION"
fi
git -C "$ROOT/nobilis" push -q github "refs/tags/$TAG"
# Its notes: the version's major features, and the nobilis lines only.
SECTION="$VERSION"
grep -q "^## \[$VERSION\]" "$ROOT/CHANGELOG.md" || SECTION="${VERSION%%-*}"
awk -v v="$SECTION" '
index($0, "## [" v "]") == 1 { on = 1; next }
on && /^## \[/ { exit }
!on { next }
/^### / { fixes = ($0 ~ /^### Fixes/); print; next }
/^- / { if (!fixes || /\[nobilis /) print; next }
{ print }
' "$ROOT/CHANGELOG.md" > "$WORK/nobilis-notes.md"
printf '\nnobilis is the daemon inside moho %s; these are its own builds, for running it on its own.\n' "$VERSION" >> "$WORK/nobilis-notes.md"
# The daemon binaries, from the run that built this release.
RUN="$(gh run list --repo Moho-Chat/moho --workflow release.yml --branch "$TAG" --status success --limit 1 --json databaseId -q '.[0].databaseId')"
[ -n "$RUN" ] || { echo "no successful release run for $TAG" >&2; exit 1; }
mkdir -p "$WORK/nobilis"
gh run download "$RUN" --repo Moho-Chat/moho -n daemon-linux -D "$WORK/d-linux"
gh run download "$RUN" --repo Moho-Chat/moho -n daemon-windows -D "$WORK/d-win"
install -m 755 "$WORK/d-linux/nobilis" "$WORK/nobilis/nobilis-$VERSION-linux-x86_64"
install -m 644 "$WORK/d-win/nobilis.exe" "$WORK/nobilis/nobilis-$VERSION-windows-x86_64.exe"
NOBILIS_FLAGS=(--latest)
[ "$PRE" = "true" ] && NOBILIS_FLAGS=(--prerelease --latest=false)
if gh release view "$TAG" --repo Moho-Chat/nobilis >/dev/null 2>&1; then
gh release edit "$TAG" --repo Moho-Chat/nobilis --notes-file "$WORK/nobilis-notes.md"
gh release upload "$TAG" --repo Moho-Chat/nobilis "$WORK"/nobilis/* --clobber
else
gh release create "$TAG" --repo Moho-Chat/nobilis --verify-tag --title "nobilis $VERSION" \
--notes-file "$WORK/nobilis-notes.md" "${NOBILIS_FLAGS[@]}" "$WORK"/nobilis/*
fi
echo " GitHub Moho-Chat/nobilis $TAG"
if [ -n "$KEEP" ]; then
mkdir -p "$KEEP"
cp "$WORK/nobilis-notes.md" "$KEEP/"
cp -r "$WORK/nobilis" "$KEEP/"
fi