diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml new file mode 100644 index 0000000..f3b531b --- /dev/null +++ b/.forgejo/workflows/build.yml @@ -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 < ${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 diff --git a/.gitignore b/.gitignore index 9230906..3d676ca 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/build_deb.sh b/build_deb.sh new file mode 100644 index 0000000..c972544 --- /dev/null +++ b/build_deb.sh @@ -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 < ${DATE} +EOF + +# Build +dpkg-buildpackage -us -uc -b -tc + +echo "✅ Build terminé. Le .deb est dans ../" +ls -la ../*.deb diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..2818b24 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +full-updater (1.0.0) unstable; urgency=medium + + * Initial release + + -- Enzo Mon, 01 Jan 2024 00:00:00 +0000 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..940ddca --- /dev/null +++ b/debian/control @@ -0,0 +1,15 @@ +Source: full-updater +Section: admin +Priority: optional +Maintainer: Enzo +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. diff --git a/debian/postinst b/debian/postinst new file mode 100644 index 0000000..4197fae --- /dev/null +++ b/debian/postinst @@ -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 diff --git a/debian/rules b/debian/rules new file mode 100644 index 0000000..96ecdf9 --- /dev/null +++ b/debian/rules @@ -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/ diff --git a/install.sh b/install.sh deleted file mode 100644 index cc53445..0000000 --- a/install.sh +++ /dev/null @@ -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'." diff --git a/scripts/fullupdater b/scripts/fullupdater new file mode 100644 index 0000000..8eb8655 --- /dev/null +++ b/scripts/fullupdater @@ -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 "$@" diff --git a/scripts/fullupdater-update b/scripts/fullupdater-update new file mode 100644 index 0000000..8d28379 --- /dev/null +++ b/scripts/fullupdater-update @@ -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}"