feat: add debian packaging, CI/CD and update script

- Add debian/ packaging for .deb generation
- Add .forgejo/workflows/build.yml for CI/CD (runner label: docker)
- Add scripts/fullupdater and scripts/fullupdater-update
- Remove obsolete install.sh
- Update .gitignore for debian build artifacts
This commit is contained in:
enzo 2026-05-13 00:10:49 +02:00
parent 184b0e6033
commit 57e6b2557b
10 changed files with 281 additions and 30 deletions

View file

@ -0,0 +1,95 @@
name: Build and Release .deb
on:
push:
branches:
- main
jobs:
build-deb:
runs-on: [docker]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # nécessaire pour les tags et le versioning
- name: Determine version
id: version
run: |
set -e
if git describe --tags --exact-match HEAD 2>/dev/null; then
# Le commit actuel est déjà un tag
VERSION=$(git describe --tags --exact-match HEAD | sed 's/^v//')
else
# Incrémente le patch du dernier tag
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
VERSION_BASE=${LAST_TAG#v}
MAJOR=$(echo "$VERSION_BASE" | cut -d. -f1)
MINOR=$(echo "$VERSION_BASE" | cut -d. -f2)
PATCH=$(echo "$VERSION_BASE" | cut -d. -f3)
NEW_PATCH=$((PATCH + 1))
VERSION="${MAJOR}.${MINOR}.${NEW_PATCH}"
# Créer un tag léger pour cette release
git config user.email "ci@geronzi.fr"
git config user.name "Forgejo CI"
git tag -a "v${VERSION}" -m "Release v${VERSION}"
git push origin "v${VERSION}" || true
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Detected version: ${VERSION}"
- name: Update debian changelog
run: |
VERSION=${{ steps.version.outputs.version }}
DATE=$(date -R)
cat > debian/changelog <<EOF
full-updater (${VERSION}) unstable; urgency=medium
* Auto-built release from commit ${GITHUB_SHA}
-- Forgejo CI <ci@geronzi.fr> ${DATE}
EOF
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y debhelper dh-python python3-all python3-venv devscripts
- name: Build .deb package
run: |
dpkg-buildpackage -us -uc -b -tc
mkdir -p dist
cp ../*.deb dist/
# Renommer proprement
mv dist/full-updater_*.deb "dist/full-updater_${{ steps.version.outputs.version }}_all.deb"
- name: Upload release asset
env:
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
run: |
VERSION=${{ steps.version.outputs.version }}
TAG="v${VERSION}"
FILE="dist/full-updater_${VERSION}_all.deb"
# Créer la release si elle n'existe pas
curl -s -X POST \
-H "Authorization: token ${FORGEJO_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"tag_name\": \"${TAG}\", \"name\": \"Release ${TAG}\", \"body\": \"Automated build from main\"}" \
"https://git.geronzi.fr/api/v1/repos/geronzi/full_updater/releases" || true
# Récupérer l'ID de la release
RELEASE_ID=$(curl -s -H "Authorization: token ${FORGEJO_TOKEN}" \
"https://git.geronzi.fr/api/v1/repos/geronzi/full_updater/releases/latest" | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))")
if [ -n "$RELEASE_ID" ] && [ "$RELEASE_ID" != "None" ]; then
curl -s -X POST \
-H "Authorization: token ${FORGEJO_TOKEN}" \
-H "Content-Type: application/octet-stream" \
--data-binary @"${FILE}" \
"https://git.geronzi.fr/api/v1/repos/geronzi/full_updater/releases/${RELEASE_ID}/assets?name=$(basename ${FILE})"
fi
- name: Store artifact
uses: actions/upload-artifact@v4
with:
name: full-updater-deb
path: dist/*.deb

14
.gitignore vendored
View file

@ -22,3 +22,17 @@ wheels/
.venv
env/
venv/
# Debian build artifacts
debian/files
debian/full-updater/
debian/*.debhelper
debian/*.substvars
debian/changelog.dch
*.deb
*.build
*.buildinfo
*.changes
# Cache
/tmp/full-updater-cache/

30
build_deb.sh Normal file
View file

@ -0,0 +1,30 @@
#!/bin/bash
set -e
# Script de build local du .deb (à lancer manuellement si besoin)
# Usage : bash build_deb.sh
cd "$(dirname "$0")"
# Vérifier les dépendances
if ! command -v dpkg-buildpackage &> /dev/null; then
echo "Installation des dépendances de build..."
apt-get update
apt-get install -y debhelper dh-python python3-all python3-venv devscripts
fi
# Mettre à jour le changelog avec la date actuelle
DATE=$(date -R)
cat > debian/changelog <<EOF
full-updater (1.0.0) unstable; urgency=medium
* Local build
-- Enzo <admin@geronzi.fr> ${DATE}
EOF
# Build
dpkg-buildpackage -us -uc -b -tc
echo "✅ Build terminé. Le .deb est dans ../"
ls -la ../*.deb

5
debian/changelog vendored Normal file
View file

@ -0,0 +1,5 @@
full-updater (1.0.0) unstable; urgency=medium
* Initial release
-- Enzo <admin@geronzi.fr> Mon, 01 Jan 2024 00:00:00 +0000

15
debian/control vendored Normal file
View file

@ -0,0 +1,15 @@
Source: full-updater
Section: admin
Priority: optional
Maintainer: Enzo <admin@geronzi.fr>
Build-Depends: debhelper-compat (= 13), dh-python, python3-all, python3-venv
Standards-Version: 4.6.0
Package: full-updater
Architecture: all
Depends: ${python3:Depends}, python3-textual, python3-pyperclip, python3-venv, git, pct
Description: TUI for APT/CVE updates on Proxmox host and LXC
Full Updater is a terminal user interface (TUI) that visualizes
available APT updates and CVEs for the Proxmox host and all LXC
containers. It supports keyboard and mouse controls, real-time
scanning, caching, and one-click upgrades via pct exec.

23
debian/postinst vendored Normal file
View file

@ -0,0 +1,23 @@
#!/bin/bash
set -e
VENV_DIR="/opt/full-updater/.venv"
OPT_DIR="/opt/full-updater"
# Create venv and install deps
if [ ! -d "$VENV_DIR" ]; then
python3 -m venv "$VENV_DIR"
fi
"$VENV_DIR/bin/pip" install --upgrade pip
"$VENV_DIR/bin/pip" install -r "$OPT_DIR/requirements.txt"
# Ensure symlinks
ln -sf "$OPT_DIR/scripts/fullupdater" /usr/local/bin/fullupdater
# Ensure cache dir exists
mkdir -p /tmp/full-updater-cache
# Upgrade existing install if deps changed
"$VENV_DIR/bin/pip" install -r "$OPT_DIR/requirements.txt" --upgrade
exit 0

14
debian/rules vendored Normal file
View file

@ -0,0 +1,14 @@
#!/usr/bin/make -f
export DH_VERBOSE = 1
export PYBUILD_NAME = full-updater
%:
dh $@ --with python3 --buildsystem=pybuild
override_dh_auto_install:
dh_auto_install
install -D -m 755 scripts/fullupdater $(CURDIR)/debian/full-updater/opt/full-updater/scripts/fullupdater
install -D -m 755 scripts/fullupdater-update $(CURDIR)/debian/full-updater/usr/local/bin/fullupdater-update
install -D -m 644 requirements.txt $(CURDIR)/debian/full-updater/opt/full-updater/requirements.txt
cp -r full_updater $(CURDIR)/debian/full-updater/opt/full-updater/

View file

@ -1,30 +0,0 @@
#!/bin/bash
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
VENV_DIR="$SCRIPT_DIR/.venv"
BIN_PATH="/usr/local/bin/fullupdater"
echo "=== Full Updater - Installation ==="
# Créer le venv
if [ ! -d "$VENV_DIR" ]; then
echo "Création du venv..."
python3 -m venv "$VENV_DIR"
fi
echo "Installation des dépendances..."
"$VENV_DIR/bin/pip" install --upgrade pip
"$VENV_DIR/bin/pip" install -r "$SCRIPT_DIR/requirements.txt"
# Créer le wrapper
cat > "$BIN_PATH" << 'EOF'
#!/bin/bash
SCRIPT_DIR="/opt/full-updater"
source "$SCRIPT_DIR/.venv/bin/activate"
python3 -m full_updater "$@"
EOF
chmod +x "$BIN_PATH"
echo "Installation terminée. Lancez 'fullupdater'."

14
scripts/fullupdater Normal file
View file

@ -0,0 +1,14 @@
#!/bin/bash
set -e
# Wrapper script installed at /usr/local/bin/fullupdater
SCRIPT_DIR="/opt/full-updater"
VENV_DIR="$SCRIPT_DIR/.venv"
if [ ! -d "$VENV_DIR" ]; then
echo "Erreur : le venv n'existe pas. Réinstallez le paquet full-updater."
exit 1
fi
source "$VENV_DIR/bin/activate"
python3 -m full_updater "$@"

View file

@ -0,0 +1,71 @@
#!/bin/bash
set -e
REPO_URL="https://git.geronzi.fr"
OWNER="geronzi"
REPO="full_updater"
TOKEN_FILE="/etc/full-updater/token"
CONFIG_FILE="/etc/full-updater/config.ini"
INSTALLED_VERSION=$(dpkg -s full-updater 2>/dev/null | grep "^Version:" | awk '{print $2}' || echo "0.0.0")
echo "=== Full Updater Update ==="
echo "Version installée : ${INSTALLED_VERSION}"
# Build API headers
HEADERS=(-H "Content-Type: application/json")
if [ -f "$TOKEN_FILE" ]; then
TOKEN=$(cat "$TOKEN_FILE" | tr -d '[:space:]')
HEADERS+=("-H" "Authorization: token ${TOKEN}")
fi
# Fetch latest release
API_URL="${REPO_URL}/api/v1/repos/${OWNER}/${REPO}/releases/latest"
echo "Recherche de la dernière release..."
RESPONSE=$(curl -s -L "${HEADERS[@]}" "$API_URL")
if [ -z "$RESPONSE" ] || echo "$RESPONSE" | grep -q "Not Found"; then
echo "Erreur : impossible de récupérer la dernière release."
echo "Vérifiez l'URL : $API_URL"
echo "Pour un repo privé, créez /etc/full-updater/token avec un token d'accès Forgejo."
exit 1
fi
LATEST_TAG=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('tag_name',''))")
if [ -z "$LATEST_TAG" ]; then
echo "Erreur : aucune release trouvée."
exit 1
fi
LATEST_VERSION=${LATEST_TAG#v}
echo "Dernière version : ${LATEST_VERSION}"
if [ "$INSTALLED_VERSION" = "$LATEST_VERSION" ]; then
echo "✅ Full Updater est déjà à jour (${INSTALLED_VERSION})."
exit 0
fi
# Find .deb asset
ASSET_URL=$(echo "$RESPONSE" | python3 -c "
import sys, json
d = json.load(sys.stdin)
for a in d.get('assets', []):
if a['name'].endswith('.deb'):
print(a['browser_download_url'])
break
")
if [ -z "$ASSET_URL" ]; then
echo "Erreur : aucun fichier .deb trouvé dans la release ${LATEST_TAG}."
exit 1
fi
TMP_DEB="/tmp/full-updater-${LATEST_VERSION}.deb"
echo "Téléchargement de ${ASSET_URL}..."
curl -s -L -o "$TMP_DEB" "${HEADERS[@]}" "$ASSET_URL"
echo "Installation..."
dpkg -i "$TMP_DEB"
apt-get install -f -y
rm -f "$TMP_DEB"
echo "✅ Mise à jour terminée : ${INSTALLED_VERSION} → ${LATEST_VERSION}"