The release job feeds packages.arasaka.software itself; YoloCICD is gone
Build / Desktop, server and tools (push) Successful in 1m17s

.gitea/scripts/packages.sh signs the rpm with the org secret PACKAGES_SIGNING_KEY,
publishes the deb and rpm into a new snapshot of the repository, signs its metadata and
rewrites SHA256SUMS.txt, on the nuvola runner. Tested against a copy of the live
repository with Debian 13 apt and Fedora 44 dnf.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KizzWs2WQPWN2qgE7G6r8B
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-23 10:38:55 +02:00
1 parent 50eaf7d0b3
commit 599ea2bf84
4 files changed
+116 -14

No files matched your search

+99
View File
@@ -0,0 +1,99 @@
#!/bin/sh
set -eu
version=$1
releases=$(pwd)/releases/$version
root=${PACKAGES_ROOT:-/var/www/packages.arasaka.software}
keep=${PACKAGES_KEEP:-5}
url=https://packages.arasaka.software
fingerprint=F92C166E9B1C13EDD1629E76888DCF969D133FB2
deb=$releases/MeWeb-$version-linux-x64.deb
rpm=$releases/MeWeb-$version-linux-x64.rpm
test -f "$deb"
test -f "$rpm"
exec 9>>"$root/.lock"
flock -w 2700 9
keys=$(mktemp -d)
trap 'rm -rf "$keys"' EXIT
export GNUPGHOME="$keys"
printf '%s\n' "$PACKAGES_SIGNING_KEY" | gpg --batch --quiet --import
gpg --batch --with-colons --list-secret-keys | grep -q "^fpr:::::::::$fingerprint:$"
gpg --batch --armor --export "$fingerprint" > "$keys/public.asc"
rpmsign --define "__gpg /usr/bin/gpg" --define "_gpg_name $fingerprint" --define "_gpg_path $keys" --addsign "$rpm" >/dev/null
rpmkeys --dbpath "$keys/rpmdb" --import "$keys/public.asc"
rpmkeys --dbpath "$keys/rpmdb" -K "$rpm" | grep -q 'digests signatures OK'
full=$(dpkg-deb -f "$deb" Version)
test "$(dpkg-deb -f "$deb" Package)" = meweb
test "${full%-*}" = "$version"
debname=meweb_${full}_$(dpkg-deb -f "$deb" Architecture).deb
rpmname=$(rpm -qp --nosignature --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}.rpm' "$rpm")
test "$(rpm -qp --nosignature --qf '%{NAME} %{VERSION}' "$rpm")" = "meweb $version"
snap=$root/.snap/$(date -u +%Y%m%d%H%M%S)-$version
mkdir -p "$snap/apt/pool/main" "$snap/rpm"
if [ -d "$root/apt/pool/main" ]; then cp -al "$root/apt/pool/main/." "$snap/apt/pool/main/"; fi
if [ -d "$root/rpm" ]; then
for folder in "$root"/rpm/*/; do
[ "$(basename "$folder")" = repodata ] || cp -al "$folder" "$snap/rpm/"
done
fi
mkdir -p "$snap/apt/pool/main/m/meweb" "$snap/rpm/meweb"
rm -f "$snap/apt/pool/main/m/meweb/$debname" "$snap/rpm/meweb/$rpmname"
cp "$deb" "$snap/apt/pool/main/m/meweb/$debname"
cp "$rpm" "$snap/rpm/meweb/$rpmname"
for folder in "$snap/apt/pool/main/m/meweb" "$snap/rpm/meweb"; do
ls "$folder" | sed -E 's/^meweb[_-]([0-9.]+)-.*/\1/' | sort -uV | head -n "-$keep" | while read -r old; do
rm -f "$folder/meweb_$old-"* "$folder/meweb-$old-"*
done
done
binary=$snap/apt/dists/stable/main/binary-amd64
mkdir -p "$binary"
(cd "$snap/apt" && apt-ftparchive packages pool) > "$binary/Packages"
gzip -9nc "$binary/Packages" > "$binary/Packages.gz"
(cd "$snap/apt/dists/stable" && apt-ftparchive \
-o APT::FTPArchive::Release::Origin=Arasaka -o APT::FTPArchive::Release::Label=Arasaka \
-o APT::FTPArchive::Release::Suite=stable -o APT::FTPArchive::Release::Codename=stable \
-o APT::FTPArchive::Release::Architectures=amd64 -o APT::FTPArchive::Release::Components=main \
-o APT::FTPArchive::Release::NotAutomatic=yes -o APT::FTPArchive::Release::ButAutomaticUpgrades=yes \
-o "APT::FTPArchive::Release::Description=Arasaka packages" release .) > "$keys/Release"
mv "$keys/Release" "$snap/apt/dists/stable/Release"
gpg --batch --yes --local-user "$fingerprint" --clearsign -o "$snap/apt/dists/stable/InRelease" "$snap/apt/dists/stable/Release"
gpg --batch --yes --local-user "$fingerprint" --armor --detach-sign -o "$snap/apt/dists/stable/Release.gpg" "$snap/apt/dists/stable/Release"
createrepo_c --quiet "$snap/rpm"
repodata=$snap/rpm/repodata
gpg --batch --yes --local-user "$fingerprint" --armor --detach-sign -o "$repodata/repomd.xml.asc" "$repodata/repomd.xml"
cp "$keys/public.asc" "$repodata/repomd.xml.key"
if [ -f "$root/rpm/repodata/repomd.xml" ]; then
grep -o 'repodata/[^"]*' "$root/rpm/repodata/repomd.xml" | while read -r href; do
[ -e "$snap/rpm/$href" ] || cp "$root/rpm/$href" "$snap/rpm/$href"
done
fi
chmod -R u=rwX,go=rX "$snap"
for part in apt rpm; do
ln -sfn ".snap/$(basename "$snap")/$part" "$root/$part.new"
mv -T -f "$root/$part.new" "$root/$part"
done
ls -1d "$root"/.snap/* | sort | head -n -3 | while read -r old; do
find "$old" -maxdepth 0 -mmin +1440 -exec rm -rf {} +
done
echo "published $debname and $rpmname in $root"
(cd "$releases" && for file in $(ls | LC_ALL=C sort); do [ "$file" = SHA256SUMS.txt ] || sha256sum "$file"; done) > "$keys/sums"
mv "$keys/sums" "$releases/SHA256SUMS.txt"
if [ "$root" = /var/www/packages.arasaka.software ]; then
curl -fsS "$url/apt/dists/stable/main/binary-amd64/Packages" | grep -qx "Version: $full"
curl -fsS "$url/apt/dists/stable/InRelease" > "$keys/InRelease"
gpg --batch --quiet --verify "$keys/InRelease"
curl -fsS "$url/rpm/repodata/repomd.xml" > "$keys/repomd.xml"
curl -fsS "$url/rpm/repodata/repomd.xml.asc" > "$keys/repomd.xml.asc"
gpg --batch --quiet --verify "$keys/repomd.xml.asc" "$keys/repomd.xml"
curl -fsSI "$url/rpm/meweb/$rpmname" > /dev/null
echo "live at $url: meweb $version"
fi
+2 -6
View File
@@ -46,12 +46,8 @@ jobs:
- name: The deb and rpm on packages.arasaka.software, the rpm signed - name: The deb and rpm on packages.arasaka.software, the rpm signed
if: ${{ github.ref_type == 'tag' }} if: ${{ github.ref_type == 'tag' }}
env: env:
YOLO_TOKEN: ${{ secrets.YOLO_TOKEN }} PACKAGES_SIGNING_KEY: ${{ secrets.PACKAGES_SIGNING_KEY }}
YOLO_GITEA: http://localhost:3000 run: .gitea/scripts/packages.sh "$VERSION"
YOLO_MIN: "0.1.0"
run: |
yolo repo submit --project meweb --version "$VERSION" --replace-signed "releases/$VERSION/MeWeb-$VERSION-linux-x64.deb" "releases/$VERSION/MeWeb-$VERSION-linux-x64.rpm"
yolo sums "releases/$VERSION"
- name: Publish the release - name: Publish the release
if: ${{ github.ref_type == 'tag' || inputs.publish == 'true' }} if: ${{ github.ref_type == 'tag' || inputs.publish == 'true' }}
+14 -7
View File
@@ -143,13 +143,20 @@ The Android release key: alias `meweb`, certificate SHA-256
the network and the block without the publisher's server. A change to any knowledge file's format bumps the network and the block without the publisher's server. A change to any knowledge file's format bumps
`KnowledgeFeeder.Format` and the `"format":N` that `wait-knowledge.sh` waits for: the feeder rebuilds only when a `KnowledgeFeeder.Format` and the `"format":N` that `wait-knowledge.sh` waits for: the feeder rebuilds only when a
source changes or the format differs, and a release must not embed the previous build. source changes or the format differs, and a release must not embed the previous build.
- **The deb and rpm reach packages.arasaka.software through YoloCICD.** `release.yml` runs `yolo repo submit - **The deb and rpm reach packages.arasaka.software from this repository's own release job.** On tags,
--replace-signed` on tags (org secret `YOLO_TOKEN`, `yolo` installed on nuvola by YoloCICD): the files go to the `.gitea/scripts/packages.sh` runs on the `nuvola` runner (host mode, user `gitea-runner`, which owns
bot's private inbox, YoloCICD's `publish.yml` checks this run against the tag, signs the rpm, gates on an upgrade `/var/www/packages.arasaka.software`). It imports the org secret `PACKAGES_SIGNING_KEY` into a throwaway
check in containers and publishes; the signed rpm replaces the local one, then `yolo sums` rewrites SHA256SUMS. `GNUPGHOME`, refuses any key but `F92C166E…3FB2`, signs the rpm in place, hard-links the current pool into a new
`packaging/arasaka-repository.sh` is generated (`yolo repo kit --out`, never edited by hand) and is written into `.snap/` folder, adds this version, keeps the newest five, rebuilds and signs the apt (`InRelease`, `Release.gpg`)
both maintainer scripts by `tools/release.cs`; the package owns `/usr/share/arasaka-repository/meweb`, the marker and rpm (`repomd.xml.asc`) metadata, carries over the files the previous `repomd.xml` named so a client mid-refresh
that keeps the repository configured while any Arasaka package is installed. still finds them, swaps the `apt` and `rpm` links, rewrites `SHA256SUMS.txt` for the signed rpm, and checks the live
site. Never copy a package over a pool file: the pools are hard links into older snapshots, so it is `rm` then `cp`.
`PACKAGES_ROOT` and `PACKAGES_KEEP` exist for a test against a copy. YoloCICD, which used to do this, was erased on
23 Oct 2026. `packaging/arasaka-repository.sh` is written into both maintainer scripts by `tools/release.cs`; it is
now maintained here by hand, and any change to a file it writes needs the old content's SHA-256 kept in
`arasaka_repository_known`, or installed copies are treated as edited by hand and left alone. The package owns
`/usr/share/arasaka-repository/meweb`, the marker that keeps the repository configured while any Arasaka package
is installed. The signing key's only copies are that secret and the owner's Nextcloud backup.
- **The server cannot ping**: `NoNewPrivileges` drops `ping`'s file capability and `ping_group_range` is closed, so - **The server cannot ping**: `NoNewPrivileges` drops `ping`'s file capability and `ping_group_range` is closed, so
the trace back to a caller uses `tracepath` (UDP, unprivileged) and keeps only public hops outside `Probe:Refuse`, the trace back to a caller uses `tracepath` (UDP, unprivileged) and keeps only public hops outside `Probe:Refuse`,
so the box's own network never reaches an app. so the box's own network never reaches an app.
+1 -1
View File
@@ -50,7 +50,7 @@ Linux (deb, rpm), Windows, macOS and Android. Builds are published as releases o
On Linux the deb and the rpm add the Arasaka package repository, packages.arasaka.software, when they are installed, On Linux the deb and the rpm add the Arasaka package repository, packages.arasaka.software, when they are installed,
so later versions arrive through the package manager. The rpm is signed with the repository's key; on openSUSE, so later versions arrive through the package manager. The rpm is signed with the repository's key; on openSUSE,
import it first with `sudo rpm --import https://packages.arasaka.software/arasaka.asc`. The script the packages run import it first with `sudo rpm --import https://packages.arasaka.software/arasaka.asc`. The script the packages run
is `packaging/arasaka-repository.sh`, generated by YoloCICD (`yolo repo kit`); it never calls the package manager, is `packaging/arasaka-repository.sh`; it never calls the package manager,
leaves files you edited alone, and removes the repository only when no Arasaka package is left (purge or erase). leaves files you edited alone, and removes the repository only when no Arasaka package is left (purge or erase).
## Privacy ## Privacy