#!/bin/bash set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT" if [[ $# -ne 1 ]]; then echo "Usage: $0 VERSION" exit 1 fi VERSION="$1" if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "Invalid version: $VERSION" echo "Expected MAJOR.MINOR.PATCH, for example 0.1.6" exit 1 fi STAGE="$ROOT/packaging/root" OUTPUT="$ROOT/dist/ekklesia-classroom_${VERSION}_amd64.deb" # Syntax check everything the package ships, by shebang, so this cannot # drift out of date as classroom commands are added. echo "Validating sources" for script in "$ROOT/packaging/debian/postinst" "$ROOT"/scripts/* "$ROOT"/tests/*; do [[ -f "$script" ]] || continue case "$(head -n 1 "$script")" in *python3*) python3 -m py_compile "$script" ;; *bash*|*bin/sh*) bash -n "$script" ;; esac done for module in "$ROOT"/lib/*.py; do [[ -f "$module" ]] || continue python3 -m py_compile "$module" done for policy in "$ROOT"/config/chrome/policies/*/*.json; do [[ -f "$policy" ]] || continue python3 -c 'import json, sys; json.load(open(sys.argv[1]))' "$policy" done find "$ROOT/scripts" "$ROOT/lib" \ -name '__pycache__' -type d -prune -exec rm -rf {} + 2>/dev/null || true for test in "$ROOT"/tests/test-*.sh; do [[ -x "$test" ]] || continue echo "Running $(basename "$test")" "$test" > /dev/null || { echo "Tests failed. Run it directly to see why:" echo " $test" exit 1 } done echo "Building Ekklesia Classroom ${VERSION}" # Always construct the package from clean canonical sources. rm -rf "$STAGE" mkdir -p "$STAGE/DEBIAN" "$ROOT/dist" # Debian package metadata. sed \ "s/^Version: @VERSION@$/Version: ${VERSION}/" \ "$ROOT/packaging/debian/control.template" \ > "$STAGE/DEBIAN/control" install -m755 \ "$ROOT/packaging/debian/postinst" \ "$STAGE/DEBIAN/postinst" # Classroom commands. install -Dm755 \ "$ROOT/scripts/classroom-browser" \ "$STAGE/usr/local/bin/classroom-browser" install -Dm755 \ "$ROOT/scripts/classroom-dvd" \ "$STAGE/usr/local/bin/classroom-dvd" install -Dm755 \ "$ROOT/scripts/classroom-dvd-session" \ "$STAGE/usr/local/bin/classroom-dvd-session" install -Dm755 \ "$ROOT/scripts/classroom-dvd-css-setup" \ "$STAGE/usr/local/bin/classroom-dvd-css-setup" install -Dm755 \ "$ROOT/scripts/classroom-mqtt" \ "$STAGE/usr/local/bin/classroom-mqtt" install -Dm755 \ "$ROOT/scripts/classroom-scale" \ "$STAGE/usr/local/bin/classroom-scale" install -Dm755 \ "$ROOT/scripts/classroom-shutdown" \ "$STAGE/usr/local/bin/classroom-shutdown" install -Dm755 \ "$ROOT/scripts/classroom-chrome-setup" \ "$STAGE/usr/local/bin/classroom-chrome-setup" install -Dm755 \ "$ROOT/scripts/classroom-provision" \ "$STAGE/usr/local/bin/classroom-provision" install -Dm755 \ "$ROOT/scripts/classroom-printer-setup" \ "$STAGE/usr/local/bin/classroom-printer-setup" # Shared helpers imported by the classroom commands. install -Dm644 \ "$ROOT/lib/classroom_config.py" \ "$STAGE/usr/local/lib/ekklesia-classroom/classroom_config.py" install -Dm644 \ "$ROOT/lib/classroom_chrome.py" \ "$STAGE/usr/local/lib/ekklesia-classroom/classroom_chrome.py" install -Dm644 \ "$ROOT/lib/classroom_mqtt.py" \ "$STAGE/usr/local/lib/ekklesia-classroom/classroom_mqtt.py" install -Dm644 \ "$ROOT/lib/classroom_vlc.py" \ "$STAGE/usr/local/lib/ekklesia-classroom/classroom_vlc.py" install -Dm644 \ "$ROOT/config/wallpapers/classroom-calm.png" \ "$STAGE/usr/share/backgrounds/ekklesia/classroom-calm.png" # Chrome enterprise policy: suppress first-run and sign-in nags, and pin # Home to Wonder Ink. Nothing here restricts where teachers can browse. install -Dm644 \ "$ROOT/config/chrome/policies/managed/ekklesia-classroom.json" \ "$STAGE/etc/opt/chrome/policies/managed/ekklesia-classroom.json" install -Dm644 \ "$ROOT/config/chrome/policies/recommended/ekklesia-classroom.json" \ "$STAGE/etc/opt/chrome/policies/recommended/ekklesia-classroom.json" install -Dm755 \ "$ROOT/scripts/ekklesia-classroom-update" \ "$STAGE/usr/local/bin/ekklesia-classroom-update" # System configuration. install -Dm644 \ "$ROOT/config/sddm/ekklesia-classroom.conf" \ "$STAGE/etc/sddm.conf.d/ekklesia-classroom.conf" install -Dm644 \ "$ROOT/systemd/updater/ekklesia-classroom-update.service" \ "$STAGE/etc/systemd/system/ekklesia-classroom-update.service" install -Dm644 \ "$ROOT/systemd/updater/ekklesia-classroom-update.timer" \ "$STAGE/etc/systemd/system/ekklesia-classroom-update.timer" install -Dm644 \ "$ROOT/systemd/provision/ekklesia-classroom-provision.service" \ "$STAGE/etc/systemd/system/ekklesia-classroom-provision.service" install -Dm644 \ "$ROOT/systemd/shutdown/ekklesia-classroom-shutdown.service" \ "$STAGE/etc/systemd/system/ekklesia-classroom-shutdown.service" install -Dm644 \ "$ROOT/systemd/mqtt/ekklesia-classroom-mqtt.service" \ "$STAGE/etc/systemd/system/ekklesia-classroom-mqtt.service" # The classroom desktop. # # Not a shell, and not a daemon: a Plasma session described in files Plasma # already reads. The panel, the window behaviour, the notifications, the # lockdown and the palette are all in here, which is why there is no longer # a dock, a window helper, a notification wrapper or a compositor config in # the list above. # Not /etc/xdg: plasma-workspace already owns files by these names there. # The classroom's directory goes in front of it in XDG_CONFIG_DIRS instead. for setting in kdeglobals kwinrc kwinrulesrc kscreenlockerrc ksmserverrc \ krunnerrc plasmanotifyrc; do install -Dm644 \ "$ROOT/config/plasma/xdg/${setting}" \ "$STAGE/etc/ekklesia-classroom/xdg/${setting}" done install -Dm644 \ "$ROOT/config/environment/90-ekklesia-classroom.conf" \ "$STAGE/etc/environment.d/90-ekklesia-classroom.conf" for scheme in EkklesiaDark EkklesiaLight; do install -Dm644 \ "$ROOT/config/plasma/colors/${scheme}.colors" \ "$STAGE/usr/share/color-schemes/${scheme}.colors" done LOOK="$STAGE/usr/share/plasma/look-and-feel/org.ekklesia.classroom.desktop" install -Dm644 \ "$ROOT/config/plasma/lookandfeel/metadata.json" \ "$LOOK/metadata.json" install -Dm644 \ "$ROOT/config/plasma/lookandfeel/contents/defaults" \ "$LOOK/contents/defaults" install -Dm644 \ "$ROOT/config/plasma/lookandfeel/contents/layouts/org.kde.plasma.desktop-layout.js" \ "$LOOK/contents/layouts/org.kde.plasma.desktop-layout.js" for entry in "$ROOT"/config/plasma/applications/*.desktop; do install -Dm644 "$entry" \ "$STAGE/usr/share/applications/$(basename "$entry")" done # Shadows Chrome's own entry. XDG_DATA_DIRS searches /usr/local/share first, # so the panel matches a Chrome window to this launcher instead of to # Chrome's, and the room gets one button rather than two. for entry in "$ROOT"/config/plasma/applications-local/*.desktop; do install -Dm644 "$entry" \ "$STAGE/usr/local/share/applications/$(basename "$entry")" done install -Dm644 \ "$ROOT/config/plasma/solid/ekklesia-dvd.desktop" \ "$STAGE/usr/share/solid/actions/ekklesia-dvd.desktop" for icon in ekklesia-wonderink ekklesia-parent-call; do install -Dm644 \ "$ROOT/config/icons/${icon}.svg" \ "$STAGE/usr/share/icons/hicolor/scalable/apps/${icon}.svg" done # The panel is the only way a teacher has of getting anywhere. Plasma gives # up restarting it after three crashes in a minute; this does not. install -Dm644 \ "$ROOT/systemd/user/plasma-plasmashell.service.d/ekklesia-classroom.conf" \ "$STAGE/etc/systemd/user/plasma-plasmashell.service.d/ekklesia-classroom.conf" install -Dm644 \ "$ROOT/systemd/user/ekklesia-classroom-audio.service" \ "$STAGE/etc/systemd/user/ekklesia-classroom-audio.service" install -Dm755 \ "$ROOT/scripts/classroom-wonderink" \ "$STAGE/usr/local/bin/classroom-wonderink" install -Dm755 \ "$ROOT/scripts/classroom-audio" \ "$STAGE/usr/local/bin/classroom-audio" install -Dm755 \ "$ROOT/scripts/classroom-theme" \ "$STAGE/usr/local/bin/classroom-theme" install -Dm644 \ "$ROOT/lib/classroom_audio.py" \ "$STAGE/usr/local/lib/ekklesia-classroom/classroom_audio.py" # Still here, and still sway-shaped. # # The DVD control surface and the MQTT notifier were deliberately not # rewritten in this change, because the room's disc playback works and # breaking it to tidy the tree would be a bad trade. classroom-window and # classroom_sway speak sway's IPC, so the DVD player's focus handling is # the one part of the classroom that does NOT yet work on this desktop. # See docs/classroom-v2-experiment.md. install -Dm755 \ "$ROOT/scripts/classroom-window" \ "$STAGE/usr/local/bin/classroom-window" install -Dm755 \ "$ROOT/scripts/classroom-notify" \ "$STAGE/usr/local/bin/classroom-notify" install -Dm755 \ "$ROOT/scripts/classroom-notify-test" \ "$STAGE/usr/local/bin/classroom-notify-test" install -Dm644 \ "$ROOT/lib/classroom_sway.py" \ "$STAGE/usr/local/lib/ekklesia-classroom/classroom_sway.py" install -Dm644 \ "$ROOT/lib/classroom_optical.py" \ "$STAGE/usr/local/lib/ekklesia-classroom/classroom_optical.py" # The DVD overlay draws its own control bar as a layer-shell surface, so it # still needs the icon and stylesheet helpers the dock used to share. install -Dm644 \ "$ROOT/lib/classroom_icons.py" \ "$STAGE/usr/local/lib/ekklesia-classroom/classroom_icons.py" install -Dm644 \ "$ROOT/lib/classroom_style.py" \ "$STAGE/usr/local/lib/ekklesia-classroom/classroom_style.py" install -Dm644 \ "$ROOT/config/icons/dvd.svg" \ "$STAGE/etc/ekklesia-classroom/icons/dvd.svg" # DVD mode control bar. for icon in media-play media-pause chapter-prev chapter-next \ disc-menu eject close; do install -Dm644 \ "$ROOT/config/icons/${icon}.svg" \ "$STAGE/etc/ekklesia-classroom/icons/${icon}.svg" done printf '%s\n' "$VERSION" > "$ROOT/VERSION" install -Dm644 \ "$ROOT/VERSION" \ "$STAGE/usr/local/lib/ekklesia-classroom/VERSION" dpkg-deb \ --root-owner-group \ --build "$STAGE" "$OUTPUT" echo echo "Built:" echo "$OUTPUT" sha256sum "$OUTPUT"