Packaging: containerised CI, Flatpak/AppImage, bundled simd, licence notices, and release-please (#53)
This commit is contained in:
Executable
+75
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
# Collect licence and copyright information for everything an AppImage bundles.
|
||||
#
|
||||
# usage: tools/appimage-collect-licenses.sh <AppDir>
|
||||
#
|
||||
# A .deb declares only what it ships, because its dependencies remain separate
|
||||
# packages carrying their own copyright files. An AppImage carries those
|
||||
# libraries inside it, so their notices have to travel with it -- and most of
|
||||
# them here are LGPL (GTK, glib, pango and friends), where the obligation also
|
||||
# covers saying where the corresponding source can be had.
|
||||
#
|
||||
# The mapping is mechanical rather than researched: every bundled library came
|
||||
# from a Debian/Ubuntu package on the build host, so dpkg can name it, and the
|
||||
# archive already holds a copyright file for each. Run this after linuxdeploy
|
||||
# has populated the AppDir and before it packages the image.
|
||||
set -euo pipefail
|
||||
|
||||
APPDIR="${1:?AppDir path}"
|
||||
DOCDIR="$APPDIR/usr/share/doc"
|
||||
MANIFEST="$DOCDIR/BUNDLED-LIBRARIES.txt"
|
||||
|
||||
mkdir -p "$DOCDIR"
|
||||
|
||||
{
|
||||
echo "Libraries bundled in this AppImage"
|
||||
echo "=================================="
|
||||
echo
|
||||
echo "Each library below was taken from the Debian/Ubuntu package named"
|
||||
echo "beside it on the build host. That package's copyright file is included"
|
||||
echo "under usr/share/doc/<package>/copyright in this image."
|
||||
echo
|
||||
echo "The corresponding source for any of them can be obtained with:"
|
||||
echo " apt-get source <package>=<version>"
|
||||
echo "from the distribution and release recorded below."
|
||||
echo
|
||||
echo "Build host: $( (. /etc/os-release && echo "$PRETTY_NAME") 2>/dev/null || echo unknown)"
|
||||
echo
|
||||
printf '%-44s %-34s %s\n' "LIBRARY" "PACKAGE" "VERSION"
|
||||
} > "$MANIFEST"
|
||||
|
||||
found=0
|
||||
unowned=0
|
||||
|
||||
while IFS= read -r so; do
|
||||
base="$(basename "$so")"
|
||||
pkg=""
|
||||
# Try the usual multiarch location first, then fall back to a name search.
|
||||
for candidate in "/usr/lib/x86_64-linux-gnu/$base" "/lib/x86_64-linux-gnu/$base" "/usr/lib/$base"; do
|
||||
pkg="$(dpkg -S "$candidate" 2>/dev/null | head -1 | cut -d: -f1 || true)"
|
||||
[ -n "$pkg" ] && break
|
||||
done
|
||||
if [ -z "$pkg" ]; then
|
||||
pkg="$(dpkg -S "$base" 2>/dev/null | head -1 | cut -d: -f1 || true)"
|
||||
fi
|
||||
|
||||
if [ -n "$pkg" ]; then
|
||||
ver="$(dpkg-query -W -f='${Version}' "$pkg" 2>/dev/null || echo unknown)"
|
||||
printf '%-44s %-34s %s\n' "$base" "$pkg" "$ver" >> "$MANIFEST"
|
||||
if [ -f "/usr/share/doc/$pkg/copyright" ] && [ ! -f "$DOCDIR/$pkg/copyright" ]; then
|
||||
install -Dm644 "/usr/share/doc/$pkg/copyright" "$DOCDIR/$pkg/copyright"
|
||||
fi
|
||||
found=$((found + 1))
|
||||
else
|
||||
# Built by this job rather than installed from a package -- its licence is
|
||||
# collected separately, from its own source tree.
|
||||
printf '%-44s %-34s %s\n' "$base" "(built from source in this job)" "-" >> "$MANIFEST"
|
||||
unowned=$((unowned + 1))
|
||||
fi
|
||||
done < <(find "$APPDIR" -name '*.so*' -type f | sort)
|
||||
|
||||
echo >> "$MANIFEST"
|
||||
echo "$found libraries from distribution packages, $unowned built in this job." >> "$MANIFEST"
|
||||
|
||||
echo "collected copyright for $found bundled libraries ($unowned built here)"
|
||||
echo "manifest: $MANIFEST"
|
||||
@@ -5,4 +5,4 @@ Priority: optional
|
||||
Architecture: amd64
|
||||
Maintainer: Paul Jones <paul@spacefreak18.xyz>
|
||||
Description: Racing Simulator Device Manager
|
||||
Depends: libpulse0,libconfig11,libargtable2-0,liblua5.4-0,libuv1t64,libserialport0,libxml2,libxdg-basedir1,libhidapi-hidraw0,libgtk-3-0t64,libcurl4t64,libglu1-mesa
|
||||
Depends: libpulse0,libconfig11,libargtable2-0,liblua5.4-0,libuv1t64,libserialport0,libxml2-16,libxdg-basedir1,libhidapi-hidraw0,libgtk-3-0t64,libcurl4t64,libglu1-mesa
|
||||
|
||||
@@ -5,4 +5,4 @@ Priority: optional
|
||||
Architecture: amd64
|
||||
Maintainer: Paul Jones <paul@spacefreak18.xyz>
|
||||
Description: Racing Simulator Device Manager
|
||||
Depends: libpulse0,libconfig9,libargtable2-0,liblua5.4-0,libuv1,libserialport0,libxml2,libxdg-basedir1,libhidapi-hidraw0,libglu1-mesa,libcurl4,libgtk-3-0
|
||||
Depends: libpulse0,libconfig11,libargtable2-0,liblua5.4-0,libuv1t64,libserialport0,libxml2-16,libxdg-basedir1,libhidapi-hidraw0,libglu1-mesa,libcurl4t64,libgtk-3-0t64
|
||||
|
||||
@@ -15,14 +15,21 @@ Requires: pulseaudio-libs argtable libconfig hidapi libserialport libuv libxdg-b
|
||||
%description
|
||||
A device manager for Racing sims
|
||||
|
||||
# Builds whatever tree has been staged at %{_sourcedir}/monocoque, cloning it
|
||||
# from upstream master only if nothing is staged. The unconditional clone this
|
||||
# replaced meant an rpm's contents tracked master rather than the tag being
|
||||
# built -- so a fix on the branch being released was absent from its own
|
||||
# release. CI stages the checked-out tree; a bare `rpmbuild -ba` on a
|
||||
# workstation still works exactly as before.
|
||||
%prep
|
||||
rm -rf $RPM_BUILD_DIR/monocoque
|
||||
rm -rf $RPM_SOURCE_DIR/monocoque
|
||||
cd $RPM_SOURCE_DIR
|
||||
git clone https://github.com/spacefreak18/monocoque
|
||||
cd monocoque
|
||||
git submodule update --init --recursive
|
||||
cd ..
|
||||
if [ ! -d $RPM_SOURCE_DIR/monocoque ]; then
|
||||
cd $RPM_SOURCE_DIR
|
||||
git clone https://github.com/spacefreak18/monocoque
|
||||
cd monocoque
|
||||
git submodule update --init --recursive
|
||||
cd ..
|
||||
fi
|
||||
cp -r $RPM_SOURCE_DIR/monocoque $RPM_BUILD_DIR/
|
||||
|
||||
%build
|
||||
|
||||
Executable
+59
@@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate a third-party notices file from the Flatpak manifest.
|
||||
|
||||
A .deb lists only what it actually ships, because its dependencies are separate
|
||||
packages carrying their own copyright files. A Flatpak or AppImage distributes
|
||||
those libraries itself, so the notices have to travel with the artifact -- and
|
||||
for the LGPL ones (libconfig, argtable2, libserialport, orcania, yder) that
|
||||
includes saying where the corresponding source can be obtained.
|
||||
|
||||
The manifest already pins every dependency by URL and sha256, which is exactly
|
||||
that information, so this is generated from it rather than maintained by hand
|
||||
where it would drift.
|
||||
"""
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
manifest = Path(sys.argv[1] if len(sys.argv) > 1
|
||||
else "flatpak/io.github.spacefreak18.monocoque.yml")
|
||||
text = manifest.read_text()
|
||||
|
||||
entries, name = [], None
|
||||
for line in text.splitlines():
|
||||
m = re.match(r"^ - name: (\S+)", line)
|
||||
if m:
|
||||
name = m.group(1)
|
||||
entries.append({"name": name, "url": None, "sha256": None, "commit": None, "tag": None})
|
||||
elif entries:
|
||||
for key in ("url", "sha256", "commit", "tag"):
|
||||
k = re.match(rf"^\s+{key}: (\S+)", line)
|
||||
if k and entries[-1][key] is None:
|
||||
entries[-1][key] = k.group(1)
|
||||
|
||||
out = [
|
||||
"# Third-party notices",
|
||||
"",
|
||||
"This package bundles the libraries below. Each one's own licence text is",
|
||||
"installed alongside it under `/app/share/licenses/<name>/`.",
|
||||
"",
|
||||
"Where a bundled library is under the LGPL, the corresponding source is the",
|
||||
"exact archive listed here, identified by URL and SHA-256; the same version",
|
||||
"can be rebuilt from it, and the Flatpak links these libraries dynamically.",
|
||||
"",
|
||||
"| Component | Source | Checksum / revision |",
|
||||
"|---|---|---|",
|
||||
]
|
||||
for e in entries:
|
||||
if not e["url"]:
|
||||
continue
|
||||
rev = e["sha256"] or e["commit"] or e["tag"] or ""
|
||||
out.append(f"| {e['name']} | {e['url']} | `{rev[:16]}{'…' if len(rev) > 16 else ''}` |")
|
||||
|
||||
out += [
|
||||
"",
|
||||
"Generated by tools/generate-third-party-notices.py from the Flatpak",
|
||||
"manifest -- do not edit by hand.",
|
||||
"",
|
||||
]
|
||||
print("\n".join(out))
|
||||
@@ -3,7 +3,7 @@ Version=1.0
|
||||
Type=Application
|
||||
Name=Monocoque
|
||||
Comment=Launch Monocoque
|
||||
Exec=/usr/bin/gmonocoque
|
||||
Exec=gmonocoque
|
||||
Icon=monocoque
|
||||
Terminal=false
|
||||
Categories=Game;Development;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100%" height="100%">
|
||||
<!-- Square Flatpak icon canvas wrapping the real monocoque.svg artwork
|
||||
(fetched from https://repo.spacefreak18.xyz/monocoque/icons/monocoque.svg,
|
||||
viewBox 0 0 100 50), vertically centered via translate(0,25) rather
|
||||
than stretched. Flatpak's export step requires square icons and
|
||||
appstreamcli additionally requires any desktop-application to have
|
||||
one at all, confirmed via two failed real CI runs. -->
|
||||
<g transform="translate(0,25)">
|
||||
<!-- Main Body / Chassis -->
|
||||
<path d="M 25 28 C 35 28, 40 22, 55 22 L 72 24 C 76 24, 80 28, 85 28 L 85 34 L 25 34 Z" fill="#E10600" />
|
||||
|
||||
<!-- Nose Cone -->
|
||||
<path d="M 25 28 L 12 30 C 10 30.5, 10 32.5, 12 33 L 25 34 Z" fill="#C00500" />
|
||||
|
||||
<!-- Front Wing -->
|
||||
<rect x="5" y="31" width="10" height="4" rx="1" fill="#1A1A1A" />
|
||||
<path d="M 12 31 L 12 35" stroke="#FFFFFF" stroke-width="1" />
|
||||
|
||||
<!-- Rear Wing -->
|
||||
<path d="M 82 28 L 84 15 L 92 15 L 90 28 Z" fill="#1A1A1A" />
|
||||
<rect x="80" y="13" width="14" height="4" rx="0.5" fill="#1A1A1A" />
|
||||
|
||||
<!-- Engine Cover / Airbox Intake -->
|
||||
<path d="M 58 22 C 58 16, 64 16, 66 16 L 70 24 Z" fill="#E10600" />
|
||||
<ellipse cx="61" cy="19" rx="2" ry="1.5" fill="#1A1A1A" />
|
||||
|
||||
<!-- Cockpit / Driver Helmet -->
|
||||
<path d="M 48 23 C 48 20, 54 20, 54 23 Z" fill="#1A1A1A" />
|
||||
<circle cx="52" cy="19" r="2.5" fill="#FFFFFF" />
|
||||
<path d="M 51.5 17.5 L 54.5 18.5 L 53.5 20.5 L 51.5 19.5 Z" fill="#1A1A1A" /> <!-- Visor -->
|
||||
|
||||
<!-- Bargeboard / Sidepod Detail -->
|
||||
<path d="M 38 27 L 55 25 L 58 34 L 36 34 Z" fill="#B00400" />
|
||||
|
||||
<!-- Wheels (Tires & Rims) -->
|
||||
<!-- Rear Wheel -->
|
||||
<circle cx="78" cy="32" r="11" fill="#1A1A1A" />
|
||||
<circle cx="78" cy="32" r="5" fill="#4A4A4A" />
|
||||
<circle cx="78" cy="32" r="2" fill="#D4AF37" />
|
||||
|
||||
<!-- Front Wheel -->
|
||||
<circle cx="22" cy="33" r="9" fill="#1A1A1A" />
|
||||
<circle cx="22" cy="33" r="4.2" fill="#4A4A4A" />
|
||||
<circle cx="22" cy="33" r="1.8" fill="#D4AF37" />
|
||||
|
||||
<!-- Ground Shadow -->
|
||||
<ellipse cx="50" cy="44" rx="42" ry="2" fill="#000000" fill-opacity="0.2" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
Reference in New Issue
Block a user