Files
duplicate-finder/debian/build-deb.sh
Carlos 293355b724 SFTP: switch to Transport-based connection (fixes Synology 'Channel closed')
paramiko's SSHClient.open_sftp() allocates an exec channel before the
SFTP subsystem request, which Synology DSM closes immediately with
'Channel closed'. Manual sftp(1) and WinSCP avoid this by going straight
to the SFTP subsystem on a fresh channel.

Replaced SSHClient with direct paramiko.Transport + SFTPClient.from_transport,
matching the OpenSSH/WinSCP flow. Larger flow-control windows (128 MB) too
since Synology has been observed to bail mid-handshake with the default 1 MB.

test_connection_verbose now reports per-step status (connect+auth,
open_sftp, listdir /, stat base_path, write probe). API returns the
steps array so the UI can show exactly which step failed.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-26 21:43:56 -04:00

146 lines
7.8 KiB
Bash

#!/bin/bash
# Build dupfinder.deb and upload it to the Gitea package registry.
# Run this on the NAS / any Linux machine with dpkg-deb and curl installed.
#
# Usage:
# ./debian/build-deb.sh
# ./debian/build-deb.sh --no-upload # build only, skip Gitea upload
set -e
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
DEBIAN_DIR="$REPO_ROOT/debian"
BUILD_DIR="$REPO_ROOT/build/deb"
# ── Config ────────────────────────────────────────────────────────────────────
PKG_NAME="dupfinder"
PKG_VERSION="1.1.2"
PKG_ARCH="amd64"
DEB_FILE="${PKG_NAME}_${PKG_VERSION}_${PKG_ARCH}.deb"
GITEA_URL="http://192.168.1.64:3000"
GITEA_OWNER="tocmo0nlord"
GITEA_TOKEN="${GITEA_TOKEN:-7f8d32ca83f2af6047e78cba0e13b5d63269c104}"
DISTRO="bookworm"
COMPONENT="main"
NO_UPLOAD=false
[[ "${1}" == "--no-upload" ]] && NO_UPLOAD=true
# ── Helpers ───────────────────────────────────────────────────────────────────
info() { echo -e "\033[0;36m==> $*\033[0m"; }
ok() { echo -e "\033[0;32m OK $*\033[0m"; }
fail() { echo -e "\033[0;31m !! $*\033[0m"; exit 1; }
# ── Check dependencies ────────────────────────────────────────────────────────
command -v dpkg-deb &>/dev/null || fail "dpkg-deb not found. Run: sudo apt install dpkg-dev"
command -v curl &>/dev/null || fail "curl not found. Run: sudo apt install curl"
# ── Prepare staging area ──────────────────────────────────────────────────────
info "Preparing build directory..."
PKG_STAGE="$BUILD_DIR/${PKG_NAME}_${PKG_VERSION}_${PKG_ARCH}"
rm -rf "$PKG_STAGE"
mkdir -p "$PKG_STAGE/DEBIAN"
# ── Copy DEBIAN control files ─────────────────────────────────────────────────
info "Copying control files..."
cp "$DEBIAN_DIR/control" "$PKG_STAGE/DEBIAN/control"
cp "$DEBIAN_DIR/postinst" "$PKG_STAGE/DEBIAN/postinst"
cp "$DEBIAN_DIR/prerm" "$PKG_STAGE/DEBIAN/prerm"
cp "$DEBIAN_DIR/postrm" "$PKG_STAGE/DEBIAN/postrm"
# Inject current version into control file
sed -i "s/^Version:.*/Version: $PKG_VERSION/" "$PKG_STAGE/DEBIAN/control"
# Fix permissions — maintainer scripts must be executable
chmod 755 "$PKG_STAGE/DEBIAN/postinst" \
"$PKG_STAGE/DEBIAN/prerm" \
"$PKG_STAGE/DEBIAN/postrm"
# ── Copy payload files ────────────────────────────────────────────────────────
info "Copying payload files..."
cp -r "$DEBIAN_DIR/files/." "$PKG_STAGE/"
# Copy the docker-compose.yml from repo root into the package
mkdir -p "$PKG_STAGE/opt/dupfinder"
cp "$REPO_ROOT/docker-compose.yml" "$PKG_STAGE/opt/dupfinder/docker-compose.yml"
# Copy source as fallback build path. Preserve the app/ subdirectory layout
# so the Dockerfile's `COPY app/ /app/` resolves correctly when building from
# this staged source dir.
SRC_STAGE="$PKG_STAGE/opt/dupfinder/source"
mkdir -p "$SRC_STAGE"
cp -r "$REPO_ROOT/app" "$SRC_STAGE/app"
cp -r "$REPO_ROOT/templates" "$SRC_STAGE/templates"
cp "$REPO_ROOT/Dockerfile" "$SRC_STAGE/Dockerfile"
cp "$REPO_ROOT/requirements.txt" "$SRC_STAGE/requirements.txt"
# ── Fix file permissions ──────────────────────────────────────────────────────
find "$PKG_STAGE" -type f -name "*.sh" -exec chmod 755 {} \;
chmod 755 "$PKG_STAGE/usr/local/bin/dupfinder" 2>/dev/null || true
# Directories must be 755, files 644 (except executables)
find "$PKG_STAGE" -type d -exec chmod 755 {} \;
find "$PKG_STAGE" -type f ! -name "*.sh" \
! -path "*/DEBIAN/*" \
! -name "dupfinder" \
-exec chmod 644 {} \;
ok "Staging area ready: $PKG_STAGE"
# ── Build .deb ────────────────────────────────────────────────────────────────
info "Building $DEB_FILE ..."
mkdir -p "$BUILD_DIR"
dpkg-deb --build --root-owner-group "$PKG_STAGE" "$BUILD_DIR/$DEB_FILE"
DEB_SIZE=$(du -sh "$BUILD_DIR/$DEB_FILE" | cut -f1)
ok "Built: $BUILD_DIR/$DEB_FILE ($DEB_SIZE)"
# ── Upload to Gitea ───────────────────────────────────────────────────────────
if [[ "$NO_UPLOAD" == "true" ]]; then
echo ""
echo "Skipping upload (--no-upload). File is at:"
echo " $BUILD_DIR/$DEB_FILE"
exit 0
fi
info "Uploading to Gitea package registry..."
# Gitea's Debian registry requires HTTP basic auth (user + token-as-password)
# and the literal /upload endpoint — token-bearer auth returns 405.
UPLOAD_URL="$GITEA_URL/api/packages/$GITEA_OWNER/debian/pool/$DISTRO/$COMPONENT/upload"
HTTP_STATUS=$(curl -s -o /tmp/gitea_upload_response.txt -w "%{http_code}" \
-u "$GITEA_OWNER:$GITEA_TOKEN" \
--upload-file "$BUILD_DIR/$DEB_FILE" \
"$UPLOAD_URL")
if [[ "$HTTP_STATUS" == "201" || "$HTTP_STATUS" == "200" ]]; then
ok "Uploaded successfully (HTTP $HTTP_STATUS)"
elif [[ "$HTTP_STATUS" == "409" ]]; then
echo " Package version $PKG_VERSION already exists in registry."
echo " Bump PKG_VERSION in this script to publish a new version."
else
echo " Upload failed (HTTP $HTTP_STATUS):"
cat /tmp/gitea_upload_response.txt
exit 1
fi
# ── Print install instructions ────────────────────────────────────────────────
echo ""
echo "╔══════════════════════════════════════════════════════════════════╗"
echo "║ Package published! Install on any Ubuntu/Debian machine with: ║"
echo "╠══════════════════════════════════════════════════════════════════╣"
echo "║ ║"
echo "║ 1. Add the repo: ║"
echo "║ echo \"deb [trusted=yes] \\ ║"
echo "$GITEA_URL/api/packages/$GITEA_OWNER/debian \\ ║"
echo "$DISTRO $COMPONENT\" \\ ║"
echo "║ | sudo tee /etc/apt/sources.list.d/dupfinder.list ║"
echo "║ ║"
echo "║ 2. Install: ║"
echo "║ sudo apt update && sudo apt install dupfinder ║"
echo "║ ║"
echo "║ 3. Configure: ║"
echo "║ sudo dupfinder setup ║"
echo "║ ║"
echo "╚══════════════════════════════════════════════════════════════════╝"
echo ""