From eaf99e7f5b70cb8bddb8d2f614b47e8f1aa586d6 Mon Sep 17 00:00:00 2001 From: Vladimir Burdukov Date: Fri, 15 May 2026 23:48:15 +0300 Subject: [PATCH] Implemented deb packaging and deployment --- .github/workflows/deploy.yml | 31 +++++-- .github/workflows/pr.yml | 61 +++++++++++++ packaging/deb/env/elisa.env.example | 7 ++ packaging/deb/env/elisheba.env.example | 5 ++ packaging/deb/env/isabel.env.example | 5 ++ packaging/deb/systemd/elisa.service | 17 ++++ packaging/deb/systemd/elisheba.service | 17 ++++ packaging/deb/systemd/isabel.service | 19 ++++ scripts/package_deb.sh | 120 +++++++++++++++++++++++++ 9 files changed, 273 insertions(+), 9 deletions(-) create mode 100644 packaging/deb/env/elisa.env.example create mode 100644 packaging/deb/env/elisheba.env.example create mode 100644 packaging/deb/env/isabel.env.example create mode 100644 packaging/deb/systemd/elisa.service create mode 100644 packaging/deb/systemd/elisheba.service create mode 100644 packaging/deb/systemd/isabel.service create mode 100755 scripts/package_deb.sh diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ccd4951..3979303 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -82,12 +82,24 @@ jobs: docker run --rm -v "$PWD/build:/build" ghcr.io/chipp/${{ matrix.binary }}:latest \ cp /root/${{ matrix.binary }} /build/${{ matrix.binary }} - - name: Archive arm64 artifact + - name: Build deb package + if: matrix.mode == 'binary' + run: | + scripts/package_deb.sh \ + ${{ matrix.binary }} \ + 0.1.${{ github.run_number }} \ + build/${{ matrix.binary }} \ + build + + dpkg-deb --info build/${{ matrix.binary }}_0.1.${{ github.run_number }}_arm64.deb + dpkg-deb --contents build/${{ matrix.binary }}_0.1.${{ github.run_number }}_arm64.deb + + - name: Archive arm64 deb artifact if: matrix.mode == 'binary' uses: actions/upload-artifact@v4 with: name: ${{ matrix.binary }} - path: build/${{ matrix.binary }} + path: build/${{ matrix.binary }}_*.deb retention-days: 1 deploy: @@ -150,12 +162,13 @@ jobs: export TUNNEL_SERVICE_TOKEN_ID=${{ secrets.TUNNEL_SERVICE_TOKEN_ID }} export TUNNEL_SERVICE_TOKEN_SECRET=${{ secrets.TUNNEL_SERVICE_TOKEN_SECRET }} - ssh chipp@pi4.chipp.dev "sudo service elisa stop" - ssh chipp@pi4.chipp.dev "sudo service elisheba stop" - ssh chipp@pi4.chipp.dev "sudo service isabel stop" + mkdir -p lisa-deploy + cp ./*.deb lisa-deploy/ + + ssh chipp@pi4.chipp.dev "mkdir -p /tmp/lisa-deploy" + rsync -av --delete lisa-deploy/ chipp@pi4.chipp.dev:/tmp/lisa-deploy/ - scp elisa elisheba isabel chipp@pi4.chipp.dev:/usr/local/bin + ssh chipp@pi4.chipp.dev "sudo systemctl stop elisa elisheba isabel || true" + ssh chipp@pi4.chipp.dev "sudo dpkg -i /tmp/lisa-deploy/*.deb" - ssh chipp@pi4.chipp.dev "sudo service elisa start" - ssh chipp@pi4.chipp.dev "sudo service elisheba start" - ssh chipp@pi4.chipp.dev "sudo service isabel start" + ssh chipp@pi4.chipp.dev "sudo systemctl start elisa elisheba isabel" diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 0520a8b..aac2911 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -25,6 +25,67 @@ jobs: - name: Check formatting run: cargo fmt --all -- --check + deb: + runs-on: ubuntu-24.04-arm + + strategy: + matrix: + binary: + - elisa + - elisheba + - isabel + + steps: + - uses: actions/checkout@v4 + + - name: Verify packaging script syntax + run: bash -n scripts/package_deb.sh + + - name: Build deb package + run: | + mkdir -p target/deb-check build + printf '#!/bin/sh\nexit 0\n' > target/deb-check/${{ matrix.binary }} + chmod 755 target/deb-check/${{ matrix.binary }} + + scripts/package_deb.sh \ + ${{ matrix.binary }} \ + 0.1.0 \ + target/deb-check/${{ matrix.binary }} \ + build + + - name: Verify deb package contents + run: | + package=build/${{ matrix.binary }}_0.1.0_arm64.deb + + dpkg-deb --info "$package" + dpkg-deb --contents "$package" + + dpkg-deb --field "$package" Package | grep -Fx ${{ matrix.binary }} + dpkg-deb --field "$package" Version | grep -Fx 0.1.0 + dpkg-deb --field "$package" Architecture | grep -Fx arm64 + dpkg-deb --contents "$package" | grep -F ./usr/bin/${{ matrix.binary }} + dpkg-deb --contents "$package" | grep -F ./lib/systemd/system/${{ matrix.binary }}.service + dpkg-deb --contents "$package" | grep -F ./etc/lisa/${{ matrix.binary }}.env.example + + rm -rf target/deb-extract + mkdir -p target/deb-extract + dpkg-deb --extract "$package" target/deb-extract + grep -Fx User=${{ matrix.binary }} target/deb-extract/lib/systemd/system/${{ matrix.binary }}.service + grep -Fx Group=${{ matrix.binary }} target/deb-extract/lib/systemd/system/${{ matrix.binary }}.service + + - name: Verify architecture override + if: matrix.binary == 'elisa' + run: | + ARCH=amd64 scripts/package_deb.sh \ + ${{ matrix.binary }} \ + 0.1.0 \ + target/deb-check/${{ matrix.binary }} \ + build + + package=build/${{ matrix.binary }}_0.1.0_amd64.deb + + dpkg-deb --field "$package" Architecture | grep -Fx amd64 + test: runs-on: ubuntu-24.04-arm diff --git a/packaging/deb/env/elisa.env.example b/packaging/deb/env/elisa.env.example new file mode 100644 index 0000000..be1e007 --- /dev/null +++ b/packaging/deb/env/elisa.env.example @@ -0,0 +1,7 @@ +RUST_LOG=elisa=debug,roborock=debug,info +MQTT_ADDRESS=mqtts://lisa.chipp.dev:8880 +MQTT_USER=elisa +MQTT_PASS= +ROBOROCK_IP=10.0.1.150 +ROBOROCK_DUID= +ROBOROCK_LOCAL_KEY= diff --git a/packaging/deb/env/elisheba.env.example b/packaging/deb/env/elisheba.env.example new file mode 100644 index 0000000..51fd2ea --- /dev/null +++ b/packaging/deb/env/elisheba.env.example @@ -0,0 +1,5 @@ +RUST_LOG=elisheba=debug,sonoff=debug,info +MQTT_ADDRESS=mqtts://lisa.chipp.dev:8880 +MQTT_USER=elisheba +MQTT_PASS= +KEYS= diff --git a/packaging/deb/env/isabel.env.example b/packaging/deb/env/isabel.env.example new file mode 100644 index 0000000..8c552a2 --- /dev/null +++ b/packaging/deb/env/isabel.env.example @@ -0,0 +1,5 @@ +RUST_LOG=isabel=debug,info +MQTT_ADDRESS=mqtts://lisa.chipp.dev:8880 +MQTT_USER=isabel +MQTT_PASS= +DB_PATH=/var/lib/lisa/isabel/isabel.db diff --git a/packaging/deb/systemd/elisa.service b/packaging/deb/systemd/elisa.service new file mode 100644 index 0000000..9fd057c --- /dev/null +++ b/packaging/deb/systemd/elisa.service @@ -0,0 +1,17 @@ +[Unit] +Description=Lisa Roborock gateway +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +EnvironmentFile=/etc/lisa/elisa.env +ExecStart=/usr/bin/elisa +WorkingDirectory=/var/lib/lisa/elisa +Restart=always +RestartSec=5 +User=elisa +Group=elisa + +[Install] +WantedBy=multi-user.target diff --git a/packaging/deb/systemd/elisheba.service b/packaging/deb/systemd/elisheba.service new file mode 100644 index 0000000..2ed51f1 --- /dev/null +++ b/packaging/deb/systemd/elisheba.service @@ -0,0 +1,17 @@ +[Unit] +Description=Lisa Sonoff gateway +After=network-online.target +Wants=network-online.target + +[Service] +Type=simple +EnvironmentFile=/etc/lisa/elisheba.env +ExecStart=/usr/bin/elisheba +WorkingDirectory=/var/lib/lisa/elisheba +Restart=always +RestartSec=5 +User=elisheba +Group=elisheba + +[Install] +WantedBy=multi-user.target diff --git a/packaging/deb/systemd/isabel.service b/packaging/deb/systemd/isabel.service new file mode 100644 index 0000000..ea3094d --- /dev/null +++ b/packaging/deb/systemd/isabel.service @@ -0,0 +1,19 @@ +[Unit] +Description=Lisa Bluetooth temperature gateway +After=network-online.target bluetooth.service +Wants=network-online.target bluetooth.service + +[Service] +Type=simple +EnvironmentFile=/etc/lisa/isabel.env +ExecStart=/usr/bin/isabel +WorkingDirectory=/var/lib/lisa/isabel +Restart=always +RestartSec=5 +User=isabel +Group=isabel +AmbientCapabilities=CAP_NET_ADMIN CAP_NET_RAW +CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_RAW + +[Install] +WantedBy=multi-user.target diff --git a/scripts/package_deb.sh b/scripts/package_deb.sh new file mode 100755 index 0000000..ba7a8be --- /dev/null +++ b/scripts/package_deb.sh @@ -0,0 +1,120 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [ "$#" -ne 4 ]; then + echo "usage: $0 " >&2 + exit 64 +fi + +service="$1" +version="$2" +binary_path="$3" +output_dir="$4" +arch="${ARCH:-arm64}" + +case "$service" in + elisa|elisheba|isabel) ;; + *) + echo "unsupported service: $service" >&2 + exit 64 + ;; +esac + +if [ ! -f "$binary_path" ]; then + echo "binary not found: $binary_path" >&2 + exit 66 +fi + +depends="ca-certificates, systemd" +if [ "$service" = "isabel" ]; then + depends="$depends, bluez" +fi + +script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +repo_dir="$(cd "$script_dir/.." && pwd)" +package_root="$(mktemp -d)" +trap 'rm -rf "$package_root"' EXIT + +install -d \ + "$package_root/DEBIAN" \ + "$package_root/usr/bin" \ + "$package_root/lib/systemd/system" \ + "$package_root/etc/lisa" + +installed_size="$(du -k "$binary_path" | awk '{ print $1 }')" + +cat > "$package_root/DEBIAN/control" < "$package_root/DEBIAN/postinst" </dev/null 2>&1; then + useradd \ + --system \ + --user-group \ + --home-dir /var/lib/lisa/$service \ + --no-create-home \ + --shell /usr/sbin/nologin \ + $service +fi + +install -d -m 755 -o $service -g $service /var/lib/lisa/$service + +if command -v systemctl >/dev/null 2>&1; then + systemctl daemon-reload || true + systemctl enable $service.service || true + + if [ -f /etc/lisa/$service.env ]; then + systemctl restart $service.service || true + fi +fi +EOF + +cat > "$package_root/DEBIAN/prerm" </dev/null 2>&1; then + systemctl stop $service.service || true + fi +fi +EOF + +cat > "$package_root/DEBIAN/postrm" </dev/null 2>&1; then + systemctl daemon-reload || true +fi +EOF + +chmod 755 \ + "$package_root/DEBIAN/postinst" \ + "$package_root/DEBIAN/prerm" \ + "$package_root/DEBIAN/postrm" + +install -m 755 "$binary_path" "$package_root/usr/bin/$service" +install -m 644 "$repo_dir/packaging/deb/systemd/$service.service" \ + "$package_root/lib/systemd/system/$service.service" +install -m 644 "$repo_dir/packaging/deb/env/$service.env.example" \ + "$package_root/etc/lisa/$service.env.example" + +install -d "$output_dir" +dpkg-deb --build --root-owner-group "$package_root" \ + "$output_dir/${service}_${version}_${arch}.deb"