From 13301087add97ac5bd0968d86584689ee6154e55 Mon Sep 17 00:00:00 2001 From: Amir Husayn Panahifar Date: Wed, 15 Jul 2026 11:54:20 +0330 Subject: [PATCH] feat: debian packaging, release pipeline, and build scripts - debian/postinst: create daena user, directories, reload systemd - debian/prerm: stop and disable service on removal - scripts/build-deb.sh: build self-contained .deb with all deps - CI: add release job triggered by v* tags, builds wheel + .deb, uploads both to GitHub Release --- .github/workflows/ci.yml | 38 ++++++++++++++++++++ debian/postinst | 21 +++++++++++ debian/prerm | 11 ++++++ scripts/build-deb.sh | 77 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+) create mode 100644 debian/postinst create mode 100644 debian/prerm create mode 100755 scripts/build-deb.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aad5be5..53a3dc3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,6 +3,7 @@ name: CI on: push: branches: [main, dev] + tags: ["v*"] pull_request: branches: [main] @@ -36,3 +37,40 @@ jobs: run: uv sync --extra dev - name: Run tests run: uv run pytest tests/ -v + + release: + if: startsWith(github.ref, 'refs/tags/v') + needs: [lint, test] + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.13" + + - name: Install uv + run: pip install uv --no-cache-dir + + - name: Build wheel + run: uv build + + - name: Install system deps + run: sudo apt-get update -qq && sudo apt-get install -y -qq fakeroot dpkg-dev + + - name: Build .deb package + run: bash scripts/build-deb.sh "${GITHUB_REF_NAME#v}" + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + name: "daena ${{ github.ref_name }}" + body: | + ## daena ${{ github.ref_name }} + + See `CHANGELOG.md` for details. + files: | + dist/*.whl + dist/*.deb + fail_on_unmatched_files: true diff --git a/debian/postinst b/debian/postinst new file mode 100644 index 0000000..e647d6f --- /dev/null +++ b/debian/postinst @@ -0,0 +1,21 @@ +#!/bin/sh +set -e + +case "$1" in + configure) + # Create daena user if it doesn't exist + if ! getent passwd daena >/dev/null 2>&1; then + adduser --system --group --no-create-home --home /var/lib/daena \ + --shell /sbin/nologin daena + fi + + # Create required directories + mkdir -p /var/lib/daena /var/log/daena /run/daena /etc/daena + chown daena:daena /var/lib/daena /var/log/daena /run/daena + + # Reload systemd + if command -v systemctl >/dev/null 2>&1; then + systemctl daemon-reload >/dev/null 2>&1 || true + fi + ;; +esac diff --git a/debian/prerm b/debian/prerm new file mode 100644 index 0000000..8641e83 --- /dev/null +++ b/debian/prerm @@ -0,0 +1,11 @@ +#!/bin/sh +set -e + +case "$1" in + remove|upgrade|deconfigure) + if command -v systemctl >/dev/null 2>&1; then + systemctl stop daena.service >/dev/null 2>&1 || true + systemctl disable daena.service >/dev/null 2>&1 || true + fi + ;; +esac diff --git a/scripts/build-deb.sh b/scripts/build-deb.sh new file mode 100755 index 0000000..20c46bc --- /dev/null +++ b/scripts/build-deb.sh @@ -0,0 +1,77 @@ +#!/usr/bin/env bash +set -euo pipefail + +VERSION="${1:-0.1.0}" +PACKAGE="daena_${VERSION}_all" +BUILDROOT="/tmp/build/${PACKAGE}" +DISTDIR="dist" + +pip install uv --quiet +uv sync --no-dev --frozen --quiet + +# Create package directory structure +rm -rf "${BUILDROOT}" +mkdir -p "${BUILDROOT}/DEBIAN" +mkdir -p "${BUILDROOT}/usr/bin" +mkdir -p "${BUILDROOT}/usr/lib/python3/dist-packages" +mkdir -p "${BUILDROOT}/lib/systemd/system" +mkdir -p "${BUILDROOT}/etc/daena" + +# Install the package and all dependencies into dist-packages +uv pip install --python "$(which python3)" \ + --target="${BUILDROOT}/usr/lib/python3/dist-packages" \ + --no-compile \ + . 2>/dev/null + +# Install script entry points +cat > "${BUILDROOT}/usr/bin/daena" << 'SCRIPT' +#!/usr/bin/env python3 +from daena.cli.main import app +app() +SCRIPT +chmod +x "${BUILDROOT}/usr/bin/daena" + +cat > "${BUILDROOT}/usr/bin/daena-serve" << 'SCRIPT' +#!/usr/bin/env python3 +from daena.app import serve +serve() +SCRIPT +chmod +x "${BUILDROOT}/usr/bin/daena-serve" + +# Install systemd service +cp deploy/daena.service "${BUILDROOT}/lib/systemd/system/daena.service" + +# Install default config +cp config/daena.yaml "${BUILDROOT}/etc/daena/daena.yaml" + +# Install maintainer scripts +cp debian/postinst "${BUILDROOT}/DEBIAN/postinst" +cp debian/prerm "${BUILDROOT}/DEBIAN/prerm" +chmod 755 "${BUILDROOT}/DEBIAN/postinst" "${BUILDROOT}/DEBIAN/prerm" + +# Compute installed size (in KB) +INSTALLED_SIZE=$(du -sk "${BUILDROOT}" | cut -f1) + +# Generate control file +cat > "${BUILDROOT}/DEBIAN/control" << CONTROL +Package: daena +Version: ${VERSION} +Section: utils +Priority: optional +Architecture: all +Maintainer: Amir Husayn Panahifar +Installed-Size: ${INSTALLED_SIZE} +Depends: python3 (>= 3.13), python3-pip, liblmdb0 +Recommends: systemd +Description: Collect, buffer, and forward logs and events + Daena is a modular, extensible Linux service that collects + logs, events, and telemetry from pluggable sources, processes + them through a configurable pipeline, persists data locally + in LMDB, and forwards records reliably to remote sinks. +CONTROL + +# Build .deb +mkdir -p "${DISTDIR}" +fakeroot dpkg-deb --build "${BUILDROOT}" "${DISTDIR}/${PACKAGE}.deb" + +echo "Built: ${DISTDIR}/${PACKAGE}.deb"